From 786198f130ba2acbf1e8fa9afb2e65d51898f456 Mon Sep 17 00:00:00 2001 From: xnova <xnova@counterparty.co> Date: Wed, 5 Mar 2014 16:53:29 -0500 Subject: [PATCH] * Fixes address.js to be able to deal with testnet P2SH addresses * Enhanced address.js testsuite...now also verifies address versions * Enhances README to show how to run test suite --- README.md | 6 ++++++ src/address.js | 2 +- src/script.js | 17 +++++++++-------- test/address.js | 51 ++++++++++++++++++++++++++++--------------------- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 1adac0a..0c9e191 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,12 @@ Bitcoin library for node.js and browsers. `npm run-script compile` +## Run the test suite + +First install `mocha` (e.g. `npm install -g mocha` ). + +Then, just run `mocha` at the root of the `bitcoinjs-lib` checkout directory. + # Usage ## node.js diff --git a/src/address.js b/src/address.js index c99e4bd..a4e6a63 100644 --- a/src/address.js +++ b/src/address.js @@ -12,7 +12,7 @@ var Address = function (bytes, version) { } else if (typeof bytes === 'string') { this.hash = - bytes.length <= 34 ? base58.checkDecode(bytes) + bytes.length <= 35 ? base58.checkDecode(bytes) : bytes.length <= 40 ? conv.hexToBytes(bytes) : util.error('Bad input'); diff --git a/src/script.js b/src/script.js index d630727..1b48500 100644 --- a/src/script.js +++ b/src/script.js @@ -2,6 +2,7 @@ var Opcode = require('./opcode'); var util = require('./util'); var conv = require('./convert'); var Address = require('./address'); +var network = require('./network'); var Script = function(data) { this.buffer = data || []; @@ -295,20 +296,20 @@ Script.prototype.writeBytes = function(data) { Script.createOutputScript = function(address) { var script = new Script(); address = new Address(address); - // Standard pay-to-pubkey-hash - if (!address.version) { + if (address.version == network.mainnet.p2shVersion || address.version == network.testnet.p2shVersion) { + // Standard pay-to-script-hash + script.writeOp(Opcode.map.OP_HASH160); + script.writeBytes(address.hash); + script.writeOp(Opcode.map.OP_EQUAL); + } + 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); } - // Standard pay-to-script-hash - else { - script.writeOp(Opcode.map.OP_HASH160); - script.writeBytes(address.hash); - script.writeOp(Opcode.map.OP_EQUAL); - } return script; }; diff --git a/test/address.js b/test/address.js index 40de751..e5a505a 100644 --- a/test/address.js +++ b/test/address.js @@ -1,6 +1,7 @@ /* global describe, it */ var assert = require('assert'); var Address = require('../src/address.js'); +var network = require('../src/network.js'); describe('Address', function() { describe('toString', function() { @@ -12,41 +13,47 @@ describe('Address', function() { describe('validate', function() { it('validates known good addresses', function() { - function validate(addr) { + function validate(addr, expectedVersion) { assert.ok(Address.validate(addr)); + var address = new Address(addr); + assert.ok(address.version == expectedVersion); } - validate('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'); - // validate('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 'mainnet'); - validate('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef'); - // validate('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'testnet'); + validate('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', network.mainnet.addressVersion); + validate('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', network.testnet.addressVersion); - validate('12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP'); - validate('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y'); - validate('1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs'); - validate('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez'); - validate('116CGDLddrZhMrTwhCVJXtXQpxygTT1kHd'); + validate('12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP', network.mainnet.addressVersion); + validate('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', network.mainnet.addressVersion); + validate('1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs', network.mainnet.addressVersion); + validate('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez', network.mainnet.addressVersion); + validate('116CGDLddrZhMrTwhCVJXtXQpxygTT1kHd', network.mainnet.addressVersion); // p2sh addresses - validate('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt'); - // validate('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'mainnet'); - validate('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7'); - // validate('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'testnet'); + validate('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', network.mainnet.p2shVersion); + validate('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', network.testnet.p2shVersion); }) it('does not validate illegal examples', function() { function invalid(addr) { assert.ok(!Address.validate(addr)); } + function invalidNetwork(addr, unexpectedVersion) { + assert.ok(Address.validate(addr)); //must be a valid address itself + if(addr.length >= 34 && unexpectedVersion !== undefined) { + var address = new Address(addr); + if(unexpectedVersion !== undefined) + assert.ok(address.version != unexpectedVersion); + } + } - invalid(''); - invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhe'); - - // invalid('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 'testnet'); - // invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'mainnet'); - - // invalid base58 string - invalid('%%@'); + invalid(''); //empty should be invalid + invalid('%%@'); // invalid base58 string + invalid('1A1zP1eP5QGefi2DzPTf2L5SLmv7DivfNz'); // bad address (doesn't checksum) + invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhe'); // bad address (doesn't checksum) + + //and test for the wrong networks + invalidNetwork('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', network.mainnet.addressVersion); + invalidNetwork('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', network.testnet.addressVersion); }) }) })