From 6fec5d9a8770e75af78da32996d9840a34eae3bd Mon Sep 17 00:00:00 2001 From: Nodari Chkuaselidze Date: Tue, 5 Dec 2023 14:42:08 +0400 Subject: [PATCH 1/2] test: add in memory dns cache. --- test/auction-reorg-test.js | 11 ++++ test/auction-test.js | 11 ++++ test/chain-checkpoints-test.js | 5 ++ test/chain-icann-lockup-test.js | 11 ++++ test/claim-test.js | 5 ++ test/mempool-invalidation-test.js | 11 ++++ test/mempool-test.js | 11 ++++ test/txstart-test.js | 5 ++ test/util/stub.js | 85 +++++++++++++++++++++++++++++++ 9 files changed, 155 insertions(+) create mode 100644 test/util/stub.js diff --git a/test/auction-reorg-test.js b/test/auction-reorg-test.js index 0108bd0a4..2b50436e0 100644 --- a/test/auction-reorg-test.js +++ b/test/auction-reorg-test.js @@ -12,6 +12,7 @@ const MemWallet = require('./util/memwallet'); const Network = require('../lib/protocol/network'); const rules = require('../lib/covenants/rules'); const {ownership} = require('../lib/covenants/ownership'); +const {CachedStubResolver} = require('./util/stub'); const network = Network.get('regtest'); const {treeInterval} = network.names; @@ -73,6 +74,16 @@ function createNode() { describe('Auction Reorg', function() { this.timeout(20000); + const originalResolver = ownership.Resolver; + + before(() => { + ownership.Resolver = CachedStubResolver; + }); + + after(() => { + ownership.Resolver = originalResolver; + }); + describe('Vickrey Auction Reorg', function() { const node = createNode(); const orig = createNode(); diff --git a/test/auction-test.js b/test/auction-test.js index ac03d05dd..6a712bc9e 100644 --- a/test/auction-test.js +++ b/test/auction-test.js @@ -9,6 +9,7 @@ const MemWallet = require('./util/memwallet'); const Network = require('../lib/protocol/network'); const rules = require('../lib/covenants/rules'); const {ownership} = require('../lib/covenants/ownership'); +const {CachedStubResolver} = require('./util/stub'); const network = Network.get('regtest'); const GNAME_SIZE = 10; @@ -69,6 +70,16 @@ function createNode() { describe('Auction', function() { this.timeout(15000); + const originalResolver = ownership.Resolver; + + before(() => { + ownership.Resolver = CachedStubResolver; + }); + + after(() => { + ownership.Resolver = originalResolver; + }); + describe('Vickrey Auction', function() { const node = createNode(); const orig = createNode(); diff --git a/test/chain-checkpoints-test.js b/test/chain-checkpoints-test.js index bff0639cf..0c26ff4c9 100644 --- a/test/chain-checkpoints-test.js +++ b/test/chain-checkpoints-test.js @@ -13,6 +13,7 @@ const Network = require('../lib/protocol/network'); const rules = require('../lib/covenants/rules'); const {Resource} = require('../lib/dns/resource'); const AirdropProof = require('../lib/primitives/airdropproof'); +const {CachedStubResolver} = require('./util/stub'); const network = Network.get('regtest'); @@ -91,8 +92,11 @@ async function mineBlocks(n, label) { } describe('Checkpoints', function() { + const originalResolver = ownership.Resolver; + before(async () => { ownership.ignore = true; + ownership.Resolver = CachedStubResolver; await blocks.open(); await chainGenerator.open(); @@ -105,6 +109,7 @@ describe('Checkpoints', function() { await blocks.close(); ownership.ignore = false; + ownership.Resolver = originalResolver; }); it('should add addrs to miner', async () => { diff --git a/test/chain-icann-lockup-test.js b/test/chain-icann-lockup-test.js index 477624cf3..c168afcb1 100644 --- a/test/chain-icann-lockup-test.js +++ b/test/chain-icann-lockup-test.js @@ -10,6 +10,7 @@ const chainCommon = require('../lib/blockchain/common'); const {BufferMap} = require('buffer-map'); const {thresholdStates} = chainCommon; const {isReserved, isLockedUp, hashName} = require('../lib/covenants/rules'); +const {CachedStubResolver} = require('./util/stub'); const SOFT_FORK_NAME = 'icannlockup'; @@ -52,6 +53,16 @@ const ACTUAL_RENEWAL_WINDOW = network.names.renewalWindow; describe('BIP9 - ICANN lockup (integration)', function() { this.timeout(20000); + const originalResolver = ownership.Resolver; + + before(() => { + ownership.Resolver = CachedStubResolver; + }); + + after(() => { + ownership.Resolver = originalResolver; + }); + const CUSTOM = [ 'cloudflare', 'nlnetlabs', diff --git a/test/claim-test.js b/test/claim-test.js index 942491115..264394a8e 100644 --- a/test/claim-test.js +++ b/test/claim-test.js @@ -9,6 +9,7 @@ const consensus = require('../lib/protocol/consensus'); const {ownership} = require('../lib/covenants/ownership'); const reserved = require('../lib/covenants/reserved'); const {Resource} = require('../lib/dns/resource'); +const {CachedStubResolver} = require('./util/stub'); const network = Network.get('regtest'); @@ -47,15 +48,19 @@ async function mineBlocks(n, addr) { describe('Reserved Name Claims', function() { this.timeout(10000); + const originalResolver = ownership.Resolver; + before(async () => { await node.open(); wallet = await wdb.create(); addr = await wallet.receiveAddress(); + ownership.Resolver = CachedStubResolver; }); after(async () => { await node.close(); + ownership.Resolver = originalResolver; }); // Reset the ownership flag after every test, diff --git a/test/mempool-invalidation-test.js b/test/mempool-invalidation-test.js index 85c27bffe..dbaf6dfa7 100644 --- a/test/mempool-invalidation-test.js +++ b/test/mempool-invalidation-test.js @@ -9,6 +9,7 @@ const rules = require('../lib/covenants/rules'); const {states} = require('../lib/covenants/namestate'); const {Resource} = require('../lib/dns/resource'); const {forEvent} = require('./util/common'); +const {CachedStubResolver} = require('./util/stub'); const network = Network.get('regtest'); const { @@ -21,6 +22,16 @@ const ACTUAL_CLAIM_PERIOD = claimPeriod; const ACTUAL_RENEWAL_WINDOW = renewalWindow; describe('Mempool Invalidation', function() { + const originalResolver = ownership.Resolver; + + before(() => { + ownership.Resolver = CachedStubResolver; + }); + + after(() => { + ownership.Resolver = originalResolver; + }); + const NAMES = [ // roots 'nl', diff --git a/test/mempool-test.js b/test/mempool-test.js index c193354c9..6c8ab73ac 100644 --- a/test/mempool-test.js +++ b/test/mempool-test.js @@ -33,6 +33,7 @@ const rules = require('../lib/covenants/rules'); const NameState = require('../lib/covenants/namestate'); const {states} = NameState; const {ownership} = require('../lib/covenants/ownership'); +const {CachedStubResolver} = require('./util/stub'); const ONE_HASH = Buffer.alloc(32, 0x00); ONE_HASH[0] = 0x01; @@ -75,6 +76,16 @@ async function getMockBlock(chain, txs = [], cb = true) { describe('Mempool', function() { this.timeout(5000); + const originalResolver = ownership.Resolver; + + before(() => { + ownership.Resolver = CachedStubResolver; + }); + + after(() => { + ownership.Resolver = originalResolver; + }); + describe('Mempool TXs', function() { let workers, blocks, chain, mempool, wallet; let cachedTX; diff --git a/test/txstart-test.js b/test/txstart-test.js index bc70a4c45..c40d502aa 100644 --- a/test/txstart-test.js +++ b/test/txstart-test.js @@ -14,6 +14,7 @@ const Address = require('../lib/primitives/address'); const Script = require('../lib/script/script'); const common = require('../lib/blockchain/common'); const {ownership} = require('../lib/covenants/ownership'); +const {CachedStubResolver} = require('./util/stub'); const VERIFY_NONE = common.flags.VERIFY_NONE; const node = new FullNode({ @@ -49,6 +50,8 @@ describe('Disable TXs', function() { let utxo, lastTX; + const originalResolver = ownership.Resolver; + before(async () => { node.network.txStart = 5; await node.open(); @@ -56,11 +59,13 @@ describe('Disable TXs', function() { // Start with one block for the fakeClaim const block = await node.miner.mineBlock(); assert(await node.chain.add(block)); + ownership.Resolver = CachedStubResolver; }); after(async () => { await node.close(); node.network.txStart = RESET_TXSTART; + ownership.Resolver = originalResolver; }); it('should reject tx from mempool before txStart', async () => { diff --git a/test/util/stub.js b/test/util/stub.js new file mode 100644 index 000000000..95aef072e --- /dev/null +++ b/test/util/stub.js @@ -0,0 +1,85 @@ +'use strict'; + +const assert = require('bsert'); +const path = require('path'); +const {StubResolver, wire} = require('bns'); +const fs = require('bfile'); +const {tmpdir} = require('os'); + +let CACHE = {}; + +/** + * Proxy requests if they are not cached. + */ + +class CachedStubResolver extends StubResolver { + constructor(options) { + super(options); + + this.enabled = true; + this.cacheOnDisk = false; + this.cacheFile = path.join(tmpdir(), 'hsd', 'dns-cache.json'); + + this.loadCacheSync(); + } + + loadCacheSync() { + if (!this.cacheOnDisk) + return; + + if (fs.existsSync(this.cacheFile)) + CACHE = JSON.parse(fs.readFileSync(this.cacheFile, 'utf8')); + } + + saveCacheSync() { + if (!this.cacheOnDisk) + return; + + const stringified = JSON.stringify(CACHE, null, 2); + fs.writeFileSync(this.cacheFile, stringified, 'utf8'); + } + + setCache(qs, res) { + if (!this.enabled) + return; + + assert(qs instanceof wire.Question); + assert(res instanceof wire.Message); + + CACHE[qs.toString()] = res.toString(); + this.saveCacheSync(); + } + + hasCache(qs) { + if (!this.enabled) + return false; + + assert(qs instanceof wire.Question); + + return Boolean(CACHE[qs.toString()]); + } + + getCache(qs) { + if (!this.enabled) + return null; + + assert(qs instanceof wire.Question); + + return wire.Message.fromString(CACHE[qs.toString()]); + } + + async resolve(qs) { + if (this.hasCache(qs)) + return this.getCache(qs); + + const resolved = await super.resolve(qs); + + if (!resolved) + return null; + + this.setCache(qs, resolved); + return resolved; + } +} + +exports.CachedStubResolver = CachedStubResolver; From 357b4200a654573f0b4fea837c2b22970f646636 Mon Sep 17 00:00:00 2001 From: Nodari Chkuaselidze Date: Tue, 5 Dec 2023 15:07:54 +0400 Subject: [PATCH 2/2] test: put dns disk cache behind a flag. When actively woring on the claim related test cases, setting HSD_TEST_DNS_FILE_CACHE=true will cache the requests locally. NOTE: the cache does not have any expiration logic. --- test/util/stub.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/util/stub.js b/test/util/stub.js index 95aef072e..5ce561743 100644 --- a/test/util/stub.js +++ b/test/util/stub.js @@ -17,8 +17,9 @@ class CachedStubResolver extends StubResolver { super(options); this.enabled = true; - this.cacheOnDisk = false; - this.cacheFile = path.join(tmpdir(), 'hsd', 'dns-cache.json'); + this.cacheOnDisk = process.env['HSD_TEST_DNS_FILE_CACHE'] === 'true'; + this.cacheDir = path.join(tmpdir(), 'hsd-test'); + this.cacheFile = path.join(this.cacheDir, 'dns-cache.json'); this.loadCacheSync(); } @@ -27,6 +28,9 @@ class CachedStubResolver extends StubResolver { if (!this.cacheOnDisk) return; + if (!fs.existsSync(this.cacheDir)) + fs.mkdirSync(this.cacheDir); + if (fs.existsSync(this.cacheFile)) CACHE = JSON.parse(fs.readFileSync(this.cacheFile, 'utf8')); }