From 14069155b0b450b924369043e600c0d069bed47f Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
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)
+        }
+      })
+    })
+  })
+})