diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index 5093f788..5b6d59cf 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -319,7 +319,9 @@ func NewChainControl(cfg *Config, blockCache *blockcache.BlockCache) ( cc.ChainNotifier = neutrinonotify.New( cfg.NeutrinoCS, hintCache, hintCache, ) - cc.ChainView, err = chainview.NewCfFilteredChainView(cfg.NeutrinoCS) + cc.ChainView, err = chainview.NewCfFilteredChainView( + cfg.NeutrinoCS, blockCache, + ) if err != nil { return nil, nil, err } diff --git a/routing/chainview/interface_test.go b/routing/chainview/interface_test.go index 439b8d7f..8f6c2560 100644 --- a/routing/chainview/interface_test.go +++ b/routing/chainview/interface_test.go @@ -895,7 +895,11 @@ var interfaceImpls = []struct { os.RemoveAll(spvDir) } - chainView, err := NewCfFilteredChainView(spvNode) + blockCache := blockcache.NewBlockCache(10000) + + chainView, err := NewCfFilteredChainView( + spvNode, blockCache, + ) if err != nil { return nil, nil, err } diff --git a/routing/chainview/neutrino.go b/routing/chainview/neutrino.go index 792e2dba..20504391 100644 --- a/routing/chainview/neutrino.go +++ b/routing/chainview/neutrino.go @@ -11,7 +11,9 @@ import ( "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/gcs/builder" "github.com/lightninglabs/neutrino" + "github.com/lightningnetwork/lnd/blockcache" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/lntypes" ) // CfFilteredChainView is an implementation of the FilteredChainView interface @@ -40,6 +42,9 @@ type CfFilteredChainView struct { // chainView. blockQueue *blockEventQueue + // blockCache is an LRU block cache. + blockCache *blockcache.BlockCache + // chainFilter is the filterMtx sync.RWMutex chainFilter map[wire.OutPoint][]byte @@ -57,13 +62,15 @@ var _ FilteredChainView = (*CfFilteredChainView)(nil) // // NOTE: The node should already be running and syncing before being passed into // this function. -func NewCfFilteredChainView(node *neutrino.ChainService) (*CfFilteredChainView, error) { +func NewCfFilteredChainView(node *neutrino.ChainService, + blockCache *blockcache.BlockCache) (*CfFilteredChainView, error) { return &CfFilteredChainView{ blockQueue: newBlockEventQueue(), quit: make(chan struct{}), rescanErrChan: make(chan error), chainFilter: make(map[wire.OutPoint][]byte), p2pNode: node, + blockCache: blockCache, }, nil } @@ -269,7 +276,7 @@ func (c *CfFilteredChainView) FilterBlock(blockHash *chainhash.Hash) (*FilteredB // If we reach this point, then there was a match, so we'll need to // fetch the block itself so we can scan it for any actual matches (as // there's a fp rate). - block, err := c.p2pNode.GetBlock(*blockHash) + block, err := c.GetBlock(*blockHash) if err != nil { return nil, err } @@ -364,3 +371,18 @@ func (c *CfFilteredChainView) FilteredBlocks() <-chan *FilteredBlock { func (c *CfFilteredChainView) DisconnectedBlocks() <-chan *FilteredBlock { return c.blockQueue.staleBlocks } + +// GetBlock is used to retrieve the block with the given hash. Since the block +// cache used by neutrino will be the same as that used by LND (since it is +// passed to neutrino on initialisation), the neutrino GetBlock method can be +// called directly since it already uses the block cache. However, neutrino +// does not lock the block cache mutex for the given block hash and so that is +// done here. +func (c *CfFilteredChainView) GetBlock(hash chainhash.Hash) ( + *btcutil.Block, error) { + + c.blockCache.HashMutex.Lock(lntypes.Hash(hash)) + defer c.blockCache.HashMutex.Unlock(lntypes.Hash(hash)) + + return c.p2pNode.GetBlock(hash) +}