mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-05-19 08:10:07 +02:00
chainntnfs: move cache implementation to channeldb
This commit moves the `HeightHintCache` implementation to the `channeldb` package and inverts the dependency relation between `chainntnfs` and `channeldb`. Many packages depend on channeldb for type definitions, interfaces, etc. `chainntnfs` is an example of that. `chainntnfs` defines the `SpendHintCache` and `ConfirmHintCache` interfaces but it also implments them (`HeightHintCache` struct). The implementation uses logic that should not leak from channeldb (ex: bucket paths). This makes our code highly coupled + it would not allow us to use any of these interfaces in a package that is imported by `channeldb` (circular dependency).
This commit is contained in:
parent
681da4b2b5
commit
c602ac07e7
@ -31,7 +31,7 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func initHintCache(t *testing.T) *chainntnfs.HeightHintCache {
|
func initHintCache(t *testing.T) *channeldb.HeightHintCache {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
db, err := channeldb.Open(t.TempDir())
|
db, err := channeldb.Open(t.TempDir())
|
||||||
@ -40,10 +40,10 @@ func initHintCache(t *testing.T) *chainntnfs.HeightHintCache {
|
|||||||
require.NoError(t, db.Close())
|
require.NoError(t, db.Close())
|
||||||
})
|
})
|
||||||
|
|
||||||
testCfg := chainntnfs.CacheConfig{
|
testCfg := channeldb.CacheConfig{
|
||||||
QueryDisable: false,
|
QueryDisable: false,
|
||||||
}
|
}
|
||||||
hintCache, err := chainntnfs.NewHeightHintCache(testCfg, db.Backend)
|
hintCache, err := channeldb.NewHeightHintCache(testCfg, db.Backend)
|
||||||
require.NoError(t, err, "unable to create hint cache")
|
require.NoError(t, err, "unable to create hint cache")
|
||||||
|
|
||||||
return hintCache
|
return hintCache
|
||||||
|
@ -29,7 +29,7 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func initHintCache(t *testing.T) *chainntnfs.HeightHintCache {
|
func initHintCache(t *testing.T) *channeldb.HeightHintCache {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
db, err := channeldb.Open(t.TempDir())
|
db, err := channeldb.Open(t.TempDir())
|
||||||
@ -38,10 +38,10 @@ func initHintCache(t *testing.T) *chainntnfs.HeightHintCache {
|
|||||||
require.NoError(t, db.Close())
|
require.NoError(t, db.Close())
|
||||||
})
|
})
|
||||||
|
|
||||||
testCfg := chainntnfs.CacheConfig{
|
testCfg := channeldb.CacheConfig{
|
||||||
QueryDisable: false,
|
QueryDisable: false,
|
||||||
}
|
}
|
||||||
hintCache, err := chainntnfs.NewHeightHintCache(testCfg, db.Backend)
|
hintCache, err := channeldb.NewHeightHintCache(testCfg, db.Backend)
|
||||||
require.NoError(t, err, "unable to create hint cache")
|
require.NoError(t, err, "unable to create hint cache")
|
||||||
|
|
||||||
return hintCache
|
return hintCache
|
||||||
|
18
chainntnfs/errors.go
Normal file
18
chainntnfs/errors.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package chainntnfs
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrCorruptedHeightHintCache indicates that the on-disk representation
|
||||||
|
// has altered since the height hint cache instance was initialized.
|
||||||
|
ErrCorruptedHeightHintCache = errors.New("height hint cache has been " +
|
||||||
|
"corrupted")
|
||||||
|
|
||||||
|
// ErrSpendHintNotFound is an error returned when a spend hint for an
|
||||||
|
// outpoint was not found.
|
||||||
|
ErrSpendHintNotFound = errors.New("spend hint not found")
|
||||||
|
|
||||||
|
// ErrConfirmHintNotFound is an error returned when a confirm hint for a
|
||||||
|
// transaction was not found.
|
||||||
|
ErrConfirmHintNotFound = errors.New("confirm hint not found")
|
||||||
|
)
|
@ -773,3 +773,38 @@ func ConfDetailsFromTxIndex(chainConn TxIndexConn, r ConfRequest,
|
|||||||
return nil, TxNotFoundIndex, fmt.Errorf("unable to locate "+
|
return nil, TxNotFoundIndex, fmt.Errorf("unable to locate "+
|
||||||
"tx %v in block %v", r.TxID, blockHash)
|
"tx %v in block %v", r.TxID, blockHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SpendHintCache is an interface whose duty is to cache spend hints for
|
||||||
|
// outpoints. A spend hint is defined as the earliest height in the chain at
|
||||||
|
// which an outpoint could have been spent within.
|
||||||
|
type SpendHintCache interface {
|
||||||
|
// CommitSpendHint commits a spend hint for the outpoints to the cache.
|
||||||
|
CommitSpendHint(height uint32, spendRequests ...SpendRequest) error
|
||||||
|
|
||||||
|
// QuerySpendHint returns the latest spend hint for an outpoint.
|
||||||
|
// ErrSpendHintNotFound is returned if a spend hint does not exist
|
||||||
|
// within the cache for the outpoint.
|
||||||
|
QuerySpendHint(spendRequest SpendRequest) (uint32, error)
|
||||||
|
|
||||||
|
// PurgeSpendHint removes the spend hint for the outpoints from the
|
||||||
|
// cache.
|
||||||
|
PurgeSpendHint(spendRequests ...SpendRequest) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfirmHintCache is an interface whose duty is to cache confirm hints for
|
||||||
|
// transactions. A confirm hint is defined as the earliest height in the chain
|
||||||
|
// at which a transaction could have been included in a block.
|
||||||
|
type ConfirmHintCache interface {
|
||||||
|
// CommitConfirmHint commits a confirm hint for the transactions to the
|
||||||
|
// cache.
|
||||||
|
CommitConfirmHint(height uint32, confRequests ...ConfRequest) error
|
||||||
|
|
||||||
|
// QueryConfirmHint returns the latest confirm hint for a transaction
|
||||||
|
// hash. ErrConfirmHintNotFound is returned if a confirm hint does not
|
||||||
|
// exist within the cache for the transaction hash.
|
||||||
|
QueryConfirmHint(confRequest ConfRequest) (uint32, error)
|
||||||
|
|
||||||
|
// PurgeConfirmHint removes the confirm hint for the transactions from
|
||||||
|
// the cache.
|
||||||
|
PurgeConfirmHint(confRequests ...ConfRequest) error
|
||||||
|
}
|
||||||
|
@ -1836,10 +1836,10 @@ func TestInterfaces(t *testing.T, targetBackEnd string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create db: %v", err)
|
t.Fatalf("unable to create db: %v", err)
|
||||||
}
|
}
|
||||||
testCfg := chainntnfs.CacheConfig{
|
testCfg := channeldb.CacheConfig{
|
||||||
QueryDisable: false,
|
QueryDisable: false,
|
||||||
}
|
}
|
||||||
hintCache, err := chainntnfs.NewHeightHintCache(
|
hintCache, err := channeldb.NewHeightHintCache(
|
||||||
testCfg, db.Backend,
|
testCfg, db.Backend,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -201,21 +200,6 @@ func (r ConfRequest) String() string {
|
|||||||
return fmt.Sprintf("script=%v", r.PkScript)
|
return fmt.Sprintf("script=%v", r.PkScript)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfHintKey returns the key that will be used to index the confirmation
|
|
||||||
// request's hint within the height hint cache.
|
|
||||||
func (r ConfRequest) ConfHintKey() ([]byte, error) {
|
|
||||||
if r.TxID == ZeroHash {
|
|
||||||
return r.PkScript.Script(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var txid bytes.Buffer
|
|
||||||
if err := channeldb.WriteElement(&txid, r.TxID); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return txid.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchesTx determines whether the given transaction satisfies the confirmation
|
// MatchesTx determines whether the given transaction satisfies the confirmation
|
||||||
// request. If the confirmation request is for a script, then we'll check all of
|
// request. If the confirmation request is for a script, then we'll check all of
|
||||||
// the outputs of the transaction to determine if it matches. Otherwise, we'll
|
// the outputs of the transaction to determine if it matches. Otherwise, we'll
|
||||||
@ -369,22 +353,6 @@ func (r SpendRequest) String() string {
|
|||||||
return fmt.Sprintf("outpoint=<zero>, script=%v", r.PkScript)
|
return fmt.Sprintf("outpoint=<zero>, script=%v", r.PkScript)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SpendHintKey returns the key that will be used to index the spend request's
|
|
||||||
// hint within the height hint cache.
|
|
||||||
func (r SpendRequest) SpendHintKey() ([]byte, error) {
|
|
||||||
if r.OutPoint == ZeroOutPoint {
|
|
||||||
return r.PkScript.Script(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var outpoint bytes.Buffer
|
|
||||||
err := channeldb.WriteElement(&outpoint, r.OutPoint)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return outpoint.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchesTx determines whether the given transaction satisfies the spend
|
// MatchesTx determines whether the given transaction satisfies the spend
|
||||||
// request. If the spend request is for an outpoint, then we'll check all of
|
// request. If the spend request is for an outpoint, then we'll check all of
|
||||||
// the outputs being spent by the inputs of the transaction to determine if it
|
// the outputs being spent by the inputs of the transaction to determine if it
|
||||||
|
@ -292,7 +292,7 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
heightHintCacheConfig := chainntnfs.CacheConfig{
|
heightHintCacheConfig := channeldb.CacheConfig{
|
||||||
QueryDisable: cfg.HeightHintCacheQueryDisable,
|
QueryDisable: cfg.HeightHintCacheQueryDisable,
|
||||||
}
|
}
|
||||||
if cfg.HeightHintCacheQueryDisable {
|
if cfg.HeightHintCacheQueryDisable {
|
||||||
@ -300,7 +300,7 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the height hint cache within the chain directory.
|
// Initialize the height hint cache within the chain directory.
|
||||||
hintCache, err := chainntnfs.NewHeightHintCache(
|
hintCache, err := channeldb.NewHeightHintCache(
|
||||||
heightHintCacheConfig, cfg.HeightHintDB,
|
heightHintCacheConfig, cfg.HeightHintDB,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
package chainntnfs
|
package channeldb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/kvdb"
|
"github.com/lightningnetwork/lnd/kvdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,20 +18,6 @@ var (
|
|||||||
// height at which its corresponding transaction could have been
|
// height at which its corresponding transaction could have been
|
||||||
// confirmed within.
|
// confirmed within.
|
||||||
confirmHintBucket = []byte("confirm-hints")
|
confirmHintBucket = []byte("confirm-hints")
|
||||||
|
|
||||||
// ErrCorruptedHeightHintCache indicates that the on-disk bucketing
|
|
||||||
// structure has altered since the height hint cache instance was
|
|
||||||
// initialized.
|
|
||||||
ErrCorruptedHeightHintCache = errors.New("height hint cache has been " +
|
|
||||||
"corrupted")
|
|
||||||
|
|
||||||
// ErrSpendHintNotFound is an error returned when a spend hint for an
|
|
||||||
// outpoint was not found.
|
|
||||||
ErrSpendHintNotFound = errors.New("spend hint not found")
|
|
||||||
|
|
||||||
// ErrConfirmHintNotFound is an error returned when a confirm hint for a
|
|
||||||
// transaction was not found.
|
|
||||||
ErrConfirmHintNotFound = errors.New("confirm hint not found")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CacheConfig contains the HeightHintCache configuration.
|
// CacheConfig contains the HeightHintCache configuration.
|
||||||
@ -44,41 +29,6 @@ type CacheConfig struct {
|
|||||||
QueryDisable bool
|
QueryDisable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// SpendHintCache is an interface whose duty is to cache spend hints for
|
|
||||||
// outpoints. A spend hint is defined as the earliest height in the chain at
|
|
||||||
// which an outpoint could have been spent within.
|
|
||||||
type SpendHintCache interface {
|
|
||||||
// CommitSpendHint commits a spend hint for the outpoints to the cache.
|
|
||||||
CommitSpendHint(height uint32, spendRequests ...SpendRequest) error
|
|
||||||
|
|
||||||
// QuerySpendHint returns the latest spend hint for an outpoint.
|
|
||||||
// ErrSpendHintNotFound is returned if a spend hint does not exist
|
|
||||||
// within the cache for the outpoint.
|
|
||||||
QuerySpendHint(spendRequest SpendRequest) (uint32, error)
|
|
||||||
|
|
||||||
// PurgeSpendHint removes the spend hint for the outpoints from the
|
|
||||||
// cache.
|
|
||||||
PurgeSpendHint(spendRequests ...SpendRequest) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfirmHintCache is an interface whose duty is to cache confirm hints for
|
|
||||||
// transactions. A confirm hint is defined as the earliest height in the chain
|
|
||||||
// at which a transaction could have been included in a block.
|
|
||||||
type ConfirmHintCache interface {
|
|
||||||
// CommitConfirmHint commits a confirm hint for the transactions to the
|
|
||||||
// cache.
|
|
||||||
CommitConfirmHint(height uint32, confRequests ...ConfRequest) error
|
|
||||||
|
|
||||||
// QueryConfirmHint returns the latest confirm hint for a transaction
|
|
||||||
// hash. ErrConfirmHintNotFound is returned if a confirm hint does not
|
|
||||||
// exist within the cache for the transaction hash.
|
|
||||||
QueryConfirmHint(confRequest ConfRequest) (uint32, error)
|
|
||||||
|
|
||||||
// PurgeConfirmHint removes the confirm hint for the transactions from
|
|
||||||
// the cache.
|
|
||||||
PurgeConfirmHint(confRequests ...ConfRequest) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// HeightHintCache is an implementation of the SpendHintCache and
|
// HeightHintCache is an implementation of the SpendHintCache and
|
||||||
// ConfirmHintCache interfaces backed by a channeldb DB instance where the hints
|
// ConfirmHintCache interfaces backed by a channeldb DB instance where the hints
|
||||||
// will be stored.
|
// will be stored.
|
||||||
@ -89,8 +39,8 @@ type HeightHintCache struct {
|
|||||||
|
|
||||||
// Compile-time checks to ensure HeightHintCache satisfies the SpendHintCache
|
// Compile-time checks to ensure HeightHintCache satisfies the SpendHintCache
|
||||||
// and ConfirmHintCache interfaces.
|
// and ConfirmHintCache interfaces.
|
||||||
var _ SpendHintCache = (*HeightHintCache)(nil)
|
var _ chainntnfs.SpendHintCache = (*HeightHintCache)(nil)
|
||||||
var _ ConfirmHintCache = (*HeightHintCache)(nil)
|
var _ chainntnfs.ConfirmHintCache = (*HeightHintCache)(nil)
|
||||||
|
|
||||||
// NewHeightHintCache returns a new height hint cache backed by a database.
|
// NewHeightHintCache returns a new height hint cache backed by a database.
|
||||||
func NewHeightHintCache(cfg CacheConfig, db kvdb.Backend) (*HeightHintCache,
|
func NewHeightHintCache(cfg CacheConfig, db kvdb.Backend) (*HeightHintCache,
|
||||||
@ -120,28 +70,29 @@ func (c *HeightHintCache) initBuckets() error {
|
|||||||
|
|
||||||
// CommitSpendHint commits a spend hint for the outpoints to the cache.
|
// CommitSpendHint commits a spend hint for the outpoints to the cache.
|
||||||
func (c *HeightHintCache) CommitSpendHint(height uint32,
|
func (c *HeightHintCache) CommitSpendHint(height uint32,
|
||||||
spendRequests ...SpendRequest) error {
|
spendRequests ...chainntnfs.SpendRequest) error {
|
||||||
|
|
||||||
if len(spendRequests) == 0 {
|
if len(spendRequests) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Tracef("Updating spend hint to height %d for %v", height,
|
log.Tracef("Updating spend hint to height %d for %v", height,
|
||||||
spendRequests)
|
spendRequests)
|
||||||
|
|
||||||
return kvdb.Batch(c.db, func(tx kvdb.RwTx) error {
|
return kvdb.Batch(c.db, func(tx kvdb.RwTx) error {
|
||||||
spendHints := tx.ReadWriteBucket(spendHintBucket)
|
spendHints := tx.ReadWriteBucket(spendHintBucket)
|
||||||
if spendHints == nil {
|
if spendHints == nil {
|
||||||
return ErrCorruptedHeightHintCache
|
return chainntnfs.ErrCorruptedHeightHintCache
|
||||||
}
|
}
|
||||||
|
|
||||||
var hint bytes.Buffer
|
var hint bytes.Buffer
|
||||||
if err := channeldb.WriteElement(&hint, height); err != nil {
|
if err := WriteElement(&hint, height); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, spendRequest := range spendRequests {
|
for _, spendRequest := range spendRequests {
|
||||||
spendHintKey, err := spendRequest.SpendHintKey()
|
spendRequest := spendRequest
|
||||||
|
spendHintKey, err := spendHintKey(&spendRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -158,29 +109,31 @@ func (c *HeightHintCache) CommitSpendHint(height uint32,
|
|||||||
// QuerySpendHint returns the latest spend hint for an outpoint.
|
// QuerySpendHint returns the latest spend hint for an outpoint.
|
||||||
// ErrSpendHintNotFound is returned if a spend hint does not exist within the
|
// ErrSpendHintNotFound is returned if a spend hint does not exist within the
|
||||||
// cache for the outpoint.
|
// cache for the outpoint.
|
||||||
func (c *HeightHintCache) QuerySpendHint(spendRequest SpendRequest) (uint32, error) {
|
func (c *HeightHintCache) QuerySpendHint(
|
||||||
|
spendRequest chainntnfs.SpendRequest) (uint32, error) {
|
||||||
|
|
||||||
var hint uint32
|
var hint uint32
|
||||||
if c.cfg.QueryDisable {
|
if c.cfg.QueryDisable {
|
||||||
Log.Debugf("Ignoring spend height hint for %v (height hint cache "+
|
log.Debugf("Ignoring spend height hint for %v (height hint "+
|
||||||
"query disabled)", spendRequest)
|
"cache query disabled)", spendRequest)
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
||||||
spendHints := tx.ReadBucket(spendHintBucket)
|
spendHints := tx.ReadBucket(spendHintBucket)
|
||||||
if spendHints == nil {
|
if spendHints == nil {
|
||||||
return ErrCorruptedHeightHintCache
|
return chainntnfs.ErrCorruptedHeightHintCache
|
||||||
}
|
}
|
||||||
|
|
||||||
spendHintKey, err := spendRequest.SpendHintKey()
|
spendHintKey, err := spendHintKey(&spendRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
spendHint := spendHints.Get(spendHintKey)
|
spendHint := spendHints.Get(spendHintKey)
|
||||||
if spendHint == nil {
|
if spendHint == nil {
|
||||||
return ErrSpendHintNotFound
|
return chainntnfs.ErrSpendHintNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
return channeldb.ReadElement(bytes.NewReader(spendHint), &hint)
|
return ReadElement(bytes.NewReader(spendHint), &hint)
|
||||||
}, func() {
|
}, func() {
|
||||||
hint = 0
|
hint = 0
|
||||||
})
|
})
|
||||||
@ -192,21 +145,24 @@ func (c *HeightHintCache) QuerySpendHint(spendRequest SpendRequest) (uint32, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PurgeSpendHint removes the spend hint for the outpoints from the cache.
|
// PurgeSpendHint removes the spend hint for the outpoints from the cache.
|
||||||
func (c *HeightHintCache) PurgeSpendHint(spendRequests ...SpendRequest) error {
|
func (c *HeightHintCache) PurgeSpendHint(
|
||||||
|
spendRequests ...chainntnfs.SpendRequest) error {
|
||||||
|
|
||||||
if len(spendRequests) == 0 {
|
if len(spendRequests) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Tracef("Removing spend hints for %v", spendRequests)
|
log.Tracef("Removing spend hints for %v", spendRequests)
|
||||||
|
|
||||||
return kvdb.Batch(c.db, func(tx kvdb.RwTx) error {
|
return kvdb.Batch(c.db, func(tx kvdb.RwTx) error {
|
||||||
spendHints := tx.ReadWriteBucket(spendHintBucket)
|
spendHints := tx.ReadWriteBucket(spendHintBucket)
|
||||||
if spendHints == nil {
|
if spendHints == nil {
|
||||||
return ErrCorruptedHeightHintCache
|
return chainntnfs.ErrCorruptedHeightHintCache
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, spendRequest := range spendRequests {
|
for _, spendRequest := range spendRequests {
|
||||||
spendHintKey, err := spendRequest.SpendHintKey()
|
spendRequest := spendRequest
|
||||||
|
spendHintKey, err := spendHintKey(&spendRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -221,28 +177,29 @@ func (c *HeightHintCache) PurgeSpendHint(spendRequests ...SpendRequest) error {
|
|||||||
|
|
||||||
// CommitConfirmHint commits a confirm hint for the transactions to the cache.
|
// CommitConfirmHint commits a confirm hint for the transactions to the cache.
|
||||||
func (c *HeightHintCache) CommitConfirmHint(height uint32,
|
func (c *HeightHintCache) CommitConfirmHint(height uint32,
|
||||||
confRequests ...ConfRequest) error {
|
confRequests ...chainntnfs.ConfRequest) error {
|
||||||
|
|
||||||
if len(confRequests) == 0 {
|
if len(confRequests) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Tracef("Updating confirm hints to height %d for %v", height,
|
log.Tracef("Updating confirm hints to height %d for %v", height,
|
||||||
confRequests)
|
confRequests)
|
||||||
|
|
||||||
return kvdb.Batch(c.db, func(tx kvdb.RwTx) error {
|
return kvdb.Batch(c.db, func(tx kvdb.RwTx) error {
|
||||||
confirmHints := tx.ReadWriteBucket(confirmHintBucket)
|
confirmHints := tx.ReadWriteBucket(confirmHintBucket)
|
||||||
if confirmHints == nil {
|
if confirmHints == nil {
|
||||||
return ErrCorruptedHeightHintCache
|
return chainntnfs.ErrCorruptedHeightHintCache
|
||||||
}
|
}
|
||||||
|
|
||||||
var hint bytes.Buffer
|
var hint bytes.Buffer
|
||||||
if err := channeldb.WriteElement(&hint, height); err != nil {
|
if err := WriteElement(&hint, height); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, confRequest := range confRequests {
|
for _, confRequest := range confRequests {
|
||||||
confHintKey, err := confRequest.ConfHintKey()
|
confRequest := confRequest
|
||||||
|
confHintKey, err := confHintKey(&confRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -259,29 +216,31 @@ func (c *HeightHintCache) CommitConfirmHint(height uint32,
|
|||||||
// QueryConfirmHint returns the latest confirm hint for a transaction hash.
|
// QueryConfirmHint returns the latest confirm hint for a transaction hash.
|
||||||
// ErrConfirmHintNotFound is returned if a confirm hint does not exist within
|
// ErrConfirmHintNotFound is returned if a confirm hint does not exist within
|
||||||
// the cache for the transaction hash.
|
// the cache for the transaction hash.
|
||||||
func (c *HeightHintCache) QueryConfirmHint(confRequest ConfRequest) (uint32, error) {
|
func (c *HeightHintCache) QueryConfirmHint(
|
||||||
|
confRequest chainntnfs.ConfRequest) (uint32, error) {
|
||||||
|
|
||||||
var hint uint32
|
var hint uint32
|
||||||
if c.cfg.QueryDisable {
|
if c.cfg.QueryDisable {
|
||||||
Log.Debugf("Ignoring confirmation height hint for %v (height hint "+
|
log.Debugf("Ignoring confirmation height hint for %v (height "+
|
||||||
"cache query disabled)", confRequest)
|
"hint cache query disabled)", confRequest)
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
||||||
confirmHints := tx.ReadBucket(confirmHintBucket)
|
confirmHints := tx.ReadBucket(confirmHintBucket)
|
||||||
if confirmHints == nil {
|
if confirmHints == nil {
|
||||||
return ErrCorruptedHeightHintCache
|
return chainntnfs.ErrCorruptedHeightHintCache
|
||||||
}
|
}
|
||||||
|
|
||||||
confHintKey, err := confRequest.ConfHintKey()
|
confHintKey, err := confHintKey(&confRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
confirmHint := confirmHints.Get(confHintKey)
|
confirmHint := confirmHints.Get(confHintKey)
|
||||||
if confirmHint == nil {
|
if confirmHint == nil {
|
||||||
return ErrConfirmHintNotFound
|
return chainntnfs.ErrConfirmHintNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
return channeldb.ReadElement(bytes.NewReader(confirmHint), &hint)
|
return ReadElement(bytes.NewReader(confirmHint), &hint)
|
||||||
}, func() {
|
}, func() {
|
||||||
hint = 0
|
hint = 0
|
||||||
})
|
})
|
||||||
@ -294,21 +253,24 @@ func (c *HeightHintCache) QueryConfirmHint(confRequest ConfRequest) (uint32, err
|
|||||||
|
|
||||||
// PurgeConfirmHint removes the confirm hint for the transactions from the
|
// PurgeConfirmHint removes the confirm hint for the transactions from the
|
||||||
// cache.
|
// cache.
|
||||||
func (c *HeightHintCache) PurgeConfirmHint(confRequests ...ConfRequest) error {
|
func (c *HeightHintCache) PurgeConfirmHint(
|
||||||
|
confRequests ...chainntnfs.ConfRequest) error {
|
||||||
|
|
||||||
if len(confRequests) == 0 {
|
if len(confRequests) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Tracef("Removing confirm hints for %v", confRequests)
|
log.Tracef("Removing confirm hints for %v", confRequests)
|
||||||
|
|
||||||
return kvdb.Batch(c.db, func(tx kvdb.RwTx) error {
|
return kvdb.Batch(c.db, func(tx kvdb.RwTx) error {
|
||||||
confirmHints := tx.ReadWriteBucket(confirmHintBucket)
|
confirmHints := tx.ReadWriteBucket(confirmHintBucket)
|
||||||
if confirmHints == nil {
|
if confirmHints == nil {
|
||||||
return ErrCorruptedHeightHintCache
|
return chainntnfs.ErrCorruptedHeightHintCache
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, confRequest := range confRequests {
|
for _, confRequest := range confRequests {
|
||||||
confHintKey, err := confRequest.ConfHintKey()
|
confRequest := confRequest
|
||||||
|
confHintKey, err := confHintKey(&confRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -320,3 +282,34 @@ func (c *HeightHintCache) PurgeConfirmHint(confRequests ...ConfRequest) error {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// confHintKey returns the key that will be used to index the confirmation
|
||||||
|
// request's hint within the height hint cache.
|
||||||
|
func confHintKey(r *chainntnfs.ConfRequest) ([]byte, error) {
|
||||||
|
if r.TxID == chainntnfs.ZeroHash {
|
||||||
|
return r.PkScript.Script(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var txid bytes.Buffer
|
||||||
|
if err := WriteElement(&txid, r.TxID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return txid.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// spendHintKey returns the key that will be used to index the spend request's
|
||||||
|
// hint within the height hint cache.
|
||||||
|
func spendHintKey(r *chainntnfs.SpendRequest) ([]byte, error) {
|
||||||
|
if r.OutPoint == chainntnfs.ZeroOutPoint {
|
||||||
|
return r.PkScript.Script(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var outpoint bytes.Buffer
|
||||||
|
err := WriteElement(&outpoint, r.OutPoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return outpoint.Bytes(), nil
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package chainntnfs
|
package channeldb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ func initHintCache(t *testing.T) *HeightHintCache {
|
|||||||
func initHintCacheWithConfig(t *testing.T, cfg CacheConfig) *HeightHintCache {
|
func initHintCacheWithConfig(t *testing.T, cfg CacheConfig) *HeightHintCache {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
db, err := channeldb.Open(t.TempDir())
|
db, err := Open(t.TempDir())
|
||||||
require.NoError(t, err, "unable to create db")
|
require.NoError(t, err, "unable to create db")
|
||||||
hintCache, err := NewHeightHintCache(cfg, db.Backend)
|
hintCache, err := NewHeightHintCache(cfg, db.Backend)
|
||||||
require.NoError(t, err, "unable to create hint cache")
|
require.NoError(t, err, "unable to create hint cache")
|
||||||
@ -46,21 +46,19 @@ func TestHeightHintCacheConfirms(t *testing.T) {
|
|||||||
// return an error indication so.
|
// return an error indication so.
|
||||||
var unknownHash chainhash.Hash
|
var unknownHash chainhash.Hash
|
||||||
copy(unknownHash[:], bytes.Repeat([]byte{0x01}, 32))
|
copy(unknownHash[:], bytes.Repeat([]byte{0x01}, 32))
|
||||||
unknownConfRequest := ConfRequest{TxID: unknownHash}
|
unknownConfRequest := chainntnfs.ConfRequest{TxID: unknownHash}
|
||||||
_, err := hintCache.QueryConfirmHint(unknownConfRequest)
|
_, err := hintCache.QueryConfirmHint(unknownConfRequest)
|
||||||
if err != ErrConfirmHintNotFound {
|
require.ErrorIs(t, err, chainntnfs.ErrConfirmHintNotFound)
|
||||||
t.Fatalf("expected ErrConfirmHintNotFound, got: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, we'll create some transaction hashes and commit them to the
|
// Now, we'll create some transaction hashes and commit them to the
|
||||||
// cache with the same confirm hint.
|
// cache with the same confirm hint.
|
||||||
const height = 100
|
const height = 100
|
||||||
const numHashes = 5
|
const numHashes = 5
|
||||||
confRequests := make([]ConfRequest, numHashes)
|
confRequests := make([]chainntnfs.ConfRequest, numHashes)
|
||||||
for i := 0; i < numHashes; i++ {
|
for i := 0; i < numHashes; i++ {
|
||||||
var txHash chainhash.Hash
|
var txHash chainhash.Hash
|
||||||
copy(txHash[:], bytes.Repeat([]byte{byte(i + 1)}, 32))
|
copy(txHash[:], bytes.Repeat([]byte{byte(i + 1)}, 32))
|
||||||
confRequests[i] = ConfRequest{TxID: txHash}
|
confRequests[i] = chainntnfs.ConfRequest{TxID: txHash}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = hintCache.CommitConfirmHint(height, confRequests...)
|
err = hintCache.CommitConfirmHint(height, confRequests...)
|
||||||
@ -70,28 +68,20 @@ func TestHeightHintCacheConfirms(t *testing.T) {
|
|||||||
// we're able to properly retrieve the confirm hints.
|
// we're able to properly retrieve the confirm hints.
|
||||||
for _, confRequest := range confRequests {
|
for _, confRequest := range confRequests {
|
||||||
confirmHint, err := hintCache.QueryConfirmHint(confRequest)
|
confirmHint, err := hintCache.QueryConfirmHint(confRequest)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to query for hint of %v: %v", confRequest, err)
|
require.EqualValues(t, height, confirmHint)
|
||||||
}
|
|
||||||
if confirmHint != height {
|
|
||||||
t.Fatalf("expected confirm hint %d, got %d", height,
|
|
||||||
confirmHint)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll also attempt to purge all of them in a single database
|
// We'll also attempt to purge all of them in a single database
|
||||||
// transaction.
|
// transaction.
|
||||||
if err := hintCache.PurgeConfirmHint(confRequests...); err != nil {
|
err = hintCache.PurgeConfirmHint(confRequests...)
|
||||||
t.Fatalf("unable to remove confirm hints: %v", err)
|
require.NoError(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, we'll attempt to query for each hash. We should expect not
|
// Finally, we'll attempt to query for each hash. We should expect not
|
||||||
// to find a hint for any of them.
|
// to find a hint for any of them.
|
||||||
for _, confRequest := range confRequests {
|
for _, confRequest := range confRequests {
|
||||||
_, err := hintCache.QueryConfirmHint(confRequest)
|
_, err := hintCache.QueryConfirmHint(confRequest)
|
||||||
if err != ErrConfirmHintNotFound {
|
require.ErrorIs(t, err, chainntnfs.ErrConfirmHintNotFound)
|
||||||
t.Fatalf("expected ErrConfirmHintNotFound, got :%v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,19 +95,19 @@ func TestHeightHintCacheSpends(t *testing.T) {
|
|||||||
// Querying for an outpoint not found within the cache should return an
|
// Querying for an outpoint not found within the cache should return an
|
||||||
// error indication so.
|
// error indication so.
|
||||||
unknownOutPoint := wire.OutPoint{Index: 1}
|
unknownOutPoint := wire.OutPoint{Index: 1}
|
||||||
unknownSpendRequest := SpendRequest{OutPoint: unknownOutPoint}
|
unknownSpendRequest := chainntnfs.SpendRequest{
|
||||||
_, err := hintCache.QuerySpendHint(unknownSpendRequest)
|
OutPoint: unknownOutPoint,
|
||||||
if err != ErrSpendHintNotFound {
|
|
||||||
t.Fatalf("expected ErrSpendHintNotFound, got: %v", err)
|
|
||||||
}
|
}
|
||||||
|
_, err := hintCache.QuerySpendHint(unknownSpendRequest)
|
||||||
|
require.ErrorIs(t, err, chainntnfs.ErrSpendHintNotFound)
|
||||||
|
|
||||||
// Now, we'll create some outpoints and commit them to the cache with
|
// Now, we'll create some outpoints and commit them to the cache with
|
||||||
// the same spend hint.
|
// the same spend hint.
|
||||||
const height = 100
|
const height = 100
|
||||||
const numOutpoints = 5
|
const numOutpoints = 5
|
||||||
spendRequests := make([]SpendRequest, numOutpoints)
|
spendRequests := make([]chainntnfs.SpendRequest, numOutpoints)
|
||||||
for i := uint32(0); i < numOutpoints; i++ {
|
for i := uint32(0); i < numOutpoints; i++ {
|
||||||
spendRequests[i] = SpendRequest{
|
spendRequests[i] = chainntnfs.SpendRequest{
|
||||||
OutPoint: wire.OutPoint{Index: i + 1},
|
OutPoint: wire.OutPoint{Index: i + 1},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,28 +119,20 @@ func TestHeightHintCacheSpends(t *testing.T) {
|
|||||||
// that we're able to properly retrieve the confirm hints.
|
// that we're able to properly retrieve the confirm hints.
|
||||||
for _, spendRequest := range spendRequests {
|
for _, spendRequest := range spendRequests {
|
||||||
spendHint, err := hintCache.QuerySpendHint(spendRequest)
|
spendHint, err := hintCache.QuerySpendHint(spendRequest)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to query for hint: %v", err)
|
require.EqualValues(t, height, spendHint)
|
||||||
}
|
|
||||||
if spendHint != height {
|
|
||||||
t.Fatalf("expected spend hint %d, got %d", height,
|
|
||||||
spendHint)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll also attempt to purge all of them in a single database
|
// We'll also attempt to purge all of them in a single database
|
||||||
// transaction.
|
// transaction.
|
||||||
if err := hintCache.PurgeSpendHint(spendRequests...); err != nil {
|
err = hintCache.PurgeSpendHint(spendRequests...)
|
||||||
t.Fatalf("unable to remove spend hint: %v", err)
|
require.NoError(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, we'll attempt to query for each outpoint. We should expect
|
// Finally, we'll attempt to query for each outpoint. We should expect
|
||||||
// not to find a hint for any of them.
|
// not to find a hint for any of them.
|
||||||
for _, spendRequest := range spendRequests {
|
for _, spendRequest := range spendRequests {
|
||||||
_, err = hintCache.QuerySpendHint(spendRequest)
|
_, err = hintCache.QuerySpendHint(spendRequest)
|
||||||
if err != ErrSpendHintNotFound {
|
require.ErrorIs(t, err, chainntnfs.ErrSpendHintNotFound)
|
||||||
t.Fatalf("expected ErrSpendHintNotFound, got: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +147,7 @@ func TestQueryDisable(t *testing.T) {
|
|||||||
|
|
||||||
// Insert a new confirmation hint with a non-zero height.
|
// Insert a new confirmation hint with a non-zero height.
|
||||||
const confHeight = 100
|
const confHeight = 100
|
||||||
confRequest := ConfRequest{
|
confRequest := chainntnfs.ConfRequest{
|
||||||
TxID: chainhash.Hash{0x01, 0x02, 0x03},
|
TxID: chainhash.Hash{0x01, 0x02, 0x03},
|
||||||
}
|
}
|
||||||
err := hintCache.CommitConfirmHint(confHeight, confRequest)
|
err := hintCache.CommitConfirmHint(confHeight, confRequest)
|
||||||
@ -178,7 +160,7 @@ func TestQueryDisable(t *testing.T) {
|
|||||||
|
|
||||||
// Insert a new spend hint with a non-zero height.
|
// Insert a new spend hint with a non-zero height.
|
||||||
const spendHeight = 200
|
const spendHeight = 200
|
||||||
spendRequest := SpendRequest{
|
spendRequest := chainntnfs.SpendRequest{
|
||||||
OutPoint: wire.OutPoint{
|
OutPoint: wire.OutPoint{
|
||||||
Hash: chainhash.Hash{0x4, 0x05, 0x06},
|
Hash: chainhash.Hash{0x4, 0x05, 0x06},
|
||||||
Index: 42,
|
Index: 42,
|
@ -3055,10 +3055,10 @@ func TestLightningWallet(t *testing.T, targetBackEnd string) {
|
|||||||
tempDir := t.TempDir()
|
tempDir := t.TempDir()
|
||||||
db, err := channeldb.Open(tempDir)
|
db, err := channeldb.Open(tempDir)
|
||||||
require.NoError(t, err, "unable to create db")
|
require.NoError(t, err, "unable to create db")
|
||||||
testCfg := chainntnfs.CacheConfig{
|
testCfg := channeldb.CacheConfig{
|
||||||
QueryDisable: false,
|
QueryDisable: false,
|
||||||
}
|
}
|
||||||
hintCache, err := chainntnfs.NewHeightHintCache(testCfg, db.Backend)
|
hintCache, err := channeldb.NewHeightHintCache(testCfg, db.Backend)
|
||||||
require.NoError(t, err, "unable to create height hint cache")
|
require.NoError(t, err, "unable to create height hint cache")
|
||||||
blockCache := blockcache.NewBlockCache(10000)
|
blockCache := blockcache.NewBlockCache(10000)
|
||||||
chainNotifier, err := btcdnotify.New(
|
chainNotifier, err := btcdnotify.New(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user