diff --git a/test/aes-test.js b/test/aes-test.js index fbea6ac44..aa560d045 100644 --- a/test/aes-test.js +++ b/test/aes-test.js @@ -4,153 +4,46 @@ 'use strict'; const assert = require('assert'); -const digest = require('../lib/crypto/digest'); const aes = require('../lib/crypto/aes'); -const pbkdf2 = require('../lib/crypto/pbkdf2'); -const ncrypto = require('crypto'); describe('AES', function() { - function pbkdf2key(passphrase, iterations, dkLen, ivLen, alg) { - const key = pbkdf2.derive( - passphrase, '', iterations, dkLen + ivLen, 'sha512'); - return { - key: key.slice(0, dkLen), - iv: key.slice(dkLen, dkLen + ivLen) - }; - } + const key = Buffer.from( + '3a0c0bf669694ac7685e6806eeadee8e56c9b9bd22c3caa81c718ed4bbf809a1', + 'hex'); - function nencrypt(data, passphrase) { - assert(ncrypto, 'No crypto module available.'); - assert(passphrase, 'No passphrase.'); + const iv = Buffer.from('6dd26d9045b73c377a9ed2ffeca72ffd', 'hex'); - if (typeof data === 'string') - data = Buffer.from(data, 'utf8'); + it('should encrypt and decrypt with 2 blocks', () => { + const data = Buffer.from( + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', + 'hex'); - if (typeof passphrase === 'string') - passphrase = Buffer.from(passphrase, 'utf8'); + const expected = Buffer.from('' + + '83de502a9c83112ca6383f2214a892a0cdad5ab2b3e192e' + + '9921ddb126b25262c41f1dcff4d67ccfb40e4116e5a4569c1', + 'hex'); - const key = pbkdf2key(passphrase, 2048, 32, 16); - const cipher = ncrypto.createCipheriv('aes-256-cbc', key.key, key.iv); + const ciphertext = aes.encipher(data, key, iv); + assert.deepStrictEqual(ciphertext, expected); - return Buffer.concat([ - cipher.update(data), - cipher.final() - ]); - } - - function ndecrypt(data, passphrase) { - assert(ncrypto, 'No crypto module available.'); - assert(passphrase, 'No passphrase.'); - - if (typeof data === 'string') - data = Buffer.from(data, 'hex'); - - if (typeof passphrase === 'string') - passphrase = Buffer.from(passphrase, 'utf8'); - - const key = pbkdf2key(passphrase, 2048, 32, 16); - const decipher = ncrypto.createDecipheriv('aes-256-cbc', key.key, key.iv); - - return Buffer.concat([ - decipher.update(data), - decipher.final() - ]); - } - - function bencrypt(data, passphrase) { - assert(ncrypto, 'No crypto module available.'); - assert(passphrase, 'No passphrase.'); - - if (typeof data === 'string') - data = Buffer.from(data, 'utf8'); - - if (typeof passphrase === 'string') - passphrase = Buffer.from(passphrase, 'utf8'); - - const key = pbkdf2key(passphrase, 2048, 32, 16); - return aes.encipher(data, key.key, key.iv); - } - - function bdecrypt(data, passphrase) { - assert(ncrypto, 'No crypto module available.'); - assert(passphrase, 'No passphrase.'); - - if (typeof data === 'string') - data = Buffer.from(data, 'hex'); - - if (typeof passphrase === 'string') - passphrase = Buffer.from(passphrase, 'utf8'); - - const key = pbkdf2key(passphrase, 2048, 32, 16); - return aes.decipher(data, key.key, key.iv); - } - - function encrypt(data, passphrase) { - assert(ncrypto, 'No crypto module available.'); - assert(passphrase, 'No passphrase.'); - - if (typeof data === 'string') - data = Buffer.from(data, 'utf8'); - - if (typeof passphrase === 'string') - passphrase = Buffer.from(passphrase, 'utf8'); - - const key = pbkdf2key(passphrase, 2048, 32, 16); - - return aes.encipher(data, key.key, key.iv); - } - - function decrypt(data, passphrase) { - assert(ncrypto, 'No crypto module available.'); - assert(passphrase, 'No passphrase.'); - - if (typeof data === 'string') - data = Buffer.from(data, 'hex'); - - if (typeof passphrase === 'string') - passphrase = Buffer.from(passphrase, 'utf8'); - - const key = pbkdf2key(passphrase, 2048, 32, 16); - - return aes.decipher(data, key.key, key.iv); - } - - it('should encrypt and decrypt a hash with 2 blocks', () => { - const hash = digest.sha256(Buffer.alloc(0)); - const enchash = encrypt(hash, 'foo'); - const dechash = decrypt(enchash, 'foo'); - - const hash2 = digest.sha256(Buffer.alloc(0)); - const enchash2 = nencrypt(hash2, 'foo'); - const dechash2 = ndecrypt(enchash2, 'foo'); - - const hash3 = digest.sha256(Buffer.alloc(0)); - const enchash3 = bencrypt(hash3, 'foo'); - const dechash3 = bdecrypt(enchash3, 'foo'); - - assert.deepEqual(hash, hash2); - assert.deepEqual(enchash, enchash2); - assert.deepEqual(dechash, dechash2); - assert.deepEqual(dechash, dechash3); + const plaintext = aes.decipher(ciphertext, key, iv); + assert.deepStrictEqual(plaintext, data); }); - it('should encrypt and decrypt a hash with uneven blocks', () => { - const hash = Buffer.concat([ - digest.sha256(Buffer.alloc(0)), - Buffer.from([1,2,3])]); - - const enchash = encrypt(hash, 'foo'); - const dechash = decrypt(enchash, 'foo'); + it('should encrypt and decrypt with uneven blocks', () => { + const data = Buffer.from( + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855010203', + 'hex'); - const hash2 = Buffer.concat([ - digest.sha256(Buffer.alloc(0)), - Buffer.from([1,2,3])]); + const expected = Buffer.from('' + + '83de502a9c83112ca6383f2214a892a0cdad5ab2b3e192e9' + + '921ddb126b25262c5211801019a30c0c6f795296923e0af8', + 'hex'); - const enchash2 = nencrypt(hash2, 'foo'); - const dechash2 = ndecrypt(enchash2, 'foo'); + const ciphertext = aes.encipher(data, key, iv); + assert.deepStrictEqual(ciphertext, expected); - assert.deepEqual(hash, hash2); - assert.deepEqual(enchash, enchash2); - assert.deepEqual(dechash, dechash2); + const plaintext = aes.decipher(ciphertext, key, iv); + assert.deepStrictEqual(plaintext, data); }); }); diff --git a/test/bech32-test.js b/test/bech32-test.js index 1e4477d78..996a36b94 100644 --- a/test/bech32-test.js +++ b/test/bech32-test.js @@ -22,7 +22,6 @@ // THE SOFTWARE. /* eslint-env mocha */ -/* eslint max-len: "off" */ /* eslint prefer-arrow-callback: "off" */ 'use strict'; @@ -33,9 +32,11 @@ const Address = require('../lib/primitives/address'); const validChecksums = [ 'A12UEL5L', - 'an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs', + 'an83characterlonghumanreadablepartthatcontains' + + 'thenumber1andtheexcludedcharactersbio1tt5tgs', 'abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw', - '11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j', + '11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq' + + 'qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j', 'split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w' ]; @@ -57,7 +58,8 @@ const validAddresses = [ ]) ], [ - 'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx', + 'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw50' + + '8d6qejxtdg4y5r3zarvary0c5xw7k7grplx', Buffer.from([ 0x81, 0x28, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6, @@ -94,7 +96,8 @@ const invalidAddresses = [ 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5', 'BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2', 'bc1rw5uspcuh', - 'bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90', + 'bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d' + + '6qejxtdg4y5r3zarvary0c5xw7kw5rljs90', 'BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P', 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7', 'tb1pw508d6qejxtdg4y5r3zarqfsj6c3', @@ -140,7 +143,7 @@ describe('Bech32', function() { for (const [addr, script] of validAddresses) { it(`should have valid address for ${addr}`, () => { let hrp = 'bc'; - let ret; + let ret = null; try { ret = fromAddress(hrp, addr); @@ -175,14 +178,16 @@ describe('Bech32', function() { for (const addr of invalidAddresses) { it(`should have invalid address for ${addr}`, () => { - let ok1; + let ok1 = null; + try { ok1 = fromAddress('bc', addr); } catch (e) { ok1 = null; } - let ok2; + let ok2 = null; + try { ok2 = fromAddress('tb', addr); } catch (e) { @@ -196,7 +201,7 @@ describe('Bech32', function() { for (const [addr, script] of validAddresses) { it(`should have valid address for ${addr}`, () => { - let ret; + let ret = null; try { ret = Address.fromBech32(addr, 'main'); @@ -230,14 +235,16 @@ describe('Bech32', function() { for (const addr of invalidAddresses) { it(`should have invalid address for ${addr}`, () => { - let ok1; + let ok1 = null; + try { ok1 = Address.fromBech32(addr, 'main'); } catch (e) { ok1 = null; } - let ok2; + let ok2 = null; + try { ok2 = Address.fromBech32(addr, 'testnet'); } catch (e) { diff --git a/test/bip150-test.js b/test/bip150-test.js index cbfdcb4d2..79d2735fc 100644 --- a/test/bip150-test.js +++ b/test/bip150-test.js @@ -8,24 +8,24 @@ const secp256k1 = require('../lib/crypto/secp256k1'); const BIP150 = require('../lib/net/bip150'); const BIP151 = require('../lib/net/bip151'); -describe('BIP150', function() { - const db = new BIP150.AuthDB(); - const ck = secp256k1.generatePrivateKey(); - const sk = secp256k1.generatePrivateKey(); +const db = new BIP150.AuthDB(); +const ck = secp256k1.generatePrivateKey(); +const sk = secp256k1.generatePrivateKey(); - db.addAuthorized(secp256k1.publicKeyCreate(ck, true)); - db.addKnown('127.0.0.2', secp256k1.publicKeyCreate(sk, true)); +db.addAuthorized(secp256k1.publicKeyCreate(ck, true)); +db.addKnown('127.0.0.2', secp256k1.publicKeyCreate(sk, true)); - const client = new BIP151(); - const server = new BIP151(); +const client = new BIP151(); +const server = new BIP151(); - client.bip150 = new BIP150(client, '127.0.0.2', true, db, ck); - server.bip150 = new BIP150(server, '127.0.0.1', false, db, sk); +client.bip150 = new BIP150(client, '127.0.0.2', true, db, ck); +server.bip150 = new BIP150(server, '127.0.0.1', false, db, sk); - function payload() { - return Buffer.from('deadbeef', 'hex'); - } +function payload() { + return Buffer.from('deadbeef', 'hex'); +} +describe('BIP150', function() { it('should do encinit', () => { const init = server.toEncinit(); client.encinit(init.publicKey, init.cipher); @@ -69,8 +69,8 @@ describe('BIP150', function() { let emitted = false; server.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); server.feed(packet); assert(emitted); @@ -81,8 +81,8 @@ describe('BIP150', function() { let emitted = false; client.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); client.feed(packet); assert(emitted); @@ -93,8 +93,8 @@ describe('BIP150', function() { let emitted = false; server.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); server.feed(packet); assert(emitted); @@ -105,8 +105,8 @@ describe('BIP150', function() { let emitted = false; client.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); client.feed(packet); assert(emitted); @@ -122,7 +122,7 @@ describe('BIP150', function() { let emitted = false; server.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'encack'); + assert.strictEqual(cmd, 'encack'); server.encack(body); }); server.feed(packet); @@ -144,8 +144,8 @@ describe('BIP150', function() { let emitted = false; server.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); server.feed(packet); assert(emitted); @@ -156,8 +156,8 @@ describe('BIP150', function() { let emitted = false; client.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); client.feed(packet); assert(emitted); @@ -168,8 +168,8 @@ describe('BIP150', function() { let emitted = false; server.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); server.feed(packet); assert(emitted); @@ -180,8 +180,8 @@ describe('BIP150', function() { let emitted = false; client.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); client.feed(packet); assert(emitted); @@ -194,13 +194,13 @@ describe('BIP150', function() { let semitted = false; client.once('packet', (cmd, body) => { cemitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); server.once('packet', (cmd, body) => { semitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); client.feed(spacket); server.feed(cpacket); diff --git a/test/bip151-test.js b/test/bip151-test.js index 1f121fdb0..e45d28004 100644 --- a/test/bip151-test.js +++ b/test/bip151-test.js @@ -6,14 +6,14 @@ const assert = require('assert'); const BIP151 = require('../lib/net/bip151'); -describe('BIP151', function() { - const client = new BIP151(); - const server = new BIP151(); +const client = new BIP151(); +const server = new BIP151(); - function payload() { - return Buffer.from('deadbeef', 'hex'); - } +function payload() { + return Buffer.from('deadbeef', 'hex'); +} +describe('BIP151', function() { it('should do encinit', () => { let init = server.toEncinit(); client.encinit(init.publicKey, init.cipher); @@ -44,8 +44,8 @@ describe('BIP151', function() { let emitted = false; server.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); server.feed(packet); assert(emitted); @@ -56,8 +56,8 @@ describe('BIP151', function() { let emitted = false; client.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); client.feed(packet); assert(emitted); @@ -68,8 +68,8 @@ describe('BIP151', function() { let emitted = false; server.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); server.feed(packet); assert(emitted); @@ -80,8 +80,8 @@ describe('BIP151', function() { let emitted = false; client.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); client.feed(packet); assert(emitted); @@ -97,7 +97,7 @@ describe('BIP151', function() { let emitted = false; server.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'encack'); + assert.strictEqual(cmd, 'encack'); server.encack(body); }); server.feed(packet); @@ -119,8 +119,8 @@ describe('BIP151', function() { let emitted = false; server.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); server.feed(packet); assert(emitted); @@ -131,8 +131,8 @@ describe('BIP151', function() { let emitted = false; client.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); client.feed(packet); assert(emitted); @@ -143,8 +143,8 @@ describe('BIP151', function() { let emitted = false; server.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); server.feed(packet); assert(emitted); @@ -155,8 +155,8 @@ describe('BIP151', function() { let emitted = false; client.once('packet', (cmd, body) => { emitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); client.feed(packet); assert(emitted); @@ -169,13 +169,13 @@ describe('BIP151', function() { let semitted = false; client.once('packet', (cmd, body) => { cemitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); server.once('packet', (cmd, body) => { semitted = true; - assert.equal(cmd, 'fake'); - assert.equal(body.toString('hex'), 'deadbeef'); + assert.strictEqual(cmd, 'fake'); + assert.strictEqual(body.toString('hex'), 'deadbeef'); }); client.feed(spacket); server.feed(cpacket); diff --git a/test/bip70-test.js b/test/bip70-test.js index a92bdb349..e51f5c068 100644 --- a/test/bip70-test.js +++ b/test/bip70-test.js @@ -28,22 +28,21 @@ x509.verifyTime = function() { return true; }; -describe('BIP70', function() { - function testRequest(data) { - const req = bip70.PaymentRequest.fromRaw(data); +function testRequest(data) { + const req = bip70.PaymentRequest.fromRaw(data); - assert.equal(req.pkiType, 'x509+sha256'); - assert(req.pkiData); - assert(req.getChain()); - assert(req.paymentDetails); - assert(req.paymentDetails.memo.length !== 0); - assert(req.paymentDetails.paymentUrl.length !== 0); + assert.strictEqual(req.pkiType, 'x509+sha256'); + assert(req.pkiData); + assert(req.getChain()); + assert(req.paymentDetails); + assert(req.paymentDetails.memo.length !== 0); + assert(req.paymentDetails.paymentUrl.length !== 0); - const raw = req.toRaw(); - assert.equal(raw.toString('hex'), data.toString('hex')); - assert(req.verify()); - } + assert.deepStrictEqual(req.toRaw(), data); + assert(req.verify()); +} +describe('BIP70', function() { it('should parse and verify a payment request', () => { testRequest(tests.valid); testRequest(tests.invalid); @@ -53,14 +52,14 @@ describe('BIP70', function() { it('should verify cert chain', () => { const req1 = bip70.PaymentRequest.fromRaw(tests.valid); - assert.equal(req1.version, 1); - assert.equal(req1.getChain().length, 4); - assert.equal(req1.paymentDetails.paymentUrl, + assert.strictEqual(req1.version, 1); + assert.strictEqual(req1.getChain().length, 4); + assert.strictEqual(req1.paymentDetails.paymentUrl, 'https://test.bitpay.com/i/CMWpuFsjgmQ2ZLiyGfcF1W'); - assert.equal(req1.paymentDetails.network, 'test'); - assert.equal(req1.paymentDetails.time, 1408645830); - assert.equal(req1.paymentDetails.expires, 1408646730); - assert.equal(req1.paymentDetails.outputs.length, 1); + assert.strictEqual(req1.paymentDetails.network, 'test'); + assert.strictEqual(req1.paymentDetails.time, 1408645830); + assert.strictEqual(req1.paymentDetails.expires, 1408646730); + assert.strictEqual(req1.paymentDetails.outputs.length, 1); assert(!req1.paymentDetails.merchantData); assert(req1.paymentDetails.isExpired()); @@ -68,37 +67,37 @@ describe('BIP70', function() { const req2 = bip70.PaymentRequest.fromRaw(tests.invalid); - assert.equal(req2.version, 1); - assert.equal(req2.getChain().length, 3); - assert.equal(req2.paymentDetails.paymentUrl, + assert.strictEqual(req2.version, 1); + assert.strictEqual(req2.getChain().length, 3); + assert.strictEqual(req2.paymentDetails.paymentUrl, 'https://bitpay.com/i/PAQtNxX7KL8BtJBnfXyTaH'); - assert.equal(req2.paymentDetails.network, 'main'); - assert.equal(req2.paymentDetails.time, 1442409238); - assert.equal(req2.paymentDetails.expires, 1442410138); - assert.equal(req2.paymentDetails.outputs.length, 1); - assert.equal(req2.paymentDetails.merchantData.length, 76); + assert.strictEqual(req2.paymentDetails.network, 'main'); + assert.strictEqual(req2.paymentDetails.time, 1442409238); + assert.strictEqual(req2.paymentDetails.expires, 1442410138); + assert.strictEqual(req2.paymentDetails.outputs.length, 1); + assert.strictEqual(req2.paymentDetails.merchantData.length, 76); assert(req2.paymentDetails.getData('json')); assert(req2.paymentDetails.isExpired()); assert(req2.verifyChain()); req2.paymentDetails.setData({foo:1}, 'json'); - assert.equal(req2.paymentDetails.merchantData.length, 9); + assert.strictEqual(req2.paymentDetails.merchantData.length, 9); assert.deepStrictEqual(req2.paymentDetails.getData('json'), {foo:1}); assert(!req2.verify()); const req3 = bip70.PaymentRequest.fromRaw(tests.untrusted); - assert.equal(req3.version, -1); - assert.equal(req3.getChain().length, 2); - assert.equal(req3.paymentDetails.paymentUrl, + assert.strictEqual(req3.version, -1); + assert.strictEqual(req3.getChain().length, 2); + assert.strictEqual(req3.paymentDetails.paymentUrl, 'https://www.coinbase.com/rp/55f9ca703d5d80008c0001f4'); - assert.equal(req3.paymentDetails.network, null); - assert.equal(req3.paymentDetails.time, 1442433682); - assert.equal(req3.paymentDetails.expires, 1442434548); - assert.equal(req3.paymentDetails.outputs.length, 1); - assert.equal(req3.paymentDetails.merchantData.length, 32); - assert.equal(req3.paymentDetails.getData('utf8'), + assert.strictEqual(req3.paymentDetails.network, null); + assert.strictEqual(req3.paymentDetails.time, 1442433682); + assert.strictEqual(req3.paymentDetails.expires, 1442434548); + assert.strictEqual(req3.paymentDetails.outputs.length, 1); + assert.strictEqual(req3.paymentDetails.merchantData.length, 32); + assert.strictEqual(req3.paymentDetails.getData('utf8'), 'bb79b6f2310e321bd3b1d929edbeb358'); assert(req3.paymentDetails.isExpired()); @@ -134,8 +133,8 @@ describe('BIP70', function() { it('should get chain and ca for request', () => { const req = bip70.PaymentRequest.fromRaw(tests.valid); - assert.equal(req.getChain().length, 4); - assert.equal(req.getCA().name, + assert.strictEqual(req.getChain().length, 4); + assert.strictEqual(req.getCA().name, 'Go Daddy Class 2 Certification Authority'); }); @@ -145,16 +144,16 @@ describe('BIP70', function() { const req2 = bip70.PaymentRequest.fromRaw(tests.untrusted); assert(req2.verifyChain()); - assert.equal(req2.getCA().name, + assert.strictEqual(req2.getCA().name, 'DigiCert SHA2 Extended Validation Server CA'); }); it('should parse a payment ack', () => { const ack = bip70.PaymentACK.fromRaw(tests.ack); - assert.equal(ack.memo.length, 95); - assert.equal(ack.memo, 'Transaction received by BitPay.' + assert.strictEqual(ack.memo.length, 95); + assert.strictEqual(ack.memo, 'Transaction received by BitPay.' + ' Invoice will be marked as paid if the transaction is confirmed.'); - assert.equal(ack.toRaw().toString('hex'), tests.ack.toString('hex')); + assert.deepStrictEqual(ack.toRaw(), tests.ack); }); it('should create a payment request, sign, and verify', () => { @@ -162,7 +161,7 @@ describe('BIP70', function() { version: 25, paymentDetails: { network: 'testnet', - paymentUrl: 'http://bcoin.io/payme', + paymentUrl: 'http://bcoin.io/payment', memo: 'foobar', time: util.now(), expires: util.now() + 3600, @@ -174,21 +173,21 @@ describe('BIP70', function() { } }); - assert.equal(req.pkiType, null); + assert.strictEqual(req.pkiType, null); assert(!req.pkiData); - assert.equal(req.getChain().length, 0); + assert.strictEqual(req.getChain().length, 0); assert(req.paymentDetails); assert(req.paymentDetails.memo.length !== 0); assert(req.paymentDetails.paymentUrl.length !== 0); assert.deepStrictEqual(req.paymentDetails.getData('json'), {foo:'bar'}); - assert.equal(req.version, 25); - assert.equal(req.paymentDetails.paymentUrl, 'http://bcoin.io/payme'); - assert.equal(req.paymentDetails.network, 'testnet'); + assert.strictEqual(req.version, 25); + assert.strictEqual(req.paymentDetails.paymentUrl, 'http://bcoin.io/payment'); + assert.strictEqual(req.paymentDetails.network, 'testnet'); assert(req.paymentDetails.time <= util.now()); - assert.equal(req.paymentDetails.expires, + assert.strictEqual(req.paymentDetails.expires, req.paymentDetails.time + 3600); - assert.equal(req.paymentDetails.outputs.length, 2); + assert.strictEqual(req.paymentDetails.outputs.length, 2); assert(req.paymentDetails.merchantData); assert(!req.paymentDetails.isExpired()); @@ -197,8 +196,8 @@ describe('BIP70', function() { req.sign(tests.ca.priv); assert(req.pkiData); - assert.equal(req.pkiType, 'x509+sha256'); - assert.equal(req.getChain().length, 1); + assert.strictEqual(req.pkiType, 'x509+sha256'); + assert.strictEqual(req.getChain().length, 1); assert(req.verify()); assert(!req.verifyChain()); @@ -207,7 +206,7 @@ describe('BIP70', function() { x509.setTrust([tests.ca.crt]); assert(req.verifyChain()); - assert.equal(req.getCA().name, 'JJs CA'); + assert.strictEqual(req.getCA().name, 'JJs CA'); req.version = 24; assert(!req.verify()); diff --git a/test/block-test.js b/test/block-test.js index 09d333e2e..efb715277 100644 --- a/test/block-test.js +++ b/test/block-test.js @@ -1,11 +1,10 @@ /* eslint-env mocha */ -/* eslint max-len: "off" */ /* eslint prefer-arrow-callback: "off" */ 'use strict'; const assert = require('assert'); -const fs = require('fs'); +const fs = require('../lib/utils/fs'); const common = require('./util/common'); const Bloom = require('../lib/utils/bloom'); const Block = require('../lib/primitives/block'); @@ -53,15 +52,15 @@ describe('Block', function() { const tree = mblock.getTree(); - assert.equal(tree.matches.length, 2); - assert.equal(mblock.hash('hex'), + assert.strictEqual(tree.matches.length, 2); + assert.strictEqual(mblock.hash('hex'), '8cc72c02a958de5a8b35a23bb7e3bced8bf840cc0a4e1c820000000000000000'); - assert.equal(mblock.rhash(), + assert.strictEqual(mblock.rhash(), '0000000000000000821c4e0acc40f88bedbce3b73ba2358b5ade58a9022cc78c'); - assert.equal( + assert.strictEqual( tree.matches[0].toString('hex'), '7393f84cd04ca8931975c66282ebf1847c78d8de6c2578d4f9bae23bc6f30857'); - assert.equal( + assert.strictEqual( tree.matches[1].toString('hex'), 'ec8c51de3170301430ec56f6703533d9ea5b05c6fa7068954bcb90eed8c2ee5c'); }); @@ -69,8 +68,8 @@ describe('Block', function() { it('should decode/encode merkle block', () => { const merkle = MerkleBlock.fromRaw(merkle300025); merkle.refresh(); - assert.deepEqual(merkle.toRaw(), merkle300025); - assert.deepEqual(merkle300025, mblock.toRaw()); + assert.deepStrictEqual(merkle.toRaw(), merkle300025); + assert.deepStrictEqual(merkle300025, mblock.toRaw()); }); it('should be verify merkle block', () => { @@ -81,14 +80,14 @@ describe('Block', function() { it('should be encoded/decoded and still verify', () => { const raw = mblock.toRaw(); const merkle = MerkleBlock.fromRaw(raw); - assert.deepEqual(merkle.toRaw(), raw); + assert.deepStrictEqual(merkle.toRaw(), raw); assert(merkle.verify()); }); it('should be jsonified/unjsonified and still verify', () => { const json = mblock.toJSON(); const merkle = MerkleBlock.fromJSON(json); - assert.deepEqual(merkle.toJSON(), json); + assert.deepStrictEqual(merkle.toJSON(), json); assert(merkle.verify()); }); @@ -105,17 +104,17 @@ describe('Block', function() { height++; } - assert.equal(height, 6930000); - assert.equal(total, 2099999997690000); + assert.strictEqual(height, 6930000); + assert.strictEqual(total, 2099999997690000); }); it('should parse JSON', () => { const block = Block.fromJSON(Block.fromRaw(block300025).toJSON()); - assert.equal(block.hash('hex'), + assert.strictEqual(block.hash('hex'), '8cc72c02a958de5a8b35a23bb7e3bced8bf840cc0a4e1c820000000000000000'); - assert.equal(block.rhash(), + assert.strictEqual(block.rhash(), '0000000000000000821c4e0acc40f88bedbce3b73ba2358b5ade58a9022cc78c'); - assert.equal(block.merkleRoot, block.createMerkleRoot('hex')); + assert.strictEqual(block.merkleRoot, block.createMerkleRoot('hex')); }); it('should create a merkle block', () => { @@ -132,7 +131,7 @@ describe('Block', function() { const merkle = MerkleBlock.fromBlock(block, filter); assert(merkle.verifyBody()); - assert.deepEqual(merkle.toRaw(), mblock.toRaw()); + assert.deepStrictEqual(merkle.toRaw(), mblock.toRaw()); }); it('should verify a historical block', () => { @@ -146,7 +145,7 @@ describe('Block', function() { assert(block.txs[0].isCoinbase()); assert(block.txs[0].isSane()); assert(!block.hasWitness()); - assert.equal(block.getWeight(), 1136924); + assert.strictEqual(block.getWeight(), 1136924); let sigops = 0; let reward = 0; @@ -164,9 +163,9 @@ describe('Block', function() { reward += consensus.getReward(height, 210000); - assert.equal(sigops, 5280); - assert.equal(reward, 2507773345); - assert.equal(reward, block.txs[0].outputs[0].value); + assert.strictEqual(sigops, 5280); + assert.strictEqual(reward, 2507773345); + assert.strictEqual(reward, block.txs[0].outputs[0].value); }); it('should fail with a bad merkle root', () => { @@ -175,7 +174,7 @@ describe('Block', function() { block2.refresh(); assert(!block2.verifyPOW()); const [, reason] = block2.checkBody(); - assert.equal(reason, 'bad-txnmrklroot'); + assert.strictEqual(reason, 'bad-txnmrklroot'); assert(!block2.verify()); block2.merkleRoot = block.merkleRoot; block2.refresh(); @@ -188,7 +187,7 @@ describe('Block', function() { mblock2.refresh(); assert(!mblock2.verifyPOW()); const [, reason] = mblock2.checkBody(); - assert.equal(reason, 'bad-txnmrklroot'); + assert.strictEqual(reason, 'bad-txnmrklroot'); assert(!mblock2.verify()); mblock2.merkleRoot = mblock.merkleRoot; mblock2.refresh(); @@ -212,7 +211,7 @@ describe('Block', function() { block2.txs.push(block2.txs[block2.txs.length - 1]); block2.refresh(); const [, reason] = block2.checkBody(); - assert.equal(reason, 'bad-txns-duplicate'); + assert.strictEqual(reason, 'bad-txns-duplicate'); }); it('should verify with headers', () => { @@ -229,8 +228,8 @@ describe('Block', function() { assert(cblock1.init()); - assert.deepEqual(cblock1.toRaw(), compact426884); - assert.deepEqual(cblock2.toRaw(), compact426884); + assert.deepStrictEqual(cblock1.toRaw(), compact426884); + assert.deepStrictEqual(cblock2.toRaw(), compact426884); const map = new Map(); @@ -245,9 +244,7 @@ describe('Block', function() { for (const tx of cblock1.available) assert(tx); - assert.equal( - cblock1.toBlock().toRaw().toString('hex'), - block.toRaw().toString('hex')); + assert.deepStrictEqual(cblock1.toBlock().toRaw(), block.toRaw()); }); it('should handle half-full compact block', () => { @@ -257,8 +254,8 @@ describe('Block', function() { assert(cblock1.init()); - assert.deepEqual(cblock1.toRaw(), compact426884); - assert.deepEqual(cblock2.toRaw(), compact426884); + assert.deepStrictEqual(cblock1.toRaw(), compact426884); + assert.deepStrictEqual(cblock2.toRaw(), compact426884); const map = new Map(); @@ -271,10 +268,10 @@ describe('Block', function() { assert(!full); let req = cblock1.toRequest(); - assert.equal(req.hash, cblock1.hash('hex')); + assert.strictEqual(req.hash, cblock1.hash('hex')); req = TXRequest.fromRaw(req.toRaw()); - assert.equal(req.hash, cblock1.hash('hex')); + assert.strictEqual(req.hash, cblock1.hash('hex')); let res = TXResponse.fromBlock(block, req); res = TXResponse.fromRaw(res.toRaw()); @@ -285,9 +282,7 @@ describe('Block', function() { for (const tx of cblock1.available) assert(tx); - assert.equal( - cblock1.toBlock().toRaw().toString('hex'), - block.toRaw().toString('hex')); + assert.deepStrictEqual(cblock1.toBlock().toRaw(), block.toRaw()); }); it('should handle compact block', () => { @@ -297,10 +292,10 @@ describe('Block', function() { assert(cblock1.init()); - assert.deepEqual(cblock1.toRaw(), compact898352); - assert.deepEqual(cblock2.toRaw(), compact898352); + assert.deepStrictEqual(cblock1.toRaw(), compact898352); + assert.deepStrictEqual(cblock2.toRaw(), compact898352); - assert.equal(cblock1.sid(block.txs[1].hash()), 125673511480291); + assert.strictEqual(cblock1.sid(block.txs[1].hash()), 125673511480291); const map = new Map(); @@ -315,9 +310,7 @@ describe('Block', function() { for (const tx of cblock1.available) assert(tx); - assert.equal( - cblock1.toBlock().toRaw().toString('hex'), - block.toRaw().toString('hex')); + assert.deepStrictEqual(cblock1.toBlock().toRaw(), block.toRaw()); }); it('should handle half-full compact block', () => { @@ -327,10 +320,10 @@ describe('Block', function() { assert(cblock1.init()); - assert.deepEqual(cblock1.toRaw(), compact898352); - assert.deepEqual(cblock2.toRaw(), compact898352); + assert.deepStrictEqual(cblock1.toRaw(), compact898352); + assert.deepStrictEqual(cblock2.toRaw(), compact898352); - assert.equal(cblock1.sid(block.txs[1].hash()), 125673511480291); + assert.strictEqual(cblock1.sid(block.txs[1].hash()), 125673511480291); const map = new Map(); @@ -343,12 +336,12 @@ describe('Block', function() { assert(!full); let req = cblock1.toRequest(); - assert.equal(req.hash, cblock1.hash('hex')); - assert.deepEqual(req.indexes, [5, 6, 7, 8, 9]); + assert.strictEqual(req.hash, cblock1.hash('hex')); + assert.deepStrictEqual(req.indexes, [5, 6, 7, 8, 9]); req = TXRequest.fromRaw(req.toRaw()); - assert.equal(req.hash, cblock1.hash('hex')); - assert.deepEqual(req.indexes, [5, 6, 7, 8, 9]); + assert.strictEqual(req.hash, cblock1.hash('hex')); + assert.deepStrictEqual(req.indexes, [5, 6, 7, 8, 9]); let res = TXResponse.fromBlock(block, req); res = TXResponse.fromRaw(res.toRaw()); @@ -359,9 +352,7 @@ describe('Block', function() { for (const tx of cblock1.available) assert(tx); - assert.equal( - cblock1.toBlock().toRaw().toString('hex'), - block.toRaw().toString('hex')); + assert.deepStrictEqual(cblock1.toBlock().toRaw(), block.toRaw()); }); it('should count sigops for block 928927 (testnet)', () => { @@ -374,8 +365,8 @@ describe('Block', function() { for (const tx of block.txs) sigops += tx.getSigopsCost(view, flags); - assert.equal(sigops, 10015); - assert.equal(block.getWeight(), 3992391); + assert.strictEqual(sigops, 10015); + assert.strictEqual(block.getWeight(), 3992391); }); it('should count sigops for block 928828 (testnet)', () => { @@ -388,8 +379,8 @@ describe('Block', function() { for (const tx of block.txs) sigops += tx.getSigopsCost(view, flags); - assert.equal(sigops, 23236); - assert.equal(block.getWeight(), 2481560); + assert.strictEqual(sigops, 23236); + assert.strictEqual(block.getWeight(), 2481560); }); it('should count sigops for block 1087400 (testnet)', () => { @@ -402,7 +393,7 @@ describe('Block', function() { for (const tx of block.txs) sigops += tx.getSigopsCost(view, flags); - assert.equal(sigops, 1298); - assert.equal(block.getWeight(), 193331); + assert.strictEqual(sigops, 1298); + assert.strictEqual(block.getWeight(), 193331); }); }); diff --git a/test/bloom-test.js b/test/bloom-test.js index 15dbe3988..45387f0ea 100644 --- a/test/bloom-test.js +++ b/test/bloom-test.js @@ -9,7 +9,13 @@ const RollingFilter = require('../lib/utils/rollingfilter'); const murmur3 = require('../lib/utils/murmur3'); function testMurmur(str, seed, expect, enc) { - assert.equal(murmur3(Buffer.from(str, enc || 'ascii'), seed), expect); + if (!enc) + enc = 'ascii'; + + const data = Buffer.from(str, enc); + const hash = murmur3(data, seed); + + assert.strictEqual(hash, expect); } describe('Bloom', function() { @@ -61,14 +67,15 @@ describe('Bloom', function() { const item2 = '047b00000078da0dca3b0ec2300c00d0ab4466ed10' + 'e763272c6c9ca052972c69e3884a9022084215e2eef' + '0e6f781656b5d5a87231cd4349e534b6dea55ad4ff55e'; - const filterHex = '' + const filterRaw = Buffer.from('' + '000000000000000000000000000000000000000000000000088004000000000000000' + '000000000200000000000000000000000000000000800000000000000000002000000' + '000000000000002000000000000000000000000000000000000000000040000200000' - + '0000000001000000800000080000000'; + + '0000000001000000800000080000000', + 'hex'); filter.add(item1, 'hex'); filter.add(item2, 'hex'); - assert.equal(filter.filter.toString('hex'), filterHex); + assert.deepStrictEqual(filter.filter, filterRaw); }); it('should handle 1m ops with regular filter', () => { @@ -83,8 +90,8 @@ describe('Bloom', function() { filter.add(str, 'ascii'); do { const str = 'foobar' + j; - assert(filter.test(str, 'ascii') === true); - assert(filter.test(str + '-', 'ascii') === false); + assert(filter.test(str, 'ascii')); + assert(!filter.test(str + '-', 'ascii')); } while (j--); } }); @@ -101,8 +108,8 @@ describe('Bloom', function() { filter.add(str, 'ascii'); do { const str = 'foobar' + j; - assert(filter.test(str, 'ascii') === true); - assert(filter.test(str + '-', 'ascii') === false); + assert(filter.test(str, 'ascii')); + assert(!filter.test(str + '-', 'ascii')); } while (j--); } }); @@ -118,8 +125,8 @@ describe('Bloom', function() { filter.add(str, 'ascii'); do { const str = 'foobar' + j; - assert(filter.test(str, 'ascii') === true); - assert(filter.test(str + '-', 'ascii') === false); + assert(filter.test(str, 'ascii')); + assert(!filter.test(str + '-', 'ascii')); } while (j--); } @@ -129,8 +136,8 @@ describe('Bloom', function() { filter.add(str, 'ascii'); do { const str = 'foobar' + j; - assert(filter.test(str, 'ascii') === true, str); - assert(filter.test(str + '-', 'ascii') === false, str); + assert(filter.test(str, 'ascii')); + assert(!filter.test(str + '-', 'ascii')); } while (j--); } @@ -140,8 +147,8 @@ describe('Bloom', function() { filter.add(str, 'ascii'); do { const str = 'foobar' + j; - assert(filter.test(str, 'ascii') === true, str); - assert(filter.test(str + '-', 'ascii') === false, str); + assert(filter.test(str, 'ascii')); + assert(!filter.test(str + '-', 'ascii')); } while (j--); } @@ -151,10 +158,10 @@ describe('Bloom', function() { filter.add(str, 'ascii'); do { const str = 'foobar' + j; - assert(filter.test(str, 'ascii') === true, str); - assert(filter.test(str + '-', 'ascii') === false, str); + assert(filter.test(str, 'ascii')); + assert(!filter.test(str + '-', 'ascii')); } while (j-- > 25); - assert(filter.test('foobar 24', 'ascii') === false); + assert(!filter.test('foobar 24', 'ascii')); } for (let i = 100; i < 125; i++) { @@ -163,11 +170,11 @@ describe('Bloom', function() { filter.add(str, 'ascii'); do { const str = 'foobar' + j; - assert(filter.test(str, 'ascii') === true, str); - assert(filter.test(str + '-', 'ascii') === false, str); + assert(filter.test(str, 'ascii')); + assert(!filter.test(str + '-', 'ascii')); } while (j-- > 50); } - assert(filter.test('foobar 49', 'ascii') === false); + assert(!filter.test('foobar 49', 'ascii')); }); }); diff --git a/test/chachapoly-test.js b/test/chachapoly-test.js index 397bc0ad8..d595b74f4 100644 --- a/test/chachapoly-test.js +++ b/test/chachapoly-test.js @@ -8,63 +8,55 @@ const ChaCha20 = require('../lib/crypto/chacha20'); const Poly1305 = require('../lib/crypto/poly1305'); const AEAD = require('../lib/crypto/aead'); -describe('ChaCha20 / Poly1305 / AEAD', function() { - function testChaCha(options) { - const key = Buffer.from(options.key, 'hex'); - const nonce = Buffer.from(options.nonce, 'hex'); - const plain = Buffer.from(options.plain, 'hex'); - const ciphertext = Buffer.from(options.ciphertext, 'hex'); - const counter = options.counter; - - { - const chacha = new ChaCha20(); - chacha.init(key, nonce, counter); - const plainenc = Buffer.from(plain); - chacha.encrypt(plainenc); - assert.deepEqual(plainenc, ciphertext); - } - - { - const chacha = new ChaCha20(); - chacha.init(key, nonce, counter); - chacha.encrypt(ciphertext); - assert.deepEqual(plain, ciphertext); - } - } - - function testAEAD(options) { - const plain = Buffer.from(options.plain, 'hex'); - const aad = Buffer.from(options.aad, 'hex'); - const key = Buffer.from(options.key, 'hex'); - const nonce = Buffer.from(options.nonce, 'hex'); - const pk = Buffer.from(options.pk, 'hex'); - const ciphertext = Buffer.from(options.ciphertext, 'hex'); - const tag = Buffer.from(options.tag, 'hex'); - - { - const aead = new AEAD(); - aead.init(key, nonce); - assert.equal(aead.chacha20.getCounter(), 1); - assert.deepEqual(aead.polyKey, pk); - aead.aad(aad); - const plainenc = Buffer.from(plain); - aead.encrypt(plainenc); - assert.deepEqual(plainenc, ciphertext); - assert.deepEqual(aead.finish(), tag); - } - - { - const aead = new AEAD(); - aead.init(key, nonce); - assert.equal(aead.chacha20.getCounter(), 1); - assert.deepEqual(aead.polyKey, pk); - aead.aad(aad); - aead.decrypt(ciphertext); - assert.deepEqual(ciphertext, plain); - assert.deepEqual(aead.finish(), tag); - } - } +function testChaCha(options) { + const key = Buffer.from(options.key, 'hex'); + const nonce = Buffer.from(options.nonce, 'hex'); + const plain = Buffer.from(options.plain, 'hex'); + const ciphertext = Buffer.from(options.ciphertext, 'hex'); + const counter = options.counter; + + const ctx1 = new ChaCha20(); + ctx1.init(key, nonce, counter); + const plainenc = Buffer.from(plain); + ctx1.encrypt(plainenc); + assert.deepStrictEqual(plainenc, ciphertext); + + const ctx2 = new ChaCha20(); + ctx2.init(key, nonce, counter); + ctx2.encrypt(ciphertext); + assert.deepStrictEqual(plain, ciphertext); +} + +function testAEAD(options) { + const plain = Buffer.from(options.plain, 'hex'); + const aad = Buffer.from(options.aad, 'hex'); + const key = Buffer.from(options.key, 'hex'); + const nonce = Buffer.from(options.nonce, 'hex'); + const pk = Buffer.from(options.pk, 'hex'); + const ciphertext = Buffer.from(options.ciphertext, 'hex'); + const tag = Buffer.from(options.tag, 'hex'); + + const ctx1 = new AEAD(); + ctx1.init(key, nonce); + assert.strictEqual(ctx1.chacha20.getCounter(), 1); + assert.deepStrictEqual(ctx1.polyKey, pk); + ctx1.aad(aad); + const plainenc = Buffer.from(plain); + ctx1.encrypt(plainenc); + assert.deepStrictEqual(plainenc, ciphertext); + assert.deepStrictEqual(ctx1.finish(), tag); + + const ctx2 = new AEAD(); + ctx2.init(key, nonce); + assert.strictEqual(ctx2.chacha20.getCounter(), 1); + assert.deepStrictEqual(ctx2.polyKey, pk); + ctx2.aad(aad); + ctx2.decrypt(ciphertext); + assert.deepStrictEqual(ciphertext, plain); + assert.deepStrictEqual(ctx2.finish(), tag); +} +describe('ChaCha20 / Poly1305 / AEAD', function() { it('should perform chacha20', () => { testChaCha({ key: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', @@ -168,7 +160,7 @@ describe('ChaCha20 / Poly1305 / AEAD', function() { const mac = Poly1305.auth(msg, key); assert(Poly1305.verify(mac, expected)); - assert.deepEqual(mac, expected); + assert.deepStrictEqual(mac, expected); }); it('should perform poly1305', () => { diff --git a/test/chain-test.js b/test/chain-test.js index 19d0a8950..22df2c1c5 100644 --- a/test/chain-test.js +++ b/test/chain-test.js @@ -18,69 +18,89 @@ const Output = require('../lib/primitives/output'); const common = require('../lib/blockchain/common'); const opcodes = Script.opcodes; -describe('Chain', function() { - const network = Network.get('regtest'); - const chain = new Chain({ db: 'memory', network: network }); - const miner = new Miner({ chain: chain, version: 4 }); - const wallet = new MemWallet({ network: network }); - const wwallet = new MemWallet({ network: network, witness: true }); - const cpu = miner.cpu; - let tip1, tip2; +const network = Network.get('regtest'); - this.timeout(45000); +const chain = new Chain({ + db: 'memory', + network +}); - async function addBlock(block, flags) { - let entry; +const miner = new Miner({ + chain, + version: 4 +}); - try { - entry = await chain.add(block, flags); - } catch (e) { - assert(e.type === 'VerifyError'); - return e.reason; - } +const cpu = miner.cpu; - if (!entry) - return 'bad-prevblk'; +const wallet = new MemWallet({ + network, + witness: false +}); - return 'OK'; - } +const witWallet = new MemWallet({ + network, + witness: true +}); - async function mineBlock(job, flags) { - const block = await job.mineAsync(); - return await addBlock(block, flags); +let tip1 = null; +let tip2 = null; + +async function addBlock(block, flags) { + let entry; + + try { + entry = await chain.add(block, flags); + } catch (e) { + assert(e.type === 'VerifyError'); + return e.reason; } - async function mineCSV(tx) { - const job = await cpu.createJob(); - const rtx = new MTX(); + if (!entry) + return 'bad-prevblk'; - rtx.addOutput({ - script: [ - Script.array(new BN(1)), - Script.opcodes.OP_CHECKSEQUENCEVERIFY - ], - value: 10000 - }); + return 'OK'; +} - rtx.addTX(tx, 0); +async function mineBlock(job, flags) { + const block = await job.mineAsync(); + return await addBlock(block, flags); +} - rtx.setLocktime(chain.height); +async function mineCSV(fund) { + const job = await cpu.createJob(); + const spend = new MTX(); - wallet.sign(rtx); + spend.addOutput({ + script: [ + Script.array(new BN(1)), + Script.opcodes.OP_CHECKSEQUENCEVERIFY + ], + value: 10000 + }); - job.addTX(rtx.toTX(), rtx.view); - job.refresh(); + spend.addTX(fund, 0); + spend.setLocktime(chain.height); - return await job.mineAsync(); - } + wallet.sign(spend); - chain.on('connect', (entry, block) => { - wallet.addBlock(entry, block.txs); - }); + const [tx, view] = spend.commit(); - chain.on('disconnect', (entry, block) => { - wallet.removeBlock(entry, block.txs); - }); + job.addTX(tx, view); + job.refresh(); + + return await job.mineAsync(); +} + +chain.on('connect', (entry, block) => { + wallet.addBlock(entry, block.txs); +}); + +chain.on('disconnect', (entry, block) => { + wallet.removeBlock(entry, block.txs); +}); + +describe('Chain', function() { + this.timeout(45000); it('should open chain and miner', async () => { await chain.open(); @@ -99,7 +119,7 @@ describe('Chain', function() { assert(await chain.add(block)); } - assert.equal(chain.height, 200); + assert.strictEqual(chain.height, 200); }); it('should mine competing chains', async () => { @@ -142,19 +162,17 @@ describe('Chain', function() { }); it('should have correct chain value', () => { - assert.equal(chain.db.state.value, 897500000000); - assert.equal(chain.db.state.coin, 220); - assert.equal(chain.db.state.tx, 221); + assert.strictEqual(chain.db.state.value, 897500000000); + assert.strictEqual(chain.db.state.coin, 220); + assert.strictEqual(chain.db.state.tx, 221); }); it('should have correct wallet balance', async () => { - assert.equal(wallet.balance, 897500000000); + assert.strictEqual(wallet.balance, 897500000000); }); it('should handle a reorg', async () => { - let forked = false; - - assert.equal(chain.height, 210); + assert.strictEqual(chain.height, 210); const entry = await chain.db.getEntry(tip2.hash); assert(entry); @@ -163,6 +181,7 @@ describe('Chain', function() { const block = await cpu.mineBlock(entry); assert(block); + let forked = false; chain.once('reorganize', () => { forked = true; }); @@ -175,13 +194,13 @@ describe('Chain', function() { }); it('should have correct chain value', () => { - assert.equal(chain.db.state.value, 900000000000); - assert.equal(chain.db.state.coin, 221); - assert.equal(chain.db.state.tx, 222); + assert.strictEqual(chain.db.state.value, 900000000000); + assert.strictEqual(chain.db.state.coin, 221); + assert.strictEqual(chain.db.state.tx, 222); }); it('should have correct wallet balance', async () => { - assert.equal(wallet.balance, 900000000000); + assert.strictEqual(wallet.balance, 900000000000); }); it('should check main chain', async () => { @@ -205,8 +224,6 @@ describe('Chain', function() { }); it('should prevent double spend on new chain', async () => { - let job = await cpu.createJob(); - const mtx = await wallet.create({ outputs: [{ address: wallet.getAddress(), @@ -214,22 +231,29 @@ describe('Chain', function() { }] }); - job.addTX(mtx.toTX(), mtx.view); - job.refresh(); + { + const job = await cpu.createJob(); - const block = await job.mineAsync(); + job.addTX(mtx.toTX(), mtx.view); + job.refresh(); - assert(await chain.add(block)); + const block = await job.mineAsync(); + + assert(await chain.add(block)); + } - job = await cpu.createJob(); + { + const job = await cpu.createJob(); - assert(mtx.outputs.length > 1); - mtx.outputs.pop(); + assert(mtx.outputs.length > 1); + mtx.outputs.pop(); - job.addTX(mtx.toTX(), mtx.view); - job.refresh(); + job.addTX(mtx.toTX(), mtx.view); + job.refresh(); - assert.equal(await mineBlock(job), 'bad-txns-inputs-missingorspent'); + assert.strictEqual(await mineBlock(job), + 'bad-txns-inputs-missingorspent'); + } }); it('should fail to connect coins on an alternate chain', async () => { @@ -246,13 +270,13 @@ describe('Chain', function() { job.addTX(mtx.toTX(), mtx.view); job.refresh(); - assert.equal(await mineBlock(job), 'bad-txns-inputs-missingorspent'); + assert.strictEqual(await mineBlock(job), 'bad-txns-inputs-missingorspent'); }); it('should have correct chain value', () => { - assert.equal(chain.db.state.value, 905000000000); - assert.equal(chain.db.state.coin, 224); - assert.equal(chain.db.state.tx, 225); + assert.strictEqual(chain.db.state.value, 905000000000); + assert.strictEqual(chain.db.state.coin, 224); + assert.strictEqual(chain.db.state.tx, 225); }); it('should get coin', async () => { @@ -285,28 +309,32 @@ describe('Chain', function() { const coin = await chain.db.getCoin(tx.hash('hex'), 2); - assert.deepEqual(coin.toRaw(), output.toRaw()); + assert.deepStrictEqual(coin.toRaw(), output.toRaw()); }); it('should have correct wallet balance', async () => { - assert.equal(wallet.balance, 907500000000); - assert.equal(wallet.receiveDepth, 15); - assert.equal(wallet.changeDepth, 14); - assert.equal(wallet.txs, 226); + assert.strictEqual(wallet.balance, 907500000000); + assert.strictEqual(wallet.receiveDepth, 15); + assert.strictEqual(wallet.changeDepth, 14); + assert.strictEqual(wallet.txs, 226); }); it('should get tips and remove chains', async () => { - let tips = await chain.db.getTips(); + { + const tips = await chain.db.getTips(); - assert.notEqual(tips.indexOf(chain.tip.hash), -1); - assert.equal(tips.length, 2); + assert.notStrictEqual(tips.indexOf(chain.tip.hash), -1); + assert.strictEqual(tips.length, 2); + } await chain.db.removeChains(); - tips = await chain.db.getTips(); + { + const tips = await chain.db.getTips(); - assert.notEqual(tips.indexOf(chain.tip.hash), -1); - assert.equal(tips.length, 1); + assert.notStrictEqual(tips.indexOf(chain.tip.hash), -1); + assert.strictEqual(tips.length, 1); + } }); it('should rescan for transactions', async () => { @@ -316,7 +344,7 @@ describe('Chain', function() { total += txs.length; }); - assert.equal(total, 226); + assert.strictEqual(total, 226); }); it('should activate csv', async () => { @@ -324,11 +352,11 @@ describe('Chain', function() { miner.options.version = -1; - assert.equal(chain.height, 214); + assert.strictEqual(chain.height, 214); const prev = await chain.tip.getPrevious(); const state = await chain.getState(prev, deployments.csv); - assert.equal(state, 1); + assert.strictEqual(state, 1); for (let i = 0; i < 417; i++) { const block = await cpu.mineBlock(); @@ -337,31 +365,31 @@ describe('Chain', function() { case 288: { const prev = await chain.tip.getPrevious(); const state = await chain.getState(prev, deployments.csv); - assert.equal(state, 1); + assert.strictEqual(state, 1); break; } case 432: { const prev = await chain.tip.getPrevious(); const state = await chain.getState(prev, deployments.csv); - assert.equal(state, 2); + assert.strictEqual(state, 2); break; } case 576: { const prev = await chain.tip.getPrevious(); const state = await chain.getState(prev, deployments.csv); - assert.equal(state, 3); + assert.strictEqual(state, 3); break; } } } - assert.equal(chain.height, 631); + assert.strictEqual(chain.height, 631); assert(chain.state.hasCSV()); assert(chain.state.hasWitness()); const cache = await chain.db.getStateCache(); - assert.deepEqual(cache, chain.db.stateCache); - assert.equal(chain.db.stateCache.updates.length, 0); + assert.deepStrictEqual(cache, chain.db.stateCache); + assert.strictEqual(chain.db.stateCache.updates.length, 0); assert(await chain.db.verifyDeployments()); }); @@ -369,20 +397,20 @@ describe('Chain', function() { const deployments = network.deployments; const prev = await chain.tip.getPrevious(); const state = await chain.getState(prev, deployments.segwit); - assert.equal(state, 3); + assert.strictEqual(state, 3); }); it('should test csv', async () => { const tx = (await chain.db.getBlock(chain.height - 100)).txs[0]; - let block = await mineCSV(tx); + const csvBlock = await mineCSV(tx); - assert(await chain.add(block)); + assert(await chain.add(csvBlock)); - const csv = block.txs[1]; + const csv = csvBlock.txs[1]; - const rtx = new MTX(); + const spend = new MTX(); - rtx.addOutput({ + spend.addOutput({ script: [ Script.array(new BN(2)), Script.opcodes.OP_CHECKSEQUENCEVERIFY @@ -390,24 +418,24 @@ describe('Chain', function() { value: 10000 }); - rtx.addTX(csv, 0); - rtx.setSequence(0, 1, false); + spend.addTX(csv, 0); + spend.setSequence(0, 1, false); const job = await cpu.createJob(); - job.addTX(rtx.toTX(), rtx.view); + job.addTX(spend.toTX(), spend.view); job.refresh(); - block = await job.mineAsync(); + const block = await job.mineAsync(); assert(await chain.add(block)); }); it('should fail csv with bad sequence', async () => { const csv = (await chain.db.getBlock(chain.height - 100)).txs[0]; - const rtx = new MTX(); + const spend = new MTX(); - rtx.addOutput({ + spend.addOutput({ script: [ Script.array(new BN(1)), Script.opcodes.OP_CHECKSEQUENCEVERIFY @@ -415,14 +443,14 @@ describe('Chain', function() { value: 1 * 1e8 }); - rtx.addTX(csv, 0); - rtx.setSequence(0, 1, false); + spend.addTX(csv, 0); + spend.setSequence(0, 1, false); const job = await cpu.createJob(); - job.addTX(rtx.toTX(), rtx.view); + job.addTX(spend.toTX(), spend.view); job.refresh(); - assert.equal(await mineBlock(job), 'mandatory-script-verify-flag-failed'); + assert.strictEqual(await mineBlock(job), 'mandatory-script-verify-flag-failed'); }); it('should mine a block', async () => { @@ -433,15 +461,15 @@ describe('Chain', function() { it('should fail csv lock checks', async () => { const tx = (await chain.db.getBlock(chain.height - 100)).txs[0]; - const block = await mineCSV(tx); + const csvBlock = await mineCSV(tx); - assert(await chain.add(block)); + assert(await chain.add(csvBlock)); - const csv = block.txs[1]; + const csv = csvBlock.txs[1]; - const rtx = new MTX(); + const spend = new MTX(); - rtx.addOutput({ + spend.addOutput({ script: [ Script.array(new BN(2)), Script.opcodes.OP_CHECKSEQUENCEVERIFY @@ -449,38 +477,38 @@ describe('Chain', function() { value: 1 * 1e8 }); - rtx.addTX(csv, 0); - rtx.setSequence(0, 2, false); + spend.addTX(csv, 0); + spend.setSequence(0, 2, false); const job = await cpu.createJob(); - job.addTX(rtx.toTX(), rtx.view); + job.addTX(spend.toTX(), spend.view); job.refresh(); - assert.equal(await mineBlock(job), 'bad-txns-nonfinal'); + assert.strictEqual(await mineBlock(job), 'bad-txns-nonfinal'); }); it('should have correct wallet balance', async () => { - assert.equal(wallet.balance, 1412499980000); + assert.strictEqual(wallet.balance, 1412499980000); }); it('should fail to connect bad bits', async () => { const job = await cpu.createJob(); job.attempt.bits = 553713663; - assert.equal(await mineBlock(job), 'bad-diffbits'); + assert.strictEqual(await mineBlock(job), 'bad-diffbits'); }); it('should fail to connect bad MTP', async () => { const mtp = await chain.tip.getMedianTime(); const job = await cpu.createJob(); job.attempt.time = mtp - 1; - assert.equal(await mineBlock(job), 'time-too-old'); + assert.strictEqual(await mineBlock(job), 'time-too-old'); }); it('should fail to connect bad time', async () => { const job = await cpu.createJob(); const now = network.now() + 3 * 60 * 60; job.attempt.time = now; - assert.equal(await mineBlock(job), 'time-too-new'); + assert.strictEqual(await mineBlock(job), 'time-too-new'); }); it('should fail to connect bad locktime', async () => { @@ -488,7 +516,7 @@ describe('Chain', function() { const tx = await wallet.send({ locktime: 100000 }); job.pushTX(tx.toTX()); job.refresh(); - assert.equal(await mineBlock(job), 'bad-txns-nonfinal'); + assert.strictEqual(await mineBlock(job), 'bad-txns-nonfinal'); }); it('should fail to connect bad cb height', async () => { @@ -500,7 +528,7 @@ describe('Chain', function() { try { network.block.bip34height = 0; - assert.equal(await mineBlock(job), 'bad-cb-height'); + assert.strictEqual(await mineBlock(job), 'bad-cb-height'); } finally { network.block.bip34height = bip34height; } @@ -513,7 +541,7 @@ describe('Chain', function() { input.witness.set(0, Buffer.allocUnsafe(33)); input.witness.compile(); block.refresh(true); - assert.equal(await addBlock(block), 'bad-witness-nonce-size'); + assert.strictEqual(await addBlock(block), 'bad-witness-nonce-size'); }); it('should fail to connect bad witness nonce', async () => { @@ -523,7 +551,7 @@ describe('Chain', function() { input.witness.set(0, encoding.ONE_HASH); input.witness.compile(); block.refresh(true); - assert.equal(await addBlock(block), 'bad-witness-merkle-match'); + assert.strictEqual(await addBlock(block), 'bad-witness-merkle-match'); }); it('should fail to connect bad witness commitment', async () => { @@ -542,7 +570,7 @@ describe('Chain', function() { block.refresh(true); block.merkleRoot = block.createMerkleRoot('hex'); - assert.equal(await addBlock(block, flags), 'bad-witness-merkle-match'); + assert.strictEqual(await addBlock(block, flags), 'bad-witness-merkle-match'); }); it('should fail to connect unexpected witness', async () => { @@ -558,13 +586,13 @@ describe('Chain', function() { block.refresh(true); block.merkleRoot = block.createMerkleRoot('hex'); - assert.equal(await addBlock(block, flags), 'unexpected-witness'); + assert.strictEqual(await addBlock(block, flags), 'unexpected-witness'); }); it('should add wit addrs to miner', async () => { miner.addresses.length = 0; - miner.addAddress(wwallet.getReceive()); - assert.equal(wwallet.getReceive().getType(), 'witness'); + miner.addAddress(witWallet.getReceive()); + assert.strictEqual(witWallet.getReceive().getType(), 'witness'); }); it('should mine 2000 witness blocks', async () => { @@ -574,24 +602,24 @@ describe('Chain', function() { assert(await chain.add(block)); } - assert.equal(chain.height, 2636); + assert.strictEqual(chain.height, 2636); }); it('should mine a witness tx', async () => { - let block = await chain.db.getBlock(chain.height - 2000); - const cb = block.txs[0]; + const prev = await chain.db.getBlock(chain.height - 2000); + const cb = prev.txs[0]; const mtx = new MTX(); mtx.addTX(cb, 0); - mtx.addOutput(wwallet.getAddress(), 1000); + mtx.addOutput(witWallet.getAddress(), 1000); - wwallet.sign(mtx); + witWallet.sign(mtx); const job = await cpu.createJob(); job.addTX(mtx.toTX(), mtx.view); job.refresh(); - block = await job.mineAsync(); + const block = await job.mineAsync(); assert(await chain.add(block)); }); @@ -609,16 +637,16 @@ describe('Chain', function() { mtx.addTX(cb, 0); for (let j = 0; j < 16; j++) - mtx.addOutput(wwallet.getAddress(), 1); + mtx.addOutput(witWallet.getAddress(), 1); - wwallet.sign(mtx); + witWallet.sign(mtx); job.pushTX(mtx.toTX()); } job.refresh(); - assert.equal(await mineBlock(job), 'bad-blk-weight'); + assert.strictEqual(await mineBlock(job), 'bad-blk-weight'); }); it('should mine fail to connect too much size', async () => { @@ -634,16 +662,16 @@ describe('Chain', function() { mtx.addTX(cb, 0); for (let j = 0; j < 20; j++) - mtx.addOutput(wwallet.getAddress(), 1); + mtx.addOutput(witWallet.getAddress(), 1); - wwallet.sign(mtx); + witWallet.sign(mtx); job.pushTX(mtx.toTX()); } job.refresh(); - assert.equal(await mineBlock(job), 'bad-blk-length'); + assert.strictEqual(await mineBlock(job), 'bad-blk-length'); }); it('should mine a big block', async () => { @@ -659,23 +687,23 @@ describe('Chain', function() { mtx.addTX(cb, 0); for (let j = 0; j < 15; j++) - mtx.addOutput(wwallet.getAddress(), 1); + mtx.addOutput(witWallet.getAddress(), 1); - wwallet.sign(mtx); + witWallet.sign(mtx); job.pushTX(mtx.toTX()); } job.refresh(); - assert.equal(await mineBlock(job), 'OK'); + assert.strictEqual(await mineBlock(job), 'OK'); }); it('should fail to connect bad versions', async () => { for (let i = 0; i <= 3; i++) { const job = await cpu.createJob(); job.attempt.version = i; - assert.equal(await mineBlock(job), 'bad-version'); + assert.strictEqual(await mineBlock(job), 'bad-version'); } }); @@ -684,7 +712,7 @@ describe('Chain', function() { job.attempt.fees += 1; job.refresh(); - assert.equal(await mineBlock(job), 'bad-cb-amount'); + assert.strictEqual(await mineBlock(job), 'bad-cb-amount'); }); it('should fail to connect premature cb spend', async () => { @@ -694,14 +722,14 @@ describe('Chain', function() { const mtx = new MTX(); mtx.addTX(cb, 0); - mtx.addOutput(wwallet.getAddress(), 1); + mtx.addOutput(witWallet.getAddress(), 1); - wwallet.sign(mtx); + witWallet.sign(mtx); job.addTX(mtx.toTX(), mtx.view); job.refresh(); - assert.equal(await mineBlock(job), + assert.strictEqual(await mineBlock(job), 'bad-txns-premature-spend-of-coinbase'); }); @@ -712,14 +740,14 @@ describe('Chain', function() { const mtx = new MTX(); mtx.addTX(cb, 0); - mtx.addOutput(wwallet.getAddress(), 1e8); + mtx.addOutput(witWallet.getAddress(), 1e8); - wwallet.sign(mtx); + witWallet.sign(mtx); job.pushTX(mtx.toTX()); job.refresh(); - assert.equal(await mineBlock(job), + assert.strictEqual(await mineBlock(job), 'bad-txns-in-belowout'); }); @@ -730,33 +758,36 @@ describe('Chain', function() { const mtx = new MTX(); mtx.addTX(cb, 0); - mtx.addOutput(wwallet.getAddress(), Math.floor(consensus.MAX_MONEY / 2)); - mtx.addOutput(wwallet.getAddress(), Math.floor(consensus.MAX_MONEY / 2)); - mtx.addOutput(wwallet.getAddress(), Math.floor(consensus.MAX_MONEY / 2)); - wwallet.sign(mtx); + const value = Math.floor(consensus.MAX_MONEY / 2); + + mtx.addOutput(witWallet.getAddress(), value); + mtx.addOutput(witWallet.getAddress(), value); + mtx.addOutput(witWallet.getAddress(), value); + + witWallet.sign(mtx); job.pushTX(mtx.toTX()); job.refresh(); - assert.equal(await mineBlock(job), + assert.strictEqual(await mineBlock(job), 'bad-txns-txouttotal-toolarge'); }); it('should mine 111 multisig blocks', async () => { const flags = common.flags.DEFAULT_FLAGS & ~common.flags.VERIFY_POW; - let script = new Script(); - script.push(new BN(20)); + const redeem = new Script(); + redeem.push(new BN(20)); for (let i = 0; i < 20; i++) - script.push(encoding.ZERO_KEY); + redeem.push(encoding.ZERO_KEY); - script.push(new BN(20)); - script.push(opcodes.OP_CHECKMULTISIG); - script.compile(); + redeem.push(new BN(20)); + redeem.push(opcodes.OP_CHECKMULTISIG); + redeem.compile(); - script = Script.fromScripthash(script.hash160()); + const script = Script.fromScripthash(redeem.hash160()); for (let i = 0; i < 111; i++) { const block = await cpu.mineBlock(); @@ -779,7 +810,7 @@ describe('Chain', function() { assert(await chain.add(block, flags)); } - assert.equal(chain.height, 2749); + assert.strictEqual(chain.height, 2749); }); it('should fail to connect too many sigops', async () => { @@ -811,14 +842,14 @@ describe('Chain', function() { mtx.inputs[j - 2].script = new Script([script.toRaw()]); } - mtx.addOutput(wwallet.getAddress(), 1); + mtx.addOutput(witWallet.getAddress(), 1); job.pushTX(mtx.toTX()); } job.refresh(); - assert.equal(await mineBlock(job), 'bad-blk-sigops'); + assert.strictEqual(await mineBlock(job), 'bad-blk-sigops'); }); it('should cleanup', async () => { diff --git a/test/coins-test.js b/test/coins-test.js index 53f6ada5e..4a570b7b7 100644 --- a/test/coins-test.js +++ b/test/coins-test.js @@ -11,7 +11,7 @@ const CoinView = require('../lib/coins/coinview'); const CoinEntry = require('../lib/coins/coinentry'); const StaticWriter = require('../lib/utils/staticwriter'); const BufferReader = require('../lib/utils/reader'); -const parseTX = require('./util/common').parseTX; +const {parseTX} = require('./util/common'); const data = parseTX('data/tx1.hex'); const tx1 = data.tx; @@ -40,18 +40,18 @@ describe('Coins', function() { view.addTX(tx1, 1); const coins = view.get(hash); - assert.equal(coins.outputs.size, tx1.outputs.length); + assert.strictEqual(coins.outputs.size, tx1.outputs.length); const entry = coins.get(0); assert(entry); assert(!entry.spent); - assert.equal(entry.version, 1); - assert.equal(entry.height, 1); - assert.equal(entry.coinbase, false); - assert.equal(entry.raw, null); + assert.strictEqual(entry.version, 1); + assert.strictEqual(entry.height, 1); + assert.strictEqual(entry.coinbase, false); + assert.strictEqual(entry.raw, null); assert(entry.output instanceof Output); - assert.equal(entry.spent, false); + assert.strictEqual(entry.spent, false); const output = view.getOutputFor(input); assert(output); @@ -81,7 +81,7 @@ describe('Coins', function() { deepCoinsEqual(entry, reserialize(entry)); assert.strictEqual(coins.outputs.size, length); - assert.equal(view.undo.items.length, 1); + assert.strictEqual(view.undo.items.length, 1); }); it('should handle coin view', () => { diff --git a/test/gcs-test.js b/test/gcs-test.js index cafe5e681..c5b5c8233 100644 --- a/test/gcs-test.js +++ b/test/gcs-test.js @@ -14,71 +14,75 @@ const Address = require('../lib/primitives/address'); const raw = fs.readFileSync(`${__dirname}/data/block928927.raw`); const block = Block.fromRaw(raw); -describe('GCS', function() { - const key = random.randomBytes(16); - const P = 20; - - const contents1 = [ - Buffer.from('Alex', 'ascii'), - Buffer.from('Bob', 'ascii'), - Buffer.from('Charlie', 'ascii'), - Buffer.from('Dick', 'ascii'), - Buffer.from('Ed', 'ascii'), - Buffer.from('Frank', 'ascii'), - Buffer.from('George', 'ascii'), - Buffer.from('Harry', 'ascii'), - Buffer.from('Ilya', 'ascii'), - Buffer.from('John', 'ascii'), - Buffer.from('Kevin', 'ascii'), - Buffer.from('Larry', 'ascii'), - Buffer.from('Michael', 'ascii'), - Buffer.from('Nate', 'ascii'), - Buffer.from('Owen', 'ascii'), - Buffer.from('Paul', 'ascii'), - Buffer.from('Quentin', 'ascii') - ]; - - const contents2 = [ - Buffer.from('Alice', 'ascii'), - Buffer.from('Betty', 'ascii'), - Buffer.from('Charmaine', 'ascii'), - Buffer.from('Donna', 'ascii'), - Buffer.from('Edith', 'ascii'), - Buffer.from('Faina', 'ascii'), - Buffer.from('Georgia', 'ascii'), - Buffer.from('Hannah', 'ascii'), - Buffer.from('Ilsbeth', 'ascii'), - Buffer.from('Jennifer', 'ascii'), - Buffer.from('Kayla', 'ascii'), - Buffer.from('Lena', 'ascii'), - Buffer.from('Michelle', 'ascii'), - Buffer.from('Natalie', 'ascii'), - Buffer.from('Ophelia', 'ascii'), - Buffer.from('Peggy', 'ascii'), - Buffer.from('Queenie', 'ascii') - ]; - - const op1 = new Outpoint( - '4cba1d1753ed19dbeafffb1a6c805d20e4af00b194a8f85353163cef83319c2c', - 4); - - const op2 = new Outpoint( - 'b7c3c4bce1a23baef2da05f9b7e4bff813449ec7e80f980ec7e4cacfadcd3314', - 3); - - const op3 = new Outpoint( - '4cba1d1753ed19dbeafffb1a6c805d20e4af00b194a8f85353163cef83319c2c', - 400); - - const op4 = new Outpoint( - 'b7c3c4bce1a23baef2da05f9b7e4bff813449ec7e80f980ec7e4cacfadcd3314', - 300); - - const addr1 = new Address('bc1qmyrddmxglk49ye2wd29wefaavw7es8k5d555lx'); - const addr2 = new Address('bc1q4645ycu0l9pnvxaxnhemushv0w4cd9flkqh95j'); - - let filter1, filter2, filter3, filter4, filter5; +const key = random.randomBytes(16); +const P = 20; + +const contents1 = [ + Buffer.from('Alex', 'ascii'), + Buffer.from('Bob', 'ascii'), + Buffer.from('Charlie', 'ascii'), + Buffer.from('Dick', 'ascii'), + Buffer.from('Ed', 'ascii'), + Buffer.from('Frank', 'ascii'), + Buffer.from('George', 'ascii'), + Buffer.from('Harry', 'ascii'), + Buffer.from('Ilya', 'ascii'), + Buffer.from('John', 'ascii'), + Buffer.from('Kevin', 'ascii'), + Buffer.from('Larry', 'ascii'), + Buffer.from('Michael', 'ascii'), + Buffer.from('Nate', 'ascii'), + Buffer.from('Owen', 'ascii'), + Buffer.from('Paul', 'ascii'), + Buffer.from('Quentin', 'ascii') +]; + +const contents2 = [ + Buffer.from('Alice', 'ascii'), + Buffer.from('Betty', 'ascii'), + Buffer.from('Charmaine', 'ascii'), + Buffer.from('Donna', 'ascii'), + Buffer.from('Edith', 'ascii'), + Buffer.from('Faina', 'ascii'), + Buffer.from('Georgia', 'ascii'), + Buffer.from('Hannah', 'ascii'), + Buffer.from('Ilsbeth', 'ascii'), + Buffer.from('Jennifer', 'ascii'), + Buffer.from('Kayla', 'ascii'), + Buffer.from('Lena', 'ascii'), + Buffer.from('Michelle', 'ascii'), + Buffer.from('Natalie', 'ascii'), + Buffer.from('Ophelia', 'ascii'), + Buffer.from('Peggy', 'ascii'), + Buffer.from('Queenie', 'ascii') +]; + +const op1 = new Outpoint( + '4cba1d1753ed19dbeafffb1a6c805d20e4af00b194a8f85353163cef83319c2c', + 4); + +const op2 = new Outpoint( + 'b7c3c4bce1a23baef2da05f9b7e4bff813449ec7e80f980ec7e4cacfadcd3314', + 3); + +const op3 = new Outpoint( + '4cba1d1753ed19dbeafffb1a6c805d20e4af00b194a8f85353163cef83319c2c', + 400); + +const op4 = new Outpoint( + 'b7c3c4bce1a23baef2da05f9b7e4bff813449ec7e80f980ec7e4cacfadcd3314', + 300); + +const addr1 = new Address('bc1qmyrddmxglk49ye2wd29wefaavw7es8k5d555lx'); +const addr2 = new Address('bc1q4645ycu0l9pnvxaxnhemushv0w4cd9flkqh95j'); + +let filter1 = null; +let filter2 = null; +let filter3 = null; +let filter4 = null; +let filter5 = null; +describe('GCS', function() { it('should test GCS filter build', () => { filter1 = GCSFilter.fromItems(P, key, contents1); assert(filter1); @@ -96,20 +100,20 @@ describe('GCS', function() { }); it('should test GCS filter metadata', () => { - assert.equal(filter1.p, P); - assert.equal(filter1.n, contents1.length); - assert.equal(filter1.p, filter2.p); - assert.equal(filter1.n, filter2.n); - assert.deepEqual(filter1.data, filter2.data); - assert.equal(filter1.p, filter3.p); - assert.equal(filter1.n, filter3.n); - assert.deepEqual(filter1.data, filter3.data); - assert.equal(filter1.p, filter4.p); - assert.equal(filter1.n, filter4.n); - assert.deepEqual(filter1.data, filter4.data); - assert.equal(filter1.p, filter5.p); - assert.equal(filter1.n, filter5.n); - assert.deepEqual(filter1.data, filter5.data); + assert.strictEqual(filter1.p, P); + assert.strictEqual(filter1.n, contents1.length); + assert.strictEqual(filter1.p, filter2.p); + assert.strictEqual(filter1.n, filter2.n); + assert.deepStrictEqual(filter1.data, filter2.data); + assert.strictEqual(filter1.p, filter3.p); + assert.strictEqual(filter1.n, filter3.n); + assert.deepStrictEqual(filter1.data, filter3.data); + assert.strictEqual(filter1.p, filter4.p); + assert.strictEqual(filter1.n, filter4.n); + assert.deepStrictEqual(filter1.data, filter4.data); + assert.strictEqual(filter1.p, filter5.p); + assert.strictEqual(filter1.n, filter5.n); + assert.deepStrictEqual(filter1.data, filter5.data); }); it('should test GCS filter match', () => { diff --git a/test/hd-test.js b/test/hd-test.js index 05d4b622c..51e2ffe96 100644 --- a/test/hd-test.js +++ b/test/hd-test.js @@ -11,76 +11,77 @@ const vectors = require('./data/hd.json'); const vector1 = vectors.vector1; const vector2 = vectors.vector2; -function ub58(data) { +let master = null; +let child = null; + +function unbase58(data) { return base58.decode(data).toString('hex'); } -function equal(a, b) { - assert.equal(a, b); - assert.equal(ub58(a), ub58(b)); +function base58Equal(a, b) { + assert.strictEqual(a, b); + assert.strictEqual(unbase58(a), unbase58(b)); } describe('HD', function() { - let master, child; - it('should create a pbkdf2 seed', () => { const seed = pbkdf2.derive( vectors.phrase, 'mnemonicfoo', 2048, 64, 'sha512'); - assert.equal(seed.toString('hex'), vectors.seed); + assert.strictEqual(seed.toString('hex'), vectors.seed); }); it('should create master private key', () => { const seed = Buffer.from(vectors.seed, 'hex'); const key = HD.PrivateKey.fromSeed(seed); - assert.equal(key.toBase58(), vectors.master_priv); - assert.equal(key.toPublic().toBase58(), vectors.master_pub); + assert.strictEqual(key.toBase58(), vectors.master_priv); + assert.strictEqual(key.toPublic().toBase58(), vectors.master_pub); master = key; }); it('should derive(0) child from master', () => { const child1 = master.derive(0); - assert.equal(child1.toBase58(), vectors.child1_priv); - assert.equal(child1.toPublic().toBase58(), vectors.child1_pub); + assert.strictEqual(child1.toBase58(), vectors.child1_priv); + assert.strictEqual(child1.toPublic().toBase58(), vectors.child1_pub); }); it('should derive(1) child from master public key', () => { const child2 = master.toPublic().derive(1); - assert.equal(child2.toBase58(), vectors.child2_pub); + assert.strictEqual(child2.toBase58(), vectors.child2_pub); }); it('should derive(1) child from master', () => { const child3 = master.derive(1); - assert.equal(child3.toBase58(), vectors.child3_priv); - assert.equal(child3.toPublic().toBase58(), vectors.child3_pub); + assert.strictEqual(child3.toBase58(), vectors.child3_priv); + assert.strictEqual(child3.toPublic().toBase58(), vectors.child3_pub); }); it('should derive(2) child from master', () => { const child4 = master.derive(2); - assert.equal(child4.toBase58(), vectors.child4_priv); - assert.equal(child4.toPublic().toBase58(), vectors.child4_pub); + assert.strictEqual(child4.toBase58(), vectors.child4_priv); + assert.strictEqual(child4.toPublic().toBase58(), vectors.child4_pub); child = child4; }); it('should derive(0) child from child(2)', () => { const child5 = child.derive(0); - assert.equal(child5.toBase58(), vectors.child5_priv); - assert.equal(child5.toPublic().toBase58(), vectors.child5_pub); + assert.strictEqual(child5.toBase58(), vectors.child5_priv); + assert.strictEqual(child5.toPublic().toBase58(), vectors.child5_pub); }); it('should derive(1) child from child(2)', () => { const child6 = child.derive(1); - assert.equal(child6.toBase58(), vectors.child6_priv); - assert.equal(child6.toPublic().toBase58(), vectors.child6_pub); + assert.strictEqual(child6.toBase58(), vectors.child6_priv); + assert.strictEqual(child6.toPublic().toBase58(), vectors.child6_pub); }); it('should derive correctly when private key has leading zeros', () => { const key = HD.PrivateKey.fromBase58(vectors.zero_priv); - assert.equal(key.privateKey.toString('hex'), + assert.strictEqual(key.privateKey.toString('hex'), '00000055378cf5fafb56c711c674143f9b0ee82ab0ba2924f19b64f5ae7cdbfd'); const child = key.derivePath('m/44\'/0\'/0\'/0/0\''); - assert.equal(child.privateKey.toString('hex'), + assert.strictEqual(child.privateKey.toString('hex'), '3348069561d2a0fb925e74bf198762acc47dce7db27372257d2d959a9e6f8aeb'); }); @@ -94,16 +95,20 @@ describe('HD', function() { it('should deserialize and reserialize', () => { const key = HD.generate(); - assert.equal(HD.fromJSON(key.toJSON()).toBase58(), key.toBase58()); + assert.strictEqual(HD.fromJSON(key.toJSON()).toBase58(), key.toBase58()); }); for (const vector of [vector1, vector2]) { - let master; + let master = null; it('should create from a seed', () => { - master = HD.PrivateKey.fromSeed(Buffer.from(vector.seed, 'hex')); - equal(master.toBase58(), vector.m.prv); - equal(master.toPublic().toBase58(), vector.m.pub); + const key = HD.PrivateKey.fromSeed(Buffer.from(vector.seed, 'hex')); + const pub = key.toPublic(); + + base58Equal(key.toBase58(), vector.m.prv); + base58Equal(pub.toBase58(), vector.m.pub); + + master = key; }); for (const path of Object.keys(vector)) { @@ -114,8 +119,9 @@ describe('HD', function() { it(`should derive ${path} from master`, () => { const key = master.derivePath(path); - equal(key.toBase58(), kp.prv); - equal(key.toPublic().toBase58(), kp.pub); + const pub = key.toPublic(); + base58Equal(key.toBase58(), kp.prv); + base58Equal(pub.toBase58(), kp.pub); }); } } diff --git a/test/hkdf-test.js b/test/hkdf-test.js index f2a047668..a2493f9b2 100644 --- a/test/hkdf-test.js +++ b/test/hkdf-test.js @@ -7,69 +7,78 @@ const assert = require('assert'); const hkdf = require('../lib/crypto/hkdf'); describe('HKDF', function() { - it('should do proper hkdf', () => { + it('should do proper hkdf (1)', () => { // https://tools.ietf.org/html/rfc5869 - let alg = 'sha256'; - let ikm = '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'; - let salt = '000102030405060708090a0b0c'; - let info = 'f0f1f2f3f4f5f6f7f8f9'; - let len = 42; - - let prkE = '077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec8' - + '44ad7c2b3e5'; - let okmE = '3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1' - + 'a5a4c5db02d56ecc4c5bf34007208d5b887185865'; - - ikm = Buffer.from(ikm, 'hex'); - salt = Buffer.from(salt, 'hex'); - info = Buffer.from(info, 'hex'); - - let prk = hkdf.extract(ikm, salt, alg); - let okm = hkdf.expand(prk, info, len, alg); - - assert.equal(prk.toString('hex'), prkE); - assert.equal(okm.toString('hex'), okmE); + const alg = 'sha256'; + const ikm = Buffer.from( + '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', 'hex'); + const salt = Buffer.from('000102030405060708090a0b0c', 'hex'); + const info = Buffer.from('f0f1f2f3f4f5f6f7f8f9', 'hex'); + const len = 42; + + const prkE = Buffer.from( + '077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5', + 'hex'); + + const okmE = Buffer.from('' + + '3cb25f25faacd57a90434f64d0362f2a2d2d0a90' + + 'cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865', + 'hex'); + + const prk = hkdf.extract(ikm, salt, alg); + const okm = hkdf.expand(prk, info, len, alg); + + assert.deepStrictEqual(prk, prkE); + assert.deepStrictEqual(okm, okmE); + }); - alg = 'sha256'; + it('should do proper hkdf (2)', () => { + const alg = 'sha256'; - ikm = '000102030405060708090a0b0c0d0e0f' + const ikm = Buffer.from('' + + '000102030405060708090a0b0c0d0e0f' + '101112131415161718191a1b1c1d1e1f' + '202122232425262728292a2b2c2d2e2f' + '303132333435363738393a3b3c3d3e3f' - + '404142434445464748494a4b4c4d4e4f'; + + '404142434445464748494a4b4c4d4e4f', + 'hex'); - salt = '606162636465666768696a6b6c6d6e6f' + const salt = Buffer.from('' + + '606162636465666768696a6b6c6d6e6f' + '707172737475767778797a7b7c7d7e7f' + '808182838485868788898a8b8c8d8e8f' + '909192939495969798999a9b9c9d9e9f' - + 'a0a1a2a3a4a5a6a7a8a9aaabacadaeaf'; + + 'a0a1a2a3a4a5a6a7a8a9aaabacadaeaf', + 'hex'); - info = 'b0b1b2b3b4b5b6b7b8b9babbbcbdbebf' + const info = Buffer.from('' + + 'b0b1b2b3b4b5b6b7b8b9babbbcbdbebf' + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf' + 'd0d1d2d3d4d5d6d7d8d9dadbdcdddedf' + 'e0e1e2e3e4e5e6e7e8e9eaebecedeeef' - + 'f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'; + + 'f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff', + 'hex'); - len = 82; + const len = 82; - prkE = '06a6b88c5853361a06104c9ceb35b45c' - + 'ef760014904671014a193f40c15fc244'; + const prkE = Buffer.from('' + + '06a6b88c5853361a06104c9ceb35b45c' + + 'ef760014904671014a193f40c15fc244', + 'hex'); - okmE = 'b11e398dc80327a1c8e7f78c596a4934' + const okmE = Buffer.from('' + + 'b11e398dc80327a1c8e7f78c596a4934' + '4f012eda2d4efad8a050cc4c19afa97c' + '59045a99cac7827271cb41c65e590e09' + 'da3275600c2f09b8367793a9aca3db71' + 'cc30c58179ec3e87c14c01d5c1f3434f' - + '1d87'; - - ikm = Buffer.from(ikm, 'hex'); - salt = Buffer.from(salt, 'hex'); - info = Buffer.from(info, 'hex'); + + '1d87', + 'hex'); - prk = hkdf.extract(ikm, salt, alg); - okm = hkdf.expand(prk, info, len, alg); + const prk = hkdf.extract(ikm, salt, alg); + const okm = hkdf.expand(prk, info, len, alg); - assert.equal(prk.toString('hex'), prkE); - assert.equal(okm.toString('hex'), okmE); + assert.deepStrictEqual(prk, prkE); + assert.deepStrictEqual(okm, okmE); }); }); diff --git a/test/http-test.js b/test/http-test.js index 22fa44999..b6e794403 100644 --- a/test/http-test.js +++ b/test/http-test.js @@ -15,24 +15,25 @@ const HTTP = require('../lib/http'); const FullNode = require('../lib/node/fullnode'); const pkg = require('../lib/pkg'); -describe('HTTP', function() { - const node = new FullNode({ - network: 'regtest', - apiKey: 'foo', - walletAuth: true, - db: 'memory', - plugins: [require('../lib/wallet/plugin')] - }); +const node = new FullNode({ + network: 'regtest', + apiKey: 'foo', + walletAuth: true, + db: 'memory', + plugins: [require('../lib/wallet/plugin')] +}); - const wallet = new HTTP.Wallet({ - network: 'regtest', - apiKey: 'foo' - }); +const wallet = new HTTP.Wallet({ + network: 'regtest', + apiKey: 'foo' +}); - const wdb = node.require('walletdb'); +const wdb = node.require('walletdb'); - let addr, hash; +let addr = null; +let hash = null; +describe('HTTP', function() { this.timeout(15000); it('should open node', async () => { @@ -42,46 +43,47 @@ describe('HTTP', function() { it('should create wallet', async () => { const info = await wallet.create({ id: 'test' }); - assert.equal(info.id, 'test'); + assert.strictEqual(info.id, 'test'); }); it('should get info', async () => { const info = await wallet.client.getInfo(); - assert.equal(info.network, node.network.type); - assert.equal(info.version, pkg.version); - assert.equal(info.pool.agent, node.pool.options.agent); - assert.equal(typeof info.chain, 'object'); - assert.equal(info.chain.height, 0); + assert.strictEqual(info.network, node.network.type); + assert.strictEqual(info.version, pkg.version); + assert.strictEqual(info.pool.agent, node.pool.options.agent); + assert.strictEqual(typeof info.chain, 'object'); + assert.strictEqual(info.chain.height, 0); }); it('should get wallet info', async () => { const info = await wallet.getInfo(); - assert.equal(info.id, 'test'); + assert.strictEqual(info.id, 'test'); addr = info.account.receiveAddress; - assert.equal(typeof addr, 'string'); + assert.strictEqual(typeof addr, 'string'); addr = Address.fromString(addr); }); it('should fill with funds', async () => { - let tx, balance, receive, details; + const mtx = new MTX(); + mtx.addOutpoint(new Outpoint(encoding.NULL_HASH, 0)); + mtx.addOutput(addr, 50460); + mtx.addOutput(addr, 50460); + mtx.addOutput(addr, 50460); + mtx.addOutput(addr, 50460); - // Coinbase - tx = new MTX(); - tx.addOutpoint(new Outpoint(encoding.NULL_HASH, 0)); - tx.addOutput(addr, 50460); - tx.addOutput(addr, 50460); - tx.addOutput(addr, 50460); - tx.addOutput(addr, 50460); - tx = tx.toTX(); + const tx = mtx.toTX(); + let balance = null; wallet.once('balance', (b) => { balance = b; }); + let receive = null; wallet.once('address', (r) => { receive = r[0]; }); + let details = null; wallet.once('tx', (d) => { details = d; }); @@ -90,25 +92,23 @@ describe('HTTP', function() { await co.timeout(300); assert(receive); - assert.equal(receive.id, 'test'); - assert.equal(receive.type, 'pubkeyhash'); - assert.equal(receive.branch, 0); + assert.strictEqual(receive.id, 'test'); + assert.strictEqual(receive.type, 'pubkeyhash'); + assert.strictEqual(receive.branch, 0); assert(balance); - assert.equal(balance.confirmed, 0); - assert.equal(balance.unconfirmed, 201840); + assert.strictEqual(balance.confirmed, 0); + assert.strictEqual(balance.unconfirmed, 201840); assert(details); - assert.equal(details.hash, tx.rhash()); + assert.strictEqual(details.hash, tx.rhash()); }); it('should get balance', async () => { const balance = await wallet.getBalance(); - assert.equal(balance.confirmed, 0); - assert.equal(balance.unconfirmed, 201840); + assert.strictEqual(balance.confirmed, 0); + assert.strictEqual(balance.unconfirmed, 201840); }); it('should send a tx', async () => { - let value = 0; - const options = { rate: 10000, outputs: [{ @@ -120,12 +120,14 @@ describe('HTTP', function() { const tx = await wallet.send(options); assert(tx); - assert.equal(tx.inputs.length, 1); - assert.equal(tx.outputs.length, 2); + assert.strictEqual(tx.inputs.length, 1); + assert.strictEqual(tx.outputs.length, 2); + let value = 0; value += tx.outputs[0].value; value += tx.outputs[1].value; - assert.equal(value, 48190); + + assert.strictEqual(value, 48190); hash = tx.hash; }); @@ -133,24 +135,24 @@ describe('HTTP', function() { it('should get a tx', async () => { const tx = await wallet.getTX(hash); assert(tx); - assert.equal(tx.hash, hash); + assert.strictEqual(tx.hash, hash); }); it('should generate new api key', async () => { - const t = wallet.token.toString('hex'); + const old = wallet.token.toString('hex'); const token = await wallet.retoken(null); assert(token.length === 64); - assert.notEqual(token, t); + assert.notStrictEqual(token, old); }); it('should get balance', async () => { const balance = await wallet.getBalance(); - assert.equal(balance.unconfirmed, 199570); + assert.strictEqual(balance.unconfirmed, 199570); }); it('should execute an rpc call', async () => { const info = await wallet.client.rpc.execute('getblockchaininfo', []); - assert.equal(info.blocks, 0); + assert.strictEqual(info.blocks, 0); }); it('should execute an rpc call with bool parameter', async () => { @@ -162,10 +164,10 @@ describe('HTTP', function() { const info = await wallet.createAccount('foo1'); assert(info); assert(info.initialized); - assert.equal(info.name, 'foo1'); - assert.equal(info.accountIndex, 1); - assert.equal(info.m, 1); - assert.equal(info.n, 1); + assert.strictEqual(info.name, 'foo1'); + assert.strictEqual(info.accountIndex, 1); + assert.strictEqual(info.m, 1); + assert.strictEqual(info.n, 1); }); it('should create account', async () => { @@ -176,10 +178,10 @@ describe('HTTP', function() { }); assert(info); assert(!info.initialized); - assert.equal(info.name, 'foo2'); - assert.equal(info.accountIndex, 2); - assert.equal(info.m, 1); - assert.equal(info.n, 2); + assert.strictEqual(info.name, 'foo2'); + assert.strictEqual(info.accountIndex, 2); + assert.strictEqual(info.m, 1); + assert.strictEqual(info.n, 2); }); it('should get a block template', async () => { diff --git a/test/key-address-test.js b/test/keyring-test.js similarity index 79% rename from test/key-address-test.js rename to test/keyring-test.js index 4b56fdef9..70bccde1f 100644 --- a/test/key-address-test.js +++ b/test/keyring-test.js @@ -4,48 +4,48 @@ 'use strict'; const assert = require('assert'); -const keyring = require('../lib/primitives/keyring'); +const KeyRing = require('../lib/primitives/keyring'); -describe('Keyring Address', function() { - const ukey = keyring.fromSecret( +describe('KeyRing', function() { + const ukey = KeyRing.fromSecret( '5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss'); - const ckey = keyring.fromSecret( + const ckey = KeyRing.fromSecret( 'L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1'); it('check uncompressed public key', () => { - assert.equal( + assert.strictEqual( '04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b' + '8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235', ukey.getPublicKey('hex')); }); it('check uncompressed public key to address', () => { - assert.equal( + assert.strictEqual( '1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN', ukey.getKeyAddress('base58')); }); it('check uncompressed secret', () => { - assert.equal( + assert.strictEqual( '5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss', ukey.toSecret()); }); it('check compressed public key', () => { - assert.equal( + assert.strictEqual( '03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd', ckey.getPublicKey('hex')); }); it('check compressed public key to address', () => { - assert.equal( + assert.strictEqual( '1F3sAm6ZtwLAUnj7d38pGFxtP3RVEvtsbV', ckey.getKeyAddress('base58')); }); it('check compressed secret', () => { - assert.equal( + assert.strictEqual( 'L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1', ckey.toSecret()); }); diff --git a/test/mempool-test.js b/test/mempool-test.js index f73a77b8c..593d5bfd4 100644 --- a/test/mempool-test.js +++ b/test/mempool-test.js @@ -17,36 +17,44 @@ const Outpoint = require('../lib/primitives/outpoint'); const Script = require('../lib/script/script'); const Witness = require('../lib/script/witness'); const MemWallet = require('./util/memwallet'); +const ALL = Script.hashType.ALL; -describe('Mempool', function() { - const chain = new Chain({ db: 'memory' }); - const mempool = new Mempool({ chain: chain, db: 'memory' }); - const wallet = new MemWallet(); - let cached; +const chain = new Chain({ + db: 'memory' +}); - this.timeout(5000); +const mempool = new Mempool({ + chain, + db: 'memory' +}); + +const wallet = new MemWallet(); + +let cachedTX = null; - function dummy(prev, prevHash) { - if (!prevHash) - prevHash = encoding.ONE_HASH.toString('hex'); +function dummyInput(script, hash) { + const coin = new Coin(); + coin.height = 0; + coin.value = 0; + coin.script = script; + coin.hash = hash; + coin.index = 0; - const coin = new Coin(); - coin.height = 0; - coin.value = 0; - coin.script = prev; - coin.hash = prevHash; - coin.index = 0; + const fund = new MTX(); + fund.addCoin(coin); + fund.addOutput(script, 70000); - const fund = new MTX(); - fund.addCoin(coin); - fund.addOutput(prev, 70000); + const [tx, view] = fund.commit(); - const entry = MempoolEntry.fromTX(fund.toTX(), fund.view, 0); + const entry = MempoolEntry.fromTX(tx, view, 0); - mempool.trackEntry(entry, fund.view); + mempool.trackEntry(entry, view); - return Coin.fromTX(fund, 0, -1); - } + return Coin.fromTX(fund, 0, -1); +} + +describe('Mempool', function() { + this.timeout(5000); it('should open mempool', async () => { await mempool.open(); @@ -54,97 +62,102 @@ describe('Mempool', function() { }); it('should handle incoming orphans and TXs', async () => { - const kp = KeyRing.generate(); - const w = wallet; + const key = KeyRing.generate(); + + const t1 = new MTX(); + t1.addOutput(wallet.getAddress(), 50000); + t1.addOutput(wallet.getAddress(), 10000); + + const script = Script.fromPubkey(key.publicKey); + + t1.addCoin(dummyInput(script, encoding.ONE_HASH.toString('hex'))); - let t1 = new MTX(); - t1.addOutput(w.getAddress(), 50000); - t1.addOutput(w.getAddress(), 10000); + const sig = t1.signature(0, script, 70000, key.privateKey, ALL, 0); - const prev = Script.fromPubkey(kp.publicKey); - t1.addCoin(dummy(prev)); - const sig = t1.signature( - 0, prev, 70000, kp.privateKey, Script.hashType.ALL, 0); t1.inputs[0].script = new Script([sig]); // balance: 51000 - w.sign(t1); - t1 = t1.toTX(); + wallet.sign(t1); - let t2 = new MTX(); + const t2 = new MTX(); t2.addTX(t1, 0); // 50000 - t2.addOutput(w.getAddress(), 20000); - t2.addOutput(w.getAddress(), 20000); + t2.addOutput(wallet.getAddress(), 20000); + t2.addOutput(wallet.getAddress(), 20000); // balance: 49000 - w.sign(t2); - t2 = t2.toTX(); + wallet.sign(t2); - let t3 = new MTX(); + const t3 = new MTX(); t3.addTX(t1, 1); // 10000 t3.addTX(t2, 0); // 20000 - t3.addOutput(w.getAddress(), 23000); + t3.addOutput(wallet.getAddress(), 23000); // balance: 47000 - w.sign(t3); - t3 = t3.toTX(); + wallet.sign(t3); - let t4 = new MTX(); + const t4 = new MTX(); t4.addTX(t2, 1); // 24000 t4.addTX(t3, 0); // 23000 - t4.addOutput(w.getAddress(), 11000); - t4.addOutput(w.getAddress(), 11000); + t4.addOutput(wallet.getAddress(), 11000); + t4.addOutput(wallet.getAddress(), 11000); // balance: 22000 - w.sign(t4); - t4 = t4.toTX(); + wallet.sign(t4); - let f1 = new MTX(); + const f1 = new MTX(); f1.addTX(t4, 1); // 11000 f1.addOutput(new Address(), 9000); // balance: 11000 - w.sign(f1); - f1 = f1.toTX(); + wallet.sign(f1); - let fake = new MTX(); + const fake = new MTX(); fake.addTX(t1, 1); // 1000 (already redeemed) - fake.addOutput(w.getAddress(), 6000); // 6000 instead of 500 + fake.addOutput(wallet.getAddress(), 6000); // 6000 instead of 500 // Script inputs but do not sign - w.template(fake); + wallet.template(fake); // Fake signature fake.inputs[0].script.set(0, encoding.ZERO_SIG); fake.inputs[0].script.compile(); - fake = fake.toTX(); // balance: 11000 - await mempool.addTX(fake); - await mempool.addTX(t4); + { + await mempool.addTX(fake.toTX()); + await mempool.addTX(t4.toTX()); - let balance = mempool.getBalance(); - assert.equal(balance, 70000); // note: funding balance + const balance = mempool.getBalance(); + assert.strictEqual(balance, 70000); // note: funding balance + } - await mempool.addTX(t1); + { + await mempool.addTX(t1.toTX()); - balance = mempool.getBalance(); - assert.equal(balance, 60000); + const balance = mempool.getBalance(); + assert.strictEqual(balance, 60000); + } - await mempool.addTX(t2); + { + await mempool.addTX(t2.toTX()); - balance = mempool.getBalance(); - assert.equal(balance, 50000); + const balance = mempool.getBalance(); + assert.strictEqual(balance, 50000); + } - await mempool.addTX(t3); + { + await mempool.addTX(t3.toTX()); - balance = mempool.getBalance(); - assert.equal(balance, 22000); + const balance = mempool.getBalance(); + assert.strictEqual(balance, 22000); + } - await mempool.addTX(f1); + { + await mempool.addTX(f1.toTX()); - balance = mempool.getBalance(); - assert.equal(balance, 20000); + const balance = mempool.getBalance(); + assert.strictEqual(balance, 20000); + } const txs = mempool.getHistory(); assert(txs.some((tx) => { @@ -153,54 +166,47 @@ describe('Mempool', function() { }); it('should handle locktime', async () => { - const w = wallet; - const kp = KeyRing.generate(); + const key = KeyRing.generate(); - let tx = new MTX(); - tx.addOutput(w.getAddress(), 50000); - tx.addOutput(w.getAddress(), 10000); + const tx = new MTX(); + tx.addOutput(wallet.getAddress(), 50000); + tx.addOutput(wallet.getAddress(), 10000); - const prev = Script.fromPubkey(kp.publicKey); + const prev = Script.fromPubkey(key.publicKey); const prevHash = random.randomBytes(32).toString('hex'); - tx.addCoin(dummy(prev, prevHash)); + tx.addCoin(dummyInput(prev, prevHash)); tx.setLocktime(200); chain.tip.height = 200; - const sig = tx.signature( - 0, prev, 70000, kp.privateKey, Script.hashType.ALL, 0); + const sig = tx.signature(0, prev, 70000, key.privateKey, ALL, 0); tx.inputs[0].script = new Script([sig]); - tx = tx.toTX(); - - await mempool.addTX(tx); + await mempool.addTX(tx.toTX()); chain.tip.height = 0; }); it('should handle invalid locktime', async () => { - const w = wallet; - const kp = KeyRing.generate(); + const key = KeyRing.generate(); - let tx = new MTX(); - tx.addOutput(w.getAddress(), 50000); - tx.addOutput(w.getAddress(), 10000); + const tx = new MTX(); + tx.addOutput(wallet.getAddress(), 50000); + tx.addOutput(wallet.getAddress(), 10000); - const prev = Script.fromPubkey(kp.publicKey); + const prev = Script.fromPubkey(key.publicKey); const prevHash = random.randomBytes(32).toString('hex'); - tx.addCoin(dummy(prev, prevHash)); + tx.addCoin(dummyInput(prev, prevHash)); tx.setLocktime(200); chain.tip.height = 200 - 1; - const sig = tx.signature( - 0, prev, 70000, kp.privateKey, Script.hashType.ALL, 0); + const sig = tx.signature(0, prev, 70000, key.privateKey, ALL, 0); tx.inputs[0].script = new Script([sig]); - tx = tx.toTX(); let err; try { - await mempool.addTX(tx); + await mempool.addTX(tx.toTX()); } catch (e) { err = e; } @@ -211,32 +217,29 @@ describe('Mempool', function() { }); it('should not cache a malleated wtx with mutated sig', async () => { - const w = wallet; - const kp = KeyRing.generate(); + const key = KeyRing.generate(); - kp.witness = true; + key.witness = true; - let tx = new MTX(); - tx.addOutput(w.getAddress(), 50000); - tx.addOutput(w.getAddress(), 10000); + const tx = new MTX(); + tx.addOutput(wallet.getAddress(), 50000); + tx.addOutput(wallet.getAddress(), 10000); - const prev = Script.fromProgram(0, kp.getKeyHash()); + const prev = Script.fromProgram(0, key.getKeyHash()); const prevHash = random.randomBytes(32).toString('hex'); - tx.addCoin(dummy(prev, prevHash)); + tx.addCoin(dummyInput(prev, prevHash)); - const prevs = Script.fromPubkeyhash(kp.getKeyHash()); + const prevs = Script.fromPubkeyhash(key.getKeyHash()); - const sig = tx.signature( - 0, prevs, 70000, kp.privateKey, Script.hashType.ALL, 1); + const sig = tx.signature(0, prevs, 70000, key.privateKey, ALL, 1); sig[sig.length - 1] = 0; - tx.inputs[0].witness = new Witness([sig, kp.publicKey]); - tx = tx.toTX(); + tx.inputs[0].witness = new Witness([sig, key.publicKey]); let err; try { - await mempool.addTX(tx); + await mempool.addTX(tx.toTX()); } catch (e) { err = e; } @@ -246,27 +249,24 @@ describe('Mempool', function() { }); it('should not cache a malleated tx with unnecessary witness', async () => { - const w = wallet; - const kp = KeyRing.generate(); + const key = KeyRing.generate(); - let tx = new MTX(); - tx.addOutput(w.getAddress(), 50000); - tx.addOutput(w.getAddress(), 10000); + const tx = new MTX(); + tx.addOutput(wallet.getAddress(), 50000); + tx.addOutput(wallet.getAddress(), 10000); - const prev = Script.fromPubkey(kp.publicKey); + const prev = Script.fromPubkey(key.publicKey); const prevHash = random.randomBytes(32).toString('hex'); - tx.addCoin(dummy(prev, prevHash)); + tx.addCoin(dummyInput(prev, prevHash)); - const sig = tx.signature( - 0, prev, 70000, kp.privateKey, Script.hashType.ALL, 0); + const sig = tx.signature(0, prev, 70000, key.privateKey, ALL, 0); tx.inputs[0].script = new Script([sig]); tx.inputs[0].witness.push(Buffer.alloc(0)); - tx = tx.toTX(); let err; try { - await mempool.addTX(tx); + await mempool.addTX(tx.toTX()); } catch (e) { err = e; } @@ -276,25 +276,22 @@ describe('Mempool', function() { }); it('should not cache a malleated wtx with wit removed', async () => { - const w = wallet; - const kp = KeyRing.generate(); + const key = KeyRing.generate(); - kp.witness = true; + key.witness = true; - let tx = new MTX(); - tx.addOutput(w.getAddress(), 50000); - tx.addOutput(w.getAddress(), 10000); + const tx = new MTX(); + tx.addOutput(wallet.getAddress(), 50000); + tx.addOutput(wallet.getAddress(), 10000); - const prev = Script.fromProgram(0, kp.getKeyHash()); + const prev = Script.fromProgram(0, key.getKeyHash()); const prevHash = random.randomBytes(32).toString('hex'); - tx.addCoin(dummy(prev, prevHash)); - - tx = tx.toTX(); + tx.addCoin(dummyInput(prev, prevHash)); let err; try { - await mempool.addTX(tx); + await mempool.addTX(tx.toTX()); } catch (e) { err = e; } @@ -305,23 +302,20 @@ describe('Mempool', function() { }); it('should cache non-malleated tx without sig', async () => { - const w = wallet; - const kp = KeyRing.generate(); + const key = KeyRing.generate(); - let tx = new MTX(); - tx.addOutput(w.getAddress(), 50000); - tx.addOutput(w.getAddress(), 10000); + const tx = new MTX(); + tx.addOutput(wallet.getAddress(), 50000); + tx.addOutput(wallet.getAddress(), 10000); - const prev = Script.fromPubkey(kp.publicKey); + const prev = Script.fromPubkey(key.publicKey); const prevHash = random.randomBytes(32).toString('hex'); - tx.addCoin(dummy(prev, prevHash)); - - tx = tx.toTX(); + tx.addCoin(dummyInput(prev, prevHash)); let err; try { - await mempool.addTX(tx); + await mempool.addTX(tx.toTX()); } catch (e) { err = e; } @@ -329,20 +323,20 @@ describe('Mempool', function() { assert(err); assert(!err.malleated); assert(mempool.hasReject(tx.hash())); - cached = tx; + + cachedTX = tx; }); it('should clear reject cache', async () => { - const w = wallet; - - let tx = new MTX(); + const tx = new MTX(); tx.addOutpoint(new Outpoint()); - tx.addOutput(w.getAddress(), 50000); - tx = tx.toTX(); + tx.addOutput(wallet.getAddress(), 50000); + + assert(mempool.hasReject(cachedTX.hash())); + + await mempool.addBlock({ height: 1 }, [tx.toTX()]); - assert(mempool.hasReject(cached.hash())); - await mempool.addBlock({ height: 1 }, [tx]); - assert(!mempool.hasReject(cached.hash())); + assert(!mempool.hasReject(cachedTX.hash())); }); it('should destroy mempool', async () => { diff --git a/test/mnemonic-test.js b/test/mnemonic-test.js index aae034f46..106de9828 100644 --- a/test/mnemonic-test.js +++ b/test/mnemonic-test.js @@ -30,11 +30,11 @@ describe('Mnemonic', function() { passphrase: passphrase }); - assert.equal(mnemonic.getPhrase(), phrase); - assert.equal(mnemonic.toSeed().toString('hex'), seed.toString('hex')); + assert.strictEqual(mnemonic.getPhrase(), phrase); + assert.deepStrictEqual(mnemonic.toSeed(), seed); const key = HDPrivateKey.fromMnemonic(mnemonic); - assert.equal(key.toBase58(), xpriv); + assert.strictEqual(key.toBase58(), xpriv); }); } } @@ -42,9 +42,9 @@ describe('Mnemonic', function() { it('should verify phrase', () => { const m1 = new Mnemonic(); const m2 = Mnemonic.fromPhrase(m1.getPhrase()); - assert.deepEqual(m2.getEntropy(), m1.getEntropy()); - assert.equal(m2.bits, m1.bits); - assert.equal(m2.language, m1.language); - assert.deepEqual(m2.toSeed(), m1.toSeed()); + assert.deepStrictEqual(m2.getEntropy(), m1.getEntropy()); + assert.strictEqual(m2.bits, m1.bits); + assert.strictEqual(m2.language, m1.language); + assert.deepStrictEqual(m2.toSeed(), m1.toSeed()); }); }); diff --git a/test/node-test.js b/test/node-test.js index 6dbe5759c..4907576bf 100644 --- a/test/node-test.js +++ b/test/node-test.js @@ -14,46 +14,76 @@ const MTX = require('../lib/primitives/mtx'); const TX = require('../lib/primitives/tx'); const Address = require('../lib/primitives/address'); -describe('Node', function() { - const node = new FullNode({ - db: 'memory', - apiKey: 'foo', - network: 'regtest', - workers: true, - plugins: [require('../lib/wallet/plugin')] - }); +const node = new FullNode({ + db: 'memory', + apiKey: 'foo', + network: 'regtest', + workers: true, + plugins: [require('../lib/wallet/plugin')] +}); - const chain = node.chain; - const miner = node.miner; - const wdb = node.require('walletdb'); +const chain = node.chain; +const miner = node.miner; +const wdb = node.require('walletdb'); - let wallet, tip1, tip2, cb1, cb2; - let tx1, tx2; +let wallet = null; +let tip1 = null; +let tip2 = null; +let cb1 = null; +let cb2 = null; +let tx1 = null; +let tx2 = null; - this.timeout(5000); +async function mineBlock(tip, tx) { + const job = await miner.createJob(tip); - async function mineBlock(tip, tx) { - const job = await miner.createJob(tip); + if (!tx) + return await job.mineAsync(); - if (!tx) - return await job.mineAsync(); + const spend = new MTX(); - const rtx = new MTX(); + spend.addTX(tx, 0); - rtx.addTX(tx, 0); + spend.addOutput(wallet.getReceive(), 25 * 1e8); + spend.addOutput(wallet.getChange(), 5 * 1e8); - rtx.addOutput(wallet.getReceive(), 25 * 1e8); - rtx.addOutput(wallet.getChange(), 5 * 1e8); + spend.setLocktime(chain.height); - rtx.setLocktime(chain.height); + await wallet.sign(spend); - await wallet.sign(rtx); + job.addTX(spend.toTX(), spend.view); + job.refresh(); - job.addTX(rtx.toTX(), rtx.view); - job.refresh(); + return await job.mineAsync(); +} - return await job.mineAsync(); - } +async function mineCSV(fund) { + const job = await miner.createJob(); + const spend = new MTX(); + + spend.addOutput({ + script: [ + Script.array(new BN(1)), + Script.opcodes.OP_CHECKSEQUENCEVERIFY + ], + value: 10 * 1e8 + }); + + spend.addTX(fund, 0); + spend.setLocktime(chain.height); + + await wallet.sign(spend); + + const [tx, view] = spend.commit(); + + job.addTX(tx, view); + job.refresh(); + + return await job.mineAsync(); +} + +describe('Node', function() { + this.timeout(5000); it('should open chain and miner', async () => { miner.mempool = null; @@ -100,22 +130,22 @@ describe('Node', function() { }); it('should have correct chain value', () => { - assert.equal(chain.db.state.value, 55000000000); - assert.equal(chain.db.state.coin, 20); - assert.equal(chain.db.state.tx, 21); + assert.strictEqual(chain.db.state.value, 55000000000); + assert.strictEqual(chain.db.state.coin, 20); + assert.strictEqual(chain.db.state.tx, 21); }); it('should have correct balance', async () => { await co.timeout(100); const balance = await wallet.getBalance(); - assert.equal(balance.unconfirmed, 550 * 1e8); - assert.equal(balance.confirmed, 550 * 1e8); + assert.strictEqual(balance.unconfirmed, 550 * 1e8); + assert.strictEqual(balance.confirmed, 550 * 1e8); }); it('should handle a reorg', async () => { - assert.equal(wdb.state.height, chain.height); - assert.equal(chain.height, 11); + assert.strictEqual(wdb.state.height, chain.height); + assert.strictEqual(chain.height, 11); const entry = await chain.db.getEntry(tip2.hash); assert(entry); @@ -137,17 +167,17 @@ describe('Node', function() { }); it('should have correct chain value', () => { - assert.equal(chain.db.state.value, 60000000000); - assert.equal(chain.db.state.coin, 21); - assert.equal(chain.db.state.tx, 22); + assert.strictEqual(chain.db.state.value, 60000000000); + assert.strictEqual(chain.db.state.coin, 21); + assert.strictEqual(chain.db.state.tx, 22); }); it('should have correct balance', async () => { await co.timeout(100); const balance = await wallet.getBalance(); - assert.equal(balance.unconfirmed, 1100 * 1e8); - assert.equal(balance.confirmed, 600 * 1e8); + assert.strictEqual(balance.unconfirmed, 1100 * 1e8); + assert.strictEqual(balance.confirmed, 600 * 1e8); }); it('should check main chain', async () => { @@ -171,8 +201,8 @@ describe('Node', function() { it('should prevent double spend on new chain', async () => { const block = await mineBlock(null, cb2); const tip = chain.tip; - let err; + let err; try { await chain.add(block); } catch (e) { @@ -180,15 +210,15 @@ describe('Node', function() { } assert(err); - assert.equal(err.reason, 'bad-txns-inputs-missingorspent'); + assert.strictEqual(err.reason, 'bad-txns-inputs-missingorspent'); assert(chain.tip === tip); }); it('should fail to mine block with coins on an alternate chain', async () => { const block = await mineBlock(null, cb1); const tip = chain.tip; - let err; + let err; try { await chain.add(block); } catch (e) { @@ -196,59 +226,63 @@ describe('Node', function() { } assert(err); - assert.equal(err.reason, 'bad-txns-inputs-missingorspent'); + assert.strictEqual(err.reason, 'bad-txns-inputs-missingorspent'); assert(chain.tip === tip); }); it('should have correct chain value', () => { - assert.equal(chain.db.state.value, 65000000000); - assert.equal(chain.db.state.coin, 23); - assert.equal(chain.db.state.tx, 24); + assert.strictEqual(chain.db.state.value, 65000000000); + assert.strictEqual(chain.db.state.coin, 23); + assert.strictEqual(chain.db.state.tx, 24); }); it('should get coin', async () => { - let block = await mineBlock(); - await chain.add(block); + const block1 = await mineBlock(); + await chain.add(block1); - block = await mineBlock(null, block.txs[0]); - await chain.add(block); + const block2 = await mineBlock(null, block1.txs[0]); + await chain.add(block2); - const tx = block.txs[1]; + const tx = block2.txs[1]; const output = Coin.fromTX(tx, 1, chain.height); const coin = await chain.db.getCoin(tx.hash('hex'), 1); - assert.deepEqual(coin.toRaw(), output.toRaw()); + assert.deepStrictEqual(coin.toRaw(), output.toRaw()); }); it('should get balance', async () => { await co.timeout(100); const balance = await wallet.getBalance(); - assert.equal(balance.unconfirmed, 1250 * 1e8); - assert.equal(balance.confirmed, 750 * 1e8); + assert.strictEqual(balance.unconfirmed, 1250 * 1e8); + assert.strictEqual(balance.confirmed, 750 * 1e8); assert(wallet.account.receiveDepth >= 7); assert(wallet.account.changeDepth >= 6); - assert.equal(wdb.state.height, chain.height); + assert.strictEqual(wdb.state.height, chain.height); const txs = await wallet.getHistory(); - assert.equal(txs.length, 45); + assert.strictEqual(txs.length, 45); }); it('should get tips and remove chains', async () => { - let tips = await chain.db.getTips(); + { + const tips = await chain.db.getTips(); - assert.notEqual(tips.indexOf(chain.tip.hash), -1); - assert.equal(tips.length, 2); + assert.notStrictEqual(tips.indexOf(chain.tip.hash), -1); + assert.strictEqual(tips.length, 2); + } await chain.db.removeChains(); - tips = await chain.db.getTips(); + { + const tips = await chain.db.getTips(); - assert.notEqual(tips.indexOf(chain.tip.hash), -1); - assert.equal(tips.length, 1); + assert.notStrictEqual(tips.indexOf(chain.tip.hash), -1); + assert.strictEqual(tips.length, 1); + } }); it('should rescan for transactions', async () => { @@ -258,7 +292,7 @@ describe('Node', function() { total += txs.length; }); - assert.equal(total, 26); + assert.strictEqual(total, 26); }); it('should activate csv', async () => { @@ -297,46 +331,22 @@ describe('Node', function() { assert(chain.state.hasCSV()); const cache = await chain.db.getStateCache(); - assert.deepEqual(cache, chain.db.stateCache); - assert.equal(chain.db.stateCache.updates.length, 0); + assert.deepStrictEqual(cache, chain.db.stateCache); + assert.strictEqual(chain.db.stateCache.updates.length, 0); assert(await chain.db.verifyDeployments()); }); - async function mineCSV(tx) { - const job = await miner.createJob(); - const redeemer = new MTX(); - - redeemer.addOutput({ - script: [ - Script.array(new BN(1)), - Script.opcodes.OP_CHECKSEQUENCEVERIFY - ], - value: 10 * 1e8 - }); - - redeemer.addTX(tx, 0); - - redeemer.setLocktime(chain.height); - - await wallet.sign(redeemer); - - job.addTX(redeemer.toTX(), redeemer.view); - job.refresh(); - - return await job.mineAsync(); - } - it('should test csv', async () => { const tx = (await chain.db.getBlock(chain.height)).txs[0]; - let block = await mineCSV(tx); + const csvBlock = await mineCSV(tx); - await chain.add(block); + await chain.add(csvBlock); - const csv = block.txs[1]; + const csv = csvBlock.txs[1]; - const redeemer = new MTX(); + const spend = new MTX(); - redeemer.addOutput({ + spend.addOutput({ script: [ Script.array(new BN(2)), Script.opcodes.OP_CHECKSEQUENCEVERIFY @@ -344,24 +354,24 @@ describe('Node', function() { value: 10 * 1e8 }); - redeemer.addTX(csv, 0); - redeemer.setSequence(0, 1, false); + spend.addTX(csv, 0); + spend.setSequence(0, 1, false); const job = await miner.createJob(); - job.addTX(redeemer.toTX(), redeemer.view); + job.addTX(spend.toTX(), spend.view); job.refresh(); - block = await job.mineAsync(); + const block = await job.mineAsync(); await chain.add(block); }); it('should fail csv with bad sequence', async () => { const csv = (await chain.db.getBlock(chain.height)).txs[1]; - const redeemer = new MTX(); + const spend = new MTX(); - redeemer.addOutput({ + spend.addOutput({ script: [ Script.array(new BN(1)), Script.opcodes.OP_CHECKSEQUENCEVERIFY @@ -369,12 +379,12 @@ describe('Node', function() { value: 10 * 1e8 }); - redeemer.addTX(csv, 0); - redeemer.setSequence(0, 1, false); + spend.addTX(csv, 0); + spend.setSequence(0, 1, false); const job = await miner.createJob(); - job.addTX(redeemer.toTX(), redeemer.view); + job.addTX(spend.toTX(), spend.view); job.refresh(); const block = await job.mineAsync(); @@ -398,15 +408,15 @@ describe('Node', function() { it('should fail csv lock checks', async () => { const tx = (await chain.db.getBlock(chain.height)).txs[0]; - let block = await mineCSV(tx); + const csvBlock = await mineCSV(tx); - await chain.add(block); + await chain.add(csvBlock); - const csv = block.txs[1]; + const csv = csvBlock.txs[1]; - const redeemer = new MTX(); + const spend = new MTX(); - redeemer.addOutput({ + spend.addOutput({ script: [ Script.array(new BN(2)), Script.opcodes.OP_CHECKSEQUENCEVERIFY @@ -414,15 +424,15 @@ describe('Node', function() { value: 10 * 1e8 }); - redeemer.addTX(csv, 0); - redeemer.setSequence(0, 2, false); + spend.addTX(csv, 0); + spend.setSequence(0, 2, false); const job = await miner.createJob(); - job.addTX(redeemer.toTX(), redeemer.view); + job.addTX(spend.toTX(), spend.view); job.refresh(); - block = await job.mineAsync(); + const block = await job.mineAsync(); let err; try { @@ -432,12 +442,12 @@ describe('Node', function() { } assert(err); - assert.equal(err.reason, 'bad-txns-nonfinal'); + assert.strictEqual(err.reason, 'bad-txns-nonfinal'); }); it('should rescan for transactions', async () => { await wdb.rescan(0); - assert.equal(wallet.txdb.state.confirmed, 1289250000000); + assert.strictEqual(wallet.txdb.state.confirmed, 1289250000000); }); it('should reset miner mempool', async () => { @@ -449,7 +459,7 @@ describe('Node', function() { method: 'getblocktemplate' }, {}); assert(json.error); - assert.equal(json.error.code, -8); + assert.strictEqual(json.error.code, -8); }); it('should get a block template', async () => { @@ -534,7 +544,7 @@ describe('Node', function() { assert(!json.error); assert(json.result === null); - assert.equal(node.chain.tip.hash, block.hash('hex')); + assert.strictEqual(node.chain.tip.hash, block.hash('hex')); }); it('should validate an address', async () => { @@ -569,7 +579,6 @@ describe('Node', function() { assert(mtx.isSigned()); - tx1 = mtx; const tx = mtx.toTX(); await wallet.db.addTX(tx); @@ -577,7 +586,9 @@ describe('Node', function() { const missing = await node.mempool.addTX(tx); assert(!missing || missing.length === 0); - assert.equal(node.mempool.map.size, 1); + assert.strictEqual(node.mempool.map.size, 1); + + tx1 = mtx; }); it('should add lesser transaction to mempool', async () => { @@ -593,7 +604,6 @@ describe('Node', function() { assert(mtx.isSigned()); - tx2 = mtx; const tx = mtx.toTX(); await wallet.db.addTX(tx); @@ -601,7 +611,9 @@ describe('Node', function() { const missing = await node.mempool.addTX(tx); assert(!missing || missing.length === 0); - assert.equal(node.mempool.map.size, 2); + assert.strictEqual(node.mempool.map.size, 2); + + tx2 = mtx; }); it('should get a block template', async () => { @@ -628,12 +640,12 @@ describe('Node', function() { weight += item.weight; } - assert.equal(result.transactions.length, 2); - assert.equal(fees, tx1.getFee() + tx2.getFee()); - assert.equal(weight, tx1.getWeight() + tx2.getWeight()); - assert.equal(result.transactions[0].hash, tx1.txid()); - assert.equal(result.transactions[1].hash, tx2.txid()); - assert.equal(result.coinbasevalue, 125e7 + fees); + assert.strictEqual(result.transactions.length, 2); + assert.strictEqual(fees, tx1.getFee() + tx2.getFee()); + assert.strictEqual(weight, tx1.getWeight() + tx2.getWeight()); + assert.strictEqual(result.transactions[0].hash, tx1.txid()); + assert.strictEqual(result.transactions[1].hash, tx2.txid()); + assert.strictEqual(result.coinbasevalue, 125e7 + fees); }); it('should get raw transaction', async () => { @@ -645,7 +657,7 @@ describe('Node', function() { assert(!json.error); const tx = TX.fromRaw(json.result, 'hex'); - assert.equal(tx.txid(), tx2.txid()); + assert.strictEqual(tx.txid(), tx2.txid()); }); it('should prioritise transaction', async () => { @@ -683,12 +695,12 @@ describe('Node', function() { weight += item.weight; } - assert.equal(result.transactions.length, 2); - assert.equal(fees, tx1.getFee() + tx2.getFee()); - assert.equal(weight, tx1.getWeight() + tx2.getWeight()); - assert.equal(result.transactions[0].hash, tx2.txid()); - assert.equal(result.transactions[1].hash, tx1.txid()); - assert.equal(result.coinbasevalue, 125e7 + fees); + assert.strictEqual(result.transactions.length, 2); + assert.strictEqual(fees, tx1.getFee() + tx2.getFee()); + assert.strictEqual(weight, tx1.getWeight() + tx2.getWeight()); + assert.strictEqual(result.transactions[0].hash, tx2.txid()); + assert.strictEqual(result.transactions[1].hash, tx1.txid()); + assert.strictEqual(result.coinbasevalue, 125e7 + fees); }); it('should cleanup', async () => { diff --git a/test/protocol-test.js b/test/protocol-test.js index 399b1dbc5..2231bea78 100644 --- a/test/protocol-test.js +++ b/test/protocol-test.js @@ -32,7 +32,7 @@ describe('Protocol', function() { it(`should encode/decode ${command}`, (cb) => { const ver = Buffer.from(framer.packet(command, payload.toRaw())); parser.once('packet', (packet) => { - assert.equal(packet.cmd, command); + assert.strictEqual(packet.cmd, command); test(packet); cb(); }); @@ -53,10 +53,10 @@ describe('Protocol', function() { }); packetTest('version', v1, (payload) => { - assert.equal(payload.version, 300); - assert.equal(payload.agent, agent); - assert.equal(payload.height, 0); - assert.equal(payload.noRelay, false); + assert.strictEqual(payload.version, 300); + assert.strictEqual(payload.agent, agent); + assert.strictEqual(payload.height, 0); + assert.strictEqual(payload.noRelay, false); }); const v2 = packets.VersionPacket.fromOptions({ @@ -72,10 +72,10 @@ describe('Protocol', function() { }); packetTest('version', v2, (payload) => { - assert.equal(payload.version, 300); - assert.equal(payload.agent, agent); - assert.equal(payload.height, 10); - assert.equal(payload.noRelay, true); + assert.strictEqual(payload.version, 300); + assert.strictEqual(payload.agent, agent); + assert.strictEqual(payload.height, 10); + assert.strictEqual(payload.noRelay, true); }); packetTest('verack', new packets.VerackPacket(), (payload) => { @@ -97,18 +97,18 @@ describe('Protocol', function() { ]; packetTest('addr', new packets.AddrPacket(hosts), (payload) => { - assert.equal(typeof payload.items.length, 'number'); - assert.equal(payload.items.length, 2); - - assert.equal(typeof payload.items[0].time, 'number'); - assert.equal(payload.items[0].services, 1); - assert.equal(payload.items[0].host, hosts[0].host); - assert.equal(payload.items[0].port, hosts[0].port); - - assert.equal(typeof payload.items[1].time, 'number'); - assert.equal(payload.items[1].services, 1); - assert.equal(payload.items[1].host, hosts[1].host); - assert.equal(payload.items[1].port, hosts[1].port); + assert.strictEqual(typeof payload.items.length, 'number'); + assert.strictEqual(payload.items.length, 2); + + assert.strictEqual(typeof payload.items[0].time, 'number'); + assert.strictEqual(payload.items[0].services, 1); + assert.strictEqual(payload.items[0].host, hosts[0].host); + assert.strictEqual(payload.items[0].port, hosts[0].port); + + assert.strictEqual(typeof payload.items[1].time, 'number'); + assert.strictEqual(payload.items[1].services, 1); + assert.strictEqual(payload.items[1].host, hosts[1].host); + assert.strictEqual(payload.items[1].port, hosts[1].port); }); it('should include the raw data of only one transaction', () => { @@ -117,6 +117,6 @@ describe('Protocol', function() { const tx = TX.fromRaw(raw); tx.refresh(); - assert.deepEqual(tx.toRaw(), tx8.tx.toRaw()); + assert.deepStrictEqual(tx.toRaw(), tx8.tx.toRaw()); }); }); diff --git a/test/schnorr-test.js b/test/schnorr-test.js index 1de62a5ba..c748f840c 100644 --- a/test/schnorr-test.js +++ b/test/schnorr-test.js @@ -15,6 +15,6 @@ describe('Schnorr', function() { const msg = digest.hash256(Buffer.from('foo', 'ascii')); const sig = schnorr.sign(msg, key); assert(schnorr.verify(msg, sig, pub)); - assert.deepEqual(schnorr.recover(sig, msg), pub); + assert.deepStrictEqual(schnorr.recover(sig, msg), pub); }); }); diff --git a/test/script-test.js b/test/script-test.js index cabac13cf..8936fd71c 100644 --- a/test/script-test.js +++ b/test/script-test.js @@ -13,7 +13,7 @@ const opcodes = Script.opcodes; const scripts = require('./data/script-tests.json'); -function success(res, stack) { +function isSuccess(res, stack) { if (!res) return false; @@ -27,7 +27,7 @@ function success(res, stack) { } function parseScriptTest(data) { - const witHex = Array.isArray(data[0]) ? data.shift() : []; + const witArr = Array.isArray(data[0]) ? data.shift() : []; const inpHex = data[0] ? data[0].trim() : data[0] || ''; const outHex = data[1] ? data[1].trim() : data[1] || ''; const names = data[2] ? data[2].trim().split(/,\s*/) : []; @@ -40,10 +40,10 @@ function parseScriptTest(data) { comments += ` (${expected})`; let amount = 0; - if (witHex.length !== 0) - amount = witHex.pop() * 1e8; + if (witArr.length !== 0) + amount = witArr.pop() * 1e8; - const witness = Witness.fromString(witHex); + const witness = Witness.fromString(witArr); const input = Script.fromString(inpHex); const output = Script.fromString(outHex); @@ -67,29 +67,31 @@ function parseScriptTest(data) { describe('Script', function() { it('should encode/decode script', () => { - const src = '20' + const src = Buffer.from('' + + '20' + '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f' + '20' + '101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f' - + 'ac'; + + 'ac', + 'hex'); - const decoded = Script.fromRaw(src, 'hex'); - assert.equal(decoded.code.length, 3); - assert.equal(decoded.code[0].data.toString('hex'), + const decoded = Script.fromRaw(src); + assert.strictEqual(decoded.code.length, 3); + assert.strictEqual(decoded.code[0].data.toString('hex'), '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'); - assert.equal(decoded.code[1].data.toString('hex'), + assert.strictEqual(decoded.code[1].data.toString('hex'), '101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f'); - assert.equal(decoded.code[2].value, opcodes.OP_CHECKSIG); + assert.strictEqual(decoded.code[2].value, opcodes.OP_CHECKSIG); const dst = decoded.toRaw(); - assert.equal(dst.toString('hex'), src); + assert.deepStrictEqual(dst, src); }); it('should encode/decode numbers', () => { const script = [0, 0x51, 0x52, 0x60]; const encoded = Script.fromArray(script).raw; const decoded = Script(encoded).toArray(); - assert.deepEqual(decoded, script); + assert.deepStrictEqual(decoded, script); }); it('should recognize a P2SH output', () => { @@ -226,7 +228,7 @@ describe('Script', function() { const stack = new Stack(); assert(input.execute(stack)); - assert(success(output.execute(stack), stack)); + assert(isSuccess(output.execute(stack), stack)); }); it('should handle CScriptNums correctly', () => { @@ -245,7 +247,7 @@ describe('Script', function() { const stack = new Stack(); assert(input.execute(stack)); - assert(success(output.execute(stack), stack)); + assert(isSuccess(output.execute(stack), stack)); }); it('should handle OP_ROLL correctly', () => { @@ -268,7 +270,7 @@ describe('Script', function() { const stack = new Stack(); assert(input.execute(stack)); - assert(success(output.execute(stack), stack)); + assert(isSuccess(output.execute(stack), stack)); }); for (const data of scripts) { @@ -337,7 +339,7 @@ describe('Script', function() { if (expected !== 'OK') { assert(!res); assert(err); - assert.equal(err.code, expected); + assert.strictEqual(err.code, expected); return; } diff --git a/test/scrypt-test.js b/test/scrypt-test.js index 88999dbaf..ab5c92104 100644 --- a/test/scrypt-test.js +++ b/test/scrypt-test.js @@ -13,7 +13,7 @@ describe('Scrypt', function() { const pass = Buffer.from(''); const salt = Buffer.from(''); const result = scrypt.derive(pass, salt, 16, 1, 1, 64); - assert.equal(result.toString('hex'), '' + assert.strictEqual(result.toString('hex'), '' + '77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3f' + 'ede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628' + 'cf35e20c38d18906'); @@ -23,7 +23,7 @@ describe('Scrypt', function() { const pass = Buffer.from('password'); const salt = Buffer.from('NaCl'); const result = scrypt.derive(pass, salt, 1024, 8, 16, 64); - assert.equal(result.toString('hex'), '' + assert.strictEqual(result.toString('hex'), '' + 'fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e773' + '76634b3731622eaf30d92e22a3886ff109279d9830dac727afb9' + '4a83ee6d8360cbdfa2cc0640'); @@ -33,7 +33,7 @@ describe('Scrypt', function() { const pass = Buffer.from('pleaseletmein'); const salt = Buffer.from('SodiumChloride'); const result = scrypt.derive(pass, salt, 16384, 8, 1, 64); - assert.equal(result.toString('hex'), '' + assert.strictEqual(result.toString('hex'), '' + '7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b54' + '3f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d' + '651e40dfcf017b45575887'); @@ -44,7 +44,7 @@ describe('Scrypt', function() { // let pass = Buffer.from('pleaseletmein'); // let salt = Buffer.from('SodiumChloride'); // let result = scrypt.derive(pass, salt, 1048576, 8, 1, 64); - // assert.equal(result.toString('hex'), '' + // assert.strictEqual(result.toString('hex'), '' // + '2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5' // + 'ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049' // + 'e8a952fbcbf45c6fa77a41a4'); @@ -54,7 +54,7 @@ describe('Scrypt', function() { const pass = Buffer.from(''); const salt = Buffer.from(''); const result = await scrypt.deriveAsync(pass, salt, 16, 1, 1, 64); - assert.equal(result.toString('hex'), '' + assert.strictEqual(result.toString('hex'), '' + '77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3f' + 'ede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628' + 'cf35e20c38d18906'); @@ -64,7 +64,7 @@ describe('Scrypt', function() { const pass = Buffer.from('password'); const salt = Buffer.from('NaCl'); const result = await scrypt.deriveAsync(pass, salt, 1024, 8, 16, 64); - assert.equal(result.toString('hex'), '' + assert.strictEqual(result.toString('hex'), '' + 'fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e773' + '76634b3731622eaf30d92e22a3886ff109279d9830dac727afb9' + '4a83ee6d8360cbdfa2cc0640'); @@ -74,7 +74,7 @@ describe('Scrypt', function() { const pass = Buffer.from('pleaseletmein'); const salt = Buffer.from('SodiumChloride'); const result = await scrypt.deriveAsync(pass, salt, 16384, 8, 1, 64); - assert.equal(result.toString('hex'), '' + assert.strictEqual(result.toString('hex'), '' + '7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b54' + '3f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d' + '651e40dfcf017b45575887'); @@ -85,7 +85,7 @@ describe('Scrypt', function() { // let pass = Buffer.from('pleaseletmein'); // let salt = Buffer.from('SodiumChloride'); // let result = await scrypt.deriveAsync(pass, salt, 1048576, 8, 1, 64); - // assert.equal(result.toString('hex'), '' + // assert.strictEqual(result.toString('hex'), '' // + '2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5' // + 'ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049' // + 'e8a952fbcbf45c6fa77a41a4'); diff --git a/test/siphash-test.js b/test/siphash-test.js index a0b23a6ea..343626e4d 100644 --- a/test/siphash-test.js +++ b/test/siphash-test.js @@ -11,13 +11,13 @@ describe('SipHash', function() { it('should perform siphash with no data', () => { const data = Buffer.alloc(0); const key = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex'); - assert.deepEqual(siphash256(data, key), [1919933255, -586281423]); + assert.deepStrictEqual(siphash256(data, key), [1919933255, -586281423]); }); it('should perform siphash with data', () => { const data = Buffer.from('0001020304050607', 'hex'); const key = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex'); - assert.deepEqual(siphash256(data, key), [-1812597383, -1701632926]); + assert.deepStrictEqual(siphash256(data, key), [-1812597383, -1701632926]); }); it('should perform siphash with uint256', () => { @@ -25,6 +25,6 @@ describe('SipHash', function() { '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', 'hex'); const key = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex'); - assert.deepEqual(siphash256(data, key), [1898402095, 1928494286]); + assert.deepStrictEqual(siphash256(data, key), [1898402095, 1928494286]); }); }); diff --git a/test/tx-test.js b/test/tx-test.js index 6f1735ea7..ab0ccb3c6 100644 --- a/test/tx-test.js +++ b/test/tx-test.js @@ -37,7 +37,7 @@ const MAX_SAFE_ADDITION = 0xfffffffffffff; function clearCache(tx, noCache) { if (!noCache) { - assert.equal(tx.hash('hex'), tx.clone().hash('hex')); + assert.strictEqual(tx.hash('hex'), tx.clone().hash('hex')); return; } tx.refresh(); @@ -224,27 +224,27 @@ describe('TX', function() { const {tx} = tx5; clearCache(tx, noCache); - assert.equal(tx.inputs.length, 5); - assert.equal(tx.outputs.length, 1980); + assert.strictEqual(tx.inputs.length, 5); + assert.strictEqual(tx.outputs.length, 1980); assert(tx.hasWitness()); - assert.notEqual(tx.hash('hex'), tx.witnessHash('hex')); - assert.equal(tx.witnessHash('hex'), + assert.notStrictEqual(tx.hash('hex'), tx.witnessHash('hex')); + assert.strictEqual(tx.witnessHash('hex'), '088c919cd8408005f255c411f786928385688a9e8fdb2db4c9bc3578ce8c94cf'); - assert.equal(tx.getSize(), 62138); - assert.equal(tx.getVirtualSize(), 61813); - assert.equal(tx.getWeight(), 247250); + assert.strictEqual(tx.getSize(), 62138); + assert.strictEqual(tx.getVirtualSize(), 61813); + assert.strictEqual(tx.getWeight(), 247250); const raw1 = tx.toRaw(); clearCache(tx, true); const raw2 = tx.toRaw(); - assert.deepEqual(raw1, raw2); + assert.deepStrictEqual(raw1, raw2); const tx2 = TX.fromRaw(raw2); clearCache(tx2, noCache); - assert.equal(tx.hash('hex'), tx2.hash('hex')); - assert.equal(tx.witnessHash('hex'), tx2.witnessHash('hex')); + assert.strictEqual(tx.hash('hex'), tx2.hash('hex')); + assert.strictEqual(tx.witnessHash('hex'), tx2.witnessHash('hex')); }); it(`should verify the coolest tx ever sent ${suffix}`, () => { @@ -331,7 +331,7 @@ describe('TX', function() { it(`should get sighash of ${hash} (${hex}) ${suffix}`, () => { const subscript = script.getSubscript(0).removeSeparators(); const hash = tx.signatureHash(index, subscript, 0, type, 0); - assert.equal(hash.toString('hex'), expected); + assert.strictEqual(hash.toString('hex'), expected); }); } } @@ -628,8 +628,8 @@ describe('TX', function() { const ctx = sigopContext(input, witness, output); - assert.equal(ctx.spend.getSigopsCost(ctx.view, flags), 0); - assert.equal(ctx.fund.getSigopsCost(ctx.view, flags), + assert.strictEqual(ctx.spend.getSigopsCost(ctx.view, flags), 0); + assert.strictEqual(ctx.fund.getSigopsCost(ctx.view, flags), consensus.MAX_MULTISIG_PUBKEYS * consensus.WITNESS_SCALE_FACTOR); }); @@ -651,7 +651,7 @@ describe('TX', function() { const ctx = sigopContext(input, witness, output); - assert.equal(ctx.spend.getSigopsCost(ctx.view, flags), + assert.strictEqual(ctx.spend.getSigopsCost(ctx.view, flags), 2 * consensus.WITNESS_SCALE_FACTOR); }); @@ -670,8 +670,8 @@ describe('TX', function() { const output = Script.fromProgram(0, key.getKeyHash()); const ctx = sigopContext(input, witness, output); - assert.equal(ctx.spend.getSigopsCost(ctx.view, flags), 1); - assert.equal( + assert.strictEqual(ctx.spend.getSigopsCost(ctx.view, flags), 1); + assert.strictEqual( ctx.spend.getSigopsCost(ctx.view, flags & ~Script.flags.VERIFY_WITNESS), 0); } @@ -680,7 +680,7 @@ describe('TX', function() { const output = Script.fromProgram(1, key.getKeyHash()); const ctx = sigopContext(input, witness, output); - assert.equal(ctx.spend.getSigopsCost(ctx.view, flags), 0); + assert.strictEqual(ctx.spend.getSigopsCost(ctx.view, flags), 0); } { @@ -691,7 +691,7 @@ describe('TX', function() { ctx.spend.inputs[0].prevout.index = 0xffffffff; ctx.spend.refresh(); - assert.equal(ctx.spend.getSigopsCost(ctx.view, flags), 0); + assert.strictEqual(ctx.spend.getSigopsCost(ctx.view, flags), 0); } }); @@ -713,7 +713,7 @@ describe('TX', function() { const ctx = sigopContext(input, witness, output); - assert.equal(ctx.spend.getSigopsCost(ctx.view, flags), 1); + assert.strictEqual(ctx.spend.getSigopsCost(ctx.view, flags), 1); }); it('should count sigops for p2wsh', () => { @@ -734,8 +734,8 @@ describe('TX', function() { const ctx = sigopContext(input, witness, output); - assert.equal(ctx.spend.getSigopsCost(ctx.view, flags), 2); - assert.equal( + assert.strictEqual(ctx.spend.getSigopsCost(ctx.view, flags), 2); + assert.strictEqual( ctx.spend.getSigopsCost(ctx.view, flags & ~Script.flags.VERIFY_WITNESS), 0); }); @@ -761,6 +761,6 @@ describe('TX', function() { const ctx = sigopContext(input, witness, output); - assert.equal(ctx.spend.getSigopsCost(ctx.view, flags), 2); + assert.strictEqual(ctx.spend.getSigopsCost(ctx.view, flags), 2); }); }); diff --git a/test/util/common.js b/test/util/common.js index 6d1575849..483728679 100644 --- a/test/util/common.js +++ b/test/util/common.js @@ -1,7 +1,7 @@ 'use strict'; const assert = require('assert'); -const fs = require('fs'); +const fs = require('../../lib/utils/fs'); const TX = require('../../lib/primitives/tx'); const Output = require('../../lib/primitives/output'); const CoinView = require('../../lib/coins/coinview'); diff --git a/test/utils-test.js b/test/utils-test.js index 372e48e11..43c661994 100644 --- a/test/utils-test.js +++ b/test/utils-test.js @@ -38,13 +38,13 @@ describe('Utils', function() { const buf = Buffer.from('000000deadbeef', 'hex'); const str = base58.encode(buf); - assert.equal(str, '1116h8cQN'); - assert.deepEqual(base58.decode(str), buf); + assert.strictEqual(str, '1116h8cQN'); + assert.deepStrictEqual(base58.decode(str), buf); for (const [hex, b58] of base58Tests) { const data = Buffer.from(hex, 'hex'); - assert.equal(base58.encode(data), b58); - assert.deepEqual(base58.decode(b58), data); + assert.strictEqual(base58.encode(data), b58); + assert.deepStrictEqual(base58.decode(b58), data); } }); @@ -61,11 +61,11 @@ describe('Utils', function() { it('should convert satoshi to btc', () => { let btc = Amount.btc(5460); - assert.equal(btc, '0.0000546'); + assert.strictEqual(btc, '0.0000546'); btc = Amount.btc(54678 * 1000000); - assert.equal(btc, '546.78'); + assert.strictEqual(btc, '546.78'); btc = Amount.btc(5460 * 10000000); - assert.equal(btc, '546.0'); + assert.strictEqual(btc, '546.0'); }); it('should convert btc to satoshi', () => { @@ -122,63 +122,63 @@ describe('Utils', function() { let b = Buffer.allocUnsafe(1); b.fill(0x00); encoding.writeVarint2(b, 0, 0); - assert.equal(encoding.readVarint2(b, 0).value, 0); + assert.strictEqual(encoding.readVarint2(b, 0).value, 0); assert.deepEqual(b, [0]); b = Buffer.allocUnsafe(1); b.fill(0x00); encoding.writeVarint2(b, 1, 0); - assert.equal(encoding.readVarint2(b, 0).value, 1); + assert.strictEqual(encoding.readVarint2(b, 0).value, 1); assert.deepEqual(b, [1]); b = Buffer.allocUnsafe(1); b.fill(0x00); encoding.writeVarint2(b, 127, 0); - assert.equal(encoding.readVarint2(b, 0).value, 127); + assert.strictEqual(encoding.readVarint2(b, 0).value, 127); assert.deepEqual(b, [0x7f]); b = Buffer.allocUnsafe(2); b.fill(0x00); encoding.writeVarint2(b, 128, 0); - assert.equal(encoding.readVarint2(b, 0).value, 128); + assert.strictEqual(encoding.readVarint2(b, 0).value, 128); assert.deepEqual(b, [0x80, 0x00]); b = Buffer.allocUnsafe(2); b.fill(0x00); encoding.writeVarint2(b, 255, 0); - assert.equal(encoding.readVarint2(b, 0).value, 255); + assert.strictEqual(encoding.readVarint2(b, 0).value, 255); assert.deepEqual(b, [0x80, 0x7f]); b = Buffer.allocUnsafe(2); b.fill(0x00); encoding.writeVarint2(b, 16383, 0); - assert.equal(encoding.readVarint2(b, 0).value, 16383); + assert.strictEqual(encoding.readVarint2(b, 0).value, 16383); assert.deepEqual(b, [0xfe, 0x7f]); b = Buffer.allocUnsafe(2); b.fill(0x00); encoding.writeVarint2(b, 16384, 0); - assert.equal(encoding.readVarint2(b, 0).value, 16384); + assert.strictEqual(encoding.readVarint2(b, 0).value, 16384); assert.deepEqual(b, [0xff, 0x00]); b = Buffer.allocUnsafe(3); b.fill(0x00); encoding.writeVarint2(b, 16511, 0); - assert.equal(encoding.readVarint2(b, 0).value, 16511); + assert.strictEqual(encoding.readVarint2(b, 0).value, 16511); // assert.deepEqual(b, [0x80, 0xff, 0x7f]); assert.deepEqual(b, [0xff, 0x7f, 0x00]); b = Buffer.allocUnsafe(3); b.fill(0x00); encoding.writeVarint2(b, 65535, 0); - assert.equal(encoding.readVarint2(b, 0).value, 65535); + assert.strictEqual(encoding.readVarint2(b, 0).value, 65535); // assert.deepEqual(b, [0x82, 0xfd, 0x7f]); assert.deepEqual(b, [0x82, 0xfe, 0x7f]); b = Buffer.allocUnsafe(5); b.fill(0x00); encoding.writeVarint2(b, Math.pow(2, 32), 0); - assert.equal(encoding.readVarint2(b, 0).value, Math.pow(2, 32)); + assert.strictEqual(encoding.readVarint2(b, 0).value, Math.pow(2, 32)); assert.deepEqual(b, [0x8e, 0xfe, 0xfe, 0xff, 0x00]); }); @@ -214,11 +214,11 @@ describe('Utils', function() { const buf2 = Buffer.allocUnsafe(8); encoding.writeU64BN(buf1, num, 0); encoding.writeU64(buf2, num.toNumber(), 0); - assert.deepEqual(buf1, buf2); + assert.deepStrictEqual(buf1, buf2); const n1 = encoding.readU64BN(buf1, 0); const n2 = encoding.readU64(buf2, 0); - assert.equal(n1.toNumber(), n2); + assert.strictEqual(n1.toNumber(), n2); }); } @@ -231,11 +231,11 @@ describe('Utils', function() { const buf2 = Buffer.allocUnsafe(8); encoding.writeI64BN(buf1, num, 0); encoding.writeI64(buf2, num.toNumber(), 0); - assert.deepEqual(buf1, buf2); + assert.deepStrictEqual(buf1, buf2); const n1 = encoding.readI64BN(buf1, 0); const n2 = encoding.readI64(buf2, 0); - assert.equal(n1.toNumber(), n2); + assert.strictEqual(n1.toNumber(), n2); }); it(`should write+read a ${bits} bit ${sign} int as unsigned`, () => { @@ -243,14 +243,14 @@ describe('Utils', function() { const buf2 = Buffer.allocUnsafe(8); encoding.writeU64BN(buf1, num, 0); encoding.writeU64(buf2, num.toNumber(), 0); - assert.deepEqual(buf1, buf2); + assert.deepStrictEqual(buf1, buf2); const n1 = encoding.readU64BN(buf1, 0); if (num.isNeg()) { assert.throws(() => encoding.readU64(buf2, 0)); } else { const n2 = encoding.readU64(buf2, 0); - assert.equal(n1.toNumber(), n2); + assert.strictEqual(n1.toNumber(), n2); } }); } diff --git a/test/wallet-test.js b/test/wallet-test.js index 25f3cadc4..9440d5c0e 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -25,44 +25,205 @@ const KEY1 = 'xprv9s21ZrQH143K3Aj6xQBymM31Zb4BVc7wxqfUhMZrzewdDVCt' const KEY2 = 'xprv9s21ZrQH143K3mqiSThzPtWAabQ22Pjp3uSNnZ53A5bQ4udp' + 'faKekc2m4AChLYH1XDzANhrSdxHYWUeTWjYJwFwWFyHkTMnMeAcW4JyRCZa'; -const globalTime = util.now(); +const wdb = new WalletDB({ + db: 'memory', + verify: true +}); + +let currentWallet = null; +let importedWallet = null; +let importedKey = null; +let doubleSpendWallet = null; +let doubleSpendCoin = null; + +let globalTime = util.now(); let globalHeight = 1; -function nextBlock(height) { - if (height == null) - height = globalHeight++; +function nextBlock() { + const height = globalHeight++; + const time = globalTime++; - const hash = digest.hash256(encoding.U32(height)).toString('hex'); - const prev = digest.hash256(encoding.U32(height - 1)).toString('hex'); + const prevHead = encoding.U32(height - 1); + const prevHash = digest.hash256(prevHead); + + const head = encoding.U32(height); + const hash = digest.hash256(head); return { - hash: hash, + hash: hash.toString('hex'), height: height, - prevBlock: prev, - time: globalTime + height, + prevBlock: prevHead.toString('hex'), + time: time, merkleRoot: encoding.NULL_HASH, nonce: 0, bits: 0 }; } -function dummy(hash) { - if (!hash) - hash = random.randomBytes(32).toString('hex'); - +function dummyInput() { + const hash = random.randomBytes(32).toString('hex'); return Input.fromOutpoint(new Outpoint(hash, 0)); } -describe('Wallet', function() { - const wdb = new WalletDB({ - name: 'wallet-test', - db: 'memory', - verify: true +async function testP2PKH(witness, nesting) { + const flags = Script.flags.STANDARD_VERIFY_FLAGS; + + const wallet = await wdb.create({ + witness + }); + + const addr = Address.fromString(wallet.getAddress('string')); + + const type = witness ? Address.types.WITNESS : Address.types.PUBKEYHASH; + assert.strictEqual(addr.type, type); + + const src = new MTX(); + src.addInput(dummyInput()); + src.addOutput(nesting ? wallet.getNested() : wallet.getAddress(), 5460 * 2); + src.addOutput(new Address(), 2 * 5460); + + const mtx = new MTX(); + mtx.addTX(src, 0); + mtx.addOutput(wallet.getAddress(), 5460); + + await wallet.sign(mtx); + + const [tx, view] = mtx.commit(); + + assert(tx.verify(view, flags)); +} + +async function testP2SH(witness, nesting) { + const flags = Script.flags.STANDARD_VERIFY_FLAGS; + const receive = nesting ? 'nested' : 'receive'; + const receiveDepth = nesting ? 'nestedDepth' : 'receiveDepth'; + const vector = witness ? 'witness' : 'script'; + + // Create 3 2-of-3 wallets with our pubkeys as "shared keys" + const options = { + witness, + type: 'multisig', + m: 2, + n: 3 + }; + + const alice = await wdb.create(options); + const bob = await wdb.create(options); + const carol = await wdb.create(options); + const recipient = await wdb.create(); + + await alice.addSharedKey(bob.account.accountKey); + await alice.addSharedKey(carol.account.accountKey); + + await bob.addSharedKey(alice.account.accountKey); + await bob.addSharedKey(carol.account.accountKey); + + await carol.addSharedKey(alice.account.accountKey); + await carol.addSharedKey(bob.account.accountKey); + + // Our p2sh address + const addr1 = alice.account[receive].getAddress(); + + if (witness) { + const type = nesting ? Address.types.SCRIPTHASH : Address.types.WITNESS; + assert.strictEqual(addr1.type, type); + } else { + assert.strictEqual(addr1.type, Address.types.SCRIPTHASH); + } + + assert(alice.account[receive].getAddress().equals(addr1)); + assert(bob.account[receive].getAddress().equals(addr1)); + assert(carol.account[receive].getAddress().equals(addr1)); + + const nestedAddr1 = alice.getNested(); + + if (witness) { + assert(nestedAddr1); + assert(alice.getNested().equals(nestedAddr1)); + assert(bob.getNested().equals(nestedAddr1)); + assert(carol.getNested().equals(nestedAddr1)); + } + + { + // Add a shared unspent transaction to our wallets + const fund = new MTX(); + fund.addInput(dummyInput()); + fund.addOutput(nesting ? nestedAddr1 : addr1, 5460 * 10); + + // Simulate a confirmation + const block = nextBlock(); + + assert.strictEqual(alice.account[receiveDepth], 1); + + await wdb.addBlock(block, [fund.toTX()]); + + assert.strictEqual(alice.account[receiveDepth], 2); + assert.strictEqual(alice.account.changeDepth, 1); + } + + const addr2 = alice.account[receive].getAddress(); + assert(!addr2.equals(addr1)); + + assert(alice.account[receive].getAddress().equals(addr2)); + assert(bob.account[receive].getAddress().equals(addr2)); + assert(carol.account[receive].getAddress().equals(addr2)); + + // Create a tx requiring 2 signatures + const send = new MTX(); + + send.addOutput(recipient.getAddress(), 5460); + + assert(!send.verify(flags)); + + await alice.fund(send, { + rate: 10000, + round: true }); - let wallet, ewallet, ekey; - let doubleSpendWallet, doubleSpend; + await alice.sign(send); + + assert(!send.verify(flags)); + + await bob.sign(send); + + const [tx, view] = send.commit(); + assert(tx.verify(view, flags)); + + assert.strictEqual(alice.account.changeDepth, 1); + + const change = alice.account.change.getAddress(); + + assert(alice.account.change.getAddress().equals(change)); + assert(bob.account.change.getAddress().equals(change)); + assert(carol.account.change.getAddress().equals(change)); + + // Simulate a confirmation + { + const block = nextBlock(); + + await wdb.addBlock(block, [tx]); + + assert.strictEqual(alice.account[receiveDepth], 2); + assert.strictEqual(alice.account.changeDepth, 2); + assert(alice.account[receive].getAddress().equals(addr2)); + assert(!alice.account.change.getAddress().equals(change)); + } + + const change2 = alice.account.change.getAddress(); + + assert(alice.account.change.getAddress().equals(change2)); + assert(bob.account.change.getAddress().equals(change2)); + assert(carol.account.change.getAddress().equals(change2)); + + tx.inputs[0][vector].set(2, encoding.ZERO_SIG); + tx.inputs[0][vector].compile(); + + assert(!tx.verify(view, flags)); + assert.strictEqual(tx.getFee(view), 10000); +} + +describe('Wallet', function() { this.timeout(5000); it('should open walletdb', async () => { @@ -71,10 +232,15 @@ describe('Wallet', function() { }); it('should generate new key and address', async () => { - const w = await wdb.create(); - const addr = w.getAddress('string'); - assert(addr); - assert(Address.fromString(addr)); + const wallet = await wdb.create(); + + const addr1 = wallet.getAddress(); + assert(addr1); + + const str = addr1.toString(); + const addr2 = Address.fromString(str); + + assert(addr2.equals(addr1)); }); it('should validate existing address', () => { @@ -88,45 +254,17 @@ describe('Wallet', function() { }); it('should create and get wallet', async () => { - const w1 = await wdb.create(); - await w1.destroy(); - - const w2 = await wdb.get(w1.id); - - assert(w1 !== w2); - assert(w1.master !== w2.master); - assert.equal(w1.master.key.toBase58(), w2.master.key.toBase58()); - assert.equal( - w1.account.accountKey.toBase58(), - w2.account.accountKey.toBase58()); - }); - - async function testP2PKH(witness, bullshitNesting) { - const flags = Script.flags.STANDARD_VERIFY_FLAGS; - - const w = await wdb.create({ witness: witness }); - - const addr = Address.fromString(w.getAddress('string')); - - if (witness) - assert.equal(addr.type, Address.types.WITNESS); - else - assert.equal(addr.type, Address.types.PUBKEYHASH); + const wallet1 = await wdb.create(); - let src = new MTX(); - src.addInput(dummy()); - src.addOutput(bullshitNesting ? w.getNested() : w.getAddress(), 5460 * 2); - src.addOutput(new Address(), 2 * 5460); - src = src.toTX(); + await wallet1.destroy(); - const tx = new MTX(); - tx.addTX(src, 0); - tx.addOutput(w.getAddress(), 5460); - - await w.sign(tx); + const wallet2 = await wdb.get(wallet1.id); - assert(tx.verify(flags)); - } + assert(wallet1 !== wallet2); + assert(wallet1.master !== wallet2.master); + assert(wallet1.master.key.equals(wallet2.master.key)); + assert(wallet1.account.accountKey.equals(wallet2.account.accountKey)); + }); it('should sign/verify p2pkh tx', async () => { await testP2PKH(false, false); @@ -141,176 +279,191 @@ describe('Wallet', function() { }); it('should multisign/verify TX', async () => { - const w = await wdb.create({ + const wallet = await wdb.create({ type: 'multisig', m: 1, n: 2 }); - const k = HD.generate().deriveBIP44(0).toPublic(); + const xpriv = HD.PrivateKey.generate(); + const key = xpriv.deriveBIP44(0).toPublic(); - await w.addSharedKey(k); + await wallet.addSharedKey(key); const script = Script.fromMultisig(1, 2, [ - w.account.receive.getPublicKey(), - k.derivePath('m/0/0').publicKey + wallet.account.receive.getPublicKey(), + key.derivePath('m/0/0').publicKey ]); // Input transaction (bare 1-of-2 multisig) - let src = new MTX(); - src.addInput(dummy()); + const src = new MTX(); + src.addInput(dummyInput()); src.addOutput(script, 5460 * 2); src.addOutput(new Address(), 5460 * 2); - src = src.toTX(); const tx = new MTX(); tx.addTX(src, 0); - tx.addOutput(w.getAddress(), 5460); + tx.addOutput(wallet.getAddress(), 5460); const maxSize = await tx.estimateSize(); - await w.sign(tx); + await wallet.sign(tx); assert(tx.toRaw().length <= maxSize); assert(tx.verify()); }); it('should handle missed and invalid txs', async () => { - const w = await wdb.create(); - const f = await wdb.create(); + const alice = await wdb.create(); + const bob = await wdb.create(); // Coinbase // balance: 51000 - let t1 = new MTX(); - t1.addInput(dummy()); - t1.addOutput(w.getAddress(), 50000); - t1.addOutput(w.getAddress(), 1000); - t1 = t1.toTX(); + const t1 = new MTX(); + t1.addInput(dummyInput()); + t1.addOutput(alice.getAddress(), 50000); + t1.addOutput(alice.getAddress(), 1000); - let t2 = new MTX(); + const t2 = new MTX(); t2.addTX(t1, 0); // 50000 - t2.addOutput(w.getAddress(), 24000); - t2.addOutput(w.getAddress(), 24000); + t2.addOutput(alice.getAddress(), 24000); + t2.addOutput(alice.getAddress(), 24000); // Save for later. - doubleSpendWallet = w; - doubleSpend = Coin.fromTX(t1, 0, -1); + doubleSpendWallet = alice; + doubleSpendCoin = Coin.fromTX(t1, 0, -1); // balance: 49000 - await w.sign(t2); - t2 = t2.toTX(); - let t3 = new MTX(); + await alice.sign(t2); + + const t3 = new MTX(); t3.addTX(t1, 1); // 1000 t3.addTX(t2, 0); // 24000 - t3.addOutput(w.getAddress(), 23000); + t3.addOutput(alice.getAddress(), 23000); // balance: 47000 - await w.sign(t3); - t3 = t3.toTX(); - let t4 = new MTX(); + await alice.sign(t3); + + const t4 = new MTX(); t4.addTX(t2, 1); // 24000 t4.addTX(t3, 0); // 23000 - t4.addOutput(w.getAddress(), 11000); - t4.addOutput(w.getAddress(), 11000); + t4.addOutput(alice.getAddress(), 11000); + t4.addOutput(alice.getAddress(), 11000); // balance: 22000 - await w.sign(t4); - t4 = t4.toTX(); - let f1 = new MTX(); + await alice.sign(t4); + + const f1 = new MTX(); f1.addTX(t4, 1); // 11000 - f1.addOutput(f.getAddress(), 10000); + f1.addOutput(bob.getAddress(), 10000); // balance: 11000 - await w.sign(f1); - f1 = f1.toTX(); + await alice.sign(f1); - let fake = new MTX(); + const fake = new MTX(); fake.addTX(t1, 1); // 1000 (already redeemed) - fake.addOutput(w.getAddress(), 500); + fake.addOutput(alice.getAddress(), 500); // Script inputs but do not sign - await w.template(fake); + await alice.template(fake); // Fake signature fake.inputs[0].script.set(0, encoding.ZERO_SIG); fake.inputs[0].script.compile(); // balance: 11000 - fake = fake.toTX(); // Fake TX should temporarily change output. - await wdb.addTX(fake); + { + await wdb.addTX(fake.toTX()); + await wdb.addTX(t4.toTX()); - await wdb.addTX(t4); - - let balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 22500); + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 22500); + } - await wdb.addTX(t1); + { + await wdb.addTX(t1.toTX()); - balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 72500); + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 72500); + } - await wdb.addTX(t2); + { + await wdb.addTX(t2.toTX()); - balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 46500); + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 46500); + } - await wdb.addTX(t3); + { + await wdb.addTX(t3.toTX()); - balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 22000); + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 22000); + } - await wdb.addTX(f1); + { + await wdb.addTX(f1.toTX()); - balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 11000); + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 11000); - let txs = await w.getHistory(); - assert(txs.some((wtx) => { - return wtx.hash === f1.hash('hex'); - })); + let txs = await alice.getHistory(); + assert(txs.some((wtx) => { + return wtx.hash === f1.hash('hex'); + })); + } - balance = await f.getBalance(); - assert.equal(balance.unconfirmed, 10000); + { + const balance = await bob.getBalance(); + assert.strictEqual(balance.unconfirmed, 10000); - txs = await f.getHistory(); - assert(txs.some((wtx) => { - return wtx.tx.hash('hex') === f1.hash('hex'); - })); + const txs = await bob.getHistory(); + assert(txs.some((wtx) => { + return wtx.tx.hash('hex') === f1.hash('hex'); + })); + } }); it('should cleanup spenders after double-spend', async () => { - const w = doubleSpendWallet; + const wallet = doubleSpendWallet; - let tx = new MTX(); - tx.addCoin(doubleSpend); - tx.addOutput(w.getAddress(), 5000); + { + const txs = await wallet.getHistory(); + assert.strictEqual(txs.length, 5); - let txs = await w.getHistory(); - assert.equal(txs.length, 5); - let total = txs.reduce((t, wtx) => { - return t + wtx.tx.getOutputValue(); - }, 0); + const total = txs.reduce((t, wtx) => { + return t + wtx.tx.getOutputValue(); + }, 0); + assert.strictEqual(total, 154000); + } - assert.equal(total, 154000); + { + const balance = await wallet.getBalance(); + assert.strictEqual(balance.unconfirmed, 11000); + } - await w.sign(tx); - tx = tx.toTX(); + { + const tx = new MTX(); + tx.addCoin(doubleSpendCoin); + tx.addOutput(wallet.getAddress(), 5000); - let balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 11000); + await wallet.sign(tx); - await wdb.addTX(tx); + await wdb.addTX(tx.toTX()); - balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 6000); + const balance = await wallet.getBalance(); + assert.strictEqual(balance.unconfirmed, 6000); + } - txs = await w.getHistory(); - assert.equal(txs.length, 2); + { + const txs = await wallet.getHistory(); + assert.strictEqual(txs.length, 2); - total = txs.reduce((t, wtx) => { - return t + wtx.tx.getOutputValue(); - }, 0); - assert.equal(total, 56000); + const total = txs.reduce((t, wtx) => { + return t + wtx.tx.getOutputValue(); + }, 0); + assert.strictEqual(total, 56000); + } }); it('should handle missed txs without resolution', async () => { @@ -322,204 +475,209 @@ describe('Wallet', function() { await wdb.open(); - const w = await wdb.create(); - const f = await wdb.create(); + const alice = await wdb.create(); + const bob = await wdb.create(); // Coinbase - let t1 = new MTX(); - t1.addInput(dummy()); - t1.addOutput(w.getAddress(), 50000); - t1.addOutput(w.getAddress(), 1000); + const t1 = new MTX(); + t1.addInput(dummyInput()); + t1.addOutput(alice.getAddress(), 50000); + t1.addOutput(alice.getAddress(), 1000); // balance: 51000 - // await w.sign(t1); - t1 = t1.toTX(); - let t2 = new MTX(); + const t2 = new MTX(); t2.addTX(t1, 0); // 50000 - t2.addOutput(w.getAddress(), 24000); - t2.addOutput(w.getAddress(), 24000); + t2.addOutput(alice.getAddress(), 24000); + t2.addOutput(alice.getAddress(), 24000); // balance: 49000 - await w.sign(t2); - t2 = t2.toTX(); - let t3 = new MTX(); + await alice.sign(t2); + + const t3 = new MTX(); t3.addTX(t1, 1); // 1000 t3.addTX(t2, 0); // 24000 - t3.addOutput(w.getAddress(), 23000); + t3.addOutput(alice.getAddress(), 23000); // balance: 47000 - await w.sign(t3); - t3 = t3.toTX(); - let t4 = new MTX(); + await alice.sign(t3); + + const t4 = new MTX(); t4.addTX(t2, 1); // 24000 t4.addTX(t3, 0); // 23000 - t4.addOutput(w.getAddress(), 11000); - t4.addOutput(w.getAddress(), 11000); + t4.addOutput(alice.getAddress(), 11000); + t4.addOutput(alice.getAddress(), 11000); // balance: 22000 - await w.sign(t4); - t4 = t4.toTX(); - let f1 = new MTX(); - f1.addTX(t4, 1); // 11000 - f1.addOutput(f.getAddress(), 10000); - - // balance: 11000 - await w.sign(f1); - f1 = f1.toTX(); + await alice.sign(t4); - // fake = new MTX(); - // fake.addTX(t1, 1); // 1000 (already redeemed) - // fake.addOutput(w.getAddress(), 500); + const f1 = new MTX(); + f1.addTX(t4, 1); // 11000 + f1.addOutput(bob.getAddress(), 10000); - // Script inputs but do not sign - // await w.template(fake); - // Fake signature - // fake.inputs[0].script.set(0, encoding.ZERO_SIG); - // fake.inputs[0].script.compile(); // balance: 11000 - // fake = fake.toTX(); - - // Fake TX should temporarly change output - // await wdb.addTX(fake); - - await wdb.addTX(t4); - - let balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 22000); - - await wdb.addTX(t1); - - balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 73000); - - await wdb.addTX(t2); + await alice.sign(f1); - balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 47000); - - await wdb.addTX(t3); - - balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 22000); + { + await wdb.addTX(t4.toTX()); + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 22000); + } - await wdb.addTX(f1); + { + await wdb.addTX(t1.toTX()); + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 73000); + } - balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 11000); + { + await wdb.addTX(t2.toTX()); + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 47000); + } - let txs = await w.getHistory(); - assert(txs.some((wtx) => { - return wtx.tx.hash('hex') === f1.hash('hex'); - })); + { + await wdb.addTX(t3.toTX()); + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 22000); + } - balance = await f.getBalance(); - assert.equal(balance.unconfirmed, 10000); + { + await wdb.addTX(f1.toTX()); - txs = await f.getHistory(); - assert(txs.some((wtx) => { - return wtx.tx.hash('hex') === f1.hash('hex'); - })); + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 11000); - await wdb.addTX(t2); + const txs = await alice.getHistory(); + assert(txs.some((wtx) => { + return wtx.tx.hash('hex') === f1.hash('hex'); + })); + } - await wdb.addTX(t3); + { + const balance = await bob.getBalance(); + assert.strictEqual(balance.unconfirmed, 10000); - await wdb.addTX(t4); + const txs = await bob.getHistory(); + assert(txs.some((wtx) => { + return wtx.tx.hash('hex') === f1.hash('hex'); + })); + } - await wdb.addTX(f1); + await wdb.addTX(t2.toTX()); + await wdb.addTX(t3.toTX()); + await wdb.addTX(t4.toTX()); + await wdb.addTX(f1.toTX()); - balance = await w.getBalance(); - assert.equal(balance.unconfirmed, 11000); + { + const balance = await alice.getBalance(); + assert.strictEqual(balance.unconfirmed, 11000); + } - balance = await f.getBalance(); - assert.equal(balance.unconfirmed, 10000); + { + const balance = await bob.getBalance(); + assert.strictEqual(balance.unconfirmed, 10000); + } }); it('should fill tx with inputs', async () => { - const w1 = await wdb.create(); - const w2 = await wdb.create(); + const alice = await wdb.create(); + const bob = await wdb.create(); // Coinbase - let t1 = new MTX(); - t1.addInput(dummy()); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - - t1 = t1.toTX(); + const t1 = new MTX(); + t1.addInput(dummyInput()); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); - await wdb.addTX(t1); + await wdb.addTX(t1.toTX()); // Create new transaction - let t2 = new MTX(); - t2.addOutput(w2.getAddress(), 5460); - await w1.fund(t2, { rate: 10000, round: true }); - await w1.sign(t2); - const view = t2.view; - t2 = t2.toTX(); + const m2 = new MTX(); + m2.addOutput(bob.getAddress(), 5460); + + await alice.fund(m2, { + rate: 10000, + round: true + }); + + await alice.sign(m2); - assert(t2.verify(view)); + const [t2, v2] = m2.commit(); - assert.equal(t2.getInputValue(view), 16380); - assert.equal(t2.getOutputValue(), 6380); - assert.equal(t2.getFee(view), 10000); + assert(t2.verify(v2)); + + assert.strictEqual(t2.getInputValue(v2), 16380); + assert.strictEqual(t2.getOutputValue(), 6380); + assert.strictEqual(t2.getFee(v2), 10000); // Create new transaction const t3 = new MTX(); - t3.addOutput(w2.getAddress(), 15000); + t3.addOutput(bob.getAddress(), 15000); let err; try { - await w1.fund(t3, { rate: 10000, round: true }); + await alice.fund(t3, { + rate: 10000, + round: true + }); } catch (e) { err = e; } assert(err); - assert.equal(err.requiredFunds, 25000); + assert.strictEqual(err.requiredFunds, 25000); }); it('should fill tx with inputs with accurate fee', async () => { - const w1 = await wdb.create({ master: KEY1 }); - const w2 = await wdb.create({ master: KEY2 }); - let balance; + const alice = await wdb.create({ + master: KEY1 + }); + + const bob = await wdb.create({ + master: KEY2 + }); // Coinbase - let t1 = new MTX(); - t1.addInput(dummy(encoding.NULL_HASH)); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1 = t1.toTX(); + const t1 = new MTX(); + t1.addOutpoint(new Outpoint(encoding.NULL_HASH, 0)); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); - await wdb.addTX(t1); + await wdb.addTX(t1.toTX()); // Create new transaction - let t2 = new MTX(); - t2.addOutput(w2.getAddress(), 5460); - await w1.fund(t2, { rate: 10000 }); + const m2 = new MTX(); + m2.addOutput(bob.getAddress(), 5460); + + await alice.fund(m2, { + rate: 10000 + }); + + await alice.sign(m2); + + const [t2, v2] = m2.commit(); - await w1.sign(t2); - const view = t2.view; - t2 = t2.toTX(); - assert(t2.verify(view)); + assert(t2.verify(v2)); - assert.equal(t2.getInputValue(view), 16380); + assert.strictEqual(t2.getInputValue(v2), 16380); // Should now have a change output: - assert.equal(t2.getOutputValue(), 11130); + assert.strictEqual(t2.getOutputValue(), 11130); - assert.equal(t2.getFee(view), 5250); + assert.strictEqual(t2.getFee(v2), 5250); - assert.equal(t2.getWeight(), 2084); - assert.equal(t2.getBaseSize(), 521); - assert.equal(t2.getSize(), 521); - assert.equal(t2.getVirtualSize(), 521); + assert.strictEqual(t2.getWeight(), 2084); + assert.strictEqual(t2.getBaseSize(), 521); + assert.strictEqual(t2.getSize(), 521); + assert.strictEqual(t2.getVirtualSize(), 521); - w2.once('balance', (b) => { + let balance; + bob.once('balance', (b) => { balance = b; }); @@ -527,11 +685,13 @@ describe('Wallet', function() { // Create new transaction const t3 = new MTX(); - t3.addOutput(w2.getAddress(), 15000); + t3.addOutput(bob.getAddress(), 15000); let err; try { - await w1.fund(t3, { rate: 10000 }); + await alice.fund(t3, { + rate: 10000 + }); } catch (e) { err = e; } @@ -542,40 +702,37 @@ describe('Wallet', function() { }); it('should sign multiple inputs using different keys', async () => { - const w1 = await wdb.create(); - const w2 = await wdb.create(); - const to = await wdb.create(); + const alice = await wdb.create(); + const bob = await wdb.create(); + const carol = await wdb.create(); // Coinbase - let t1 = new MTX(); - t1.addInput(dummy()); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1 = t1.toTX(); + const t1 = new MTX(); + t1.addInput(dummyInput()); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); // Coinbase - let t2 = new MTX(); - t2.addInput(dummy()); - t2.addOutput(w2.getAddress(), 5460); - t2.addOutput(w2.getAddress(), 5460); - t2.addOutput(w2.getAddress(), 5460); - t2.addOutput(w2.getAddress(), 5460); - t2 = t2.toTX(); - - await wdb.addTX(t1); - await wdb.addTX(t2); + const t2 = new MTX(); + t2.addInput(dummyInput()); + t2.addOutput(bob.getAddress(), 5460); + t2.addOutput(bob.getAddress(), 5460); + t2.addOutput(bob.getAddress(), 5460); + t2.addOutput(bob.getAddress(), 5460); + + await wdb.addTX(t1.toTX()); + await wdb.addTX(t2.toTX()); // Create our tx with an output const tx = new MTX(); - tx.addOutput(to.getAddress(), 5460); + tx.addOutput(carol.getAddress(), 5460); const cost = tx.getOutputValue(); - let total = cost * 10000; - const coins1 = await w1.getCoins(); - const coins2 = await w2.getCoins(); + const coins1 = await alice.getCoins(); + const coins2 = await bob.getCoins(); // Add our unspent inputs to sign tx.addCoin(coins1[0]); @@ -583,326 +740,234 @@ describe('Wallet', function() { tx.addCoin(coins2[0]); // Sign transaction - total = await w1.sign(tx); - assert.equal(total, 2); - - total = await w2.sign(tx); - assert.equal(total, 1); + assert.strictEqual(await alice.sign(tx), 2); + assert.strictEqual(await bob.sign(tx), 1); // Verify - assert.equal(tx.verify(), true); + assert.strictEqual(tx.verify(), true); tx.inputs.length = 0; tx.addCoin(coins1[1]); tx.addCoin(coins1[2]); tx.addCoin(coins2[1]); - total = await w1.sign(tx); - assert.equal(total, 2); - - total = await w2.sign(tx); - assert.equal(total, 1); + assert.strictEqual(await alice.sign(tx), 2); + assert.strictEqual(await bob.sign(tx), 1); // Verify - assert.equal(tx.verify(), true); + assert.strictEqual(tx.verify(), true); }); - async function testMultisig(witness, bullshitNesting, cb) { - const flags = Script.flags.STANDARD_VERIFY_FLAGS; - const rec = bullshitNesting ? 'nested' : 'receive'; - const depth = bullshitNesting ? 'nestedDepth' : 'receiveDepth'; - - // Create 3 2-of-3 wallets with our pubkeys as "shared keys" - const options = { - witness: witness, - type: 'multisig', - m: 2, - n: 3 - }; - - const w1 = await wdb.create(options); - const w2 = await wdb.create(options); - const w3 = await wdb.create(options); - const receive = await wdb.create(); - - await w1.addSharedKey(w2.account.accountKey); - await w1.addSharedKey(w3.account.accountKey); - await w2.addSharedKey(w1.account.accountKey); - await w2.addSharedKey(w3.account.accountKey); - await w3.addSharedKey(w1.account.accountKey); - await w3.addSharedKey(w2.account.accountKey); - - // Our p2sh address - let b58 = w1.account[rec].getAddress('string'); - const addr = Address.fromString(b58); - - if (witness) { - if (bullshitNesting) - assert.equal(addr.type, Address.types.SCRIPTHASH); - else - assert.equal(addr.type, Address.types.WITNESS); - } else { - assert.equal(addr.type, Address.types.SCRIPTHASH); - } - - assert.equal(w1.account[rec].getAddress('string'), b58); - assert.equal(w2.account[rec].getAddress('string'), b58); - assert.equal(w3.account[rec].getAddress('string'), b58); - - const paddr = w1.getNested(); - - if (witness) { - assert(paddr); - assert.equal(w1.getNested('string'), paddr.toString()); - assert.equal(w2.getNested('string'), paddr.toString()); - assert.equal(w3.getNested('string'), paddr.toString()); - } - - // Add a shared unspent transaction to our wallets - let utx = new MTX(); - utx.addInput(dummy()); - utx.addOutput(bullshitNesting ? paddr : addr, 5460 * 10); - utx = utx.toTX(); - - // Simulate a confirmation - let block = nextBlock(); - - assert.equal(w1.account[depth], 1); - - await wdb.addBlock(block, [utx]); - - assert.equal(w1.account[depth], 2); - - assert.equal(w1.account.changeDepth, 1); - - assert(w1.account[rec].getAddress('string') !== b58); - b58 = w1.account[rec].getAddress('string'); - assert.equal(w1.account[rec].getAddress('string'), b58); - assert.equal(w2.account[rec].getAddress('string'), b58); - assert.equal(w3.account[rec].getAddress('string'), b58); - - // Create a tx requiring 2 signatures - let send = new MTX(); - send.addOutput(receive.getAddress(), 5460); - assert(!send.verify(flags)); - await w1.fund(send, { rate: 10000, round: true }); - - await w1.sign(send); - - assert(!send.verify(flags)); - - await w2.sign(send); - - const view = send.view; - send = send.toTX(); - assert(send.verify(view, flags)); - - assert.equal(w1.account.changeDepth, 1); - - let change = w1.account.change.getAddress('string'); - assert.equal(w1.account.change.getAddress('string'), change); - assert.equal(w2.account.change.getAddress('string'), change); - assert.equal(w3.account.change.getAddress('string'), change); - - // Simulate a confirmation - block = nextBlock(); - - await wdb.addBlock(block, [send]); - - assert.equal(w1.account[depth], 2); - assert.equal(w1.account.changeDepth, 2); - - assert(w1.account[rec].getAddress('string') === b58); - assert(w1.account.change.getAddress('string') !== change); - change = w1.account.change.getAddress('string'); - assert.equal(w1.account.change.getAddress('string'), change); - assert.equal(w2.account.change.getAddress('string'), change); - assert.equal(w3.account.change.getAddress('string'), change); - - if (witness) { - send.inputs[0].witness.set(2, 0); - send.inputs[0].witness.compile(); - } else { - send.inputs[0].script.set(2, 0); - send.inputs[0].script.compile(); - } - - assert(!send.verify(view, flags)); - assert.equal(send.getFee(view), 10000); - } - it('should verify 2-of-3 p2sh tx', async () => { - await testMultisig(false, false); + await testP2SH(false, false); }); it('should verify 2-of-3 p2wsh tx', async () => { - await testMultisig(true, false); + await testP2SH(true, false); }); it('should verify 2-of-3 p2wsh tx w/ nested bullshit', async () => { - await testMultisig(true, true); + await testP2SH(true, true); }); it('should fill tx with account 1', async () => { - const w1 = await wdb.create(); - const w2 = await wdb.create(); - - let account = await w1.createAccount({ name: 'foo' }); - assert.equal(account.name, 'foo'); - assert.equal(account.accountIndex, 1); + const alice = await wdb.create(); + const bob = await wdb.create(); + + { + const account = await alice.createAccount({ + name: 'foo' + }); + assert.strictEqual(account.name, 'foo'); + assert.strictEqual(account.accountIndex, 1); + } - account = await w1.getAccount('foo'); - assert.equal(account.name, 'foo'); - assert.equal(account.accountIndex, 1); - const rec = account.receive; + const account = await alice.getAccount('foo'); + assert.strictEqual(account.name, 'foo'); + assert.strictEqual(account.accountIndex, 1); // Coinbase - let t1 = new MTX(); - t1.addOutput(rec.getAddress(), 5460); - t1.addOutput(rec.getAddress(), 5460); - t1.addOutput(rec.getAddress(), 5460); - t1.addOutput(rec.getAddress(), 5460); - - t1.addInput(dummy()); - t1 = t1.toTX(); + const t1 = new MTX(); + t1.addInput(dummyInput()); + t1.addOutput(account.receive.getAddress(), 5460); + t1.addOutput(account.receive.getAddress(), 5460); + t1.addOutput(account.receive.getAddress(), 5460); + t1.addOutput(account.receive.getAddress(), 5460); - await wdb.addTX(t1); + await wdb.addTX(t1.toTX()); // Create new transaction const t2 = new MTX(); - t2.addOutput(w2.getAddress(), 5460); - await w1.fund(t2, { rate: 10000, round: true }); - await w1.sign(t2); + t2.addOutput(bob.getAddress(), 5460); + + await alice.fund(t2, { + rate: 10000, + round: true + }); + + await alice.sign(t2); assert(t2.verify()); - assert.equal(t2.getInputValue(), 16380); - assert.equal(t2.getOutputValue(), 6380); - assert.equal(t2.getFee(), 10000); + assert.strictEqual(t2.getInputValue(), 16380); + assert.strictEqual(t2.getOutputValue(), 6380); + assert.strictEqual(t2.getFee(), 10000); // Create new transaction const t3 = new MTX(); - t3.addOutput(w2.getAddress(), 15000); + t3.addOutput(bob.getAddress(), 15000); let err; try { - await w1.fund(t3, { rate: 10000, round: true }); + await alice.fund(t3, { + rate: 10000, + round: true + }); } catch (e) { err = e; } assert(err); - assert.equal(err.requiredFunds, 25000); + assert.strictEqual(err.requiredFunds, 25000); - const accounts = await w1.getAccounts(); - assert.deepEqual(accounts, ['default', 'foo']); + const accounts = await alice.getAccounts(); + assert.deepStrictEqual(accounts, ['default', 'foo']); }); it('should fail to fill tx with account 1', async () => { - const w = await wdb.create(); - - wallet = w; - - const acc = await w.createAccount({ name: 'foo' }); - assert.equal(acc.name, 'foo'); - assert.equal(acc.accountIndex, 1); + const wallet = await wdb.create(); + + { + const account = await wallet.createAccount({ + name: 'foo' + }); + assert.strictEqual(account.name, 'foo'); + assert.strictEqual(account.accountIndex, 1); + } - const account = await w.getAccount('foo'); - assert.equal(account.name, 'foo'); - assert.equal(account.accountIndex, 1); - assert(account.accountKey.toBase58() === acc.accountKey.toBase58()); - assert(w.account.accountIndex === 0); + const account = await wallet.getAccount('foo'); + assert.strictEqual(account.name, 'foo'); + assert.strictEqual(account.accountIndex, 1); + assert(wallet.account.accountIndex === 0); - assert.notEqual( - account.receive.getAddress('string'), - w.account.receive.getAddress('string')); + assert(!account.receive.getAddress().equals( + wallet.account.receive.getAddress())); - assert.equal(w.getAddress('string'), - w.account.receive.getAddress('string')); + assert(wallet.getAddress().equals(wallet.account.receive.getAddress())); // Coinbase - let t1 = new MTX(); - t1.addOutput(w.getAddress(), 5460); - t1.addOutput(w.getAddress(), 5460); - t1.addOutput(w.getAddress(), 5460); + const t1 = new MTX(); + t1.addInput(dummyInput()); + t1.addOutput(wallet.getAddress(), 5460); + t1.addOutput(wallet.getAddress(), 5460); + t1.addOutput(wallet.getAddress(), 5460); t1.addOutput(account.receive.getAddress(), 5460); - t1.addInput(dummy()); - t1 = t1.toTX(); - - await wdb.addTX(t1); + await wdb.addTX(t1.toTX()); // Should fill from `foo` and fail - let t2 = new MTX(); - t2.addOutput(w.getAddress(), 5460); + const t2 = new MTX(); + + t2.addOutput(wallet.getAddress(), 5460); + let err; try { - await w.fund(t2, { rate: 10000, round: true, account: 'foo' }); + await wallet.fund(t2, { + rate: 10000, + round: true, + account: 'foo' + }); } catch (e) { err = e; } + assert(err); // Should fill from whole wallet and succeed - t2 = new MTX(); - t2.addOutput(w.getAddress(), 5460); - await w.fund(t2, { rate: 10000, round: true }); + const t3 = new MTX(); + t3.addOutput(wallet.getAddress(), 5460); + + await wallet.fund(t3, { + rate: 10000, + round: true + }); // Coinbase - t1 = new MTX(); - t1.addInput(dummy()); - t1.addOutput(account.receive.getAddress(), 5460); - t1.addOutput(account.receive.getAddress(), 5460); - t1.addOutput(account.receive.getAddress(), 5460); - t1 = t1.toTX(); + const t4 = new MTX(); + t4.addInput(dummyInput()); + t4.addOutput(account.receive.getAddress(), 5460); + t4.addOutput(account.receive.getAddress(), 5460); + t4.addOutput(account.receive.getAddress(), 5460); - await wdb.addTX(t1); + await wdb.addTX(t4.toTX()); // Should fill from `foo` and succeed - t2 = new MTX(); - t2.addOutput(w.getAddress(), 5460); - await w.fund(t2, { rate: 10000, round: true, account: 'foo' }); + const t5 = new MTX(); + t5.addOutput(wallet.getAddress(), 5460); + + await wallet.fund(t5, { + rate: 10000, + round: true, + account: 'foo' + }); + + currentWallet = wallet; }); it('should create two accounts (multiple encryption)', async () => { - let w = await wdb.create({ id: 'foobar', passphrase: 'foo' }); + { + const wallet = await wdb.create({ + id: 'foobar', + passphrase: 'foo' + }); + await wallet.destroy(); + } - await w.destroy(); + const wallet = await wdb.get('foobar'); + assert(wallet); - w = await wdb.get('foobar'); + const options = { + name: 'foo1' + }; + + const account = await wallet.createAccount(options, 'foo'); - const account = await w.createAccount({ name: 'foo1' }, 'foo'); assert(account); - await w.lock(); + await wallet.lock(); }); it('should fill tx with inputs when encrypted', async () => { - const w = await wdb.create({ passphrase: 'foo' }); + const wallet = await wdb.create({ + passphrase: 'foo' + }); - w.master.stop(); - w.master.key = null; + wallet.master.stop(); + wallet.master.key = null; // Coinbase - let t1 = new MTX(); - t1.addInput(dummy()); - t1.addOutput(w.getAddress(), 5460); - t1.addOutput(w.getAddress(), 5460); - t1.addOutput(w.getAddress(), 5460); - t1.addOutput(w.getAddress(), 5460); - t1 = t1.toTX(); + const t1 = new MTX(); + t1.addInput(dummyInput()); + t1.addOutput(wallet.getAddress(), 5460); + t1.addOutput(wallet.getAddress(), 5460); + t1.addOutput(wallet.getAddress(), 5460); + t1.addOutput(wallet.getAddress(), 5460); - await wdb.addTX(t1); + await wdb.addTX(t1.toTX()); // Create new transaction const t2 = new MTX(); - t2.addOutput(w.getAddress(), 5460); - await w.fund(t2, { rate: 10000, round: true }); + t2.addOutput(wallet.getAddress(), 5460); + + await wallet.fund(t2, { + rate: 10000, + round: true + }); // Should fail let err; try { - await w.sign(t2, 'bar'); + await wallet.sign(t2, 'bar'); } catch (e) { err = e; } @@ -911,321 +976,364 @@ describe('Wallet', function() { assert(!t2.verify()); // Should succeed - await w.sign(t2, 'foo'); + await wallet.sign(t2, 'foo'); assert(t2.verify()); }); it('should fill tx with inputs with subtract fee (1)', async () => { - const w1 = await wdb.create(); - const w2 = await wdb.create(); + const alice = await wdb.create(); + const bob = await wdb.create(); // Coinbase - let t1 = new MTX(); - t1.addInput(dummy()); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1 = t1.toTX(); + const t1 = new MTX(); + t1.addInput(dummyInput()); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); - await wdb.addTX(t1); + await wdb.addTX(t1.toTX()); // Create new transaction const t2 = new MTX(); - t2.addOutput(w2.getAddress(), 21840); - await w1.fund(t2, { rate: 10000, round: true, subtractFee: true }); - await w1.sign(t2); + t2.addOutput(bob.getAddress(), 21840); + + await alice.fund(t2, { + rate: 10000, + round: true, + subtractFee: true + }); + + await alice.sign(t2); assert(t2.verify()); - assert.equal(t2.getInputValue(), 5460 * 4); - assert.equal(t2.getOutputValue(), 21840 - 10000); - assert.equal(t2.getFee(), 10000); + assert.strictEqual(t2.getInputValue(), 5460 * 4); + assert.strictEqual(t2.getOutputValue(), 21840 - 10000); + assert.strictEqual(t2.getFee(), 10000); }); it('should fill tx with inputs with subtract fee (2)', async () => { - const w1 = await wdb.create(); - const w2 = await wdb.create(); + const alice = await wdb.create(); + const bob = await wdb.create(); // Coinbase - let t1 = new MTX(); - t1.addInput(dummy()); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1 = t1.toTX(); + const t1 = new MTX(); + t1.addInput(dummyInput()); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); - await wdb.addTX(t1); + await wdb.addTX(t1.toTX()); const options = { subtractFee: true, rate: 10000, round: true, - outputs: [{ address: w2.getAddress(), value: 21840 }] + outputs: [{ address: bob.getAddress(), value: 21840 }] }; // Create new transaction - const t2 = await w1.createTX(options); - await w1.sign(t2); + const t2 = await alice.createTX(options); + await alice.sign(t2); assert(t2.verify()); - assert.equal(t2.getInputValue(), 5460 * 4); - assert.equal(t2.getOutputValue(), 21840 - 10000); - assert.equal(t2.getFee(), 10000); + assert.strictEqual(t2.getInputValue(), 5460 * 4); + assert.strictEqual(t2.getOutputValue(), 21840 - 10000); + assert.strictEqual(t2.getFee(), 10000); }); it('should fill tx with smart coin selection', async () => { - const w1 = await wdb.create(); - const w2 = await wdb.create(); - let found = false; - let total = 0; + const alice = await wdb.create(); + const bob = await wdb.create(); // Coinbase - let t1 = new MTX(); - t1.addInput(dummy()); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1.addOutput(w1.getAddress(), 5460); - t1 = t1.toTX(); + const t1 = new MTX(); + t1.addInput(dummyInput()); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(alice.getAddress(), 5460); - await wdb.addTX(t1); + await wdb.addTX(t1.toTX()); // Coinbase - let t2 = new MTX(); - t2.addInput(dummy()); - t2.addOutput(w1.getAddress(), 5460); - t2.addOutput(w1.getAddress(), 5460); - t2.addOutput(w1.getAddress(), 5460); - t2.addOutput(w1.getAddress(), 5460); - t2 = t2.toTX(); + const t2 = new MTX(); + t2.addInput(dummyInput()); + t2.addOutput(alice.getAddress(), 5460); + t2.addOutput(alice.getAddress(), 5460); + t2.addOutput(alice.getAddress(), 5460); + t2.addOutput(alice.getAddress(), 5460); const block = nextBlock(); - await wdb.addBlock(block, [t2]); + await wdb.addBlock(block, [t2.toTX()]); - let coins = await w1.getSmartCoins(); - assert.equal(coins.length, 4); + { + const coins = await alice.getSmartCoins(); + assert.strictEqual(coins.length, 4); - for (let i = 0; i < coins.length; i++) { - const coin = coins[i]; - assert.equal(coin.height, block.height); + for (let i = 0; i < coins.length; i++) { + const coin = coins[i]; + assert.strictEqual(coin.height, block.height); + } } // Create a change output for ourselves. - await w1.send({ + await alice.send({ subtractFee: true, rate: 1000, depth: 1, - outputs: [{ address: w2.getAddress(), value: 1461 }] + outputs: [{ address: bob.getAddress(), value: 1461 }] }); - coins = await w1.getSmartCoins(); - assert.equal(coins.length, 4); - - for (let i = 0; i < coins.length; i++) { - const coin = coins[i]; - if (coin.height === -1) { - assert(!found); - assert(coin.value < 5460); - found = true; - } else { - assert.equal(coin.height, block.height); + const coins = await alice.getSmartCoins(); + assert.strictEqual(coins.length, 4); + + let total = 0; + + { + let found = false; + + for (let i = 0; i < coins.length; i++) { + const coin = coins[i]; + if (coin.height === -1) { + assert(!found); + assert(coin.value < 5460); + found = true; + } else { + assert.strictEqual(coin.height, block.height); + } + total += coin.value; } - total += coin.value; - } - assert(found); + assert(found); + } // Use smart selection const options = { subtractFee: true, smart: true, rate: 10000, - outputs: [{ address: w2.getAddress(), value: total }] + outputs: [{ + address: bob.getAddress(), + value: total + }] }; - const t3 = await w1.createTX(options); - assert.equal(t3.inputs.length, 4); - - found = false; - for (let i = 0; i < t3.inputs.length; i++) { - const coin = t3.view.getCoinFor(t3.inputs[i]); - if (coin.height === -1) { - assert(!found); - assert(coin.value < 5460); - found = true; - } else { - assert.equal(coin.height, block.height); + const t3 = await alice.createTX(options); + assert.strictEqual(t3.inputs.length, 4); + + { + let found = false; + + for (let i = 0; i < t3.inputs.length; i++) { + const coin = t3.view.getCoinFor(t3.inputs[i]); + if (coin.height === -1) { + assert(!found); + assert(coin.value < 5460); + found = true; + } else { + assert.strictEqual(coin.height, block.height); + } } - } - assert(found); + assert(found); + } - await w1.sign(t3); + await alice.sign(t3); assert(t3.verify()); }); it('should get range of txs', async () => { - const w = wallet; - const txs = await w.getRange({ start: util.now() - 1000 }); - assert.equal(txs.length, 2); + const wallet = currentWallet; + const txs = await wallet.getRange({ + start: util.now() - 1000 + }); + assert.strictEqual(txs.length, 2); }); it('should get range of txs from account', async () => { - const w = wallet; - const txs = await w.getRange('foo', { start: util.now() - 1000 }); - assert.equal(txs.length, 2); + const wallet = currentWallet; + const txs = await wallet.getRange('foo', { + start: util.now() - 1000 + }); + assert.strictEqual(txs.length, 2); }); it('should not get range of txs from non-existent account', async () => { - const w = wallet; - let txs, err; + const wallet = currentWallet; + let txs, err; try { - txs = await w.getRange('bad', { start: 0xdeadbeef - 1000 }); + txs = await wallet.getRange('bad', { + start: 0xdeadbeef - 1000 + }); } catch (e) { err = e; } assert(!txs); assert(err); - assert.equal(err.message, 'Account not found.'); + assert.strictEqual(err.message, 'Account not found.'); }); it('should get account balance', async () => { - const w = wallet; - const balance = await w.getBalance('foo'); - assert.equal(balance.unconfirmed, 21840); + const wallet = currentWallet; + const balance = await wallet.getBalance('foo'); + assert.strictEqual(balance.unconfirmed, 21840); }); it('should import privkey', async () => { const key = KeyRing.generate(); - const w = await wdb.create({ passphrase: 'test' }); - await w.importKey('default', key, 'test'); + const wallet = await wdb.create({ + passphrase: 'test' + }); + + await wallet.importKey('default', key, 'test'); - const k = await w.getKey(key.getHash('hex')); + const wkey = await wallet.getKey(key.getHash('hex')); - assert.equal(k.getHash('hex'), key.getHash('hex')); + assert.strictEqual(wkey.getHash('hex'), key.getHash('hex')); // Coinbase - let t1 = new MTX(); + const t1 = new MTX(); t1.addOutput(key.getAddress(), 5460); t1.addOutput(key.getAddress(), 5460); t1.addOutput(key.getAddress(), 5460); t1.addOutput(key.getAddress(), 5460); - t1.addInput(dummy()); - t1 = t1.toTX(); + t1.addInput(dummyInput()); - await wdb.addTX(t1); + await wdb.addTX(t1.toTX()); - const wtx = await w.getTX(t1.hash('hex')); + const wtx = await wallet.getTX(t1.hash('hex')); assert(wtx); - assert.equal(t1.hash('hex'), wtx.hash); + assert.strictEqual(t1.hash('hex'), wtx.hash); const options = { rate: 10000, round: true, - outputs: [{ address: w.getAddress(), value: 7000 }] + outputs: [{ + address: wallet.getAddress(), + value: 7000 + }] }; // Create new transaction - const t2 = await w.createTX(options); - await w.sign(t2); + const t2 = await wallet.createTX(options); + await wallet.sign(t2); assert(t2.verify()); assert(t2.inputs[0].prevout.hash === wtx.hash); - ewallet = w; - ekey = key; + importedWallet = wallet; + importedKey = key; }); it('should import pubkey', async () => { - const priv = KeyRing.generate(); - const key = new KeyRing(priv.publicKey); - const w = await wdb.create({ watchOnly: true }); + const key = KeyRing.generate(); + const pub = new KeyRing(key.publicKey); - await w.importKey('default', key); + const wallet = await wdb.create({ + watchOnly: true + }); - let k = await w.getPath(key.getHash('hex')); + await wallet.importKey('default', pub); - assert.equal(k.hash, key.getHash('hex')); + const path = await wallet.getPath(pub.getHash('hex')); + assert.strictEqual(path.hash, pub.getHash('hex')); - k = await w.getKey(key.getHash('hex')); - assert(k); + const wkey = await wallet.getKey(pub.getHash('hex')); + assert(wkey); }); it('should import address', async () => { const key = KeyRing.generate(); - const w = await wdb.create({ watchOnly: true }); - await w.importAddress('default', key.getAddress()); + const wallet = await wdb.create({ + watchOnly: true + }); - let k = await w.getPath(key.getHash('hex')); + await wallet.importAddress('default', key.getAddress()); - assert.equal(k.hash, key.getHash('hex')); + const path = await wallet.getPath(key.getHash('hex')); + assert(path); + assert.strictEqual(path.hash, key.getHash('hex')); - k = await w.getKey(key.getHash('hex')); - assert(!k); + const wkey = await wallet.getKey(key.getHash('hex')); + assert(!wkey); }); it('should get details', async () => { - const w = wallet; - const txs = await w.getRange('foo', { start: util.now() - 1000 }); - const details = await w.toDetails(txs); + const wallet = currentWallet; + + const txs = await wallet.getRange('foo', { + start: util.now() - 1000 + }); + + const details = await wallet.toDetails(txs); + assert(details.some((tx) => { return tx.toJSON().outputs[0].path.name === 'foo'; })); }); it('should rename wallet', async () => { - const w = wallet; + const wallet = currentWallet; + await wallet.rename('test'); - const txs = await w.getRange('foo', { start: util.now() - 1000 }); - const details = await w.toDetails(txs); - assert.equal(details[0].toJSON().id, 'test'); - }); - it('should change passphrase with encrypted imports', async () => { - const w = ewallet; - const addr = ekey.getAddress(); + const txs = await wallet.getRange('foo', { + start: util.now() - 1000 + }); - assert(w.master.encrypted); + const details = await wallet.toDetails(txs); - let path = await w.getPath(addr); - assert(path); - assert(path.data && path.encrypted); - const d1 = path.data; + assert.strictEqual(details[0].toJSON().id, 'test'); + }); + + it('should change passphrase with encrypted imports', async () => { + const wallet = importedWallet; + const addr = importedKey.getAddress(); - await w.decrypt('test'); + assert(wallet.master.encrypted); - path = await w.getPath(addr); - assert(path); - assert(path.data && !path.encrypted); + let data; + { + const path = await wallet.getPath(addr); + assert(path); + assert(path.data && path.encrypted); + data = path.data; + } - let k = await w.getKey(addr); - assert(k); + await wallet.decrypt('test'); - await w.encrypt('foo'); + { + const path = await wallet.getPath(addr); + assert(path); + assert(path.data && !path.encrypted); + assert(await wallet.getKey(addr)); + } - path = await w.getPath(addr); - assert(path); - assert(path.data && path.encrypted); - const d2 = path.data; + await wallet.encrypt('foo'); - assert(!d1.equals(d2)); + { + const path = await wallet.getPath(addr); + assert(path); + assert(path.data && path.encrypted); + assert(!data.equals(path.data)); + assert(!await wallet.getKey(addr)); + } - k = await w.getKey(addr); - assert(!k); + await wallet.unlock('foo'); - await w.unlock('foo'); - k = await w.getKey(addr); - assert(k); - assert.equal(k.getHash('hex'), addr.getHash('hex')); + const key = await wallet.getKey(addr); + assert(key); + assert.strictEqual(key.getHash('hex'), addr.getHash('hex')); }); it('should recover from a missed tx', async () => { @@ -1237,57 +1345,60 @@ describe('Wallet', function() { await wdb.open(); - const alice = await wdb.create({ master: KEY1 }); - const bob = await wdb.create({ master: KEY1 }); + const alice = await wdb.create({ + master: KEY1 + }); + + const bob = await wdb.create({ + master: KEY1 + }); + const addr = alice.getAddress(); // Coinbase - let t1 = new MTX(); - t1.addInput(dummy()); + const t1 = new MTX(); + t1.addInput(dummyInput()); t1.addOutput(addr, 50000); - t1 = t1.toTX(); - await alice.add(t1); - await bob.add(t1); + await alice.add(t1.toTX()); + await bob.add(t1.toTX()); // Bob misses this tx! - let t2 = new MTX(); + const t2 = new MTX(); t2.addTX(t1, 0); t2.addOutput(addr, 24000); t2.addOutput(addr, 24000); await alice.sign(t2); - t2 = t2.toTX(); - await alice.add(t2); + await alice.add(t2.toTX()); - assert.notEqual( + assert.notStrictEqual( (await alice.getBalance()).unconfirmed, (await bob.getBalance()).unconfirmed); // Bob sees this one. - let t3 = new MTX(); + const t3 = new MTX(); t3.addTX(t2, 0); t3.addTX(t2, 1); t3.addOutput(addr, 30000); await alice.sign(t3); - t3 = t3.toTX(); - assert.equal((await bob.getBalance()).unconfirmed, 50000); + assert.strictEqual((await bob.getBalance()).unconfirmed, 50000); - await alice.add(t3); - await bob.add(t3); + await alice.add(t3.toTX()); + await bob.add(t3.toTX()); - assert.equal((await alice.getBalance()).unconfirmed, 30000); + assert.strictEqual((await alice.getBalance()).unconfirmed, 30000); // Bob sees t2 on the chain. - await bob.add(t2); + await bob.add(t2.toTX()); // Bob sees t3 on the chain. - await bob.add(t3); + await bob.add(t3.toTX()); - assert.equal((await bob.getBalance()).unconfirmed, 30000); + assert.strictEqual((await bob.getBalance()).unconfirmed, 30000); }); it('should recover from a missed tx and double spend', async () => { @@ -1299,68 +1410,70 @@ describe('Wallet', function() { await wdb.open(); - const alice = await wdb.create({ master: KEY1 }); - const bob = await wdb.create({ master: KEY1 }); + const alice = await wdb.create({ + master: KEY1 + }); + + const bob = await wdb.create({ + master: KEY1 + }); + const addr = alice.getAddress(); // Coinbase - let t1 = new MTX(); - t1.addInput(dummy()); + const t1 = new MTX(); + t1.addInput(dummyInput()); t1.addOutput(addr, 50000); - t1 = t1.toTX(); - await alice.add(t1); - await bob.add(t1); + await alice.add(t1.toTX()); + await bob.add(t1.toTX()); // Bob misses this tx! - let t2 = new MTX(); - t2.addTX(t1, 0); - t2.addOutput(addr, 24000); - t2.addOutput(addr, 24000); + const t2a = new MTX(); + t2a.addTX(t1, 0); + t2a.addOutput(addr, 24000); + t2a.addOutput(addr, 24000); - await alice.sign(t2); - t2 = t2.toTX(); + await alice.sign(t2a); - await alice.add(t2); + await alice.add(t2a.toTX()); - assert.notEqual( + assert.notStrictEqual( (await alice.getBalance()).unconfirmed, (await bob.getBalance()).unconfirmed); // Bob doublespends. - let t2a = new MTX(); - t2a.addTX(t1, 0); - t2a.addOutput(addr, 10000); - t2a.addOutput(addr, 10000); + const t2b = new MTX(); + t2b.addTX(t1, 0); + t2b.addOutput(addr, 10000); + t2b.addOutput(addr, 10000); - await bob.sign(t2a); - t2a = t2a.toTX(); + await bob.sign(t2b); - await bob.add(t2a); + await bob.add(t2b.toTX()); // Bob sees this one. - let t3 = new MTX(); - t3.addTX(t2, 0); - t3.addTX(t2, 1); + const t3 = new MTX(); + t3.addTX(t2a, 0); + t3.addTX(t2a, 1); t3.addOutput(addr, 30000); await alice.sign(t3); - t3 = t3.toTX(); - assert.equal((await bob.getBalance()).unconfirmed, 20000); + assert.strictEqual((await bob.getBalance()).unconfirmed, 20000); - await alice.add(t3); - await bob.add(t3); + await alice.add(t3.toTX()); + await bob.add(t3.toTX()); - assert.equal((await alice.getBalance()).unconfirmed, 30000); + assert.strictEqual((await alice.getBalance()).unconfirmed, 30000); - // Bob sees t2 on the chain. - await bob.add(t2); + // Bob sees t2a on the chain. + await bob.add(t2a.toTX()); // Bob sees t3 on the chain. - await bob.add(t3); + await bob.add(t3.toTX()); - assert.equal((await bob.getBalance()).unconfirmed, 30000); + assert.strictEqual((await bob.getBalance()).unconfirmed, 30000); }); it('should cleanup', () => {