address: make bech32 addrs more sane.
This commit is contained in:
parent
1eb08d39f4
commit
0ea341772c
@ -49,23 +49,14 @@ function Address(options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Address types. Note that the values
|
||||
* have a direct mapping to script types.
|
||||
* These also represent the "prefix type"
|
||||
* as a network-agnostic version of the
|
||||
* prefix byte. They DO NOT represent the
|
||||
* script type. For example, script type
|
||||
* `WITNESSMASTHASH` would be prefix type
|
||||
* `WITNESSSCRIPTHASH` with a `version`
|
||||
* of 1.
|
||||
* Address types.
|
||||
* @enum {Number}
|
||||
*/
|
||||
|
||||
Address.types = {
|
||||
PUBKEYHASH: common.types.PUBKEYHASH,
|
||||
SCRIPTHASH: common.types.SCRIPTHASH,
|
||||
WITNESSSCRIPTHASH: common.types.WITNESSSCRIPTHASH,
|
||||
WITNESSPUBKEYHASH: common.types.WITNESSPUBKEYHASH
|
||||
PUBKEYHASH: 2,
|
||||
SCRIPTHASH: 3,
|
||||
WITNESS: 4
|
||||
};
|
||||
|
||||
/**
|
||||
@ -128,7 +119,7 @@ Address.prototype.getPrefix = function getPrefix(network) {
|
||||
if (!network)
|
||||
network = this.network;
|
||||
network = Network.get(network);
|
||||
return Address.getPrefix(this.type, network);
|
||||
return Address.getPrefix(this.type, this.hash, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -231,7 +222,6 @@ Address.prototype.toBech32 = function toBech32(network) {
|
||||
network = this.network;
|
||||
|
||||
network = Network.get(network);
|
||||
|
||||
hrp = network.addressPrefix.bech32;
|
||||
|
||||
data = bech32.bitsify(hash, 65, 8, 5, version, 0);
|
||||
@ -248,14 +238,24 @@ Address.prototype.toBech32 = function toBech32(network) {
|
||||
*/
|
||||
|
||||
Address.prototype.fromString = function fromString(addr, network) {
|
||||
var i, type, hrp;
|
||||
|
||||
assert(typeof addr === 'string');
|
||||
assert(addr.length > 2);
|
||||
|
||||
if (addr[0] === 'b' && addr[1] === 'c')
|
||||
return this.fromBech32(addr, network);
|
||||
|
||||
if (addr[0] === 't' && addr[1] === 'b')
|
||||
return this.fromBech32(addr, network);
|
||||
if (network) {
|
||||
network = Network.get(network);
|
||||
hrp = network.addressPrefix.bech32;
|
||||
if (util.startsWith(addr, hrp))
|
||||
return this.fromBech32(addr, network);
|
||||
} else {
|
||||
for (i = 0; i < networks.types.length; i++) {
|
||||
type = networks.types[i];
|
||||
hrp = networks[type].addressPrefix.bech32;
|
||||
if (util.startsWith(addr, hrp))
|
||||
return this.fromBech32(addr, type);
|
||||
}
|
||||
}
|
||||
|
||||
return this.fromBase58(addr, network);
|
||||
};
|
||||
@ -383,7 +383,8 @@ Address.fromBase58 = function fromBase58(address, network) {
|
||||
*/
|
||||
|
||||
Address.prototype.fromBech32 = function fromBech32(data, network) {
|
||||
var i, addr, hash, type, version;
|
||||
var type = Address.types.WITNESS;
|
||||
var i, addr, hash, version;
|
||||
|
||||
assert(typeof data === 'string');
|
||||
|
||||
@ -410,19 +411,6 @@ Address.prototype.fromBech32 = function fromBech32(data, network) {
|
||||
|
||||
hash = bech32.bitsify(addr.data, 84, 5, 8, -1, 1);
|
||||
|
||||
// TODO: Remove this by dropping old segwit addrs.
|
||||
switch (hash.length) {
|
||||
case 20:
|
||||
type = Address.types.WITNESSPUBKEYHASH;
|
||||
break;
|
||||
case 32:
|
||||
type = Address.types.WITNESSSCRIPTHASH;
|
||||
break;
|
||||
default:
|
||||
assert(false, 'Unknown witness program data length.');
|
||||
break;
|
||||
}
|
||||
|
||||
return this.fromHash(hash, type, version, network.type);
|
||||
};
|
||||
|
||||
@ -468,21 +456,21 @@ Address.prototype.fromScript = function fromScript(script) {
|
||||
|
||||
if (script.isWitnessPubkeyhash()) {
|
||||
this.hash = script.get(1);
|
||||
this.type = Address.types.WITNESSPUBKEYHASH;
|
||||
this.type = Address.types.WITNESS;
|
||||
this.version = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (script.isWitnessScripthash()) {
|
||||
this.hash = script.get(1);
|
||||
this.type = Address.types.WITNESSSCRIPTHASH;
|
||||
this.type = Address.types.WITNESS;
|
||||
this.version = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (script.isWitnessMasthash()) {
|
||||
this.hash = script.get(1);
|
||||
this.type = Address.types.WITNESSSCRIPTHASH;
|
||||
this.type = Address.types.WITNESS;
|
||||
this.version = 1;
|
||||
return this;
|
||||
}
|
||||
@ -507,14 +495,14 @@ Address.prototype.fromWitness = function fromWitness(witness) {
|
||||
// since we can't get the version.
|
||||
if (witness.isPubkeyhashInput()) {
|
||||
this.hash = crypto.hash160(witness.get(1));
|
||||
this.type = Address.types.WITNESSPUBKEYHASH;
|
||||
this.type = Address.types.WITNESS;
|
||||
this.version = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (witness.isScripthashInput()) {
|
||||
this.hash = crypto.sha256(witness.get(witness.length - 1));
|
||||
this.type = Address.types.WITNESSSCRIPTHASH;
|
||||
this.type = Address.types.WITNESS;
|
||||
this.version = 0;
|
||||
return this;
|
||||
}
|
||||
@ -610,20 +598,19 @@ Address.prototype.fromHash = function fromHash(hash, type, version, network) {
|
||||
assert(util.isNumber(type));
|
||||
assert(util.isNumber(version));
|
||||
|
||||
assert(Address.getPrefix(type, network) !== -1, 'Not a valid address type.');
|
||||
assert(type >= Address.types.PUBKEYHASH && type <= Address.types.WITNESS,
|
||||
'Not a valid address type.');
|
||||
|
||||
if (version === -1) {
|
||||
assert(!Address.isWitness(type), 'Wrong version (witness)');
|
||||
assert(type !== Address.types.WITNESS, 'Wrong version (witness)');
|
||||
assert(hash.length === 20, 'Hash is the wrong size.');
|
||||
} else {
|
||||
assert(Address.isWitness(type), 'Wrong version (non-witness).');
|
||||
assert(type === Address.types.WITNESS, 'Wrong version (non-witness).');
|
||||
assert(version >= 0 && version <= 16, 'Bad program version.');
|
||||
if (version === 0 && type === Address.types.WITNESSPUBKEYHASH)
|
||||
assert(hash.length === 20, 'Hash is the wrong size.');
|
||||
else if (version === 0 && type === Address.types.WITNESSSCRIPTHASH)
|
||||
assert(hash.length === 32, 'Hash is the wrong size.');
|
||||
else if (version === 1 && type === Address.types.WITNESSSCRIPTHASH)
|
||||
assert(hash.length === 32, 'Hash is the wrong size.');
|
||||
if (version === 0 && type === Address.types.WITNESS) {
|
||||
assert(hash.length === 20 || hash.length === 32,
|
||||
'Witness program hash is the wrong size.');
|
||||
}
|
||||
assert(hash.length >= 2 && hash.length <= 40, 'Hash is the wrong size.');
|
||||
}
|
||||
|
||||
@ -706,7 +693,8 @@ Address.fromScripthash = function fromScripthash(hash, network) {
|
||||
*/
|
||||
|
||||
Address.prototype.fromWitnessPubkeyhash = function fromWitnessPubkeyhash(hash, network) {
|
||||
var type = Address.types.WITNESSPUBKEYHASH;
|
||||
var type = Address.types.WITNESS;
|
||||
assert(hash.length === 20, 'P2WPKH must be 20 bytes.');
|
||||
return this.fromHash(hash, type, 0, network);
|
||||
};
|
||||
|
||||
@ -730,7 +718,8 @@ Address.fromWitnessPubkeyhash = function fromWitnessPubkeyhash(hash, network) {
|
||||
*/
|
||||
|
||||
Address.prototype.fromWitnessScripthash = function fromWitnessScripthash(hash, network) {
|
||||
var type = Address.types.WITNESSSCRIPTHASH;
|
||||
var type = Address.types.WITNESS;
|
||||
assert(hash.length === 32, 'P2WPKH must be 32 bytes.');
|
||||
return this.fromHash(hash, type, 0, network);
|
||||
};
|
||||
|
||||
@ -755,25 +744,13 @@ Address.fromWitnessScripthash = function fromWitnessScripthash(hash, network) {
|
||||
*/
|
||||
|
||||
Address.prototype.fromProgram = function fromProgram(version, hash, network) {
|
||||
var type;
|
||||
var type = Address.types.WITNESS;
|
||||
|
||||
assert(version >= 0, 'Bad version for witness program.');
|
||||
|
||||
if (typeof hash === 'string')
|
||||
hash = new Buffer(hash, 'hex');
|
||||
|
||||
switch (hash.length) {
|
||||
case 20:
|
||||
type = Address.types.WITNESSPUBKEYHASH;
|
||||
break;
|
||||
case 32:
|
||||
type = Address.types.WITNESSSCRIPTHASH;
|
||||
break;
|
||||
default:
|
||||
assert(false, 'Unknown witness program data length.');
|
||||
break;
|
||||
}
|
||||
|
||||
return this.fromHash(hash, type, version, network);
|
||||
};
|
||||
|
||||
@ -813,7 +790,7 @@ Address.prototype.isScripthash = function isScripthash() {
|
||||
*/
|
||||
|
||||
Address.prototype.isWitnessPubkeyhash = function isWitnessPubkeyhash() {
|
||||
return this.version === 0 && this.type === Address.types.WITNESSPUBKEYHASH;
|
||||
return this.version === 0 && this.hash.length === 20;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -822,7 +799,7 @@ Address.prototype.isWitnessPubkeyhash = function isWitnessPubkeyhash() {
|
||||
*/
|
||||
|
||||
Address.prototype.isWitnessScripthash = function isWitnessScripthash() {
|
||||
return this.version === 0 && this.type === Address.types.WITNESSSCRIPTHASH;
|
||||
return this.version === 0 && this.hash.length === 32;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -831,7 +808,7 @@ Address.prototype.isWitnessScripthash = function isWitnessScripthash() {
|
||||
*/
|
||||
|
||||
Address.prototype.isWitnessMasthash = function isWitnessMasthash() {
|
||||
return this.version === 1 && this.type === Address.types.WITNESSSCRIPTHASH;
|
||||
return this.version === 1 && this.hash.length === 32;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -843,6 +820,21 @@ Address.prototype.isProgram = function isProgram() {
|
||||
return this.version !== -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the address is an unknown witness program.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Address.prototype.isUnknown = function isUnknown() {
|
||||
if (this.version === -1)
|
||||
return false;
|
||||
|
||||
if (this.version > 0)
|
||||
return true;
|
||||
|
||||
return this.hash.length !== 20 && this.hash.length !== 32;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the hash of a base58 address or address-related object.
|
||||
* @param {Base58Address|Address|Hash} data
|
||||
@ -878,21 +870,24 @@ Address.getHash = function getHash(data, enc) {
|
||||
/**
|
||||
* Get a network address prefix for a specified address type.
|
||||
* @param {AddressPrefix} type
|
||||
* @param {Buffer} hash
|
||||
* @param {Network} network
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Address.getPrefix = function getPrefix(type, network) {
|
||||
Address.getPrefix = function getPrefix(type, hash, network) {
|
||||
var prefixes = network.addressPrefix;
|
||||
switch (type) {
|
||||
case Address.types.PUBKEYHASH:
|
||||
return prefixes.pubkeyhash;
|
||||
case Address.types.SCRIPTHASH:
|
||||
return prefixes.scripthash;
|
||||
case Address.types.WITNESSPUBKEYHASH:
|
||||
return prefixes.witnesspubkeyhash;
|
||||
case Address.types.WITNESSSCRIPTHASH:
|
||||
return prefixes.witnessscripthash;
|
||||
case Address.types.WITNESS:
|
||||
if (hash.length === 20)
|
||||
return prefixes.witnesspubkeyhash;
|
||||
if (hash.length === 32)
|
||||
return prefixes.witnessscripthash;
|
||||
assert(false, 'No witness prefix defined.');
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -913,31 +908,14 @@ Address.getType = function getType(prefix, network) {
|
||||
case prefixes.scripthash:
|
||||
return Address.types.SCRIPTHASH;
|
||||
case prefixes.witnesspubkeyhash:
|
||||
return Address.types.WITNESSPUBKEYHASH;
|
||||
return Address.types.WITNESS;
|
||||
case prefixes.witnessscripthash:
|
||||
return Address.types.WITNESSSCRIPTHASH;
|
||||
return Address.types.WITNESS;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether an address type is a witness program.
|
||||
* @param {AddressPrefix} type
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Address.isWitness = function isWitness(type) {
|
||||
switch (type) {
|
||||
case Address.types.WITNESSPUBKEYHASH:
|
||||
return true;
|
||||
case Address.types.WITNESSSCRIPTHASH:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
@ -763,11 +763,8 @@ KeyRing.prototype.getType = function getType() {
|
||||
if (this.nested)
|
||||
return Address.types.SCRIPTHASH;
|
||||
|
||||
if (this.witness) {
|
||||
if (this.script)
|
||||
return Address.types.WITNESSSCRIPTHASH;
|
||||
return Address.types.WITNESSPUBKEYHASH;
|
||||
}
|
||||
if (this.witness)
|
||||
return Address.types.WITNESS;
|
||||
|
||||
if (this.script)
|
||||
return Address.types.SCRIPTHASH;
|
||||
|
||||
@ -157,6 +157,9 @@ Path.prototype.fromRaw = function fromRaw(data) {
|
||||
this.version = br.read8();
|
||||
this.type = br.readU8();
|
||||
|
||||
if (this.type === 129 || this.type === 130)
|
||||
this.type = 4;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
@ -257,8 +257,7 @@ describe('Bech32', function() {
|
||||
ok2 = null;
|
||||
}
|
||||
|
||||
ok = ok1 === null && ok2 === null;
|
||||
assert(ok);
|
||||
assert(!ok2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -578,7 +578,7 @@ describe('Chain', function() {
|
||||
it('should add wit addrs to miner', co(function* () {
|
||||
miner.addresses.length = 0;
|
||||
miner.addAddress(wwallet.getReceive());
|
||||
assert.equal(wwallet.getReceive().getType(), 'witnesspubkeyhash');
|
||||
assert.equal(wwallet.getReceive().getType(), 'witness');
|
||||
}));
|
||||
|
||||
it('should mine 2000 witness blocks', co(function* () {
|
||||
|
||||
@ -16,7 +16,6 @@ var Input = require('../lib/primitives/input');
|
||||
var Outpoint = require('../lib/primitives/outpoint');
|
||||
var Script = require('../lib/script/script');
|
||||
var HD = require('../lib/hd');
|
||||
var scriptTypes = Script.types;
|
||||
|
||||
var KEY1 = 'xprv9s21ZrQH143K3Aj6xQBymM31Zb4BVc7wxqfUhMZrzewdDVCt'
|
||||
+ 'qUP9iWfcHgJofs25xbaUpCps9GDXj83NiWvQCAkWQhVj5J4CorfnpKX94AZ';
|
||||
@ -114,9 +113,9 @@ describe('Wallet', function() {
|
||||
addr = Address.fromString(w.getAddress('string'));
|
||||
|
||||
if (witness)
|
||||
assert.equal(addr.type, scriptTypes.WITNESSPUBKEYHASH);
|
||||
assert.equal(addr.type, Address.types.WITNESS);
|
||||
else
|
||||
assert.equal(addr.type, scriptTypes.PUBKEYHASH);
|
||||
assert.equal(addr.type, Address.types.PUBKEYHASH);
|
||||
|
||||
src = new MTX();
|
||||
src.addInput(dummy());
|
||||
@ -652,11 +651,11 @@ describe('Wallet', function() {
|
||||
|
||||
if (witness) {
|
||||
if (bullshitNesting)
|
||||
assert.equal(addr.type, scriptTypes.SCRIPTHASH);
|
||||
assert.equal(addr.type, Address.types.SCRIPTHASH);
|
||||
else
|
||||
assert.equal(addr.type, scriptTypes.WITNESSSCRIPTHASH);
|
||||
assert.equal(addr.type, Address.types.WITNESS);
|
||||
} else {
|
||||
assert.equal(addr.type, scriptTypes.SCRIPTHASH);
|
||||
assert.equal(addr.type, Address.types.SCRIPTHASH);
|
||||
}
|
||||
|
||||
assert.equal(w1.account[rec].getAddress('string'), b58);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user