From 496e86605401003d63bcf7a90423b1627d915348 Mon Sep 17 00:00:00 2001 From: Manav Desai Date: Thu, 20 Jul 2023 22:57:46 +0530 Subject: [PATCH] feat: Neutrino Integration --- lib/wallet/client.js | 12 +++++++++++ lib/wallet/nodeclient.js | 19 +++++++++++++++++ lib/wallet/nullclient.js | 11 ++++++++++ lib/wallet/walletdb.js | 44 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/lib/wallet/client.js b/lib/wallet/client.js index 768f38e50..f60eebbb5 100644 --- a/lib/wallet/client.js +++ b/lib/wallet/client.js @@ -71,6 +71,18 @@ class WalletClient extends NodeClient { return super.setFilter(filter.toRaw()); } + /** + * Check filter against wallet key ring + * @param {WalletKey} ring + * @param {Filter} filter + * @returns {Promise} + */ + + async getBlockFromNode(hash) { + // return super.getBlockPeer(hash); + console.log('getBlockFromNode'); + } + async rescan(start) { if (Buffer.isBuffer(start)) start = util.revHex(start); diff --git a/lib/wallet/nodeclient.js b/lib/wallet/nodeclient.js index 9f6c43600..bb5bf098c 100644 --- a/lib/wallet/nodeclient.js +++ b/lib/wallet/nodeclient.js @@ -37,6 +37,13 @@ class NodeClient extends AsyncEmitter { init() { this.node.chain.on('connect', async (entry, block) => { + if (!this.opened || this.node.neutrino) + return; + + await this.emitAsync('block connect', entry, block.txs); + }); + + this.node.chain.on('getblockpeer', async (entry, block) => { if (!this.opened) return; @@ -50,6 +57,13 @@ class NodeClient extends AsyncEmitter { await this.emitAsync('block disconnect', entry); }); + this.node.pool.on('cfilter', async (blockHeight, filter) => { + if (!this.opened) + return; + + await this.emitAsync('cfilter', blockHeight, filter); + }); + this.node.on('tx', (tx) => { if (!this.opened) return; @@ -134,6 +148,11 @@ class NodeClient extends AsyncEmitter { return entry; } + async getBlockFromNode(hash) { + // await this.node.chain.getBlockPeer(hash); + console.log('getBlockFromNode'); + } + /** * Send a transaction. Do not wait for promise. * @param {TX} tx diff --git a/lib/wallet/nullclient.js b/lib/wallet/nullclient.js index 744629d4b..f08ca5d6d 100644 --- a/lib/wallet/nullclient.js +++ b/lib/wallet/nullclient.js @@ -130,6 +130,17 @@ class NullClient extends EventEmitter { this.wdb.emit('reset filter'); } + /** + * Check filter against wallet key ring + * @param {WalletKey} ring + * @param {Filter} filter + * @returns {Promise} + */ + + async getBlockFromNode(hash) { + ; + } + /** * Esimate smart fee. * @param {Number?} blocks diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js index b1f57ebf0..31ef5e04c 100644 --- a/lib/wallet/walletdb.js +++ b/lib/wallet/walletdb.js @@ -26,6 +26,8 @@ const Outpoint = require('../primitives/outpoint'); const layouts = require('./layout'); const records = require('./records'); const NullClient = require('./nullclient'); +const Script = require('../script/script'); +const Address = require('../primitives/address'); const layout = layouts.wdb; const tlayout = layouts.txdb; @@ -65,10 +67,12 @@ class WalletDB extends EventEmitter { this.state = new ChainState(); this.confirming = false; this.height = 0; + this.filterHeight = 0; this.wallets = new Map(); this.depth = 0; this.rescanning = false; this.filterSent = false; + this.isWitness = false; // Wallet read lock. this.readLock = new MapLock(); @@ -169,6 +173,14 @@ class WalletDB extends EventEmitter { this.emit('error', e); } }); + + this.client.bind('cfilter', async (blockHeight, filter) => { + try { + await this.checkFilter(blockHeight, filter); + } catch (e) { + this.emit('error', e); + } + }); } /** @@ -201,6 +213,9 @@ class WalletDB extends EventEmitter { id: 'primary' }); + const account = await wallet.getAccount(wallet.wid); + this.isWitness = account.witness; + const addr = await wallet.receiveAddress(); this.logger.info( @@ -568,6 +583,35 @@ class WalletDB extends EventEmitter { return this.client.resetFilter(); } + async checkFilter (blockHash, filter) { + this.filterHeight = this.filterHeight + 1; + const gcsKey = blockHash.slice(0, 16); + + const piter = this.db.iterator({ + gte: layout.p.min(), + lte: layout.p.max() + }); + + await piter.each(async (key) => { + const [data] = layout.p.decode(key); + let address = null; + if (data.length === 20) { + if (this.isWitness) + address = Address.fromWitnessPubkeyhash(data); + else + address = Address.fromPubkeyhash(data); + } else if (data.length === 32) { + address = Address.fromWitnessScripthash(data); + } + const script = Script.fromAddress(address); + const match = filter.match(gcsKey, script.toRaw()); + if (match) { + await this.client.getBlockFromNode(blockHash); + return; + } + }); + } + /** * Backup the wallet db. * @param {String} path