diff --git a/src/address.js b/src/address.js index 4b29a1f..0fb9383 100644 --- a/src/address.js +++ b/src/address.js @@ -1,4 +1,3 @@ -var assert = require('assert') var base58check = require('bs58check') var typeForce = require('typeforce') var networks = require('./networks') @@ -13,50 +12,52 @@ function findScriptTypeByVersion (version) { } } -function Address (hash, version) { - typeForce('Buffer', hash) - - assert.strictEqual(hash.length, 20, 'Invalid hash length') - assert.strictEqual(version & 0xff, version, 'Invalid version byte') - - this.hash = hash - this.version = version -} - -Address.fromBase58Check = function (string) { +function fromBase58Check (string) { var payload = base58check.decode(string) var version = payload.readUInt8(0) var hash = payload.slice(1) - return new Address(hash, version) + if (hash.length !== 20) throw new TypeError('Invalid hash length') + if (version & ~0xff) throw new TypeError('Invalid version byte') + + return { hash: hash, version: version } } -Address.fromOutputScript = function (script, network) { +function fromOutputScript (script, network) { network = network || networks.bitcoin - if (scripts.isPubKeyHashOutput(script)) return new Address(script.chunks[2], network.pubKeyHash) - if (scripts.isScriptHashOutput(script)) return new Address(script.chunks[1], network.scriptHash) + if (scripts.isPubKeyHashOutput(script)) return toBase58Check(script.chunks[2], network.pubKeyHash) + if (scripts.isScriptHashOutput(script)) return toBase58Check(script.chunks[1], network.scriptHash) throw new Error(script.toASM() + ' has no matching Address') } -Address.prototype.toBase58Check = function () { +function toBase58Check (hash, version) { + typeForce('Buffer', hash) + + if (hash.length !== 20) throw new TypeError('Invalid hash length') + if (version & ~0xff) throw new TypeError('Invalid version byte') + var payload = new Buffer(21) - payload.writeUInt8(this.version, 0) - this.hash.copy(payload, 1) + payload.writeUInt8(version, 0) + hash.copy(payload, 1) return base58check.encode(payload) } -Address.prototype.toOutputScript = function () { - var scriptType = findScriptTypeByVersion(this.version) +function toOutputScript (address) { + var decode = fromBase58Check(address) + var scriptType = findScriptTypeByVersion(decode.version) - if (scriptType === 'pubkeyhash') return scripts.pubKeyHashOutput(this.hash) - if (scriptType === 'scripthash') return scripts.scriptHashOutput(this.hash) + if (scriptType === 'pubkeyhash') return scripts.pubKeyHashOutput(decode.hash) + if (scriptType === 'scripthash') return scripts.scriptHashOutput(decode.hash) - throw new Error(this.toString() + ' has no matching Script') + throw new Error(address + ' has no matching Script') } -Address.prototype.toString = Address.prototype.toBase58Check - -module.exports = Address +module.exports = { + fromBase58Check: fromBase58Check, + fromOutputScript: fromOutputScript, + toBase58Check: toBase58Check, + toOutputScript: toOutputScript +} diff --git a/src/transaction_builder.js b/src/transaction_builder.js index 029ebaa..186c93d 100644 --- a/src/transaction_builder.js +++ b/src/transaction_builder.js @@ -37,7 +37,7 @@ function extractInput (txIn) { hashType = parsed.hashType pubKeys = scriptSig.chunks.slice(1) signatures = [parsed.signature] - prevOutScript = Address.fromBase58Check(ECPair.fromPublicKeyBuffer(pubKeys[0]).getAddress()).toOutputScript() + prevOutScript = Address.toOutputScript(ECPair.fromPublicKeyBuffer(pubKeys[0]).getAddress()) break } @@ -188,7 +188,7 @@ TransactionBuilder.prototype.addOutput = function (scriptPubKey, value) { // Attempt to get a valid address if it's a base58 address string if (typeof scriptPubKey === 'string') { - scriptPubKey = Address.fromBase58Check(scriptPubKey).toOutputScript() + scriptPubKey = Address.toOutputScript(scriptPubKey) } return this.tx.addOutput(scriptPubKey, value) @@ -358,7 +358,7 @@ TransactionBuilder.prototype.sign = function (index, keyPair, redeemScript, hash // we know nothin' Jon Snow, assume pubKeyHash } else { - input.prevOutScript = Address.fromBase58Check(keyPair.getAddress()).toOutputScript() + input.prevOutScript = Address.toOutputScript(keyPair.getAddress()) input.prevOutType = 'pubkeyhash' input.pubKeys = [kpPubKey] input.scriptType = input.prevOutType diff --git a/test/address.js b/test/address.js index 5259fdc..666832c 100644 --- a/test/address.js +++ b/test/address.js @@ -9,25 +9,13 @@ var Script = require('../src/script') var fixtures = require('./fixtures/address.json') describe('Address', function () { - describe('Constructor', function () { - it('does not mutate the input', function () { - fixtures.valid.forEach(function (f) { - var hash = new Buffer(f.hash, 'hex') - var addr = new Address(hash, f.version) - - assert.strictEqual(addr.version, f.version) - assert.strictEqual(addr.hash.toString('hex'), f.hash) - }) - }) - }) - describe('fromBase58Check', function () { fixtures.valid.forEach(function (f) { - it('imports ' + f.script + ' (' + f.network + ') correctly', function () { - var addr = Address.fromBase58Check(f.base58check) + it('decodes ' + f.base58check, function () { + var decode = Address.fromBase58Check(f.base58check) - assert.strictEqual(addr.version, f.version) - assert.strictEqual(addr.hash.toString('hex'), f.hash) + assert.strictEqual(decode.version, f.version) + assert.strictEqual(decode.hash.toString('hex'), f.hash) }) }) @@ -42,12 +30,11 @@ describe('Address', function () { describe('fromOutputScript', function () { fixtures.valid.forEach(function (f) { - it('imports ' + f.script + ' (' + f.network + ') correctly', function () { + it('parses ' + f.script + ' (' + f.network + ')', function () { var script = Script.fromASM(f.script) - var addr = Address.fromOutputScript(script, networks[f.network]) + var address = Address.fromOutputScript(script, networks[f.network]) - assert.strictEqual(addr.version, f.version) - assert.strictEqual(addr.hash.toString('hex'), f.hash) + assert.strictEqual(address, f.base58check) }) }) @@ -64,20 +51,18 @@ describe('Address', function () { describe('toBase58Check', function () { fixtures.valid.forEach(function (f) { - it('exports ' + f.script + ' (' + f.network + ') correctly', function () { - var addr = Address.fromBase58Check(f.base58check) - var result = addr.toBase58Check() + it('formats ' + f.hash + ' (' + f.network + ')', function () { + var address = Address.toBase58Check(new Buffer(f.hash, 'hex'), f.version) - assert.strictEqual(result, f.base58check) + assert.strictEqual(address, f.base58check) }) }) }) describe('toOutputScript', function () { fixtures.valid.forEach(function (f) { - it('imports ' + f.script + ' (' + f.network + ') correctly', function () { - var addr = Address.fromBase58Check(f.base58check) - var script = addr.toOutputScript() + it('exports ' + f.script + '(' + f.network + ')', function () { + var script = Address.toOutputScript(f.base58check) assert.strictEqual(script.toASM(), f.script) }) @@ -85,10 +70,8 @@ describe('Address', function () { fixtures.invalid.toOutputScript.forEach(function (f) { it('throws when ' + f.description, function () { - var addr = new Address(new Buffer(f.hash, 'hex'), f.version) - assert.throws(function () { - addr.toOutputScript() + Address.toOutputScript(f.address) }, new RegExp(f.description)) }) }) diff --git a/test/bitcoin.core.js b/test/bitcoin.core.js index 4ca39e3..5a20b18 100644 --- a/test/bitcoin.core.js +++ b/test/bitcoin.core.js @@ -65,10 +65,10 @@ describe('Bitcoin-core', function () { } it('can import ' + string, function () { - var address = Address.fromBase58Check(string) + var decode = Address.fromBase58Check(string) - assert.strictEqual(address.hash.toString('hex'), hex) - assert.strictEqual(address.version, network[typeMap[params.addrType]]) + assert.strictEqual(decode.hash.toString('hex'), hex) + assert.strictEqual(decode.version, network[typeMap[params.addrType]]) }) }) }) diff --git a/test/fixtures/address.json b/test/fixtures/address.json index fff8d9a..ec82861 100644 --- a/test/fixtures/address.json +++ b/test/fixtures/address.json @@ -59,8 +59,7 @@ "toOutputScript": [ { "description": "24kPZCmVgzfkpGdXExy56234MRHrsqQxNWE has no matching Script", - "hash": "751e76e8199196d454941c45d1b3a323f1433bd6", - "version": 153 + "address": "24kPZCmVgzfkpGdXExy56234MRHrsqQxNWE" } ] } diff --git a/test/transaction_builder.js b/test/transaction_builder.js index fdb0eb0..09dcb9a 100644 --- a/test/transaction_builder.js +++ b/test/transaction_builder.js @@ -65,13 +65,13 @@ describe('TransactionBuilder', function () { txb = new TransactionBuilder() prevTx = new Transaction() - prevTx.addOutput(Address.fromBase58Check('1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH').toOutputScript(), 0) - prevTx.addOutput(Address.fromBase58Check('1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP').toOutputScript(), 1) + prevTx.addOutput(Address.toOutputScript('1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH'), 0) + prevTx.addOutput(Address.toOutputScript('1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP'), 1) prevTxHash = prevTx.getHash() keyPair = new ECPair(BigInteger.ONE) privAddress = keyPair.getAddress() - privScript = Address.fromBase58Check(privAddress).toOutputScript() + privScript = Address.toOutputScript(privAddress) }) describe('addInput', function () {