From 6ad5781bf125bfb92ffba4f716d9f254ed145252 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Tue, 30 Mar 2021 10:04:30 +0200 Subject: [PATCH] routing: add block cache to CfFilteredChainView This commit adds the block cache to the CfFilteredChainView struct and wraps its GetBlock function so that block cache mutex map is used when the call to neutrino's GetBlock function is called. --- chainreg/chainregistry.go | 4 +++- routing/chainview/interface_test.go | 6 +++++- routing/chainview/neutrino.go | 26 ++++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) 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) +}