From 682ec133bb4232ca5c17bc9e9b2621761a1e7fc0 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Thu, 17 Apr 2014 23:31:45 +1000 Subject: [PATCH 1/7] Migrates Address to stricter API subset --- src/address.js | 75 +++++---------- src/eckey.js | 2 +- src/message.js | 6 +- src/script.js | 53 ++++++----- src/transaction.js | 16 +++- test/address.js | 132 +++++++++----------------- test/fixtures/address.js | 198 +++++++++++++++++++++++++++++++++++++++ test/script.js | 9 +- test/transaction.js | 12 ++- 9 files changed, 323 insertions(+), 180 deletions(-) create mode 100644 test/fixtures/address.js diff --git a/src/address.js b/src/address.js index 7de6d5d..c519147 100644 --- a/src/address.js +++ b/src/address.js @@ -1,64 +1,35 @@ -var base58 = require('./base58') +var assert = require('assert') var base58check = require('./base58check') -var convert = require('./convert') -var bitcoin = require('./network').bitcoin.pubKeyHash +var crypto = require('./crypto') +var network = require('./network') -function Address(bytes, version) { - if (!(this instanceof Address)) { - return new Address(bytes, version) - } +function Address(hash, version) { + assert(Buffer.isBuffer(hash)) + assert(hash.length === 20) + assert(typeof version === 'number') - if (bytes instanceof Address) { - this.hash = bytes.hash - this.version = bytes.version - } - else if (typeof bytes === 'string') { - if (bytes.length <= 35) { - var decode = base58check.decode(bytes) - - this.hash = decode.payload - this.version = decode.version - } - else if (bytes.length <= 40) { - this.hash = convert.hexToBytes(bytes) - this.version = version || bitcoin - } - else { - throw new Error('Invalid or unrecognized input') - } - } - else { - this.hash = bytes - this.version = version || bitcoin - } + this.hash = hash + this.version = version } -/** - * Serialize this object as a standard Bitcoin address. - * Returns the address as a base58-encoded string in the standardized format. - */ -Address.prototype.toString = function () { - return base58check.encode(this.hash.slice(0), this.version) +// Static constructors +Address.fromBase58Check = function(string) { + var decode = base58check.decode(string) + + return new Address(decode.payload, decode.version) } -/** - * Returns the version of an address, e.g. if the address belongs to the main - * net or the test net. - */ -Address.getVersion = function (address) { - return base58.decode(address)[0] +Address.fromPubKey = function(pubKey, version) { + version = version || network.bitcoin.pubKeyHash + + var hash = crypto.hash160(pubKey.toBuffer()) + return new Address(hash, version) } -/** - * Returns true if a bitcoin address is a valid address, otherwise false. - */ -Address.validate = function (address) { - try { - base58check.decode(address) - return true - } catch (e) { - return false - } +// Export functions +Address.prototype.toBase58Check = function () { + return base58check.encode(this.hash, this.version) } +Address.prototype.toString = Address.prototype.toBase58Check module.exports = Address diff --git a/src/eckey.js b/src/eckey.js index f3d7420..fc0df5e 100644 --- a/src/eckey.js +++ b/src/eckey.js @@ -121,7 +121,7 @@ ECPubKey.prototype.verify = function(hash, sig) { } ECPubKey.prototype.getAddress = function(version) { - return new Address(crypto.hash160(this.toBuffer()), version) + return Address.fromPubKey(this, version) } // Export functions diff --git a/src/message.js b/src/message.js index e3e7c63..dc4a9d5 100644 --- a/src/message.js +++ b/src/message.js @@ -47,12 +47,16 @@ function sign(key, message) { } function verify(address, sig, message) { + // FIXME: stricter API? + if (!(address instanceof Address)) { + address = Address.fromBase58Check(address) + } + sig = ecdsa.parseSigCompact(sig) var pubKey = new ECPubKey(ecdsa.recoverPubKey(sig.r, sig.s, magicHash(message), sig.i)) pubKey.compressed = !!(sig.i & 4) - address = new Address(address) return pubKey.getAddress(address.version).toString() === address.toString() } diff --git a/src/script.js b/src/script.js index 8ef82a9..e8fd5e6 100644 --- a/src/script.js +++ b/src/script.js @@ -1,7 +1,8 @@ +var assert = require('assert') var Address = require('./address') var crypto = require('./crypto') var convert = require('./convert') -var network = require('./network') +var Network = require('./network') var Opcode = require('./opcode') function Script(data) { @@ -211,22 +212,23 @@ Script.prototype.toScriptHash = function() { return crypto.hash160(this.buffer) } -//TODO: support testnet -Script.prototype.getToAddress = function() { +Script.prototype.getToAddress = function(network) { + network = network || Network.bitcoin + if(isPubkeyhash.call(this)) { - return new Address(this.chunks[2]) + return new Address(new Buffer(this.chunks[2]), network.pubKeyHash) } - if(isScripthash.call(this)) { - return new Address(this.chunks[1], 5) - } + assert(isScripthash.call(this)) - return new Address(this.chunks[1], 5) + return new Address(new Buffer(this.chunks[1]), network.scriptHash) } //TODO: support testnet -Script.prototype.getFromAddress = function(){ - return new Address(this.simpleInHash()) +Script.prototype.getFromAddress = function(version) { + version = version || Network.bitcoin.pubKeyHash + + return new Address(this.simpleInHash(), version) } /** @@ -364,25 +366,30 @@ Script.prototype.writeBytes = function(data) { /** * Create an output for an address */ -Script.createOutputScript = function(address) { +Script.createOutputScript = function(address, network) { + assert(address instanceof Address) + network = network || Network.bitcoin + var script = new Script() - address = new Address(address) - if (address.version == network.bitcoin.scriptHash || - address.version == network.testnet.scriptHash) { - // Standard pay-to-script-hash + // Standard pay-to-script-hash + if (address.version === network.scriptHash) { script.writeOp(Opcode.map.OP_HASH160) script.writeBytes(address.hash) script.writeOp(Opcode.map.OP_EQUAL) + + return script } - else { - // Standard pay-to-pubkey-hash - script.writeOp(Opcode.map.OP_DUP) - script.writeOp(Opcode.map.OP_HASH160) - script.writeBytes(address.hash) - script.writeOp(Opcode.map.OP_EQUALVERIFY) - script.writeOp(Opcode.map.OP_CHECKSIG) - } + + assert(address.version === network.pubKeyHash) + + // Standard pay-to-pubkey-hash + script.writeOp(Opcode.map.OP_DUP) + script.writeOp(Opcode.map.OP_HASH160) + script.writeBytes(address.hash) + script.writeOp(Opcode.map.OP_EQUALVERIFY) + script.writeOp(Opcode.map.OP_CHECKSIG) + return script } diff --git a/src/transaction.js b/src/transaction.js index 5f64d43..a45817b 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -8,6 +8,7 @@ var convert = require('./convert') var crypto = require('./crypto') var ECKey = require('./eckey').ECKey var ecdsa = require('./ecdsa') +var Network = require('./network') var Transaction = function (doc) { if (!(this instanceof Transaction)) { return new Transaction(doc) } @@ -98,6 +99,9 @@ Transaction.prototype.addOutput = function (address, value) { value = parseInt(args[1]) } + // FIXME: Stricter Transaction API + address = Address.fromBase58Check(address) + this.outs.push(new TransactionOut({ value: value, script: Script.createOutputScript(address) @@ -297,18 +301,20 @@ Transaction.deserialize = function(buffer) { /** * Signs a standard output at some index with the given key + * FIXME: network support is ugly */ -Transaction.prototype.sign = function(index, key, type) { +Transaction.prototype.sign = function(index, key, type, network) { assert(key instanceof ECKey) type = type || SIGHASH_ALL + network = network || Network.bitcoin + + var address = Address.fromPubKey(key.pub, network.pubKeyHash) - var pub = key.pub.toBuffer() - var hash160 = crypto.hash160(pub) - var script = Script.createOutputScript(new Address(hash160)) + var script = Script.createOutputScript(address, network) var hash = this.hashTransactionForSignature(script, index, type) var sig = key.sign(hash).concat([type]) - this.ins[index].script = Script.createInputScript(sig, pub) + this.ins[index].script = Script.createInputScript(sig, key.pub) } // Takes outputs of the form [{ output: 'txhash:index', address: 'address' },...] diff --git a/test/address.js b/test/address.js index 3d8336c..2baffef 100644 --- a/test/address.js +++ b/test/address.js @@ -1,111 +1,65 @@ var assert = require('assert') -var Address = require('../src/address') -var network = require('../src/network') -var base58 = require('../src/base58') -var base58check = require('../src/base58check') -var bitcoin = network.bitcoin.pubKeyHash -var testnet = network.testnet.pubKeyHash -describe('Address', function() { - var testnetAddress, bitcoinAddress - var testnetP2shAddress, bitcoinP2shAddress - - beforeEach(function(){ - bitcoinAddress = '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa' - testnetAddress = 'mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef' - bitcoinP2shAddress = '3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt' - testnetP2shAddress = '2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7' - }) - - describe('parsing', function() { - it('works with Address object', function() { - var addr = new Address(new Address('mwrB4fgT1KSBCqELaWv7o7tsExuQzW3NY3', network.testnet.pubKeyHash)) - - assert.equal(addr.toString(), 'mwrB4fgT1KSBCqELaWv7o7tsExuQzW3NY3') - assert.equal(addr.version, network.testnet.pubKeyHash) - }) - - it('works with hex', function() { - var addr = new Address('13483382d3c3d43fc9d7b52e652b6bbb70e8b667') - assert.equal(addr.toString(), '12kxLGqrnnchwN9bHHNV2fWDtJGwxKTcJS') - }) +var Address = require('..').Address +var ECPubKey = require('..').ECPubKey +var base58check = require('..').base58check - it('throws error for invalid or unrecognized input', function() { - assert.throws(function() { - new Address('beepboopbeepboopbeepboopbeepboopbeepboopbeep') - }, Error) - }) +var fixtures = require('./fixtures/address') - it('works for byte input', function() { - var hash = base58check.decode(bitcoinAddress) - var addr = new Address(hash.payload) - assert.equal(addr.hash, hash.payload) - assert.equal(network.bitcoin.pubKeyHash, hash.version) +describe('Address', function() { + var bothVectors = fixtures.pubKeyHash.concat(fixtures.scriptHash) - var hash = base58check.decode(testnetAddress) - var addr = new Address(hash.payload) - assert.equal(addr.hash, hash.payload) - assert.equal(network.testnet.pubKeyHash, hash.version) - }) + describe('Constructor', function() { + it('matches the test vectors', function() { + bothVectors.forEach(function(f) { + var hash = new Buffer(f.hex, 'hex') + var addr = new Address(hash, f.version) - it('fails for bad input', function() { - assert.throws(function() { - new Address('foo') - }, Error) + assert.equal(addr.version, f.version) + assert.equal(addr.hash.toString('hex'), f.hex) + }) }) }) - describe('getVersion', function() { - it('returns the proper address version', function() { - assert.equal(Address.getVersion(bitcoinAddress), network.bitcoin.pubKeyHash) - assert.equal(Address.getVersion(testnetAddress), network.testnet.pubKeyHash) + describe('fromBase58Check', function() { + it('throws on invalid base58check', function() { + fixtures.malformed.forEach(function(f) { + assert.throws(function() { + Address.fromBase58Check(f.base58check) + }) + }) }) - }) - describe('toString', function() { - it('defaults to base58', function() { - var addr = '18fN1QTGWmHWCA9r2dyDH6FbMEyc7XHmQQ' - assert.equal((new Address(addr)).toString(), addr) - }) - }) + it('output matches the test vectors', function() { + bothVectors.forEach(function(f) { + var addr = Address.fromBase58Check(f.base58check) - describe('Constructor', function(){ - it('resolves version correctly', function(){ - assert.equal((new Address(testnetAddress)).version, testnet) - assert.equal((new Address(bitcoinAddress)).version, bitcoin) - assert.equal((new Address(testnetP2shAddress)).version, network.testnet.scriptHash) - assert.equal((new Address(bitcoinP2shAddress)).version, network.bitcoin.scriptHash) + assert.equal(addr.version, f.version) + assert.equal(addr.hash.toString('hex'), f.hex) + }) }) }) - describe('validate', function() { - it('validates known good addresses', function() { - function validate(addr, expectedVersion) { - assert.ok(Address.validate(addr)) - } + describe('fromPubKey', function() { + it('output matches the test vectors', function() { + fixtures.pubKeyHash.forEach(function(f) { + var pub = ECPubKey.fromBuffer(new Buffer(f.pubKey, 'hex')) + var addr = Address.fromPubKey(pub, f.version) - validate(testnetAddress) - validate(bitcoinAddress) - validate('12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP') - validate('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y') - validate('1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs') - validate('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez') - validate('116CGDLddrZhMrTwhCVJXtXQpxygTT1kHd') - - // p2sh addresses - validate(testnetP2shAddress) - validate(bitcoinP2shAddress) + assert.equal(addr.version, f.version) + assert.equal(addr.hash.toString('hex'), f.hex) + }) }) + }) - it('does not validate illegal examples', function() { - function invalid(addr) { - assert.ok(!Address.validate(addr)) - } + describe('toBase58Check', function() { + it('output matches the test vectors', function() { + bothVectors.forEach(function(f) { + var addr = Address.fromBase58Check(f.base58check) + var base58check = addr.toBase58Check() - invalid(''); //empty should be invalid - invalid('%%@'); // invalid base58 string - invalid('1A1zP1eP5QGefi2DzPTf2L5SLmv7DivfNz'); // bad address (doesn't checksum) - invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhe'); // bad address (doesn't checksum) + assert.equal(base58check, f.base58check) + }) }) }) }) diff --git a/test/fixtures/address.js b/test/fixtures/address.js new file mode 100644 index 0000000..ad282f2 --- /dev/null +++ b/test/fixtures/address.js @@ -0,0 +1,198 @@ +module.exports = { + pubKeyHash: [ + { + version: 0, + pubKey: '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', + hex: '91b24bf9f5288532960ac687abb035127b1d28a5', + base58check: '1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm' + }, + { + version: 0, + pubKey: '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + hex: '751e76e8199196d454941c45d1b3a323f1433bd6', + base58check: '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH' + }, + { + version: 0, + pubKey: '04750578aed9dd59b43d0f3fbbcf26ed132bed71d202183674e6f0f01b71ad25eea9c42714b1f602b87164f76ef169477a7db9591e10755783006ebfa9c11946c3', + hex: 'c4fa066a855f0e2739f21393595ca3d7ff422fb6', + base58check: '1JxWxePiX2GHN444g5V5JpBLEi3LV8cHGS' + }, + { + version: 0, + pubKey: '03750578aed9dd59b43d0f3fbbcf26ed132bed71d202183674e6f0f01b71ad25ee', + hex: '6b420cc35afb4d96ea118dbf1fc8ef4b0990798c', + base58check: '1An8RkWzqVF9GvpQFVX5AM4jpFe43eoPfe' + }, + { + version: 0, + pubKey: '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777', + hex: 'bec08011c9e76dcc42e739a2d7752c2e3ac86e6e', + base58check: '1JPbzbsAx1HyaDQoLMapWGoqf9pD5uha5m' + }, + { + version: 0, + pubKey: '0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + hex: 'adde4c73c7b9cee17da6c7b3e2b2eea1a0dcbe67', + base58check: '1GrLCmVQXoyJXaPJQdqssNqwxvha1eUo2E' + }, + { + version: 0, + pubKey: '04cfd1c01397fc8d81fc6330d1a938e93551118a6f6db2e470ee353ffc1a51798073ab8fdf1fa8ffabce209ffe00538aa67d6ea819ddaa9410264faa34397306d7', + hex: 'e95895d8f1c5755b94d87bc42528ed37956971c0', + base58check: '1NGpZiQe9BDt6QEErh7cQxoaxns5fV1u9m' + }, + { + version: 0, + pubKey: '03cfd1c01397fc8d81fc6330d1a938e93551118a6f6db2e470ee353ffc1a517980', + hex: '53991cac832df8180da4c97e77734a8fbce31fdf', + base58check: '18d2WLBU9YnrdpjYVS5xBpmk5KcUPwEbYU' + }, + { + version: 0, + pubKey: '0422c39cb05bb33be292ee678c590a11ebcc75850944c8937a93bebddac4fb66cb9a473714030a262a19db874c781aa37a0ab8b7f519c2a71e94767e50f5f8900b', + hex: 'e6942137944f168785f8551956ae9a3fbbd12dc1', + base58check: '1N2BsMh9XktPCo2WxadsTV8Eni5AJhF7WG' + }, + { + version: 0, + pubKey: '0322c39cb05bb33be292ee678c590a11ebcc75850944c8937a93bebddac4fb66cb', + hex: '02e70da0f47e5178ce258e6c9f220d17a538f7a6', + base58check: '1GM9F9uX4U9AgQzitsLQXghD7fb6cWNCX' + }, + { + version: 0, + pubKey: '04c0520eb902f43b6fe91fea74eb6cab3fd5c54a6646a7e012fd244eac7864e08e276506e819cced089947254d7ed7b9a502cc77421b8d48c3dd00820f82971c85', + hex: '2ac31bc5ced6f167ff5aa4b93043590c8d6fc59c', + base58check: '14u77S4ysnoiaQXaVWBokFYwhVuPTPf2Tk' + }, + { + version: 0, + pubKey: '03c0520eb902f43b6fe91fea74eb6cab3fd5c54a6646a7e012fd244eac7864e08e', + hex: 'e522cb50376421b2034ff2770421881f8b82ceaa', + base58check: '1MtZRUP1nB1wJ7ftUeLibBM6WXEksTUtiS' + }, + { + version: 111, + pubKey: '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', + hex: '91b24bf9f5288532960ac687abb035127b1d28a5', + base58check: 'mtoKs9V381UAhUia3d7Vb9GNak8Qvmcsme' + }, + { + version: 111, + pubKey: '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + hex: '751e76e8199196d454941c45d1b3a323f1433bd6', + base58check: 'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r' + }, + { + version: 111, + pubKey: '04750578aed9dd59b43d0f3fbbcf26ed132bed71d202183674e6f0f01b71ad25eea9c42714b1f602b87164f76ef169477a7db9591e10755783006ebfa9c11946c3', + hex: 'c4fa066a855f0e2739f21393595ca3d7ff422fb6', + base58check: 'myUUFhUhL3hY9AXgPeTT8jPf6he3Ti4vtG' + }, + { + version: 111, + pubKey: '03750578aed9dd59b43d0f3fbbcf26ed132bed71d202183674e6f0f01b71ad25ee', + hex: '6b420cc35afb4d96ea118dbf1fc8ef4b0990798c', + base58check: 'mqJ5iobyeWgQ43J1y4VSzGH4gFEkxw2dFV' + }, + { + version: 111, + pubKey: '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777', + hex: 'bec08011c9e76dcc42e739a2d7752c2e3ac86e6e', + base58check: 'mxuZHex9m2jEMKtR3vZCLC2AX9QuyLzj7L' + }, + { + version: 111, + pubKey: '0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + hex: 'adde4c73c7b9cee17da6c7b3e2b2eea1a0dcbe67', + base58check: 'mwNHVpaPLqQZJgrv8CpFhJ4GpvJGumskXi' + }, + { + version: 111, + pubKey: '04cfd1c01397fc8d81fc6330d1a938e93551118a6f6db2e470ee353ffc1a51798073ab8fdf1fa8ffabce209ffe00538aa67d6ea819ddaa9410264faa34397306d7', + hex: 'e95895d8f1c5755b94d87bc42528ed37956971c0', + base58check: 'n2nmrmVcxCf8sWhraG5zEt1upnTncBNXUE' + }, + { + version: 111, + pubKey: '03cfd1c01397fc8d81fc6330d1a938e93551118a6f6db2e470ee353ffc1a517980', + hex: '53991cac832df8180da4c97e77734a8fbce31fdf', + base58check: 'mo8yoPGSxaE7QwDAD14L1jz4wKDBG3e5bV' + }, + { + version: 111, + pubKey: '0422c39cb05bb33be292ee678c590a11ebcc75850944c8937a93bebddac4fb66cb9a473714030a262a19db874c781aa37a0ab8b7f519c2a71e94767e50f5f8900b', + hex: 'e6942137944f168785f8551956ae9a3fbbd12dc1', + base58check: 'n2Y9AQn8LnKdyuW8g9cFHQLZehfsDf33fp' + }, + { + version: 111, + pubKey: '0322c39cb05bb33be292ee678c590a11ebcc75850944c8937a93bebddac4fb66cb', + hex: '02e70da0f47e5178ce258e6c9f220d17a538f7a6', + base58check: 'mfnJSJEtL5uPwntcSTqiESu257GHwWoA52' + }, + { + version: 111, + pubKey: '04c0520eb902f43b6fe91fea74eb6cab3fd5c54a6646a7e012fd244eac7864e08e276506e819cced089947254d7ed7b9a502cc77421b8d48c3dd00820f82971c85', + hex: '2ac31bc5ced6f167ff5aa4b93043590c8d6fc59c', + base58check: 'mjR4QV9xgpEyMX1CD5ABaAmGZVW6MBcEML' + }, + { + version: 111, + pubKey: '03c0520eb902f43b6fe91fea74eb6cab3fd5c54a6646a7e012fd244eac7864e08e', + hex: 'e522cb50376421b2034ff2770421881f8b82ceaa', + base58check: 'n2QWiXTzbCTC5E9WCDK6R6ZRNWqTq1o9RY' + } + ], + scriptHash: [ + { + version: 5, + hex: '30e22c5ffe8d09ab93c9cfd719cb4a0b524bb298', + base58check: '369VJYu1PiVLvnQT72MakjzGUKwzgtuLrN' + }, + { + version: 5, + hex: '16b9b33baa6e597a60f62e57775e8c9e76e215c2', + base58check: '33mBFSCFsQ29FUNW1dZGfDm1DSfcdHwJjD' + }, + { + version: 5, + hex: '57fa71c2ada72b1656fb8e44c8c2635d4f76296f', + base58check: '39iCjQvovdxeDFbfFGTF7Fc7uxECKcuasG' + }, + { + version: 5, + hex: 'f6a9a87cd6b20cf56c5a9947e04c7fbeb9d4004a', + base58check: '3QBFPnjSz6NT9fcp6Rw7jffWBM3e6uD3Rp' + }, + { + version: 196, + hex: 'fc50013ecd7e130bb33dbe0bda5c0c4bda2278e6', + base58check: '2NGFL7Tfur3FshijLTq9xrp5EWMPrHHy4N1' + }, + { + version: 196, + hex: '81fad5e4b0f4a74d50f645e02a1929de3a434dee', + base58check: '2N56VePS9LHTxxKkDSYpHVT3tTBUzXzydDR' + }, + { + version: 196, + hex: 'f7bd4199de4b0a1e85fc7d79c6a90c108a4d789f', + base58check: '2NFq9cRNwPxerxpgk5ySL87JvJi8yvZPpP9' + }, + { + version: 196, + hex: 'b43c431f0b5d3ccb638d5e4358b08129faf5355d', + base58check: '2N9gDouPBrsvZoX5bKGFBNDoApKfsLpMVJf' + } + ], + malformed: [ + 'nQyyFDwTJW5K', + 'NEqYWpmWNgjM', + 'Bv6FiH8KsiJj9aZkvCcCEv', + '39yrcy7Q82EnCdetJzZfLhQj6spq', + 'wVtEiHQZekSnDHC512mwT3g7Ahr', + '3GfCH4v3ZjfVMy7raFPPaE9fkBbh' + ] +} diff --git a/test/script.js b/test/script.js index 3e7d045..00268dc 100644 --- a/test/script.js +++ b/test/script.js @@ -115,11 +115,10 @@ describe('Script', function() { it('should create valid multi-sig address', function() { script = Script.createMultiSigOutputScript(numSigs, compressedPubKeys.map(hexToBytes)) multisig = crypto.hash160(script.buffer) - var multiSigAddress = Address(multisig, network).toString() + var multisigAddress = new Address(multisig, network) - assert.ok(Address.validate(multiSigAddress)) - assert.equal(Address.getVersion(multiSigAddress), Network.bitcoin.scriptHash) - assert.equal(multiSigAddress,'32vYjxBb7pHJJyXgNk8UoK3BdRDxBzny2v') + assert.equal(multisigAddress.version, Network.bitcoin.scriptHash) + assert.equal(multisigAddress.toString(), '32vYjxBb7pHJJyXgNk8UoK3BdRDxBzny2v') }) it('should create valid redeemScript', function() { @@ -138,7 +137,7 @@ describe('Script', function() { assert.equal(sigs[0], '02ea1297665dd733d444f31ec2581020004892cdaaf3dd6c0107c615afb839785f') assert.equal(sigs[1], '02fab2dea1458990793f56f42e4a47dbf35a12a351f26fa5d7e0cc7447eaafa21f') assert.equal(sigs[2], '036c6802ce7e8113723dd92cdb852e492ebb157a871ca532c3cb9ed08248ff0e19') - assert.equal(Address(crypto.hash160(redeemScript), network).toString(), '32vYjxBb7pHJJyXgNk8UoK3BdRDxBzny2v') + assert.equal(new Address(crypto.hash160(redeemScript), network).toString(), '32vYjxBb7pHJJyXgNk8UoK3BdRDxBzny2v') }) }) }) diff --git a/test/transaction.js b/test/transaction.js index 1a80d33..dfc9fdd 100644 --- a/test/transaction.js +++ b/test/transaction.js @@ -1,10 +1,12 @@ +var assert = require('assert') +var convert = require('../src/convert') + +var Address = require('../src/address') +var ECKey = require('../src/eckey').ECKey var T = require('../src/transaction') var Transaction = T.Transaction var TransactionOut = T.TransactionOut -var convert = require('../src/convert') -var ECKey = require('../src/eckey').ECKey var Script = require('../src/script') -var assert = require('assert') var fixtureTxes = require('./fixtures/mainnet_tx') var fixtureTx1Hex = fixtureTxes.prevTx @@ -220,9 +222,11 @@ describe('Transaction', function() { describe('TransactionOut', function() { describe('scriptPubKey', function() { it('returns hex string', function() { + var address = Address.fromBase58Check("1AZpKpcfCzKDUeTFBQUL4MokQai3m3HMXv") + var txOut = new TransactionOut({ value: 50000, - script: Script.createOutputScript("1AZpKpcfCzKDUeTFBQUL4MokQai3m3HMXv") + script: Script.createOutputScript(address) }) assert.equal(txOut.scriptPubKey(), "76a91468edf28474ee22f68dfe7e56e76c017c1701b84f88ac") From eae613d2442eee484920692cb1114a11c542e8d8 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Fri, 18 Apr 2014 06:48:40 +1000 Subject: [PATCH 2/7] Adds error messages and better version checking --- src/address.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/address.js b/src/address.js index c519147..3a52de0 100644 --- a/src/address.js +++ b/src/address.js @@ -4,9 +4,9 @@ var crypto = require('./crypto') var network = require('./network') function Address(hash, version) { - assert(Buffer.isBuffer(hash)) - assert(hash.length === 20) - assert(typeof version === 'number') + assert(Buffer.isBuffer(hash), 'First argument must be a Buffer') + assert.strictEqual(hash.length, 20, 'Invalid hash length') + assert.strictEqual(version & 0xFF, version, 'Invalid version byte') this.hash = hash this.version = version From 1d1306b0549ddd5031799da0b1affe7f703112ce Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sun, 20 Apr 2014 04:38:33 +1000 Subject: [PATCH 3/7] Removes Address.fromPubKey and improves test vectors --- src/address.js | 12 +- src/eckey.js | 4 +- src/transaction.js | 3 +- test/address.js | 30 ++--- test/fixtures/address.js | 236 +++++++-------------------------------- 5 files changed, 53 insertions(+), 232 deletions(-) diff --git a/src/address.js b/src/address.js index 3a52de0..d1d7b82 100644 --- a/src/address.js +++ b/src/address.js @@ -1,7 +1,5 @@ var assert = require('assert') var base58check = require('./base58check') -var crypto = require('./crypto') -var network = require('./network') function Address(hash, version) { assert(Buffer.isBuffer(hash), 'First argument must be a Buffer') @@ -12,19 +10,13 @@ function Address(hash, version) { this.version = version } -// Static constructors +// Import functions Address.fromBase58Check = function(string) { var decode = base58check.decode(string) return new Address(decode.payload, decode.version) } - -Address.fromPubKey = function(pubKey, version) { - version = version || network.bitcoin.pubKeyHash - - var hash = crypto.hash160(pubKey.toBuffer()) - return new Address(hash, version) -} +Address.prototype.fromString = Address.prototype.fromBase58Check // Export functions Address.prototype.toBase58Check = function () { diff --git a/src/eckey.js b/src/eckey.js index fc0df5e..7a50f3f 100644 --- a/src/eckey.js +++ b/src/eckey.js @@ -121,7 +121,9 @@ ECPubKey.prototype.verify = function(hash, sig) { } ECPubKey.prototype.getAddress = function(version) { - return Address.fromPubKey(this, version) + version = version || network.bitcoin.pubKeyHash + + return new Address(crypto.hash160(this.toBuffer()), version) } // Export functions diff --git a/src/transaction.js b/src/transaction.js index a45817b..da35409 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -308,8 +308,7 @@ Transaction.prototype.sign = function(index, key, type, network) { type = type || SIGHASH_ALL network = network || Network.bitcoin - var address = Address.fromPubKey(key.pub, network.pubKeyHash) - + var address = key.pub.getAddress(network.pubKeyHash) var script = Script.createOutputScript(address, network) var hash = this.hashTransactionForSignature(script, index, type) var sig = key.sign(hash).concat([type]) diff --git a/test/address.js b/test/address.js index 2baffef..722fa08 100644 --- a/test/address.js +++ b/test/address.js @@ -1,16 +1,12 @@ var assert = require('assert') - var Address = require('..').Address -var ECPubKey = require('..').ECPubKey -var base58check = require('..').base58check - var fixtures = require('./fixtures/address') describe('Address', function() { var bothVectors = fixtures.pubKeyHash.concat(fixtures.scriptHash) describe('Constructor', function() { - it('matches the test vectors', function() { + it('does not mutate the input', function() { bothVectors.forEach(function(f) { var hash = new Buffer(f.hex, 'hex') var addr = new Address(hash, f.version) @@ -30,8 +26,8 @@ describe('Address', function() { }) }) - it('output matches the test vectors', function() { - bothVectors.forEach(function(f) { + bothVectors.forEach(function(f) { + it('imports ' + f.description + ' correctly', function() { var addr = Address.fromBase58Check(f.base58check) assert.equal(addr.version, f.version) @@ -40,25 +36,13 @@ describe('Address', function() { }) }) - describe('fromPubKey', function() { - it('output matches the test vectors', function() { - fixtures.pubKeyHash.forEach(function(f) { - var pub = ECPubKey.fromBuffer(new Buffer(f.pubKey, 'hex')) - var addr = Address.fromPubKey(pub, f.version) - - assert.equal(addr.version, f.version) - assert.equal(addr.hash.toString('hex'), f.hex) - }) - }) - }) - describe('toBase58Check', function() { - it('output matches the test vectors', function() { - bothVectors.forEach(function(f) { + bothVectors.forEach(function(f) { + it('exports ' + f.description + ' correctly', function() { var addr = Address.fromBase58Check(f.base58check) - var base58check = addr.toBase58Check() + var result = addr.toBase58Check() - assert.equal(base58check, f.base58check) + assert.equal(result, f.base58check) }) }) }) diff --git a/test/fixtures/address.js b/test/fixtures/address.js index ad282f2..a4af18d 100644 --- a/test/fixtures/address.js +++ b/test/fixtures/address.js @@ -1,198 +1,42 @@ module.exports = { - pubKeyHash: [ - { - version: 0, - pubKey: '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', - hex: '91b24bf9f5288532960ac687abb035127b1d28a5', - base58check: '1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm' - }, - { - version: 0, - pubKey: '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - hex: '751e76e8199196d454941c45d1b3a323f1433bd6', - base58check: '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH' - }, - { - version: 0, - pubKey: '04750578aed9dd59b43d0f3fbbcf26ed132bed71d202183674e6f0f01b71ad25eea9c42714b1f602b87164f76ef169477a7db9591e10755783006ebfa9c11946c3', - hex: 'c4fa066a855f0e2739f21393595ca3d7ff422fb6', - base58check: '1JxWxePiX2GHN444g5V5JpBLEi3LV8cHGS' - }, - { - version: 0, - pubKey: '03750578aed9dd59b43d0f3fbbcf26ed132bed71d202183674e6f0f01b71ad25ee', - hex: '6b420cc35afb4d96ea118dbf1fc8ef4b0990798c', - base58check: '1An8RkWzqVF9GvpQFVX5AM4jpFe43eoPfe' - }, - { - version: 0, - pubKey: '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777', - hex: 'bec08011c9e76dcc42e739a2d7752c2e3ac86e6e', - base58check: '1JPbzbsAx1HyaDQoLMapWGoqf9pD5uha5m' - }, - { - version: 0, - pubKey: '0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - hex: 'adde4c73c7b9cee17da6c7b3e2b2eea1a0dcbe67', - base58check: '1GrLCmVQXoyJXaPJQdqssNqwxvha1eUo2E' - }, - { - version: 0, - pubKey: '04cfd1c01397fc8d81fc6330d1a938e93551118a6f6db2e470ee353ffc1a51798073ab8fdf1fa8ffabce209ffe00538aa67d6ea819ddaa9410264faa34397306d7', - hex: 'e95895d8f1c5755b94d87bc42528ed37956971c0', - base58check: '1NGpZiQe9BDt6QEErh7cQxoaxns5fV1u9m' - }, - { - version: 0, - pubKey: '03cfd1c01397fc8d81fc6330d1a938e93551118a6f6db2e470ee353ffc1a517980', - hex: '53991cac832df8180da4c97e77734a8fbce31fdf', - base58check: '18d2WLBU9YnrdpjYVS5xBpmk5KcUPwEbYU' - }, - { - version: 0, - pubKey: '0422c39cb05bb33be292ee678c590a11ebcc75850944c8937a93bebddac4fb66cb9a473714030a262a19db874c781aa37a0ab8b7f519c2a71e94767e50f5f8900b', - hex: 'e6942137944f168785f8551956ae9a3fbbd12dc1', - base58check: '1N2BsMh9XktPCo2WxadsTV8Eni5AJhF7WG' - }, - { - version: 0, - pubKey: '0322c39cb05bb33be292ee678c590a11ebcc75850944c8937a93bebddac4fb66cb', - hex: '02e70da0f47e5178ce258e6c9f220d17a538f7a6', - base58check: '1GM9F9uX4U9AgQzitsLQXghD7fb6cWNCX' - }, - { - version: 0, - pubKey: '04c0520eb902f43b6fe91fea74eb6cab3fd5c54a6646a7e012fd244eac7864e08e276506e819cced089947254d7ed7b9a502cc77421b8d48c3dd00820f82971c85', - hex: '2ac31bc5ced6f167ff5aa4b93043590c8d6fc59c', - base58check: '14u77S4ysnoiaQXaVWBokFYwhVuPTPf2Tk' - }, - { - version: 0, - pubKey: '03c0520eb902f43b6fe91fea74eb6cab3fd5c54a6646a7e012fd244eac7864e08e', - hex: 'e522cb50376421b2034ff2770421881f8b82ceaa', - base58check: '1MtZRUP1nB1wJ7ftUeLibBM6WXEksTUtiS' - }, - { - version: 111, - pubKey: '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', - hex: '91b24bf9f5288532960ac687abb035127b1d28a5', - base58check: 'mtoKs9V381UAhUia3d7Vb9GNak8Qvmcsme' - }, - { - version: 111, - pubKey: '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - hex: '751e76e8199196d454941c45d1b3a323f1433bd6', - base58check: 'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r' - }, - { - version: 111, - pubKey: '04750578aed9dd59b43d0f3fbbcf26ed132bed71d202183674e6f0f01b71ad25eea9c42714b1f602b87164f76ef169477a7db9591e10755783006ebfa9c11946c3', - hex: 'c4fa066a855f0e2739f21393595ca3d7ff422fb6', - base58check: 'myUUFhUhL3hY9AXgPeTT8jPf6he3Ti4vtG' - }, - { - version: 111, - pubKey: '03750578aed9dd59b43d0f3fbbcf26ed132bed71d202183674e6f0f01b71ad25ee', - hex: '6b420cc35afb4d96ea118dbf1fc8ef4b0990798c', - base58check: 'mqJ5iobyeWgQ43J1y4VSzGH4gFEkxw2dFV' - }, - { - version: 111, - pubKey: '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777', - hex: 'bec08011c9e76dcc42e739a2d7752c2e3ac86e6e', - base58check: 'mxuZHex9m2jEMKtR3vZCLC2AX9QuyLzj7L' - }, - { - version: 111, - pubKey: '0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - hex: 'adde4c73c7b9cee17da6c7b3e2b2eea1a0dcbe67', - base58check: 'mwNHVpaPLqQZJgrv8CpFhJ4GpvJGumskXi' - }, - { - version: 111, - pubKey: '04cfd1c01397fc8d81fc6330d1a938e93551118a6f6db2e470ee353ffc1a51798073ab8fdf1fa8ffabce209ffe00538aa67d6ea819ddaa9410264faa34397306d7', - hex: 'e95895d8f1c5755b94d87bc42528ed37956971c0', - base58check: 'n2nmrmVcxCf8sWhraG5zEt1upnTncBNXUE' - }, - { - version: 111, - pubKey: '03cfd1c01397fc8d81fc6330d1a938e93551118a6f6db2e470ee353ffc1a517980', - hex: '53991cac832df8180da4c97e77734a8fbce31fdf', - base58check: 'mo8yoPGSxaE7QwDAD14L1jz4wKDBG3e5bV' - }, - { - version: 111, - pubKey: '0422c39cb05bb33be292ee678c590a11ebcc75850944c8937a93bebddac4fb66cb9a473714030a262a19db874c781aa37a0ab8b7f519c2a71e94767e50f5f8900b', - hex: 'e6942137944f168785f8551956ae9a3fbbd12dc1', - base58check: 'n2Y9AQn8LnKdyuW8g9cFHQLZehfsDf33fp' - }, - { - version: 111, - pubKey: '0322c39cb05bb33be292ee678c590a11ebcc75850944c8937a93bebddac4fb66cb', - hex: '02e70da0f47e5178ce258e6c9f220d17a538f7a6', - base58check: 'mfnJSJEtL5uPwntcSTqiESu257GHwWoA52' - }, - { - version: 111, - pubKey: '04c0520eb902f43b6fe91fea74eb6cab3fd5c54a6646a7e012fd244eac7864e08e276506e819cced089947254d7ed7b9a502cc77421b8d48c3dd00820f82971c85', - hex: '2ac31bc5ced6f167ff5aa4b93043590c8d6fc59c', - base58check: 'mjR4QV9xgpEyMX1CD5ABaAmGZVW6MBcEML' - }, - { - version: 111, - pubKey: '03c0520eb902f43b6fe91fea74eb6cab3fd5c54a6646a7e012fd244eac7864e08e', - hex: 'e522cb50376421b2034ff2770421881f8b82ceaa', - base58check: 'n2QWiXTzbCTC5E9WCDK6R6ZRNWqTq1o9RY' - } - ], - scriptHash: [ - { - version: 5, - hex: '30e22c5ffe8d09ab93c9cfd719cb4a0b524bb298', - base58check: '369VJYu1PiVLvnQT72MakjzGUKwzgtuLrN' - }, - { - version: 5, - hex: '16b9b33baa6e597a60f62e57775e8c9e76e215c2', - base58check: '33mBFSCFsQ29FUNW1dZGfDm1DSfcdHwJjD' - }, - { - version: 5, - hex: '57fa71c2ada72b1656fb8e44c8c2635d4f76296f', - base58check: '39iCjQvovdxeDFbfFGTF7Fc7uxECKcuasG' - }, - { - version: 5, - hex: 'f6a9a87cd6b20cf56c5a9947e04c7fbeb9d4004a', - base58check: '3QBFPnjSz6NT9fcp6Rw7jffWBM3e6uD3Rp' - }, - { - version: 196, - hex: 'fc50013ecd7e130bb33dbe0bda5c0c4bda2278e6', - base58check: '2NGFL7Tfur3FshijLTq9xrp5EWMPrHHy4N1' - }, - { - version: 196, - hex: '81fad5e4b0f4a74d50f645e02a1929de3a434dee', - base58check: '2N56VePS9LHTxxKkDSYpHVT3tTBUzXzydDR' - }, - { - version: 196, - hex: 'f7bd4199de4b0a1e85fc7d79c6a90c108a4d789f', - base58check: '2NFq9cRNwPxerxpgk5ySL87JvJi8yvZPpP9' - }, - { - version: 196, - hex: 'b43c431f0b5d3ccb638d5e4358b08129faf5355d', - base58check: '2N9gDouPBrsvZoX5bKGFBNDoApKfsLpMVJf' - } - ], - malformed: [ - 'nQyyFDwTJW5K', - 'NEqYWpmWNgjM', - 'Bv6FiH8KsiJj9aZkvCcCEv', - '39yrcy7Q82EnCdetJzZfLhQj6spq', - 'wVtEiHQZekSnDHC512mwT3g7Ahr', - '3GfCH4v3ZjfVMy7raFPPaE9fkBbh' - ] + pubKeyHash: [ + { + description: 'pubKeyHash (bitcoin)', + version: 0, + hex: '751e76e8199196d454941c45d1b3a323f1433bd6', + base58check: '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH' + }, + { + description: 'pubKeyHash (testnet)', + version: 111, + hex: '751e76e8199196d454941c45d1b3a323f1433bd6', + base58check: 'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r' + } + ], + scriptHash: [ + { + description: 'scriptHash (bitcoin)', + version: 5, + hex: 'cd7b44d0b03f2d026d1e586d7ae18903b0d385f6', + base58check: '3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr' + }, + { + description: 'scriptHash (testnet)', + version: 196, + hex: 'cd7b44d0b03f2d026d1e586d7ae18903b0d385f6', + base58check: '2NByiBUaEXrhmqAsg7BbLpcQSAQs1EDwt5w' + } + ], + malformed: [ + '45k2PvUfZw', + '8cVHMKGRJGMEVz', + 'AMPCMAGBmj9EE9oGED', + 'oJPsqvHTSFFWMcmNS3aDidZexw', + 'bpiuHmqwCdiHx4ASNLGvZeBw9taY', + '2ansc1MsREU2HetNdPGs2eHXTY16ircdyaH', + 'iTKsHH39ooQPFxzX6RFtjPESpQ1', + '4TU74v3jnoTZGV5UuJGcr7XRg7hU', + '2a3wk37F1YmfqVtBam4gEn63oNuj', + '3rtH2aquyk4q1KGaXuiMGxaGfVPH' + ] } From f3a55f63dc5ad39b141d5f49ef6d77eadc3d5deb Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sun, 20 Apr 2014 04:38:57 +1000 Subject: [PATCH 4/7] Assert uses strictEqual instead of direct comparison --- src/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script.js b/src/script.js index e8fd5e6..0343557 100644 --- a/src/script.js +++ b/src/script.js @@ -381,7 +381,7 @@ Script.createOutputScript = function(address, network) { return script } - assert(address.version === network.pubKeyHash) + assert.strictEqual(address.version, network.pubKeyHash, 'Unknown address type') // Standard pay-to-pubkey-hash script.writeOp(Opcode.map.OP_DUP) From 92f1c3e3190563cd56c2cdf8d04d0b5dfdb95162 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sun, 20 Apr 2014 04:44:30 +1000 Subject: [PATCH 5/7] Fixes Transaction.addOutput() param handling to match documentation Now (horrendously) supports other networks --- src/transaction.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/transaction.js b/src/transaction.js index da35409..98b74fe 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -85,26 +85,33 @@ Transaction.prototype.addInput = function (tx, outIndex) { * i) An existing TransactionOut object * ii) An address object or an address and a value * iii) An address:value string + * iv) Either ii), iii) with an optional network argument * */ -Transaction.prototype.addOutput = function (address, value) { +Transaction.prototype.addOutput = function (address, value, network) { if (arguments[0] instanceof TransactionOut) { this.outs.push(arguments[0]) return } if (arguments[0].indexOf(':') >= 0) { + network = value + var args = arguments[0].split(':') address = args[0] value = parseInt(args[1]) } + network = network || Network.bitcoin + // FIXME: Stricter Transaction API - address = Address.fromBase58Check(address) + if (!(address instanceof Address)) { + address = Address.fromBase58Check(address) + } this.outs.push(new TransactionOut({ value: value, - script: Script.createOutputScript(address) + script: Script.createOutputScript(address, network) })) } @@ -418,6 +425,7 @@ TransactionIn.prototype.clone = function () { }) } +// FIXME: Support for alternate networks var TransactionOut = function (data) { this.script = data.script instanceof Script ? data.script.clone() From 64dc11486c28a64da2bbb88ebce6bcb0611b9b29 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sun, 20 Apr 2014 04:49:04 +1000 Subject: [PATCH 6/7] Removes resolved TODO --- src/script.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/script.js b/src/script.js index 0343557..5525f48 100644 --- a/src/script.js +++ b/src/script.js @@ -224,7 +224,6 @@ Script.prototype.getToAddress = function(network) { return new Address(new Buffer(this.chunks[1]), network.scriptHash) } -//TODO: support testnet Script.prototype.getFromAddress = function(version) { version = version || Network.bitcoin.pubKeyHash From c44af2109e2f23bf3cfdacdce61515e7f3fe239b Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sun, 20 Apr 2014 04:54:50 +1000 Subject: [PATCH 7/7] Uses typeof address === 'string' instead --- src/message.js | 4 ++-- src/transaction.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/message.js b/src/message.js index dc4a9d5..6b0738c 100644 --- a/src/message.js +++ b/src/message.js @@ -46,9 +46,9 @@ function sign(key, message) { return sig } +// FIXME: stricter API? function verify(address, sig, message) { - // FIXME: stricter API? - if (!(address instanceof Address)) { + if (typeof address === 'string') { address = Address.fromBase58Check(address) } diff --git a/src/transaction.js b/src/transaction.js index 98b74fe..203762b 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -87,6 +87,7 @@ Transaction.prototype.addInput = function (tx, outIndex) { * iii) An address:value string * iv) Either ii), iii) with an optional network argument * + * FIXME: This is a bit convoluted */ Transaction.prototype.addOutput = function (address, value, network) { if (arguments[0] instanceof TransactionOut) { @@ -104,8 +105,7 @@ Transaction.prototype.addOutput = function (address, value, network) { network = network || Network.bitcoin - // FIXME: Stricter Transaction API - if (!(address instanceof Address)) { + if (typeof address === 'string') { address = Address.fromBase58Check(address) }