Comment
Author: Admin | 2025-04-27
The chain module has the ability to store BIP157 block filters locally. Generally these filters are usefulfor doing wallet rescans. The idea is you can generate a list of script pubkeys you are interested in and see ifthe block filter matches the scriptPubKey.As we demonstrated in the chain docs with block headers, you can sync block filters from an external data sourceas well. We are going to use bitcoind as an example of an external data source to sync filters against. It is importantthat the bitcoind version you are using is >= v19 as the getblockfilterrpc is implemented there. You need to make sure bitcoind is started with the -blockfilterindex flag. This makes itso we can query filters.It is important to remember that you need fully synced block headers before you can sync filter headers and filters. Please see the chain docs for syncing block headers.Abstract idea of syncing filters.Our internal infrastructure depends on one function to be implemented to be able to sync filters.val getFilterFunc: BlockHeader => Future[FilterWithHeaderHash] = ???With getFilterFunc given a BlockHeader we can find it's associated GolombFilter -- which is our internal repesentationof a BIP157 block filter.The basic idea for FilterSync.syncFilters() is to look at our current best block header inside of our ChainApi.getBestBlockHeader()and then check what our best block filter's block hash is with ChainApi.getBestFilterHeader(). If the blockfilter returned from our internaldata store is NOT associated with our best block header, we attempt to sync our filter headers to catch up to our best block header.Syncing block filters against bitcoindWe are going to implement getFilterFunc with bitcoind and then sync a few filter headers.implicit val system: ActorSystem = ActorSystem(s"filter-sync-example")implicit val ec: ExecutionContext = system.dispatcherimplicit val chainAppConfig: ChainAppConfig = BitcoinSTestAppConfig.getNeutrinoTestConfig().chainConfval instance = BitcoindInstanceLocal.fromConfigFile(BitcoindConfig.DEFAULT_CONF_FILE)val bitcoind = BitcoindRpcClient(instance)val bitcoindWithChainApiF: Future[BitcoindBaseVersionChainHandlerViaRpc] = { ChainUnitTest.createChainApiWithBitcoindRpc(bitcoind)}val bitcoindF = bitcoindWithChainApiF.map(_.bitcoindRpc)val chainApiF = bitcoindWithChainApiF.map(_.chainHandler)val filterType = FilterType.Basicval addressF = bitcoindF.flatMap(_.getNewAddress)//this is the function that we are going to use to sync//our internal filters against. We use this function to query//for each block filter associated with a blockheaderval getFilterFunc: BlockHeader => Future[FilterWithHeaderHash] = { blockHeader => val prevFilterResultF = bitcoindF.flatMap(_.getBlockFilter(blockHeader.hashBE, filterType)) prevFilterResultF.map { filterResult
Add Comment