From 14069155b0b450b924369043e600c0d069bed47f Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Thu, 29 May 2014 01:21:56 +1000 Subject: [PATCH] tests: adds bitcoin core tests Not all tests are added yet, but this represents a significant portion. --- test/bitcoin.core.js | 195 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 test/bitcoin.core.js diff --git a/test/bitcoin.core.js b/test/bitcoin.core.js new file mode 100644 index 0000000..3c76541 --- /dev/null +++ b/test/bitcoin.core.js @@ -0,0 +1,195 @@ +var assert = require('assert') +var base58 = require('../src/base58') +var base58check = require('../src/base58check') +var networks = require('../src/networks') + +var Address = require('../src/address') +var BigInteger = require('bigi') +var ECKey = require('../src/eckey') +var Transaction = require('../src/transaction').Transaction +var Script = require('../src/script') + +var base58_encode_decode = require("./fixtures/core/base58_encode_decode.json") +var base58_keys_invalid = require("./fixtures/core/base58_keys_invalid.json") +var base58_keys_valid = require("./fixtures/core/base58_keys_valid.json") +var sig_canonical = require("./fixtures/core/sig_canonical.json") +var sig_noncanonical = require("./fixtures/core/sig_noncanonical.json") +var sighash = require("./fixtures/core/sighash.json") +var tx_valid = require("./fixtures/core/tx_valid.json") + +describe('Bitcoin-core', function() { + // base58_encode_decode + describe('base58', function() { + base58_encode_decode.forEach(function(f) { + var fhex = f[0] + var fb58 = f[1] + + it('can decode ' + fb58, function() { + var buffer = base58.decode(fb58) + var actual = buffer.toString('hex') + + assert.equal(actual, fhex) + }) + + it('can encode ' + fhex, function() { + var buffer = new Buffer(fhex, 'hex') + var actual = base58.encode(buffer) + + assert.equal(actual, fb58) + }) + }) + }) + + // base58_keys_valid + describe('Address', function() { + base58_keys_valid.forEach(function(f) { + var string = f[0] + var hex = f[1] + var params = f[2] + var network = networks.bitcoin + + if (params.isPrivkey) return + if (params.isTestnet) network = networks.testnet + + it('can import ' + string, function() { + var address = Address.fromBase58Check(string) + + assert.equal(address.hash.toString('hex'), hex) + if (params.addrType === 'pubkey') { + assert.equal(address.version, network.pubKeyHash) + + } else if (params.addrType === 'script') { + assert.equal(address.version, network.scriptHash) + } + }) + }) + }) + + // base58_keys_invalid + describe('Address', function() { + var allowedNetworks = [ + networks.bitcoin.pubKeyHash, + networks.bitcoin.scriptHash, + networks.testnet.pubKeyHash, + networks.testnet.scriptHash + ] + + base58_keys_invalid.forEach(function(f) { + var string = f[0] + + it('throws on ' + string, function() { + assert.throws(function() { + var address = Address.fromBase58Check(string) + + assert.notEqual(allowedNetworks.indexOf(address.version), -1, 'Invalid network') + }, /Invalid (checksum|hash length|network)/) + }) + }) + }) + + // base58_keys_valid + describe('ECKey', function() { + base58_keys_valid.forEach(function(f) { + var string = f[0] + var hex = f[1] + var params = f[2] + var network = networks.bitcoin + + if (!params.isPrivkey) return + if (params.isTestnet) network = networks.testnet + + it('imports ' + string + ' correctly', function() { + var privKey = ECKey.fromWIF(string) + + assert.equal(privKey.D.toHex(), hex) + assert.equal(privKey.pub.compressed, params.isCompressed) + }) + }) + }) + + // base58_keys_invalid + describe('ECKey', function() { + var allowedNetworks = [ + networks.bitcoin.wif, + networks.testnet.wif + ] + + base58_keys_invalid.forEach(function(f) { + var string = f[0] + + it('throws on ' + string, function() { + assert.throws(function() { + var privKey = ECKey.fromWIF(string) + var version = base58check.decode(string).version + + assert.notEqual(allowedNetworks.indexOf(version), -1, 'Invalid network') + }, /Invalid (checksum|compression flag|network|WIF payload)/) + }) + }) + }) + + // tx_valid + describe('Transaction', function() { + tx_valid.forEach(function(f) { + // Objects that are only a single string are ignored + if (f.length === 1) return + + var inputs = f[0] + var fhex = f[1] + // var verifyFlags = f[2] // TODO: do we need to test this? + + it('can decode ' + fhex, function() { + var transaction = Transaction.fromHex(fhex) + + transaction.ins.forEach(function(txin, i) { + var input = inputs[i] + var prevOutHash = input[0] + var prevOutIndex = input[1] + // var prevOutScriptPubKey = input[2] // TODO: we don't have a ASM parser + + assert.equal(txin.outpoint.hash, prevOutHash) + + // we read UInt32, not Int32 + assert.equal(txin.outpoint.index & 0xffffffff, prevOutIndex) + }) + }) + }) + }) + + // sighash + describe('Transaction', function() { + sighash.forEach(function(f) { + // Objects that are only a single string are ignored + if (f.length === 1) return + + var txHex = f[0] + var scriptHex = f[1] + var inIndex = f[2] + var hashType = f[3] + var expectedHash = f[4] + + it('should hash ' + txHex + ' correctly', function() { + var transaction = Transaction.fromHex(txHex) + assert.equal(transaction.toHex(), txHex) + + var script = Script.fromHex(scriptHex) + assert.equal(script.toHex(), scriptHex) + + var actualHash + try { + actualHash = transaction.hashForSignature(script, inIndex, hashType) + } catch (e) { + // don't fail if we don't support it yet, TODO + if (!e.message.match(/not yet supported/)) throw e + } + + if (actualHash != undefined) { + // BigEndian test data + Array.prototype.reverse.call(actualHash) + + assert.equal(actualHash.toString('hex'), expectedHash) + } + }) + }) + }) +})