bitcore/test/address.js

480 lines
17 KiB
JavaScript
Raw Normal View History

2014-11-20 08:31:51 -08:00
'use strict';
2014-12-09 12:25:36 -08:00
/* jshint maxstatements: 30 */
var chai = require('chai');
var should = chai.should();
var expect = chai.expect;
2014-11-20 08:31:51 -08:00
var bitcore = require('..');
var PublicKey = bitcore.PublicKey;
2014-11-20 08:31:51 -08:00
var Address = bitcore.Address;
var Script = bitcore.Script;
var Networks = bitcore.Networks;
var validbase58 = require('./data/bitcoind/base58_keys_valid.json');
var invalidbase58 = require('./data/bitcoind/base58_keys_invalid.json');
2014-08-14 08:32:47 -07:00
describe('Address', function() {
var pubkeyhash = new Buffer('3c3fa3d4adcaf8f52d5b1843975e122548269937', 'hex');
2014-09-17 14:22:18 -07:00
var buf = Buffer.concat([new Buffer([0]), pubkeyhash]);
var str = '16VZnHwRhwrExfeHFHGjwrgEMq8VcYPs9r';
it('can\'t build without data', function() {
(function() {
2014-12-09 12:25:36 -08:00
return new Address();
}).should.throw('First argument is required, please include address data.');
});
it('should throw an error because of bad network param', function() {
(function(){
2014-12-09 12:25:36 -08:00
return new Address(PKHLivenet[0], 'main', 'pubkeyhash');
}).should.throw('Second argument must be "livenet" or "testnet".');
});
it('should throw an error because of bad type param', function() {
(function() {
2014-12-09 12:25:36 -08:00
return new Address(PKHLivenet[0], 'livenet', 'pubkey');
}).should.throw('Third argument must be "pubkeyhash" or "scripthash"');
});
describe('bitcoind compliance', function() {
validbase58.map(function(d){
if (!d[2].isPrivkey) {
it('should describe address ' + d[0] + ' as valid', function() {
var type;
if (d[2].addrType === 'script') {
type = 'scripthash';
} else if (d[2].addrType === 'pubkey') {
type = 'pubkeyhash';
}
var network = 'livenet';
if (d[2].isTestnet) {
network = 'testnet';
}
return new Address(d[0], network, type);
});
}
});
invalidbase58.map(function(d){
it('should describe input ' + d[0].slice(0,10) + '... as invalid', function() {
expect(function() {
return new Address(d[0]);
}).to.throw(Error);
});
});
});
// livenet valid
2014-12-09 12:25:36 -08:00
var PKHLivenet = [
'15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2',
'1A6ut1tWnUq1SEQLMr4ttDh24wcbJ5o9TT',
'1BpbpfLdY7oBS9gK7aDXgvMgr1DPvNhEB2',
'1Jz2yCRd5ST1p2gUqFB5wsSQfdm3jaFfg7'
];
// livenet p2sh
2014-12-09 12:25:36 -08:00
var P2SHLivenet = [
'342ftSRCvFHfCeFFBuz4xwbeqnDw6BGUey',
'33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk',
'37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3',
'3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy'
];
// testnet p2sh
2014-12-09 12:25:36 -08:00
var P2SHTestnet = [
'2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C',
'2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda',
'2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN',
'2NB72XtkjpnATMggui83aEtPawyyKvnbX2o'
];
//livenet bad checksums
var badChecksums = [
'15vkcKf7gB23wLAnZLmbVuMiiVDc3nq4a2',
'1A6ut1tWnUq1SEQLMr4ttDh24wcbj4w2TT',
'1BpbpfLdY7oBS9gK7aDXgvMgr1DpvNH3B2',
'1Jz2yCRd5ST1p2gUqFB5wsSQfdmEJaffg7'
];
//livenet non-base58
var nonBase58 = [
'15vkcKf7g#23wLAnZLmb$uMiiVDc3nq4a2',
'1A601ttWnUq1SEQLMr4ttDh24wcbj4w2TT',
'1BpbpfLdY7oBS9gK7aIXgvMgr1DpvNH3B2',
'1Jz2yCRdOST1p2gUqFB5wsSQfdmEJaffg7'
];
//testnet valid
2014-12-09 12:25:36 -08:00
var PKHTestnet = [
'n28S35tqEMbt6vNad7A5K3mZ7vdn8dZ86X',
'n45x3R2w2jaSC62BMa9MeJCd3TXxgvDEmm',
'mursDVxqNQmmwWHACpM9VHwVVSfTddGsEM',
'mtX8nPZZdJ8d3QNLRJ1oJTiEi26Sj6LQXS'
];
describe('validation', function() {
it('getValidationError detects network mismatchs', function() {
var error = Address.getValidationError('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo', 'testnet');
should.exist(error);
});
it('isValid returns true on a valid address', function(){
var valid = Address.isValid('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo', 'livenet');
valid.should.equal(true);
});
it('isValid returns false on network mismatch', function(){
var valid = Address.isValid('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo', 'testnet');
valid.should.equal(false);
});
it('validates correctly the P2PKH test vector', function() {
2014-12-09 12:25:36 -08:00
for (var i = 0; i < PKHLivenet.length; i++) {
var error = Address.getValidationError(PKHLivenet[i]);
should.not.exist(error);
}
2014-08-28 17:32:08 -07:00
});
it('validates correctly the P2SH test vector', function() {
2014-12-09 12:25:36 -08:00
for (var i = 0; i < P2SHLivenet.length; i++) {
var error = Address.getValidationError(P2SHLivenet[i]);
should.not.exist(error);
}
});
it('validates correctly the P2SH testnet test vector', function() {
2014-12-09 12:25:36 -08:00
for (var i = 0; i < P2SHTestnet.length; i++) {
var error = Address.getValidationError(P2SHTestnet[i], 'testnet');
should.not.exist(error);
}
2014-09-17 14:22:18 -07:00
});
it('rejects correctly the P2PKH livenet test vector with "testnet" parameter', function() {
2014-12-09 12:25:36 -08:00
for (var i = 0; i < PKHLivenet.length; i++) {
var error = Address.getValidationError(PKHLivenet[i], 'testnet');
should.exist(error);
}
});
2014-09-17 14:22:18 -07:00
it('validates correctly the P2PKH livenet test vector with "livenet" parameter', function() {
2014-12-09 12:25:36 -08:00
for (var i = 0; i < PKHLivenet.length; i++) {
var error = Address.getValidationError(PKHLivenet[i], 'livenet');
should.not.exist(error);
}
});
it('should not validate if checksum is invalid', function() {
2014-12-09 12:25:36 -08:00
for (var i = 0; i < badChecksums.length; i++) {
var error = Address.getValidationError(badChecksums[i], 'livenet', 'pubkeyhash');
should.exist(error);
error.message.should.equal('Checksum mismatch');
}
});
it('should not validate on a network mismatch', function() {
var error, i;
for (i = 0; i < PKHLivenet.length; i++) {
error = Address.getValidationError(PKHLivenet[i], 'testnet', 'pubkeyhash');
should.exist(error);
error.message.should.equal('Address has mismatched network type.');
}
for (i = 0; i < PKHTestnet.length; i++) {
error = Address.getValidationError(PKHTestnet[i], 'livenet', 'pubkeyhash');
should.exist(error);
error.message.should.equal('Address has mismatched network type.');
}
});
2014-08-13 15:00:41 -07:00
it('should not validate on a type mismatch', function() {
2014-12-09 12:25:36 -08:00
for (var i = 0; i < PKHLivenet.length; i++) {
var error = Address.getValidationError(PKHLivenet[i], 'livenet', 'scripthash');
should.exist(error);
error.message.should.equal('Address has mismatched type.');
}
2014-08-13 15:00:41 -07:00
});
it('should not validate on non-base58 characters', function() {
2014-12-09 12:25:36 -08:00
for (var i = 0; i < nonBase58.length; i++) {
var error = Address.getValidationError(nonBase58[i], 'livenet', 'pubkeyhash');
should.exist(error);
error.message.should.equal('Non-base58 character');
}
});
it('testnet addresses are validated correctly', function() {
2014-12-09 12:25:36 -08:00
for (var i = 0; i < PKHTestnet.length; i++) {
var error = Address.getValidationError(PKHTestnet[i], 'testnet');
should.not.exist(error);
}
});
2014-08-13 15:00:41 -07:00
});
describe('encodings', function() {
it('should make an address from a buffer', function() {
2014-12-09 12:25:36 -08:00
Address.fromBuffer(buf).toString().should.equal(str);
new Address(buf).toString().should.equal(str);
new Address(buf).toString().should.equal(str);
});
it('should make an address from a string', function() {
2014-12-09 12:25:36 -08:00
Address.fromString(str).toString().should.equal(str);
new Address(str).toString().should.equal(str);
});
it('should make an address using a non-string network', function() {
Address.fromString(str, Networks.livenet).toString().should.equal(str);
});
2014-11-23 12:34:19 -08:00
it('should error because of unrecognized data format', function() {
(function() {
2014-12-09 12:25:36 -08:00
return new Address(new Error());
2014-11-23 12:34:19 -08:00
}).should.throw('First argument is an unrecognized data format.');
});
it('should error because of incorrect format for pubkey hash', function() {
(function() {
2014-12-09 12:25:36 -08:00
return new Address.fromPublicKeyHash('notahash');
2014-11-23 12:34:19 -08:00
}).should.throw('Address supplied is not a buffer.');
});
it('should error because of incorrect format for script hash', function() {
(function() {
2014-12-09 12:25:36 -08:00
return new Address.fromScriptHash('notascript');
2014-11-23 12:34:19 -08:00
}).should.throw('Address supplied is not a buffer.');
});
it('should error because of incorrect type for transform buffer', function() {
(function() {
2014-12-09 12:25:36 -08:00
return Address._transformBuffer('notabuffer');
2014-11-23 12:34:19 -08:00
}).should.throw('Address supplied is not a buffer.');
});
it('should error because of incorrect length buffer for transform buffer', function() {
(function() {
2014-12-09 12:25:36 -08:00
return Address._transformBuffer(new Buffer(20));
2014-11-23 12:34:19 -08:00
}).should.throw('Address buffers must be exactly 21 bytes.');
});
it('should error because of incorrect type for pubkey transform', function() {
(function() {
2014-12-09 12:25:36 -08:00
return Address._transformPublicKey(new Buffer(20));
}).should.throw('Address must be an instance of PublicKey.');
2014-11-23 12:34:19 -08:00
});
it('should error because of incorrect type for script transform', function() {
(function() {
2014-12-09 12:25:36 -08:00
return Address._transformScript(new Buffer(20));
2014-11-23 12:34:19 -08:00
}).should.throw('Address must be an instance of Script.');
});
it('should error because of incorrect type for string transform', function() {
(function() {
2014-12-09 12:25:36 -08:00
return Address._transformString(new Buffer(20));
2014-11-23 12:34:19 -08:00
}).should.throw('Address supplied is not a string.');
});
it('should make an address from a pubkey hash buffer', function() {
var hash = pubkeyhash; //use the same hash
2014-12-09 12:25:36 -08:00
Address.fromPublicKeyHash(hash).toString().should.equal(str);
var b = Address.fromPublicKeyHash(hash, 'testnet');
b.network.should.equal(Networks.testnet);
b.type.should.equal('pubkeyhash');
2014-12-09 12:25:36 -08:00
new Address(hash).toString().should.equal(str);
});
it('should make an address using the default network', function() {
var hash = pubkeyhash; //use the same hash
var a = Address.fromPublicKeyHash(hash);
a.network.should.equal(Networks.livenet);
// change the default
Networks.defaultNetwork = Networks.testnet;
var b = Address.fromPublicKeyHash(hash);
b.network.should.equal(Networks.testnet);
// restore the default
Networks.defaultNetwork = Networks.livenet;
});
it('should throw an error for invalid length hashBuffer', function() {
(function() {
2014-12-09 12:25:36 -08:00
return Address.fromPublicKeyHash(buf);
2014-11-23 12:34:19 -08:00
}).should.throw('Address hashbuffers must be exactly 20 bytes.');
});
it('should make this address from a compressed pubkey', function() {
var pubkey = new PublicKey('0285e9737a74c30a873f74df05124f2aa6f53042c2fc0a130d6cbd7d16b944b004');
var address = Address.fromPublicKey(pubkey);
address.toString().should.equal('19gH5uhqY6DKrtkU66PsZPUZdzTd11Y7ke');
});
it('should make this address from an uncompressed pubkey', function() {
var pubkey = new PublicKey('0485e9737a74c30a873f74df05124f2aa6f53042c2fc0a130d6cbd7d16b944b00' +
'4833fef26c8be4c4823754869ff4e46755b85d851077771c220e2610496a29d98');
var a = Address.fromPublicKey(pubkey, 'livenet');
a.toString().should.equal('16JXnhxjJUhxfyx4y6H4sFcxrgt8kQ8ewX');
var b = new Address(pubkey, 'livenet', 'pubkeyhash');
b.toString().should.equal('16JXnhxjJUhxfyx4y6H4sFcxrgt8kQ8ewX');
});
describe('from a script', function() {
it('should make this address from a script', function() {
var s = Script.fromString('OP_CHECKMULTISIG');
var buf = s.toBuffer();
var a = Address.fromScript(s);
a.toString().should.equal('3BYmEwgV2vANrmfRymr1mFnHXgLjD6gAWm');
var b = new Address(s);
b.toString().should.equal('3BYmEwgV2vANrmfRymr1mFnHXgLjD6gAWm');
var c = Address.fromScriptHash(bitcore.crypto.Hash.sha256ripemd160(buf));
c.toString().should.equal('3BYmEwgV2vANrmfRymr1mFnHXgLjD6gAWm');
});
it('should make this address from other script', function() {
var s = Script.fromString('OP_CHECKSIG OP_HASH160');
var a = Address.fromScript(s);
a.toString().should.equal('347iRqVwks5r493N1rsLN4k9J7Ljg488W7');
var b = new Address(s);
b.toString().should.equal('347iRqVwks5r493N1rsLN4k9J7Ljg488W7');
});
it('returns the same address if the script is a pay to public key hash out', function() {
var address = '16JXnhxjJUhxfyx4y6H4sFcxrgt8kQ8ewX';
var script = Script.buildPublicKeyHashOut(new Address(address));
Address(script, Networks.livenet).toString().should.equal(address);
});
it('returns the same address if the script is a pay to script hash out', function() {
var address = '3BYmEwgV2vANrmfRymr1mFnHXgLjD6gAWm';
var script = Script.buildScriptHashOut(new Address(address));
Address(script, Networks.livenet).toString().should.equal(address);
});
});
it('should derive from this known address string livenet', function() {
var address = new Address(str);
var buffer = address.toBuffer();
var slice = buffer.slice(1);
var sliceString = slice.toString('hex');
sliceString.should.equal(pubkeyhash.toString('hex'));
});
it('should derive from this known address string testnet', function() {
2014-12-09 12:25:36 -08:00
var a = new Address(PKHTestnet[0], 'testnet');
var b = new Address(a.toString());
2014-12-09 12:25:36 -08:00
b.toString().should.equal(PKHTestnet[0]);
b.network.should.equal(Networks.testnet);
});
it('should derive from this known address string livenet scripthash', function() {
2014-12-09 12:25:36 -08:00
var a = new Address(P2SHLivenet[0], 'livenet', 'scripthash');
var b = new Address(a.toString());
2014-12-09 12:25:36 -08:00
b.toString().should.equal(P2SHLivenet[0]);
});
it('should derive from this known address string testnet scripthash', function() {
2014-12-09 12:25:36 -08:00
var address = new Address(P2SHTestnet[0], 'testnet', 'scripthash');
address = new Address(address.toString());
2014-12-09 12:25:36 -08:00
address.toString().should.equal(P2SHTestnet[0]);
});
});
describe('#toBuffer', function() {
it('3c3fa3d4adcaf8f52d5b1843975e122548269937 corresponds to hash 16VZnHwRhwrExfeHFHGjwrgEMq8VcYPs9r', function() {
var address = new Address(str);
address.toBuffer().slice(1).toString('hex').should.equal(pubkeyhash.toString('hex'));
});
});
describe('#json', function() {
it('roundtrip to-from-to', function() {
var json = new Address(str).toJSON();
var address = Address.fromJSON(json);
address.toString().should.equal(str);
});
it('checks that the string parameter is valid JSON', function() {
expect(function() {
return Address.fromJSON('¹');
}).to.throw();
});
});
describe('#toString', function() {
it('livenet pubkeyhash address', function() {
var address = new Address(str);
address.toString().should.equal(str);
});
it('scripthash address', function() {
2014-12-09 12:25:36 -08:00
var address = new Address(P2SHLivenet[0]);
address.toString().should.equal(P2SHLivenet[0]);
});
it('testnet scripthash address', function() {
2014-12-09 12:25:36 -08:00
var address = new Address(P2SHTestnet[0]);
address.toString().should.equal(P2SHTestnet[0]);
});
it('testnet pubkeyhash address', function() {
2014-12-09 12:25:36 -08:00
var address = new Address(PKHTestnet[0]);
address.toString().should.equal(PKHTestnet[0]);
});
});
2014-11-23 12:34:19 -08:00
describe('#inspect', function() {
it('should output formatted output correctly', function() {
var address = new Address(str);
var output = '<Address: 16VZnHwRhwrExfeHFHGjwrgEMq8VcYPs9r, type: pubkeyhash, network: livenet>';
2014-11-23 12:34:19 -08:00
address.inspect().should.equal(output);
});
2014-12-09 12:25:36 -08:00
});
2014-11-23 12:34:19 -08:00
2014-12-09 12:25:36 -08:00
describe('questions about the address', function() {
it('should detect a P2SH address', function() {
new Address(P2SHLivenet[0]).isPayToScriptHash().should.equal(true);
new Address(P2SHLivenet[0]).isPayToPublicKeyHash().should.equal(false);
new Address(P2SHTestnet[0]).isPayToScriptHash().should.equal(true);
new Address(P2SHTestnet[0]).isPayToPublicKeyHash().should.equal(false);
});
it('should detect a Pay To PubkeyHash address', function() {
new Address(PKHLivenet[0]).isPayToPublicKeyHash().should.equal(true);
new Address(PKHLivenet[0]).isPayToScriptHash().should.equal(false);
new Address(PKHTestnet[0]).isPayToPublicKeyHash().should.equal(true);
new Address(PKHTestnet[0]).isPayToScriptHash().should.equal(false);
});
2014-11-23 12:34:19 -08:00
});
describe('creating a P2SH address from public keys', function() {
var public1 = '02da5798ed0c055e31339eb9b5cef0d3c0ccdec84a62e2e255eb5c006d4f3e7f5b';
var public2 = '0272073bf0287c4469a2a011567361d42529cd1a72ab0d86aa104ecc89342ffeb0';
var public3 = '02738a516a78355db138e8119e58934864ce222c553a5407cf92b9c1527e03c1a2';
var publics = [public1, public2, public3];
it('can create an address from a set of public keys', function() {
var address = new Address(publics, 2);
address.toString().should.equal('3FtqPRirhPvrf7mVUSkygyZ5UuoAYrTW3y');
});
it('works on testnet also', function() {
var address = new Address(publics, 2, Networks.testnet);
address.toString().should.equal('2N7T3TAetJrSCruQ39aNrJvYLhG1LJosujf');
});
it('can also be created by Address.createMultisig', function() {
var address = Address.createMultisig(publics, 2);
var address2 = Address.createMultisig(publics, 2);
address.toString().should.equal(address2.toString());
});
});
});