chainntnfs: support caching confirm/spend hints for scripts
In this commit, we refactor the HeightHintCache and its underlying interfaces to be able to manipulate hints for ConfRequests and SpendRequests. By doing so, we'll be able to manipulate hints for scripts if the request includes either a zero hash or a zero outpoint.
This commit is contained in:
4 files changed
+130
-96
No files matched your search
@@ -4,8 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
|
||||||
bolt "github.com/coreos/bbolt"
|
bolt "github.com/coreos/bbolt"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
)
|
)
|
||||||
@@ -51,16 +49,16 @@ var (
|
|||||||
// which an outpoint could have been spent within.
|
// which an outpoint could have been spent within.
|
||||||
type SpendHintCache interface {
|
type SpendHintCache interface {
|
||||||
// CommitSpendHint commits a spend hint for the outpoints to the cache.
|
// CommitSpendHint commits a spend hint for the outpoints to the cache.
|
||||||
CommitSpendHint(height uint32, ops ...wire.OutPoint) error
|
CommitSpendHint(height uint32, spendRequests ...SpendRequest) error
|
||||||
|
|
||||||
// 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
|
// ErrSpendHintNotFound is returned if a spend hint does not exist
|
||||||
// within the cache for the outpoint.
|
// within the cache for the outpoint.
|
||||||
QuerySpendHint(op wire.OutPoint) (uint32, error)
|
QuerySpendHint(spendRequest SpendRequest) (uint32, error)
|
||||||
|
|
||||||
// PurgeSpendHint removes the spend hint for the outpoints from the
|
// PurgeSpendHint removes the spend hint for the outpoints from the
|
||||||
// cache.
|
// cache.
|
||||||
PurgeSpendHint(ops ...wire.OutPoint) error
|
PurgeSpendHint(spendRequests ...SpendRequest) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfirmHintCache is an interface whose duty is to cache confirm hints for
|
// ConfirmHintCache is an interface whose duty is to cache confirm hints for
|
||||||
@@ -69,16 +67,16 @@ type SpendHintCache interface {
|
|||||||
type ConfirmHintCache interface {
|
type ConfirmHintCache interface {
|
||||||
// CommitConfirmHint commits a confirm hint for the transactions to the
|
// CommitConfirmHint commits a confirm hint for the transactions to the
|
||||||
// cache.
|
// cache.
|
||||||
CommitConfirmHint(height uint32, txids ...chainhash.Hash) error
|
CommitConfirmHint(height uint32, confRequests ...ConfRequest) error
|
||||||
|
|
||||||
// QueryConfirmHint returns the latest confirm hint for a transaction
|
// QueryConfirmHint returns the latest confirm hint for a transaction
|
||||||
// hash. ErrConfirmHintNotFound is returned if a confirm hint does not
|
// hash. ErrConfirmHintNotFound is returned if a confirm hint does not
|
||||||
// exist within the cache for the transaction hash.
|
// exist within the cache for the transaction hash.
|
||||||
QueryConfirmHint(txid chainhash.Hash) (uint32, error)
|
QueryConfirmHint(confRequest ConfRequest) (uint32, error)
|
||||||
|
|
||||||
// PurgeConfirmHint removes the confirm hint for the transactions from
|
// PurgeConfirmHint removes the confirm hint for the transactions from
|
||||||
// the cache.
|
// the cache.
|
||||||
PurgeConfirmHint(txids ...chainhash.Hash) error
|
PurgeConfirmHint(confRequests ...ConfRequest) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// HeightHintCache is an implementation of the SpendHintCache and
|
// HeightHintCache is an implementation of the SpendHintCache and
|
||||||
@@ -118,12 +116,15 @@ 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, ops ...wire.OutPoint) error {
|
func (c *HeightHintCache) CommitSpendHint(height uint32,
|
||||||
if len(ops) == 0 {
|
spendRequests ...SpendRequest) error {
|
||||||
|
|
||||||
|
if len(spendRequests) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Tracef("Updating spend hint to height %d for %v", height, ops)
|
Log.Tracef("Updating spend hint to height %d for %v", height,
|
||||||
|
spendRequests)
|
||||||
|
|
||||||
return c.db.Batch(func(tx *bolt.Tx) error {
|
return c.db.Batch(func(tx *bolt.Tx) error {
|
||||||
spendHints := tx.Bucket(spendHintBucket)
|
spendHints := tx.Bucket(spendHintBucket)
|
||||||
@@ -136,14 +137,12 @@ func (c *HeightHintCache) CommitSpendHint(height uint32, ops ...wire.OutPoint) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, op := range ops {
|
for _, spendRequest := range spendRequests {
|
||||||
var outpoint bytes.Buffer
|
spendHintKey, err := spendRequest.SpendHintKey()
|
||||||
err := channeldb.WriteElement(&outpoint, op)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = spendHints.Put(spendHintKey, hint.Bytes())
|
||||||
err = spendHints.Put(outpoint.Bytes(), hint.Bytes())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -156,7 +155,7 @@ func (c *HeightHintCache) CommitSpendHint(height uint32, ops ...wire.OutPoint) e
|
|||||||
// 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(op wire.OutPoint) (uint32, error) {
|
func (c *HeightHintCache) QuerySpendHint(spendRequest SpendRequest) (uint32, error) {
|
||||||
var hint uint32
|
var hint uint32
|
||||||
err := c.db.View(func(tx *bolt.Tx) error {
|
err := c.db.View(func(tx *bolt.Tx) error {
|
||||||
spendHints := tx.Bucket(spendHintBucket)
|
spendHints := tx.Bucket(spendHintBucket)
|
||||||
@@ -164,12 +163,11 @@ func (c *HeightHintCache) QuerySpendHint(op wire.OutPoint) (uint32, error) {
|
|||||||
return ErrCorruptedHeightHintCache
|
return ErrCorruptedHeightHintCache
|
||||||
}
|
}
|
||||||
|
|
||||||
var outpoint bytes.Buffer
|
spendHintKey, err := spendRequest.SpendHintKey()
|
||||||
if err := channeldb.WriteElement(&outpoint, op); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
spendHint := spendHints.Get(spendHintKey)
|
||||||
spendHint := spendHints.Get(outpoint.Bytes())
|
|
||||||
if spendHint == nil {
|
if spendHint == nil {
|
||||||
return ErrSpendHintNotFound
|
return ErrSpendHintNotFound
|
||||||
}
|
}
|
||||||
@@ -184,12 +182,12 @@ func (c *HeightHintCache) QuerySpendHint(op wire.OutPoint) (uint32, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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(ops ...wire.OutPoint) error {
|
func (c *HeightHintCache) PurgeSpendHint(spendRequests ...SpendRequest) error {
|
||||||
if len(ops) == 0 {
|
if len(spendRequests) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Tracef("Removing spend hints for %v", ops)
|
Log.Tracef("Removing spend hints for %v", spendRequests)
|
||||||
|
|
||||||
return c.db.Batch(func(tx *bolt.Tx) error {
|
return c.db.Batch(func(tx *bolt.Tx) error {
|
||||||
spendHints := tx.Bucket(spendHintBucket)
|
spendHints := tx.Bucket(spendHintBucket)
|
||||||
@@ -197,15 +195,12 @@ func (c *HeightHintCache) PurgeSpendHint(ops ...wire.OutPoint) error {
|
|||||||
return ErrCorruptedHeightHintCache
|
return ErrCorruptedHeightHintCache
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, op := range ops {
|
for _, spendRequest := range spendRequests {
|
||||||
var outpoint bytes.Buffer
|
spendHintKey, err := spendRequest.SpendHintKey()
|
||||||
err := channeldb.WriteElement(&outpoint, op)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := spendHints.Delete(spendHintKey); err != nil {
|
||||||
err = spendHints.Delete(outpoint.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,12 +210,15 @@ func (c *HeightHintCache) PurgeSpendHint(ops ...wire.OutPoint) 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, txids ...chainhash.Hash) error {
|
func (c *HeightHintCache) CommitConfirmHint(height uint32,
|
||||||
if len(txids) == 0 {
|
confRequests ...ConfRequest) error {
|
||||||
|
|
||||||
|
if len(confRequests) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Tracef("Updating confirm hints to height %d for %v", height, txids)
|
Log.Tracef("Updating confirm hints to height %d for %v", height,
|
||||||
|
confRequests)
|
||||||
|
|
||||||
return c.db.Batch(func(tx *bolt.Tx) error {
|
return c.db.Batch(func(tx *bolt.Tx) error {
|
||||||
confirmHints := tx.Bucket(confirmHintBucket)
|
confirmHints := tx.Bucket(confirmHintBucket)
|
||||||
@@ -233,14 +231,12 @@ func (c *HeightHintCache) CommitConfirmHint(height uint32, txids ...chainhash.Ha
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, txid := range txids {
|
for _, confRequest := range confRequests {
|
||||||
var txHash bytes.Buffer
|
confHintKey, err := confRequest.ConfHintKey()
|
||||||
err := channeldb.WriteElement(&txHash, txid)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = confirmHints.Put(confHintKey, hint.Bytes())
|
||||||
err = confirmHints.Put(txHash.Bytes(), hint.Bytes())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -253,7 +249,7 @@ func (c *HeightHintCache) CommitConfirmHint(height uint32, txids ...chainhash.Ha
|
|||||||
// 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(txid chainhash.Hash) (uint32, error) {
|
func (c *HeightHintCache) QueryConfirmHint(confRequest ConfRequest) (uint32, error) {
|
||||||
var hint uint32
|
var hint uint32
|
||||||
err := c.db.View(func(tx *bolt.Tx) error {
|
err := c.db.View(func(tx *bolt.Tx) error {
|
||||||
confirmHints := tx.Bucket(confirmHintBucket)
|
confirmHints := tx.Bucket(confirmHintBucket)
|
||||||
@@ -261,12 +257,11 @@ func (c *HeightHintCache) QueryConfirmHint(txid chainhash.Hash) (uint32, error)
|
|||||||
return ErrCorruptedHeightHintCache
|
return ErrCorruptedHeightHintCache
|
||||||
}
|
}
|
||||||
|
|
||||||
var txHash bytes.Buffer
|
confHintKey, err := confRequest.ConfHintKey()
|
||||||
if err := channeldb.WriteElement(&txHash, txid); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
confirmHint := confirmHints.Get(confHintKey)
|
||||||
confirmHint := confirmHints.Get(txHash.Bytes())
|
|
||||||
if confirmHint == nil {
|
if confirmHint == nil {
|
||||||
return ErrConfirmHintNotFound
|
return ErrConfirmHintNotFound
|
||||||
}
|
}
|
||||||
@@ -282,12 +277,12 @@ func (c *HeightHintCache) QueryConfirmHint(txid chainhash.Hash) (uint32, error)
|
|||||||
|
|
||||||
// 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(txids ...chainhash.Hash) error {
|
func (c *HeightHintCache) PurgeConfirmHint(confRequests ...ConfRequest) error {
|
||||||
if len(txids) == 0 {
|
if len(confRequests) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Tracef("Removing confirm hints for %v", txids)
|
Log.Tracef("Removing confirm hints for %v", confRequests)
|
||||||
|
|
||||||
return c.db.Batch(func(tx *bolt.Tx) error {
|
return c.db.Batch(func(tx *bolt.Tx) error {
|
||||||
confirmHints := tx.Bucket(confirmHintBucket)
|
confirmHints := tx.Bucket(confirmHintBucket)
|
||||||
@@ -295,15 +290,12 @@ func (c *HeightHintCache) PurgeConfirmHint(txids ...chainhash.Hash) error {
|
|||||||
return ErrCorruptedHeightHintCache
|
return ErrCorruptedHeightHintCache
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, txid := range txids {
|
for _, confRequest := range confRequests {
|
||||||
var txHash bytes.Buffer
|
confHintKey, err := confRequest.ConfHintKey()
|
||||||
err := channeldb.WriteElement(&txHash, txid)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := confirmHints.Delete(confHintKey); err != nil {
|
||||||
err = confirmHints.Delete(txHash.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ func TestHeightHintCacheConfirms(t *testing.T) {
|
|||||||
// Querying for a transaction hash not found within the cache should
|
// Querying for a transaction hash not found within the cache should
|
||||||
// return an error indication so.
|
// return an error indication so.
|
||||||
var unknownHash chainhash.Hash
|
var unknownHash chainhash.Hash
|
||||||
_, err := hintCache.QueryConfirmHint(unknownHash)
|
copy(unknownHash[:], bytes.Repeat([]byte{0x01}, 32))
|
||||||
|
unknownConfRequest := ConfRequest{TxID: unknownHash}
|
||||||
|
_, err := hintCache.QueryConfirmHint(unknownConfRequest)
|
||||||
if err != ErrConfirmHintNotFound {
|
if err != ErrConfirmHintNotFound {
|
||||||
t.Fatalf("expected ErrConfirmHintNotFound, got: %v", err)
|
t.Fatalf("expected ErrConfirmHintNotFound, got: %v", err)
|
||||||
}
|
}
|
||||||
@@ -48,23 +50,24 @@ func TestHeightHintCacheConfirms(t *testing.T) {
|
|||||||
// cache with the same confirm hint.
|
// cache with the same confirm hint.
|
||||||
const height = 100
|
const height = 100
|
||||||
const numHashes = 5
|
const numHashes = 5
|
||||||
txHashes := make([]chainhash.Hash, numHashes)
|
confRequests := make([]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)}, 32))
|
copy(txHash[:], bytes.Repeat([]byte{byte(i + 1)}, 32))
|
||||||
txHashes[i] = txHash
|
confRequests[i] = ConfRequest{TxID: txHash}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := hintCache.CommitConfirmHint(height, txHashes...); err != nil {
|
err = hintCache.CommitConfirmHint(height, confRequests...)
|
||||||
|
if err != nil {
|
||||||
t.Fatalf("unable to add entries to cache: %v", err)
|
t.Fatalf("unable to add entries to cache: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the hashes committed, we'll now query the cache to ensure that
|
// With the hashes committed, we'll now query the cache to ensure that
|
||||||
// we're able to properly retrieve the confirm hints.
|
// we're able to properly retrieve the confirm hints.
|
||||||
for _, txHash := range txHashes {
|
for _, confRequest := range confRequests {
|
||||||
confirmHint, err := hintCache.QueryConfirmHint(txHash)
|
confirmHint, err := hintCache.QueryConfirmHint(confRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to query for hint: %v", err)
|
t.Fatalf("unable to query for hint of %v: %v", confRequest, err)
|
||||||
}
|
}
|
||||||
if confirmHint != height {
|
if confirmHint != height {
|
||||||
t.Fatalf("expected confirm hint %d, got %d", height,
|
t.Fatalf("expected confirm hint %d, got %d", height,
|
||||||
@@ -74,14 +77,14 @@ func TestHeightHintCacheConfirms(t *testing.T) {
|
|||||||
|
|
||||||
// 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(txHashes...); err != nil {
|
if err := hintCache.PurgeConfirmHint(confRequests...); err != nil {
|
||||||
t.Fatalf("unable to remove confirm hints: %v", err)
|
t.Fatalf("unable to remove confirm hints: %v", 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 _, txHash := range txHashes {
|
for _, confRequest := range confRequests {
|
||||||
_, err := hintCache.QueryConfirmHint(txHash)
|
_, err := hintCache.QueryConfirmHint(confRequest)
|
||||||
if err != ErrConfirmHintNotFound {
|
if err != ErrConfirmHintNotFound {
|
||||||
t.Fatalf("expected ErrConfirmHintNotFound, got :%v", err)
|
t.Fatalf("expected ErrConfirmHintNotFound, got :%v", err)
|
||||||
}
|
}
|
||||||
@@ -97,8 +100,9 @@ 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.
|
||||||
var unknownOutPoint wire.OutPoint
|
unknownOutPoint := wire.OutPoint{Index: 1}
|
||||||
_, err := hintCache.QuerySpendHint(unknownOutPoint)
|
unknownSpendRequest := SpendRequest{OutPoint: unknownOutPoint}
|
||||||
|
_, err := hintCache.QuerySpendHint(unknownSpendRequest)
|
||||||
if err != ErrSpendHintNotFound {
|
if err != ErrSpendHintNotFound {
|
||||||
t.Fatalf("expected ErrSpendHintNotFound, got: %v", err)
|
t.Fatalf("expected ErrSpendHintNotFound, got: %v", err)
|
||||||
}
|
}
|
||||||
@@ -107,21 +111,22 @@ func TestHeightHintCacheSpends(t *testing.T) {
|
|||||||
// the same spend hint.
|
// the same spend hint.
|
||||||
const height = 100
|
const height = 100
|
||||||
const numOutpoints = 5
|
const numOutpoints = 5
|
||||||
var txHash chainhash.Hash
|
spendRequests := make([]SpendRequest, numOutpoints)
|
||||||
copy(txHash[:], bytes.Repeat([]byte{0xFF}, 32))
|
|
||||||
outpoints := make([]wire.OutPoint, numOutpoints)
|
|
||||||
for i := uint32(0); i < numOutpoints; i++ {
|
for i := uint32(0); i < numOutpoints; i++ {
|
||||||
outpoints[i] = wire.OutPoint{Hash: txHash, Index: i}
|
spendRequests[i] = SpendRequest{
|
||||||
|
OutPoint: wire.OutPoint{Index: i + 1},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := hintCache.CommitSpendHint(height, outpoints...); err != nil {
|
err = hintCache.CommitSpendHint(height, spendRequests...)
|
||||||
t.Fatalf("unable to add entry to cache: %v", err)
|
if err != nil {
|
||||||
|
t.Fatalf("unable to add entries to cache: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the outpoints committed, we'll now query the cache to ensure
|
// With the outpoints committed, we'll now query the cache to ensure
|
||||||
// that we're able to properly retrieve the confirm hints.
|
// that we're able to properly retrieve the confirm hints.
|
||||||
for _, op := range outpoints {
|
for _, spendRequest := range spendRequests {
|
||||||
spendHint, err := hintCache.QuerySpendHint(op)
|
spendHint, err := hintCache.QuerySpendHint(spendRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to query for hint: %v", err)
|
t.Fatalf("unable to query for hint: %v", err)
|
||||||
}
|
}
|
||||||
@@ -133,14 +138,14 @@ func TestHeightHintCacheSpends(t *testing.T) {
|
|||||||
|
|
||||||
// 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(outpoints...); err != nil {
|
if err := hintCache.PurgeSpendHint(spendRequests...); err != nil {
|
||||||
t.Fatalf("unable to remove spend hint: %v", err)
|
t.Fatalf("unable to remove spend hint: %v", 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 _, op := range outpoints {
|
for _, spendRequest := range spendRequests {
|
||||||
_, err = hintCache.QuerySpendHint(op)
|
_, err = hintCache.QuerySpendHint(spendRequest)
|
||||||
if err != ErrSpendHintNotFound {
|
if err != ErrSpendHintNotFound {
|
||||||
t.Fatalf("expected ErrSpendHintNotFound, got: %v", err)
|
t.Fatalf("expected ErrSpendHintNotFound, got: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package chainntnfs
|
package chainntnfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -8,6 +9,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/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -165,6 +167,21 @@ 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
|
||||||
|
}
|
||||||
|
|
||||||
// ConfNtfn represents a notifier client's request to receive a notification
|
// ConfNtfn represents a notifier client's request to receive a notification
|
||||||
// once the target transaction gets sufficient confirmations. The client is
|
// once the target transaction gets sufficient confirmations. The client is
|
||||||
// asynchronously notified via the ConfirmationEvent channels.
|
// asynchronously notified via the ConfirmationEvent channels.
|
||||||
@@ -265,6 +282,22 @@ func (r SpendRequest) String() string {
|
|||||||
return fmt.Sprintf("script=%v", r.PkScript)
|
return fmt.Sprintf("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
|
||||||
|
}
|
||||||
|
|
||||||
// SpendNtfn represents a client's request to receive a notification once an
|
// SpendNtfn represents a client's request to receive a notification once an
|
||||||
// outpoint has been spent on-chain. The client is asynchronously notified via
|
// outpoint has been spent on-chain. The client is asynchronously notified via
|
||||||
// the SpendEvent channels.
|
// the SpendEvent channels.
|
||||||
|
|||||||
@@ -17,29 +17,31 @@ var (
|
|||||||
|
|
||||||
type mockHintCache struct {
|
type mockHintCache struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
confHints map[chainhash.Hash]uint32
|
confHints map[chainntnfs.ConfRequest]uint32
|
||||||
spendHints map[wire.OutPoint]uint32
|
spendHints map[chainntnfs.SpendRequest]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ chainntnfs.SpendHintCache = (*mockHintCache)(nil)
|
var _ chainntnfs.SpendHintCache = (*mockHintCache)(nil)
|
||||||
var _ chainntnfs.ConfirmHintCache = (*mockHintCache)(nil)
|
var _ chainntnfs.ConfirmHintCache = (*mockHintCache)(nil)
|
||||||
|
|
||||||
func (c *mockHintCache) CommitSpendHint(heightHint uint32, ops ...wire.OutPoint) error {
|
func (c *mockHintCache) CommitSpendHint(heightHint uint32,
|
||||||
|
spendRequests ...chainntnfs.SpendRequest) error {
|
||||||
|
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
for _, op := range ops {
|
for _, spendRequest := range spendRequests {
|
||||||
c.spendHints[op] = heightHint
|
c.spendHints[spendRequest] = heightHint
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockHintCache) QuerySpendHint(op wire.OutPoint) (uint32, error) {
|
func (c *mockHintCache) QuerySpendHint(spendRequest chainntnfs.SpendRequest) (uint32, error) {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
hint, ok := c.spendHints[op]
|
hint, ok := c.spendHints[spendRequest]
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, chainntnfs.ErrSpendHintNotFound
|
return 0, chainntnfs.ErrSpendHintNotFound
|
||||||
}
|
}
|
||||||
@@ -47,33 +49,35 @@ func (c *mockHintCache) QuerySpendHint(op wire.OutPoint) (uint32, error) {
|
|||||||
return hint, nil
|
return hint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockHintCache) PurgeSpendHint(ops ...wire.OutPoint) error {
|
func (c *mockHintCache) PurgeSpendHint(spendRequests ...chainntnfs.SpendRequest) error {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
for _, op := range ops {
|
for _, spendRequest := range spendRequests {
|
||||||
delete(c.spendHints, op)
|
delete(c.spendHints, spendRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockHintCache) CommitConfirmHint(heightHint uint32, txids ...chainhash.Hash) error {
|
func (c *mockHintCache) CommitConfirmHint(heightHint uint32,
|
||||||
|
confRequests ...chainntnfs.ConfRequest) error {
|
||||||
|
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
for _, txid := range txids {
|
for _, confRequest := range confRequests {
|
||||||
c.confHints[txid] = heightHint
|
c.confHints[confRequest] = heightHint
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockHintCache) QueryConfirmHint(txid chainhash.Hash) (uint32, error) {
|
func (c *mockHintCache) QueryConfirmHint(confRequest chainntnfs.ConfRequest) (uint32, error) {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
hint, ok := c.confHints[txid]
|
hint, ok := c.confHints[confRequest]
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, chainntnfs.ErrConfirmHintNotFound
|
return 0, chainntnfs.ErrConfirmHintNotFound
|
||||||
}
|
}
|
||||||
@@ -81,12 +85,12 @@ func (c *mockHintCache) QueryConfirmHint(txid chainhash.Hash) (uint32, error) {
|
|||||||
return hint, nil
|
return hint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockHintCache) PurgeConfirmHint(txids ...chainhash.Hash) error {
|
func (c *mockHintCache) PurgeConfirmHint(confRequests ...chainntnfs.ConfRequest) error {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
for _, txid := range txids {
|
for _, confRequest := range confRequests {
|
||||||
delete(c.confHints, txid)
|
delete(c.confHints, confRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -94,8 +98,8 @@ func (c *mockHintCache) PurgeConfirmHint(txids ...chainhash.Hash) error {
|
|||||||
|
|
||||||
func newMockHintCache() *mockHintCache {
|
func newMockHintCache() *mockHintCache {
|
||||||
return &mockHintCache{
|
return &mockHintCache{
|
||||||
confHints: make(map[chainhash.Hash]uint32),
|
confHints: make(map[chainntnfs.ConfRequest]uint32),
|
||||||
spendHints: make(map[wire.OutPoint]uint32),
|
spendHints: make(map[chainntnfs.SpendRequest]uint32),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user