From cf6d606e173a0b03abf692d1dca63bbe7832580b Mon Sep 17 00:00:00 2001 From: Matthew Zipkin Date: Tue, 21 Jul 2020 12:00:03 -0400 Subject: [PATCH] wallet: check auction TXs for dust and null address before sending --- lib/wallet/wallet.js | 13 +++++++++++++ test/wallet-auction-test.js | 12 ++++++++++++ test/wallet-http-test.js | 18 +++++++++++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/wallet/wallet.js b/lib/wallet/wallet.js index aae276230..41836aa00 100644 --- a/lib/wallet/wallet.js +++ b/lib/wallet/wallet.js @@ -3400,6 +3400,19 @@ class Wallet extends EventEmitter { if (ancestors.size + 1 > this.maxAncestors) throw new Error('TX exceeds maximum unconfirmed ancestors.'); + for (const output of tx.outputs) { + if (output.isDust()) + throw new Error('Output is dust.'); + + if (output.value > 0) { + if (!output.address) + throw new Error('Cannot send to unknown address.'); + + if (output.address.isNull()) + throw new Error('Cannot send to null address.'); + } + } + await this.wdb.addTX(tx); this.logger.debug('Sending wallet tx (%s): %x', this.id, tx.hash()); diff --git a/test/wallet-auction-test.js b/test/wallet-auction-test.js index 0d11ff941..409b50fc2 100644 --- a/test/wallet-auction-test.js +++ b/test/wallet-auction-test.js @@ -12,6 +12,7 @@ const Miner = require('../lib/mining/miner'); const WalletDB = require('../lib/wallet/walletdb'); const Network = require('../lib/protocol/network'); const rules = require('../lib/covenants/rules'); +const Address = require('../lib/primitives/address'); const network = Network.get('regtest'); const NAME1 = rules.grindName(5, 2, network); @@ -123,6 +124,17 @@ describe('Wallet Auction', function() { } }); + it('should fail to send bid to null address', async () => { + const mtx = await winner.makeBid(NAME1, 1000, 2000, 0); + mtx.outputs[0].address = new Address(); + await winner.fill(mtx); + await winner.finalize(mtx); + + const fn = async () => await winner.sendMTX(mtx); + + await assert.rejects(fn, {message: 'Cannot send to null address.'}); + }); + it('should fail to re-open auction during BIDDING phase', async () => { let err; try { diff --git a/test/wallet-http-test.js b/test/wallet-http-test.js index 329b3037e..46e3f6fcb 100644 --- a/test/wallet-http-test.js +++ b/test/wallet-http-test.js @@ -508,7 +508,7 @@ describe('Wallet HTTP', function() { await assert.rejects(fn, {message: 'Lockup is required.'}); }); - it('should send bid with 0 value and 0 lockup', async () => { + it('should send bid with 0 value and non-dust lockup', async () => { await wallet.client.post(`/wallet/${wallet.id}/open`, { name: name }); @@ -516,10 +516,26 @@ describe('Wallet HTTP', function() { await mineBlocks(treeInterval + 1, cbAddress); await wallet.client.post(`/wallet/${wallet.id}/bid`, { + name: name, + bid: 0, + lockup: 1000 + }); + }); + + it('should fail to send bid with 0 value and 0 lockup', async () => { + await wallet.client.post(`/wallet/${wallet.id}/open`, { + name: name + }); + + await mineBlocks(treeInterval + 1, cbAddress); + + const fn = async () => await wallet.client.post(`/wallet/${wallet.id}/bid`, { name: name, bid: 0, lockup: 0 }); + + await assert.rejects(fn, {message: 'Output is dust.'}); }); it('should get all bids (single player)', async () => {