program. addresses.

This commit is contained in:
Christopher Jeffrey 2016-06-17 06:32:00 -07:00
parent 32e26446b1
commit 7862418ccc
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
10 changed files with 271 additions and 209 deletions

View File

@ -7,6 +7,7 @@ var utils = bcoin.utils;
var assert = utils.assert; var assert = utils.assert;
process.on('uncaughtException', function(err) { process.on('uncaughtException', function(err) {
bcoin.debug(err.stack);
bcoin.error(err); bcoin.error(err);
process.exit(1); process.exit(1);
}); });

View File

@ -35,6 +35,16 @@ function Address(options) {
if (!(this instanceof Address)) if (!(this instanceof Address))
return new Address(options); return new Address(options);
this.hash = null;
this.type = null;
this.version = null;
this.network = bcoin.network.get().type;
if (options)
this.fromOptions(options);
}
Address.prototype.fromOptions = function fromOptions(options) {
this.hash = options.hash; this.hash = options.hash;
this.type = options.type || 'pubkeyhash'; this.type = options.type || 'pubkeyhash';
this.version = options.version == null ? -1 : options.version; this.version = options.version == null ? -1 : options.version;
@ -42,7 +52,11 @@ function Address(options) {
if (!Buffer.isBuffer(this.hash)) if (!Buffer.isBuffer(this.hash))
this.hash = new Buffer(this.hash, 'hex'); this.hash = new Buffer(this.hash, 'hex');
} };
Address.fromOptions = function fromOptions(options) {
return new Address().fromOptions(options);
};
/** /**
* Get the address hash. * Get the address hash.
@ -161,7 +175,7 @@ Address.toBase58 = function toBase58(hash, type, version, network) {
* @throws Parse error * @throws Parse error
*/ */
Address.parseBase58 = function parseBase58(address) { Address.prototype.fromBase58 = function fromBase58(address) {
var i, prefix, type, version, hash, network, p; var i, prefix, type, version, hash, network, p;
if (!Buffer.isBuffer(address)) if (!Buffer.isBuffer(address))
@ -194,12 +208,12 @@ Address.parseBase58 = function parseBase58(address) {
p.verifyChecksum(); p.verifyChecksum();
return { this.network = network.type;
network: network.type, this.type = type;
type: type, this.hash = hash;
hash: hash, this.version = version == null ? -1 : version;
version: version == null ? -1 : version
}; return this;
}; };
/** /**
@ -210,7 +224,7 @@ Address.parseBase58 = function parseBase58(address) {
*/ */
Address.fromBase58 = function fromBase58(address) { Address.fromBase58 = function fromBase58(address) {
return new Address(Address.parseBase58(address)); return new Address().fromBase58(address);
}; };
/** /**
@ -221,50 +235,61 @@ Address.fromBase58 = function fromBase58(address) {
* @returns {ParsedAddress|null} * @returns {ParsedAddress|null}
*/ */
Address.parseScript = function parseScript(script) { Address.prototype.fromScript = function fromScript(script) {
var program, hash; var program, hash;
if (script.isWitnessProgram()) { if (script.isWitnessProgram()) {
program = script.getWitnessProgram(); program = script.toProgram();
if (!program.type || program.type === 'unknown') if (program.isUnknown())
return; return;
return { this.hash = program.data;
hash: program.data, this.type = program.type;
type: program.type, this.version = program.version;
version: program.version return this;
};
} }
// Fast case // Fast case
if (script.isPubkey()) { if (script.isPubkey()) {
hash = utils.ripesha(script.raw.slice(1, script.raw[0] + 1)); this.hash = utils.ripesha(script.raw.slice(1, script.raw[0] + 1));
return { hash: hash, type: 'pubkeyhash', version: -1 }; this.type = 'pubkeyhash';
this.version = -1;
return this;
} }
if (script.isPubkeyhash()) { if (script.isPubkeyhash()) {
hash = script.raw.slice(3, 23); this.hash = script.raw.slice(3, 23);
return { hash: hash, type: 'pubkeyhash', version: -1 }; this.type = 'pubkeyhash';
this.version = -1;
return this;
} }
if (script.isScripthash()) { if (script.isScripthash()) {
hash = script.raw.slice(2, 22); this.hash = script.raw.slice(2, 22);
return { hash: hash, type: 'scripthash', version: -1 }; this.type = 'scripthash';
this.version = -1;
return this;
} }
// Slow case (allow non-minimal data and parse script) // Slow case (allow non-minimal data and parse script)
if (script.isPubkey(true)) { if (script.isPubkey(true)) {
hash = utils.ripesha(script.code[0].data); this.hash = utils.ripesha(script.code[0].data);
return { hash: hash, type: 'pubkeyhash', version: -1 }; this.type = 'pubkeyhash';
this.version = -1;
return this;
} }
if (script.isPubkeyhash(true)) { if (script.isPubkeyhash(true)) {
hash = script.code[2].data; this.hash = script.code[2].data;
return { hash: hash, type: 'pubkeyhash', version: -1 }; this.type = 'pubkeyhash';
this.version = -1;
return this;
} }
if (script.isMultisig()) { if (script.isMultisig()) {
hash = utils.ripesha(script.raw); this.hash = utils.ripesha(script.raw);
return { hash: hash, type: 'scripthash', version: -1 }; this.type = 'scripthash';
this.version = -1;
return this;
} }
}; };
@ -275,17 +300,21 @@ Address.parseScript = function parseScript(script) {
* @returns {ParsedAddress|null} * @returns {ParsedAddress|null}
*/ */
Address.parseWitness = function parseWitness(witness) { Address.prototype.fromWitness = function fromWitness(witness) {
var hash; var hash;
if (witness.isPubkeyhashInput()) { if (witness.isPubkeyhashInput()) {
hash = utils.ripesha(witness.items[1]); this.hash = utils.ripesha(witness.items[1]);
return { hash: hash, type: 'witnesspubkeyhash', version: 0 }; this.type = 'witnesspubkeyhash';
this.version = 0;
return this;
} }
if (witness.isScripthashInput()) { if (witness.isScripthashInput()) {
hash = utils.sha256(witness.items[witness.items.length - 1]); this.hash = utils.sha256(witness.items[witness.items.length - 1]);
return { hash: hash, type: 'witnessscripthash', version: 0 }; this.type = 'witnessscripthash';
this.version = 0;
return this;
} }
}; };
@ -296,17 +325,21 @@ Address.parseWitness = function parseWitness(witness) {
* @returns {ParsedAddress|null} * @returns {ParsedAddress|null}
*/ */
Address.parseInputScript = function parseInputScript(script) { Address.prototype.fromInputScript = function fromInputScript(script) {
var hash; var hash;
if (script.isPubkeyhashInput()) { if (script.isPubkeyhashInput()) {
hash = utils.ripesha(script.code[1].data); this.hash = utils.ripesha(script.code[1].data);
return { hash: hash, type: 'pubkeyhash', version: -1 }; this.type = 'pubkeyhash';
this.version = -1;
return this;
} }
if (script.isScripthashInput()) { if (script.isScripthashInput()) {
hash = utils.ripesha(script.code[script.code.length - 1].data); this.hash = utils.ripesha(script.code[script.code.length - 1].data);
return { hash: hash, type: 'scripthash', version: -1 }; this.type = 'scripthash';
this.version = -1;
return this;
} }
}; };
@ -317,12 +350,7 @@ Address.parseInputScript = function parseInputScript(script) {
*/ */
Address.fromWitness = function fromWitness(witness) { Address.fromWitness = function fromWitness(witness) {
var data = Address.parseWitness(witness); return new Address().fromWitness(witness);
if (!data)
return;
return new Address(data);
}; };
/** /**
@ -332,12 +360,7 @@ Address.fromWitness = function fromWitness(witness) {
*/ */
Address.fromInputScript = function fromInputScript(script) { Address.fromInputScript = function fromInputScript(script) {
var data = Address.parseInputScript(script); return new Address().fromInputScript(script);
if (!data)
return;
return new Address(data);
}; };
/** /**
@ -347,12 +370,7 @@ Address.fromInputScript = function fromInputScript(script) {
*/ */
Address.fromScript = function fromScript(script) { Address.fromScript = function fromScript(script) {
var data = Address.parseScript(script); return new Address().fromScript(script);
if (!data)
return;
return new Address(data);
}; };
/** /**
@ -363,15 +381,16 @@ Address.fromScript = function fromScript(script) {
* @returns {ParsedAddress} * @returns {ParsedAddress}
*/ */
Address.parseHash = function parseHash(hash, type, version) { Address.prototype.fromHash = function fromHash(hash, type, version, network) {
if (!Buffer.isBuffer(hash)) if (typeof hash === 'string')
hash = new Buffer(hash, 'hex'); hash = new Buffer(hash, 'hex');
return { this.hash = hash;
hash: hash, this.type = type || 'pubkeyhash';
type: type || 'pubkeyhash', this.version = version == null ? -1 : version;
version: version == null ? -1 : version this.network = bcoin.network.get(network).type;
};
return this;
}; };
/** /**
@ -382,8 +401,8 @@ Address.parseHash = function parseHash(hash, type, version) {
* @returns {Address} * @returns {Address}
*/ */
Address.fromHash = function fromHash(hash, type, version) { Address.fromHash = function fromHash(hash, type, version, network) {
return new Address(Address.parseHash(hash, type, version)); return new Address().fromHash(hash, type, version, network);
}; };
/** /**
@ -394,13 +413,13 @@ Address.fromHash = function fromHash(hash, type, version) {
* @returns {ParsedAddress} * @returns {ParsedAddress}
*/ */
Address.parseData = function parseData(data, type, version) { Address.prototype.fromData = function fromData(data, type, version, network) {
if (type === 'witnessscripthash') if (type === 'witnessscripthash')
data = utils.sha256(data); data = utils.sha256(data);
else else
data = utils.ripesha(data); data = utils.ripesha(data);
return Address.parseHash(data, type, version); return this.fromHash(data, type, version, network);
}; };
/** /**
@ -411,8 +430,8 @@ Address.parseData = function parseData(data, type, version) {
* @returns {Address} * @returns {Address}
*/ */
Address.fromData = function fromData(data, type, version) { Address.fromData = function fromData(data, type, version, network) {
return new Address(Address.parseData(data, type, version)); return new Address().fromData(data, type, version, network);
}; };
/** /**
@ -430,7 +449,7 @@ Address.validate = function validate(address, type) {
return false; return false;
try { try {
address = Address.parseBase58(address); address = Address.fromBase58(address);
} catch (e) { } catch (e) {
return false; return false;
} }
@ -460,7 +479,7 @@ Address.getHash = function getHash(data, enc) {
hash = data.hash; hash = data.hash;
} else { } else {
try { try {
hash = Address.parseBase58(data).hash; hash = Address.fromBase58(data).hash;
} catch (e) { } catch (e) {
return; return;
} }

View File

@ -182,6 +182,7 @@ function Environment(options) {
this.walletdb = require('./walletdb'); this.walletdb = require('./walletdb');
this.provider = this.walletdb.Provider; this.provider = this.walletdb.Provider;
this.peer = require('./peer'); this.peer = require('./peer');
this.networkaddress = this.peer.NetworkAddress;
this.pool = require('./pool'); this.pool = require('./pool');
this.miner = require('./miner'); this.miner = require('./miner');
this.minerblock = this.miner.MinerBlock; this.minerblock = this.miner.MinerBlock;

View File

@ -275,12 +275,8 @@ Peer.prototype._onConnect = function _onConnect() {
version: constants.VERSION, version: constants.VERSION,
services: constants.LOCAL_SERVICES, services: constants.LOCAL_SERVICES,
ts: bcoin.now(), ts: bcoin.now(),
remote: {}, remote: new NetworkAddress(),
local: { local: this.pool.address,
services: constants.LOCAL_SERVICES,
host: this.pool.host,
port: this.pool.port
},
nonce: this.pool.localNonce, nonce: this.pool.localNonce,
agent: constants.USER_AGENT, agent: constants.USER_AGENT,
height: this.chain.height, height: this.chain.height,
@ -288,15 +284,10 @@ Peer.prototype._onConnect = function _onConnect() {
})); }));
// Advertise our address. // Advertise our address.
if (this.pool.host !== '0.0.0.0' if (this.pool.address.host !== '0.0.0.0'
&& !this.pool.options.selfish && !this.pool.options.selfish
&& this.pool.server) { && this.pool.server) {
this.write(this.framer.addr([{ this.write(this.framer.addr([this.pool.address]));
ts: utils.now() - (process.uptime() | 0),
services: constants.LOCAL_SERVICES,
host: this.pool.host,
port: this.pool.port
}]));
} }
}; };
@ -1443,7 +1434,7 @@ Peer.prototype._handleAddr = function _handleAddr(addrs) {
var i, addr; var i, addr;
for (i = 0; i < addrs.length; i++) { for (i = 0; i < addrs.length; i++) {
addr = new NetworkAddress(addrs[i]); addr = addrs[i];
this.addrFilter.add(addr.host, 'ascii'); this.addrFilter.add(addr.host, 'ascii');
hosts.push(addr); hosts.push(addr);
} }
@ -1866,17 +1857,23 @@ Peer.prototype.inspect = function inspect() {
*/ */
function NetworkAddress(options) { function NetworkAddress(options) {
var host, ts, now;
if (!(this instanceof NetworkAddress)) if (!(this instanceof NetworkAddress))
return new NetworkAddress(options); return new NetworkAddress(options);
now = utils.now(); this.id = NetworkAddress.uid++;
host = options.host; this.host = '0.0.0.0';
ts = options.ts; this.port = 0;
this.services = 0;
this.ts = 0;
if (ts <= 100000000 || ts > now + 10 * 60) if (options)
ts = now - 5 * 24 * 60 * 60; this.fromOptions(options);
}
NetworkAddress.uid = 0;
NetworkAddress.prototype.fromOptions = function fromOptions(options) {
var host = options.host;
if (IP.version(host) !== -1) if (IP.version(host) !== -1)
host = IP.normalize(host); host = IP.normalize(host);
@ -1886,14 +1883,17 @@ function NetworkAddress(options) {
assert(typeof options.services === 'number'); assert(typeof options.services === 'number');
assert(typeof options.ts === 'number'); assert(typeof options.ts === 'number');
this.id = NetworkAddress.uid++;
this.host = host; this.host = host;
this.port = options.port; this.port = options.port;
this.services = options.services; this.services = options.services;
this.ts = ts; this.ts = options.ts;
}
NetworkAddress.uid = 0; return this;
};
NetworkAddress.fromOptions = function fromOptions(options) {
return NetworkAddress().fromOptions(options);
};
/** /**
* Test whether the `host` field is an ip address. * Test whether the `host` field is an ip address.
@ -1962,18 +1962,63 @@ NetworkAddress.prototype.inspect = function inspect() {
* @returns {NetworkAddress} * @returns {NetworkAddress}
*/ */
NetworkAddress.fromHostname = function fromHostname(hostname, network) { NetworkAddress.prototype.fromHostname = function fromHostname(hostname, network) {
var address = IP.parseHost(hostname); var address = IP.parseHost(hostname);
network = bcoin.network.get(network); network = bcoin.network.get(network);
return new NetworkAddress({
host: address.host, this.host = address.host;
port: address.port || network.port, this.port = address.port || network.port;
version: constants.VERSION, this.version = constants.VERSION;
services: constants.services.NETWORK this.services = constants.services.NETWORK
| constants.services.BLOOM | constants.services.BLOOM
| constants.services.WITNESS, | constants.services.WITNESS;
ts: utils.now() this.ts = bcoin.now();
});
return this;
};
NetworkAddress.fromHostname = function fromHostname(hostname, network) {
return new NetworkAddress().fromHostname(hostname, network);
};
NetworkAddress.prototype.fromRaw = function fromRaw(data, full) {
var p = bcoin.reader(data);
var now = bcoin.now();
if (full) // only version >= 31402
this.ts = p.readU32();
else
this.ts = 0;
this.services = p.readU53();
this.host = IP.toString(p.readBytes(16));
this.port = p.readU16BE();
if (this.ts <= 100000000 || this.ts > now + 10 * 60)
this.ts = now - 5 * 24 * 60 * 60;
return this;
};
NetworkAddress.fromRaw = function fromRaw(data, full) {
return new NetworkAddress().fromRaw(data, full);
};
NetworkAddress.prototype.toRaw = function toRaw(full, writer) {
var p = bcoin.writer(writer);
if (full)
p.writeU32(this.ts);
p.writeU64(this.services);
p.writeBytes(IP.toBuffer(this.host));
p.writeU16BE(this.port);
if (!writer)
p = p.render();
return p;
}; };
/* /*

View File

@ -116,8 +116,13 @@ function Pool(options) {
this.hosts = []; this.hosts = [];
this.hostMap = {}; this.hostMap = {};
this.host = '0.0.0.0';
this.port = this.network.port; this.address = new NetworkAddress({
ts: utils.now() - (process.uptime() | 0),
services: constants.LOCAL_SERVICES,
host: '0.0.0.0',
port: this.network.port
});
this.server = null; this.server = null;
this.destroyed = false; this.destroyed = false;
@ -326,7 +331,7 @@ Pool.prototype._init = function _init() {
bcoin.error(err); bcoin.error(err);
if (ip) { if (ip) {
self.host = ip; self.address.host = ip;
bcoin.debug('External IP found: %s.', ip); bcoin.debug('External IP found: %s.', ip);
} }

View File

@ -407,34 +407,6 @@ Framer.prototype.feeFilter = function feeFilter(options) {
return this.packet('feefilter', Framer.feeFilter(options)); return this.packet('feefilter', Framer.feeFilter(options));
}; };
/**
* Serialize an address.
* @param {NakedNetworkAddress} data
* @param {Boolean?} full - Whether to include the timestamp.
* @param {BufferWriter?} writer - A buffer writer to continue writing from.
* @returns {Buffer} Returns a BufferWriter if `writer` was passed in.
*/
Framer.address = function address(data, full, writer) {
var p = new BufferWriter(writer);
if (full) {
if (!data.ts)
p.writeU32(utils.now() - (process.uptime() | 0));
else
p.writeU32(data.ts);
}
p.writeU64(data.services || 0);
p.writeBytes(IP.toBuffer(data.host));
p.writeU16BE(data.port || 0);
if (!writer)
p = p.render();
return p;
};
/** /**
* Create a version packet (without a header). * Create a version packet (without a header).
* @param {VersionPacket} options * @param {VersionPacket} options
@ -446,8 +418,8 @@ Framer.version = function version(options, writer) {
var p = new BufferWriter(writer); var p = new BufferWriter(writer);
var agent = options.agent || constants.USER_AGENT; var agent = options.agent || constants.USER_AGENT;
var services = options.services; var services = options.services;
var remote = options.remote || {}; var remote = options.remote || new bcoin.networkaddress();
var local = options.local || {}; var local = options.local || new bcoin.networkaddress();
var nonce = options.nonce; var nonce = options.nonce;
if (services == null) if (services == null)
@ -462,8 +434,8 @@ Framer.version = function version(options, writer) {
p.write32(options.version || constants.VERSION); p.write32(options.version || constants.VERSION);
p.writeU64(services); p.writeU64(services);
p.write64(options.ts || bcoin.now()); p.write64(options.ts || bcoin.now());
Framer.address(remote, false, p); remote.toRaw(false, p);
Framer.address(local, false, p); local.toRaw(false, p);
p.writeU64(nonce); p.writeU64(nonce);
p.writeVarString(agent, 'ascii'); p.writeVarString(agent, 'ascii');
p.write32(options.height || 0); p.write32(options.height || 0);
@ -765,7 +737,7 @@ Framer.reject = function reject(details, writer) {
/** /**
* Create an addr packet (without a header). * Create an addr packet (without a header).
* @param {NakedNetworkAddress[]} hosts * @param {NetworkAddress[]} hosts
* @param {BufferWriter?} writer - A buffer writer to continue writing from. * @param {BufferWriter?} writer - A buffer writer to continue writing from.
* @returns {Buffer} Returns a BufferWriter if `writer` was passed in. * @returns {Buffer} Returns a BufferWriter if `writer` was passed in.
*/ */
@ -777,7 +749,7 @@ Framer.addr = function addr(hosts, writer) {
p.writeVarint(hosts.length); p.writeVarint(hosts.length);
for (i = 0; i < hosts.length; i++) for (i = 0; i < hosts.length; i++)
Framer.address(hosts[i], true, p); hosts[i].toRaw(true, p);
if (!writer) if (!writer)
p = p.render(); p = p.render();

View File

@ -481,10 +481,10 @@ Parser.parseVersion = function parseVersion(p) {
version = p.read32(); version = p.read32();
services = p.readU53(); services = p.readU53();
ts = p.read53(); ts = p.read53();
recv = Parser.parseAddress(p, false); recv = bcoin.networkaddress.fromRaw(p, false);
if (p.left() > 0) { if (p.left() > 0) {
from = Parser.parseAddress(p, false); from = bcoin.networkaddress.fromRaw(p, false);
nonce = p.readU64(); nonce = p.readU64();
} else { } else {
from = {}; from = {};
@ -720,40 +720,10 @@ Parser.parseReject = function parseReject(p) {
}; };
}; };
/**
* Parse serialized network address.
* @param {Buffer|BufferReader} p
* @returns {NakedNetworkAddress}
*/
Parser.parseAddress = function parseAddress(p, full) {
var ts, services, ip, port;
p = new BufferReader(p);
if (full) // only version >= 31402
ts = p.readU32();
else
ts = 0;
services = p.readU53();
ip = p.readBytes(16);
port = p.readU16BE();
return {
ts: ts,
services: services,
host: IP.toString(ip),
port: port
};
};
/** /**
* Parse addr packet. * Parse addr packet.
* @param {Buffer|BufferReader} p * @param {Buffer|BufferReader} p
* @returns {NakedNetworkAddress[]} * @returns {NetworkAddress[]}
*/ */
Parser.parseAddr = function parseAddr(p) { Parser.parseAddr = function parseAddr(p) {
@ -767,7 +737,7 @@ Parser.parseAddr = function parseAddr(p) {
assert(count <= 10000, 'Too many addresses.'); assert(count <= 10000, 'Too many addresses.');
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
addrs.push(Parser.parseAddress(p, true)); addrs.push(bcoin.networkaddress.fromRaw(p, true));
return addrs; return addrs;
}; };

View File

@ -2771,7 +2771,7 @@ Script.prototype.isWitnessProgram = function isWitnessProgram() {
* @returns {Program|null} * @returns {Program|null}
*/ */
Script.prototype.getWitnessProgram = function getWitnessProgram() { Script.prototype.toProgram = function toProgram() {
var version, data, type; var version, data, type;
if (!this.isWitnessProgram()) if (!this.isWitnessProgram())
@ -2780,23 +2780,7 @@ Script.prototype.getWitnessProgram = function getWitnessProgram() {
version = Script.getSmall(this.raw[0]); version = Script.getSmall(this.raw[0]);
data = this.raw.slice(2); data = this.raw.slice(2);
if (version > 0) { return new Program(version, data);
// No interpretation of script (anyone can spend)
type = 'unknown';
} else if (version === 0 && data.length === 20) {
type = 'witnesspubkeyhash';
} else if (version === 0 && data.length === 32) {
type = 'witnessscripthash';
} else {
// Fail on bad version=0
type = null;
}
return {
version: version,
type: type,
data: data
};
}; };
/** /**
@ -3819,7 +3803,7 @@ Script.getWitnessSigops = function getWitnessSigops(input, output, witness, flag
assert((flags & constants.flags.VERIFY_P2SH) !== 0); assert((flags & constants.flags.VERIFY_P2SH) !== 0);
if (output.isWitnessProgram()) if (output.isWitnessProgram())
return Script.witnessSigops(output.getWitnessProgram(), witness, flags); return Script.witnessSigops(output.toProgram(), witness, flags);
// This is a unique situation in terms of consensus // This is a unique situation in terms of consensus
// rules. We can just grab the redeem script without // rules. We can just grab the redeem script without
@ -3831,7 +3815,7 @@ Script.getWitnessSigops = function getWitnessSigops(input, output, witness, flag
if (output.isScripthash() && input.isPushOnly()) { if (output.isScripthash() && input.isPushOnly()) {
redeem = input.getRedeem(); redeem = input.getRedeem();
if (redeem && redeem.isWitnessProgram()) if (redeem && redeem.isWitnessProgram())
return Script.witnessSigops(redeem.getWitnessProgram(), witness, flags); return Script.witnessSigops(redeem.toProgram(), witness, flags);
} }
return 0; return 0;
@ -4050,7 +4034,7 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
*/ */
Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) { Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) {
var program = output.getWitnessProgram(); var program = output.toProgram();
var stack = witness.toStack(); var stack = witness.toStack();
var witnessScript, redeem, j; var witnessScript, redeem, j;
@ -4505,6 +4489,47 @@ Opcode.isOpcode = function isOpcode(obj) {
&& (Buffer.isBuffer(obj.data) || obj.data === null); && (Buffer.isBuffer(obj.data) || obj.data === null);
}; };
/**
* Witness Program
* @constructor
* @private
* @param {Number} version
* @param {Buffer} data
*/
function Program(version, data) {
if (!(this instanceof Program))
return new Program(version, data);
this.version = version;
this.data = data;
this.type = null;
if (version > 0) {
// No interpretation of script (anyone can spend)
this.type = 'unknown';
} else if (version === 0 && data.length === 20) {
this.type = 'witnesspubkeyhash';
} else if (version === 0 && data.length === 32) {
this.type = 'witnessscripthash';
} else {
// Fail on bad version=0
this.type = null;
}
}
Program.prototype.isUnknown = function isUnknown() {
return !this.type || this.type === 'unknown';
};
Program.prototype.inspect = function inspect() {
return '<Program:'
+ ' version=' + this.version
+ ' data=' + this.data.toString('hex')
+ ' type=' + this.type
+ '>';
};
/* /*
* Expose * Expose
*/ */

View File

@ -31,14 +31,38 @@ describe('Protocol', function() {
}); });
} }
packetTest('version', {}, function(payload) { var v1 = {
version: constants.VERSION,
services: constants.LOCAL_SERVICES,
ts: bcoin.now(),
remote: new bcoin.networkaddress(),
local: new bcoin.networkaddress(),
nonce: utils.nonce(),
agent: constants.USER_AGENT,
height: 0,
relay: false
};
packetTest('version', v1, function(payload) {
assert.equal(payload.version, constants.VERSION); assert.equal(payload.version, constants.VERSION);
assert.equal(payload.agent, agent); assert.equal(payload.agent, agent);
assert.equal(payload.height, 0); assert.equal(payload.height, 0);
assert.equal(payload.relay, false); assert.equal(payload.relay, false);
}); });
packetTest('version', { relay: true, height: 10 }, function(payload) { var v2 = {
version: constants.VERSION,
services: constants.LOCAL_SERVICES,
ts: bcoin.now(),
remote: new bcoin.networkaddress(),
local: new bcoin.networkaddress(),
nonce: utils.nonce(),
agent: constants.USER_AGENT,
height: 10,
relay: true
};
packetTest('version', v2, function(payload) {
assert.equal(payload.version, constants.VERSION); assert.equal(payload.version, constants.VERSION);
assert.equal(payload.agent, agent); assert.equal(payload.agent, agent);
assert.equal(payload.height, 10); assert.equal(payload.height, 10);
@ -49,18 +73,18 @@ describe('Protocol', function() {
}); });
var hosts = [ var hosts = [
{ new bcoin.networkaddress({
services: constants.LOCAL_SERVICES, services: constants.LOCAL_SERVICES,
host: '127.0.0.1', host: '127.0.0.1',
port: 8333, port: 8333,
ts: Date.now() / 1000 | 0 ts: Date.now() / 1000 | 0
}, }),
{ new bcoin.networkaddress({
services: constants.LOCAL_SERVICES, services: constants.LOCAL_SERVICES,
host: '::123:456:789a', host: '::123:456:789a',
port: 18333, port: 18333,
ts: Date.now() / 1000 | 0 ts: Date.now() / 1000 | 0
} })
]; ];
packetTest('addr', hosts, function(payload) { packetTest('addr', hosts, function(payload) {

View File

@ -105,9 +105,9 @@ describe('Wallet', function() {
assert.ifError(err); assert.ifError(err);
if (witness) if (witness)
assert(bcoin.address.parseBase58(w.getAddress()).type === 'witnesspubkeyhash'); assert(bcoin.address.fromBase58(w.getAddress()).type === 'witnesspubkeyhash');
else else
assert(bcoin.address.parseBase58(w.getAddress()).type === 'pubkeyhash'); assert(bcoin.address.fromBase58(w.getAddress()).type === 'pubkeyhash');
var src = bcoin.mtx({ var src = bcoin.mtx({
outputs: [{ outputs: [{
@ -606,9 +606,9 @@ describe('Wallet', function() {
var addr = w1.getAddress(); var addr = w1.getAddress();
if (witness) if (witness)
assert(bcoin.address.parseBase58(addr).type === 'witnessscripthash'); assert(bcoin.address.fromBase58(addr).type === 'witnessscripthash');
else else
assert(bcoin.address.parseBase58(addr).type === 'scripthash'); assert(bcoin.address.fromBase58(addr).type === 'scripthash');
assert.equal(w1.getAddress(), addr); assert.equal(w1.getAddress(), addr);
assert.equal(w2.getAddress(), addr); assert.equal(w2.getAddress(), addr);