You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
70 lines
2.0 KiB
70 lines
2.0 KiB
package blockcache |
|
|
|
import ( |
|
"github.com/btcsuite/btcd/chaincfg/chainhash" |
|
"github.com/btcsuite/btcd/wire" |
|
"github.com/btcsuite/btcutil" |
|
"github.com/lightninglabs/neutrino/cache" |
|
"github.com/lightninglabs/neutrino/cache/lru" |
|
"github.com/lightningnetwork/lnd/lntypes" |
|
"github.com/lightningnetwork/lnd/multimutex" |
|
) |
|
|
|
// BlockCache is an lru cache for blocks. |
|
type BlockCache struct { |
|
Cache *lru.Cache |
|
HashMutex *multimutex.HashMutex |
|
} |
|
|
|
// NewBlockCache creates a new BlockCache with the given maximum capacity. |
|
func NewBlockCache(capacity uint64) *BlockCache { |
|
return &BlockCache{ |
|
Cache: lru.NewCache(capacity), |
|
HashMutex: multimutex.NewHashMutex(), |
|
} |
|
} |
|
|
|
// GetBlock first checks to see if the BlockCache already contains the block |
|
// with the given hash. If it does then the block is fetched from the cache and |
|
// returned. Otherwise the getBlockImpl function is used in order to fetch the |
|
// new block and then it is stored in the block cache and returned. |
|
func (bc *BlockCache) GetBlock(hash *chainhash.Hash, |
|
getBlockImpl func(hash *chainhash.Hash) (*wire.MsgBlock, |
|
error)) (*wire.MsgBlock, error) { |
|
|
|
bc.HashMutex.Lock(lntypes.Hash(*hash)) |
|
defer bc.HashMutex.Unlock(lntypes.Hash(*hash)) |
|
|
|
// Create an inv vector for getting the block. |
|
inv := wire.NewInvVect(wire.InvTypeWitnessBlock, hash) |
|
|
|
// Check if the block corresponding to the given hash is already |
|
// stored in the blockCache and return it if it is. |
|
cacheBlock, err := bc.Cache.Get(*inv) |
|
if err != nil && err != cache.ErrElementNotFound { |
|
return nil, err |
|
} |
|
if cacheBlock != nil { |
|
return cacheBlock.(*cache.CacheableBlock).MsgBlock(), nil |
|
} |
|
|
|
// Fetch the block from the chain backends. |
|
block, err := getBlockImpl(hash) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
// Add the new block to blockCache. If the Cache is at its maximum |
|
// capacity then the LFU item will be evicted in favour of this new |
|
// block. |
|
_, err = bc.Cache.Put( |
|
*inv, &cache.CacheableBlock{ |
|
Block: btcutil.NewBlock(block), |
|
}, |
|
) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
return block, nil |
|
}
|
|
|