more int and packet work.
This commit is contained in:
parent
5c1b136117
commit
4f8d24ba36
@ -47,6 +47,13 @@ function Block(data, subtype) {
|
||||
this.valid = null;
|
||||
this._hash = null;
|
||||
|
||||
// https://gist.github.com/sipa/bf69659f43e763540550
|
||||
// http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-August/010396.html
|
||||
this.versionBits = (this.version >>> 29) & 7;
|
||||
this.realVersion = this.version & 0x1fffffff;
|
||||
this.highVersion = this.version & 0x1ffffff8;
|
||||
this.lowVersion = this.version & 7;
|
||||
|
||||
// List of matched TXs
|
||||
this.tx = [];
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
var bn = require('bn.js');
|
||||
var bcoin = require('../bcoin');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
|
||||
/**
|
||||
* Output
|
||||
@ -30,6 +31,13 @@ function Output(options) {
|
||||
this.value = utils.satoshi(value || new bn(0));
|
||||
this.script = options.script ? options.script.slice() : [];
|
||||
|
||||
// For safety: do not allow usage of
|
||||
// Numbers, do not allow negative values.
|
||||
assert(typeof value !== 'number');
|
||||
assert(!this.value.isNeg())
|
||||
assert(this.value.bitLength() <= 63);
|
||||
assert(!(this.value.toArray('be', 8)[0] & 0x80));
|
||||
|
||||
if (options.script && options.script._raw)
|
||||
utils.hidden(this.script, '_raw', options.script._raw);
|
||||
}
|
||||
|
||||
@ -160,6 +160,7 @@ Peer.prototype._init = function init() {
|
||||
self.ack = true;
|
||||
self.emit('ack');
|
||||
self.ts = utils.now();
|
||||
self._write(self.framer.packet('getaddr', []));
|
||||
});
|
||||
};
|
||||
|
||||
@ -423,26 +424,45 @@ Peer.prototype._handleGetData = function handleGetData(items) {
|
||||
|
||||
Peer.prototype._handleAddr = function handleAddr(addrs) {
|
||||
var now = utils.now();
|
||||
|
||||
addrs.forEach(function(addr) {
|
||||
var ip, address4, address6;
|
||||
|
||||
if (addr.ts <= 100000000 || addr.ts > now + 10 * 60)
|
||||
addr.ts = now - 5 * 24 * 60 * 60;
|
||||
|
||||
ip = addr.ipv4 !== '0.0.0.0'
|
||||
? addr.ipv4
|
||||
: addr.ipv6;
|
||||
|
||||
address4 = addr.ipv4 !== '0.0.0.0'
|
||||
? addr.ipv4 + ':' + addr.port
|
||||
: null;
|
||||
|
||||
address6 = '[' + addr.ipv6 + ']:' + addr.port;
|
||||
|
||||
this.emit('addr', {
|
||||
date: new Date(addr.ts * 1000),
|
||||
ts: addr.ts,
|
||||
services: addr.services,
|
||||
ip: ip,
|
||||
ipv4: addr.ipv4,
|
||||
ipv6: addr.ipv6,
|
||||
host: addr.ipv4,
|
||||
host: ip,
|
||||
host4: addr.ipv4,
|
||||
host6: addr.ipv6,
|
||||
port: addr.port,
|
||||
addr: addr.ipv4 + ':' + addr.port,
|
||||
addr6: '[' + addr.ipv6 + ']:' + addr.port,
|
||||
// Deprecated:
|
||||
address: addr.ipv4,
|
||||
address6: addr.ipv6
|
||||
port: addr.port || network.port,
|
||||
address: address4 || address6,
|
||||
address4: address4,
|
||||
address6: address6
|
||||
});
|
||||
}, this);
|
||||
|
||||
this.pool.emit('debug',
|
||||
'Recieved %d peers (seeds=%d, peers=%d).',
|
||||
addrs.length,
|
||||
this.pool.seeds.length,
|
||||
this.pool.peers.all.length);
|
||||
};
|
||||
|
||||
Peer.prototype._handlePing = function handlePing(data) {
|
||||
@ -466,7 +486,7 @@ Peer.prototype._handleGetAddr = function handleGetAddr() {
|
||||
var peers;
|
||||
|
||||
peers = this.pool.peers.all.map(function(peer) {
|
||||
var ip, version, ipv4, ipv6;
|
||||
var ip, version;
|
||||
|
||||
if (!peer.socket || !peer.socket.remoteAddress)
|
||||
return;
|
||||
@ -482,19 +502,11 @@ Peer.prototype._handleGetAddr = function handleGetAddr() {
|
||||
|
||||
hosts[ip] = true;
|
||||
|
||||
if (version === 4) {
|
||||
ipv4 = utils.ip2array(ip, 4);
|
||||
ipv6 = utils.ip2array(ipv4, 6);
|
||||
} else if (version === 6) {
|
||||
ipv6 = utils.ip2array(ip, 6);
|
||||
ipv4 = utils.ip2array(ipv6, 4);
|
||||
}
|
||||
|
||||
return {
|
||||
ts: peer.ts,
|
||||
services: peer.version ? peer.version.services : null,
|
||||
ipv4: ipv4,
|
||||
ipv6: ipv6,
|
||||
ipv4: version === 4 ? ip : null,
|
||||
ipv6: version === 6 ? ip : null,
|
||||
port: peer.socket.remotePort || network.port
|
||||
};
|
||||
}).filter(Boolean);
|
||||
|
||||
@ -37,15 +37,15 @@ function Pool(options) {
|
||||
this.options.relay = this.options.relay == null
|
||||
? (this.options.fullNode ? true : false)
|
||||
: this.options.relay;
|
||||
this.options.seeds = options.seeds || network.seeds;
|
||||
|
||||
this.setSeeds(this.options.seeds);
|
||||
|
||||
this.storage = this.options.storage;
|
||||
this.destroyed = false;
|
||||
this.size = options.size || 32;
|
||||
this.parallel = options.parallel || 2000;
|
||||
this.redundancy = options.redundancy || 1;
|
||||
this.seeds = options.seeds
|
||||
? options.seeds.slice()
|
||||
: network.seeds.slice();
|
||||
|
||||
this._createConnection = options.createConnection;
|
||||
this._createSocket = options.createSocket;
|
||||
@ -251,29 +251,25 @@ Pool.prototype._stopInterval = function _stopInterval() {
|
||||
};
|
||||
|
||||
Pool.prototype.createConnection = function createConnection(peer, pool) {
|
||||
var addr, parts, host, net, socket, port;
|
||||
var addr, net, socket;
|
||||
|
||||
if (pool._createConnection)
|
||||
return pool._createConnection(peer, pool);
|
||||
|
||||
addr = pool.usableSeed(true);
|
||||
|
||||
parts = addr.split(':');
|
||||
host = parts[0];
|
||||
port = +parts[1] || network.port;
|
||||
|
||||
peer.host = host;
|
||||
peer.port = port;
|
||||
peer.host = addr.host;
|
||||
peer.port = addr.port;
|
||||
|
||||
if (this._createSocket) {
|
||||
socket = this._createSocket(port, host);
|
||||
socket = this._createSocket(addr.port, addr.host);
|
||||
} else {
|
||||
net = require('net');
|
||||
socket = net.connect(port, host);
|
||||
socket = net.connect(addr.port, addr.host);
|
||||
}
|
||||
|
||||
socket.on('connect', function() {
|
||||
pool.emit('debug', 'Connected to %s:%d', host, port);
|
||||
pool.emit('debug', 'Connected to %s:%d', addr.host, addr.port);
|
||||
});
|
||||
|
||||
return socket;
|
||||
@ -667,7 +663,7 @@ Pool.prototype._createPeer = function _createPeer(backoff) {
|
||||
});
|
||||
|
||||
peer.on('reject', function(payload) {
|
||||
payload.data = utils.toHex(payload.data);
|
||||
payload.data = utils.revHex(utils.toHex(payload.data));
|
||||
|
||||
self.emit('debug',
|
||||
'Reject: msg=%s ccode=%s reason=%s data=%s',
|
||||
@ -695,18 +691,13 @@ Pool.prototype._createPeer = function _createPeer(backoff) {
|
||||
self.emit('watched', tx, peer);
|
||||
});
|
||||
|
||||
peer.on('addr', function(addr) {
|
||||
var host = addr.ipv4 + ':' + addr.port;
|
||||
peer.on('addr', function(data) {
|
||||
if (self.seeds.length > 1000)
|
||||
self.setSeeds(self.options.seeds.concat(self.seeds.slice(-500)));
|
||||
|
||||
if (self.seeds.length > self.size * 2)
|
||||
self.seeds = network.seeds.slice();
|
||||
self.addSeed(data);
|
||||
|
||||
if (self.seeds.indexOf(host) !== -1) {
|
||||
self.emit('debug', 'Found new peer: %s', host);
|
||||
self.seeds.push(host);
|
||||
}
|
||||
|
||||
self.emit('addr', addr, peer);
|
||||
self.emit('addr', data, peer);
|
||||
});
|
||||
|
||||
peer.on('txs', function(txs) {
|
||||
@ -1444,18 +1435,16 @@ Pool.prototype.destroy = function destroy() {
|
||||
};
|
||||
|
||||
Pool.prototype.getPeer = function getPeer(addr) {
|
||||
var parts, host, port, i, peer;
|
||||
var i, peer;
|
||||
|
||||
if (!addr)
|
||||
return;
|
||||
|
||||
parts = addr.split(':');
|
||||
host = parts[0];
|
||||
port = +parts[1] || network.port;
|
||||
addr = utils.parseHost(addr);
|
||||
|
||||
for (i = 0; i < this.peers.all.length; i++) {
|
||||
peer = this.peers.all[i];
|
||||
if (peer.host === host)
|
||||
if (peer.host === addr.host)
|
||||
return peer;
|
||||
}
|
||||
};
|
||||
@ -1471,6 +1460,8 @@ Pool.prototype.usableSeed = function usableSeed(addrs, force) {
|
||||
if (!addrs)
|
||||
addrs = this.seeds;
|
||||
|
||||
assert(addrs.length);
|
||||
|
||||
addrs = addrs.slice().sort(function() {
|
||||
return Math.random() > 0.50 ? 1 : -1;
|
||||
});
|
||||
@ -1495,6 +1486,43 @@ Pool.prototype.usableSeed = function usableSeed(addrs, force) {
|
||||
return addr;
|
||||
};
|
||||
|
||||
Pool.prototype.setSeeds = function setSeeds(seeds) {
|
||||
this.seeds = [];
|
||||
this.hosts = {};
|
||||
seeds.forEach(function(seed) {
|
||||
this.addSeed(seed);
|
||||
}, this);
|
||||
};
|
||||
|
||||
Pool.prototype.addSeed = function addSeed(seed) {
|
||||
seed = utils.parseHost(seed);
|
||||
|
||||
if (this.hosts[seed.host] != null)
|
||||
return false;
|
||||
|
||||
this.seeds.push({
|
||||
host: seed.host,
|
||||
port: seed.port
|
||||
});
|
||||
|
||||
this.hosts[seed.host] = this.seeds.length - 1;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Pool.prototype.removeSeed = function removeSeed(seed) {
|
||||
seed = utils.parseHost(seed);
|
||||
|
||||
if (this.hosts[seed.host] == null)
|
||||
return false;
|
||||
|
||||
this.seeds.splice(this.hosts[seed.host], 1);
|
||||
|
||||
delete this.hosts[seed.host];
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Pool.prototype.toJSON = function toJSON() {
|
||||
return {
|
||||
v: 1,
|
||||
|
||||
@ -73,9 +73,6 @@ Framer.prototype._addr = function addr(p, off, data, full) {
|
||||
if (!data.ipv4)
|
||||
data.ipv4 = [];
|
||||
|
||||
if (!data.ipv6)
|
||||
data.ipv6 = [];
|
||||
|
||||
if (!data.port)
|
||||
data.port = network.port;
|
||||
|
||||
@ -86,19 +83,19 @@ Framer.prototype._addr = function addr(p, off, data, full) {
|
||||
// NODE_NETWORK services
|
||||
off += utils.writeU64(p, data.services, off);
|
||||
|
||||
// Empty bytes after services
|
||||
// (services takes the place of ts)
|
||||
if (!full)
|
||||
off += utils.writeU32(p, 0, off);
|
||||
|
||||
// ipv6
|
||||
off += utils.writeU32BE(p, utils.readU32BE(data.ipv6, 0), off);
|
||||
off += utils.writeU32BE(p, utils.readU32BE(data.ipv6, 4), off);
|
||||
off += utils.writeU32BE(p, utils.readU32BE(data.ipv6, 8), off);
|
||||
|
||||
// ipv4
|
||||
if (full)
|
||||
if (data.ipv6) {
|
||||
data.ipv6 = utils.ip2array(data.ipv6, 6);
|
||||
off += utils.writeU64BE(p, utils.readU64BE(data.ipv6, 0), off);
|
||||
off += utils.writeU64BE(p, utils.readU64BE(data.ipv6, 8), off);
|
||||
} else {
|
||||
data.ipv4 = utils.ip2array(data.ipv4, 4);
|
||||
// We don't have an ipv6, convert ipv4 to ipv4-mapped ipv6 address
|
||||
off += utils.writeU32BE(p, 0x00000000, off);
|
||||
off += utils.writeU32BE(p, 0x00000000, off);
|
||||
off += utils.writeU32BE(p, 0x0000ffff, off);
|
||||
off += utils.writeU32BE(p, utils.readU32BE(data.ipv4, 0), off);
|
||||
}
|
||||
|
||||
// port
|
||||
off += utils.writeU16BE(p, data.port, off);
|
||||
@ -280,7 +277,7 @@ Framer.tx = function tx(tx) {
|
||||
var p = [];
|
||||
var off, i, input, s, output, value, j;
|
||||
|
||||
off = writeU32(p, tx.version, 0);
|
||||
off = utils.write32(p, tx.version, 0);
|
||||
off += utils.writeIntv(p, tx.inputs.length, off);
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
@ -300,14 +297,8 @@ Framer.tx = function tx(tx) {
|
||||
for (i = 0; i < tx.outputs.length; i++) {
|
||||
output = tx.outputs[i];
|
||||
|
||||
// off += utils.write64(p, output.value, off);
|
||||
|
||||
// Put LE value
|
||||
value = output.value.toArray().slice().reverse();
|
||||
assert(value.length <= 8);
|
||||
off += utils.copy(value, p, off, true);
|
||||
for (j = value.length; j < 8; j++, off++)
|
||||
p[off] = 0;
|
||||
off += utils.write64(p, output.value, off);
|
||||
assert(output.value.byteLength() <= 8);
|
||||
|
||||
s = bcoin.script.encode(output.script);
|
||||
off += utils.writeIntv(p, s.length, off);
|
||||
@ -325,22 +316,19 @@ Framer.prototype.tx = function tx(tx) {
|
||||
Framer.block = function _block(block, type) {
|
||||
var p = [];
|
||||
var off = 0;
|
||||
var i;
|
||||
|
||||
if (!type)
|
||||
type = block.subtype;
|
||||
|
||||
// version
|
||||
off += writeU32(p, block.version, off);
|
||||
off += utils.write32(p, block.version, off);
|
||||
|
||||
// prev_block
|
||||
utils.toArray(block.prevBlock, 'hex').forEach(function(ch) {
|
||||
p[off++] = ch;
|
||||
});
|
||||
off += utils.copy(utils.toArray(block.prevBlock, 'hex'), p, off, true);
|
||||
|
||||
// merkle_root
|
||||
utils.toArray(block.merkleRoot, 'hex').forEach(function(ch) {
|
||||
p[off++] = ch;
|
||||
});
|
||||
off += utils.copy(utils.toArray(block.merkleRoot, 'hex'), p, off, true);
|
||||
|
||||
// timestamp
|
||||
off += writeU32(p, block.ts, off);
|
||||
@ -359,27 +347,19 @@ Framer.block = function _block(block, type) {
|
||||
// hash count
|
||||
off += utils.writeIntv(p, block.hashes.length, off);
|
||||
// hashes
|
||||
block.hashes.forEach(function(hash) {
|
||||
utils.toArray(hash, 'hex').forEach(function(ch) {
|
||||
p[off++] = ch;
|
||||
});
|
||||
});
|
||||
for (i = 0; i < block.hashes.length; i++)
|
||||
off += utils.copy(utils.toArray(block.hashes[i], 'hex'), p, off, true);
|
||||
// flag count
|
||||
off += utils.writeIntv(p, block.flags.length, off);
|
||||
// flags
|
||||
block.flags.forEach(function(flag) {
|
||||
p[off++] = flag;
|
||||
});
|
||||
} else if (type === 'block') {
|
||||
for (i = 0; i < block.flags.length; i++)
|
||||
p[off++] = block.flags[i];
|
||||
} else {
|
||||
// txn_count
|
||||
off += utils.writeIntv(p, block.totalTX, off);
|
||||
off += utils.writeIntv(p, block.txs.length, off);
|
||||
// txs
|
||||
block.txs.forEach(function(tx) {
|
||||
var raw = tx._raw || tx.render();
|
||||
raw.forEach(function(ch) {
|
||||
p[off++] = ch;
|
||||
});
|
||||
});
|
||||
for (i = 0; i < block.txs.length; i++)
|
||||
off += utils.copy(block.txs[i].render(), p, off, true);
|
||||
}
|
||||
|
||||
return p;
|
||||
@ -390,8 +370,6 @@ Framer.prototype.block = function _block(block) {
|
||||
};
|
||||
|
||||
Framer.prototype.merkleBlock = function merkleBlock(block) {
|
||||
// XXX Technically we're also supposed to send `tx` packets accompanying the
|
||||
// merkleblock here if we have them, as per the offical bitcoin client.
|
||||
return this.packet('merkleblock', Framer.block(block, 'merkleblock'));
|
||||
};
|
||||
|
||||
@ -405,18 +383,15 @@ Framer.prototype.reject = function reject(details) {
|
||||
var data = details.data || [];
|
||||
|
||||
off += utils.writeIntv(p, message.length, off);
|
||||
utils.writeAscii(p, message, off);
|
||||
off += message.length;
|
||||
off += utils.writeAscii(p, message, off);
|
||||
|
||||
p[off] = ccode;
|
||||
off++;
|
||||
|
||||
off += utils.writeIntv(p, reason.length, off);
|
||||
utils.writeAscii(p, reason, off);
|
||||
off += reason.length;
|
||||
off += utils.writeAscii(p, reason, off);
|
||||
|
||||
utils.copy(data, p, off, true);
|
||||
off += data.length;
|
||||
off += utils.copy(data, p, off, true);
|
||||
|
||||
return this.packet('reject', p);
|
||||
};
|
||||
@ -433,7 +408,7 @@ Framer.prototype.addr = function addr(peers) {
|
||||
|
||||
off += this._addr(p, off, {
|
||||
ts: peer.ts,
|
||||
services: 1,
|
||||
services: peer.services,
|
||||
ipv6: peer.ipv6,
|
||||
ipv4: peer.ipv4,
|
||||
port: peer.port
|
||||
|
||||
@ -275,7 +275,7 @@ Parser.prototype.parseMerkleBlock = function parseMerkleBlock(p) {
|
||||
flags = utils.toArray(p.slice(off, off + flagCount));
|
||||
|
||||
return {
|
||||
version: readU32(p, 0),
|
||||
version: utils.read32(p, 0),
|
||||
prevBlock: utils.toArray(p.slice(4, 36)),
|
||||
merkleRoot: utils.toArray(p.slice(36, 68)),
|
||||
ts: readU32(p, 68),
|
||||
@ -348,7 +348,7 @@ Parser.prototype.parseBlock = function parseBlock(p) {
|
||||
}
|
||||
|
||||
return {
|
||||
version: readU32(p, 0),
|
||||
version: utils.read32(p, 0),
|
||||
prevBlock: utils.toArray(p.slice(4, 36)),
|
||||
merkleRoot: utils.toArray(p.slice(36, 68)),
|
||||
ts: readU32(p, 68),
|
||||
@ -461,7 +461,7 @@ Parser.prototype.parseTX = function parseTX(p) {
|
||||
|
||||
return {
|
||||
_raw: p.slice(0, off + 4),
|
||||
version: readU32(p, 0),
|
||||
version: utils.read32(p, 0),
|
||||
inputs: txIn,
|
||||
outputs: txOut,
|
||||
lock: readU32(p, off),
|
||||
@ -511,7 +511,7 @@ Parser.prototype.parseReject = function parseReject(p) {
|
||||
};
|
||||
|
||||
Parser.prototype._parseAddr = function _parseAddr(p, off, full) {
|
||||
var ts, services, ip, ipv6, ipv4, port;
|
||||
var ts, services, ip, port;
|
||||
|
||||
if (!off)
|
||||
off = 0;
|
||||
@ -528,20 +528,9 @@ Parser.prototype._parseAddr = function _parseAddr(p, off, full) {
|
||||
services = utils.readU64(p, off);
|
||||
off += 8;
|
||||
|
||||
// Empty bytes after services
|
||||
// (services takes the place of ts)
|
||||
if (!full)
|
||||
off += 4;
|
||||
|
||||
// ipv6 - BE
|
||||
ipv6 = utils.toArray(p.slice(off, off + 12));
|
||||
off += 12;
|
||||
|
||||
// ipv4 - BE
|
||||
if (full) {
|
||||
ipv4 = utils.toArray(p.slice(off, off + 4));
|
||||
off += 4;
|
||||
}
|
||||
ip = utils.toArray(p.slice(off, off + 16));
|
||||
off += 16;
|
||||
|
||||
// port - BE
|
||||
port = utils.readU16BE(p, off);
|
||||
@ -556,8 +545,8 @@ Parser.prototype._parseAddr = function _parseAddr(p, off, full) {
|
||||
return {
|
||||
ts: ts,
|
||||
services: services,
|
||||
ipv6: utils.array2ip(ipv6, 6),
|
||||
ipv4: utils.array2ip(ipv4 || ipv6, 4),
|
||||
ipv6: utils.array2ip(ip, 6),
|
||||
ipv4: utils.array2ip(ip, 4),
|
||||
port: port
|
||||
};
|
||||
};
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
var utils = exports;
|
||||
|
||||
var bcoin = require('../bcoin');
|
||||
var bn = require('bn.js');
|
||||
var hash = require('hash.js');
|
||||
var util = require('util');
|
||||
@ -528,6 +529,25 @@ utils.toFloat = function toFloat(val) {
|
||||
throw new Error('Could not convert ' + val + ' to float');
|
||||
};
|
||||
|
||||
utils.parseHost = function parseHost(addr) {
|
||||
var parts;
|
||||
|
||||
utils.assert(addr);
|
||||
|
||||
if (typeof addr === 'object')
|
||||
return addr;
|
||||
|
||||
if (addr.indexOf(']') !== -1)
|
||||
parts = addr.split(/\]:?/);
|
||||
else
|
||||
parts = addr.split(':');
|
||||
|
||||
return {
|
||||
host: parts[0].replace(/[\[\]]/g, ''),
|
||||
port: +parts[1] || bcoin.protocol.network.port
|
||||
};
|
||||
};
|
||||
|
||||
utils.isIP = function isIP(ip) {
|
||||
if (typeof ip !== 'string')
|
||||
return 0;
|
||||
@ -541,67 +561,89 @@ utils.isIP = function isIP(ip) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
utils.ip2array = function ip2array(ip, version) {
|
||||
if (Array.isArray(ip)) {
|
||||
ip = ip.slice();
|
||||
utils.ip2version = function ip2version(ip, version) {
|
||||
utils.assert(Array.isArray(ip));
|
||||
utils.assert(version === 4 || version === 6);
|
||||
|
||||
utils.assert(version === 4 || version === 6);
|
||||
|
||||
if (version === 4) {
|
||||
ip = ip.slice(-4);
|
||||
|
||||
while (ip.length < 4)
|
||||
ip.unshift(0);
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
if (version === 6) {
|
||||
while (ip.length < 4)
|
||||
ip.unshift(0);
|
||||
|
||||
while (ip.length < 6)
|
||||
ip.unshift(0xff);
|
||||
|
||||
while (ip.length < 16)
|
||||
ip.unshift(0);
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
version = utils.isIP(ip);
|
||||
|
||||
if (!version)
|
||||
return ip;
|
||||
ip = ip.slice();
|
||||
|
||||
if (version === 4) {
|
||||
// Check to see if this an
|
||||
// ipv4-mapped ipv6 address.
|
||||
if (ip.length > 4) {
|
||||
while (ip[0] === 0)
|
||||
ip.shift();
|
||||
|
||||
// Found an ipv4 address
|
||||
if (ip.length === 6 && ip[0] === 0xff && ip[1] === 0xff)
|
||||
return ip.slice(-4);
|
||||
|
||||
// No ipv4 address
|
||||
return [0, 0, 0, 0];
|
||||
}
|
||||
|
||||
// Pad to 4 bytes
|
||||
while (ip.length < 4)
|
||||
ip.unshift(0);
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
if (version === 6) {
|
||||
// Pad to 4 bytes
|
||||
while (ip.length < 4)
|
||||
ip.unshift(0);
|
||||
|
||||
// Try to convert ipv4 address to
|
||||
// ipv4-mapped ipv6 address.
|
||||
if (ip.length === 4) {
|
||||
while (ip.length < 6)
|
||||
ip.unshift(0xff);
|
||||
}
|
||||
|
||||
// Pad to 16 bytes
|
||||
while (ip.length < 16)
|
||||
ip.unshift(0);
|
||||
|
||||
return ip;
|
||||
}
|
||||
};
|
||||
|
||||
utils.ip2array = function ip2array(ip, version) {
|
||||
var type = utils.isIP(ip);
|
||||
|
||||
utils.assert(version === 4 || version === 6);
|
||||
|
||||
if (type === 0) {
|
||||
if (!Array.isArray(ip))
|
||||
ip = [0, 0, 0, 0];
|
||||
} else if (type === 4) {
|
||||
ip = ip.split('.').map(function(n) {
|
||||
return +n;
|
||||
});
|
||||
utils.assert(ip.length <= 4);
|
||||
return utils.ip2array(ip, 4);
|
||||
}
|
||||
|
||||
if (version === 6) {
|
||||
} else if (type === 6) {
|
||||
ip = utils.toArray(ip.replace(/:/g, ''), 'hex');
|
||||
utils.assert(ip.length <= 16);
|
||||
return utils.ip2array(ip, 6);
|
||||
}
|
||||
|
||||
return utils.ip2version(ip, version);
|
||||
};
|
||||
|
||||
utils.array2ip = function array2ip(ip, version) {
|
||||
var out, i, hi, lo;
|
||||
|
||||
if (!Array.isArray(ip))
|
||||
return ip;
|
||||
if (!Array.isArray(ip)) {
|
||||
if (utils.isIP(ip))
|
||||
ip = utils.ip2array(ip, version);
|
||||
else
|
||||
ip = [0, 0, 0, 0];
|
||||
}
|
||||
|
||||
utils.assert(version === 4 || version === 6);
|
||||
utils.assert(ip.length <= 16);
|
||||
|
||||
ip = utils.ip2array(ip, version);
|
||||
ip = utils.ip2version(ip, version);
|
||||
|
||||
if (version === 4)
|
||||
return ip.join('.');
|
||||
@ -819,7 +861,7 @@ utils.hash = function hash(obj, enc) {
|
||||
throw new Error('Cannot get hash of object');
|
||||
};
|
||||
|
||||
utils.U64 = new bn(0xffffffff).ushln(32).uor(new bn(0xffffffff));
|
||||
utils.U64 = new bn('ffffffffffffffff', 'hex');
|
||||
|
||||
utils.nonce = function nonce() {
|
||||
var nonce = utils.U64.clone();
|
||||
@ -852,6 +894,21 @@ utils.nonce = function nonce() {
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
utils.isNegZero = function isNegZero(bytes, order) {
|
||||
var s = 0;
|
||||
|
||||
if (order === 'le')
|
||||
s = bytes.length - 1;
|
||||
|
||||
if (bytes[s] & 0x80) {
|
||||
bytes = bytes.slice();
|
||||
bytes[s] &= ~0x80;
|
||||
return new bn(bytes, order).cmpn(0) === 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
utils.readU8 = function readU8(arr, off) {
|
||||
off = off >>> 0;
|
||||
return arr[off];
|
||||
@ -888,15 +945,15 @@ utils.readU32BE = function readU32BE(arr, off) {
|
||||
utils.readU64 = function readU64(arr, off) {
|
||||
var num;
|
||||
off = off >>> 0;
|
||||
num = utils.toArray(arr.slice(off, off + 8)).reverse();
|
||||
return new bn(num);
|
||||
num = utils.toArray(arr.slice(off, off + 8));
|
||||
return new bn(num, 'le');
|
||||
};
|
||||
|
||||
utils.readU64BE = function readU64BE(arr, off) {
|
||||
var num;
|
||||
off = off >>> 0;
|
||||
num = utils.toArray(arr.slice(off, off + 8));
|
||||
return new bn(num);
|
||||
return new bn(num, 'be');
|
||||
};
|
||||
|
||||
utils.read8 = function read8(arr, off) {
|
||||
@ -943,16 +1000,18 @@ utils.read64 = function read64(arr, off) {
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
num = utils.toArray(arr.slice(off, off + 8)).reverse();
|
||||
num = utils.toArray(arr.slice(off, off + 8));
|
||||
|
||||
if (num[0] & 0x80) {
|
||||
num[0] &= ~0x80;
|
||||
num = new bn(num);
|
||||
num = num.neg();
|
||||
return num;
|
||||
// If we are signed, do (~num + 1) to get
|
||||
// the positive counterpart and set bn's
|
||||
// negative flag.
|
||||
if (num[num.length - 1] & 0x80) {
|
||||
if (utils.isNegZero(num, 'le'))
|
||||
return new bn(0);
|
||||
return new bn(num, 'le').notn(64).addn(1).neg();
|
||||
}
|
||||
|
||||
return new bn(num);
|
||||
return new bn(num, 'le');
|
||||
};
|
||||
|
||||
utils.read64BE = function read64BE(arr, off) {
|
||||
@ -962,11 +1021,13 @@ utils.read64BE = function read64BE(arr, off) {
|
||||
|
||||
num = utils.toArray(arr.slice(off, off + 8));
|
||||
|
||||
// If we are signed, do (~num + 1) to get
|
||||
// the positive counterpart and set bn's
|
||||
// negative flag.
|
||||
if (num[0] & 0x80) {
|
||||
num[0] &= ~0x80;
|
||||
num = new bn(num);
|
||||
num = num.neg();
|
||||
return num;
|
||||
if (utils.isNegZero(num, 'be'))
|
||||
return new bn(0);
|
||||
return new bn(num, 'be').notn(64).addn(1).neg();
|
||||
}
|
||||
|
||||
return new bn(num);
|
||||
@ -1018,38 +1079,48 @@ utils.writeU32BE = function writeU32BE(dst, num, off) {
|
||||
utils.writeU64 = function writeU64(dst, num, off) {
|
||||
var i;
|
||||
|
||||
if (!(num instanceof bn)) {
|
||||
num = +num;
|
||||
num = new bn(num);
|
||||
}
|
||||
if (!(num instanceof bn))
|
||||
num = new bn(+num);
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
num = num.toArray().slice(-8);
|
||||
// We shouldn't think of
|
||||
// this as negative.
|
||||
if (num.isNeg())
|
||||
num = num.neg();
|
||||
|
||||
for (i = num.length - 1; i >= 0; i--)
|
||||
if (num.bitLength() > 64)
|
||||
num = num.uand(utils.U64);
|
||||
|
||||
num = num.toArray('le', 8);
|
||||
|
||||
utils.assert.equal(num.length, 8);
|
||||
|
||||
for (i = 0; i < num.length; i++)
|
||||
dst[off++] = num[i] & 0xff;
|
||||
|
||||
for (i = num.length; i < 8; i++)
|
||||
dst[off++] = 0;
|
||||
|
||||
return 8;
|
||||
};
|
||||
|
||||
utils.writeU64BE = function writeU64BE(dst, num, off) {
|
||||
var i;
|
||||
|
||||
if (!(num instanceof bn)) {
|
||||
num = +num;
|
||||
num = new bn(num);
|
||||
}
|
||||
if (!(num instanceof bn))
|
||||
num = new bn(+num);
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
num = num.toArray().slice(-8);
|
||||
// We shouldn't think of
|
||||
// this as negative.
|
||||
if (num.isNeg())
|
||||
num = num.neg();
|
||||
|
||||
for (i = num.length; i < 8; i++)
|
||||
dst[off++] = 0;
|
||||
if (num.bitLength() > 64)
|
||||
num = num.uand(utils.U64);
|
||||
|
||||
num = num.toArray('be', 8);
|
||||
|
||||
utils.assert.equal(num.length, 8);
|
||||
|
||||
for (i = 0; i < num.length; i++)
|
||||
dst[off++] = num[i] & 0xff;
|
||||
@ -1101,64 +1172,61 @@ utils.write32BE = function write32BE(dst, num, off) {
|
||||
};
|
||||
|
||||
utils.write64 = function write64(dst, num, off) {
|
||||
var i, bytes;
|
||||
var i;
|
||||
|
||||
if (!(num instanceof bn)) {
|
||||
num = +num;
|
||||
if (num < 0) {
|
||||
num &= ~0x80000000;
|
||||
num = new bn(num);
|
||||
num = num.neg();
|
||||
} else {
|
||||
num = new bn(num);
|
||||
}
|
||||
}
|
||||
if (!(num instanceof bn))
|
||||
num = new bn(+num);
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
bytes = num.toArray().slice(-8);
|
||||
// Convert the number to the
|
||||
// negative byte representation.
|
||||
if (num.isNeg()) {
|
||||
if (num.cmpn(0) === 0)
|
||||
num = new bn(0);
|
||||
else
|
||||
num = num.neg().notn(64).addn(1);
|
||||
}
|
||||
|
||||
if (num.isNeg())
|
||||
bytes[0] |= 0x80;
|
||||
if (num.bitLength() > 64)
|
||||
num = num.uand(utils.U64);
|
||||
|
||||
for (i = bytes.length - 1; i >= 0; i--)
|
||||
dst[off++] = bytes[i] & 0xff;
|
||||
num = num.toArray('le', 8);
|
||||
|
||||
for (i = bytes.length; i < 8; i++)
|
||||
dst[off++] = 0;
|
||||
utils.assert.equal(num.length, 8);
|
||||
|
||||
if (num.isNeg())
|
||||
dst[off - 1] |= 0x80;
|
||||
for (i = 0; i < num.length; i++)
|
||||
dst[off++] = num[i] & 0xff;
|
||||
|
||||
return 8;
|
||||
};
|
||||
|
||||
utils.write64BE = function write64BE(dst, num, off) {
|
||||
var i, bytes;
|
||||
var i;
|
||||
|
||||
if (!(num instanceof bn)) {
|
||||
num = +num;
|
||||
if (num < 0) {
|
||||
num &= ~0x80000000;
|
||||
num = new bn(num);
|
||||
num = num.neg();
|
||||
} else {
|
||||
num = new bn(num);
|
||||
}
|
||||
}
|
||||
if (!(num instanceof bn))
|
||||
num = new bn(+num);
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
bytes = num.toArray().slice(-8);
|
||||
// Convert the number to the
|
||||
// negative byte representation.
|
||||
if (num.isNeg()) {
|
||||
if (num.cmpn(0) === 0)
|
||||
num = new bn(0);
|
||||
else
|
||||
num = num.neg().notn(64).addn(1);
|
||||
}
|
||||
|
||||
for (i = bytes.length; i < 8; i++)
|
||||
dst[off++] = 0;
|
||||
if (num.bitLength() > 64)
|
||||
num = num.uand(utils.U64);
|
||||
|
||||
for (i = 0; i < bytes.length; i++)
|
||||
dst[off++] = bytes[i] & 0xff;
|
||||
num = num.toArray('be', 8);
|
||||
|
||||
if (num.isNeg())
|
||||
dst[off - 8] |= 0x80;
|
||||
utils.assert.equal(num.length, 8);
|
||||
|
||||
for (i = 0; i < num.length; i++)
|
||||
dst[off++] = num[i] & 0xff;
|
||||
|
||||
return 8;
|
||||
};
|
||||
|
||||
@ -22,9 +22,9 @@
|
||||
"homepage": "https://github.com/indutny/bcoin",
|
||||
"dependencies": {
|
||||
"async": "^0.8.0",
|
||||
"bn.js": "^4.5.0",
|
||||
"elliptic": "^6.0.2",
|
||||
"hash.js": "^1.0.3",
|
||||
"bn.js": "4.6.3",
|
||||
"elliptic": "6.0.2",
|
||||
"hash.js": "1.0.3",
|
||||
"inherits": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -45,13 +45,13 @@ describe('Protocol', function() {
|
||||
var peers = [
|
||||
{
|
||||
ipv6: '0000:0000:0000:0000:0000:ffff:0000:0000',
|
||||
ipv4: '127.0.0.1',
|
||||
ipv4: '0.0.0.0',
|
||||
port: 8333,
|
||||
ts: Date.now() / 1000 | 0
|
||||
},
|
||||
{
|
||||
ipv6: '0000:0000:0000:0000:0000:ffff:7f00:0001',
|
||||
ipv4: '10.0.0.1',
|
||||
ipv4: '127.0.0.1',
|
||||
port: 18333,
|
||||
ts: Date.now() / 1000 | 0
|
||||
}
|
||||
@ -78,7 +78,7 @@ describe('Protocol', function() {
|
||||
assert.equal(payload[0].port, peers[0].port);
|
||||
|
||||
assert.equal(typeof payload[1].ts, 'number');
|
||||
assert.equal(payload[1].service, 1);
|
||||
assert.equal(payload[1].services, 1);
|
||||
assert.equal(payload[1].ipv6, peers[1]._ipv6);
|
||||
assert.equal(payload[1].ipv4, peers[1]._ipv4);
|
||||
assert.equal(payload[1].port, peers[1].port);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
var assert = require('assert');
|
||||
var bn = require('bn.js');
|
||||
var bcoin = require('../');
|
||||
var constants = bcoin.protocol.constants;
|
||||
|
||||
function printScript(input) {
|
||||
var scripts = [];
|
||||
@ -219,7 +220,7 @@ describe('Wallet', function() {
|
||||
tx.out(to, 5460);
|
||||
|
||||
var cost = tx.funds('out');
|
||||
var total = cost.add(new bn(bcoin.tx.fee));
|
||||
var total = cost.add(new bn(constants.tx.fee));
|
||||
|
||||
var unspent1 = w1.unspent();
|
||||
var unspent2 = w2.unspent();
|
||||
@ -233,7 +234,7 @@ describe('Wallet', function() {
|
||||
tx.input(unspent2[0]);
|
||||
|
||||
var left = tx.funds('in').sub(total);
|
||||
if (left.cmpn(bcoin.tx.dust) < 0) {
|
||||
if (left.cmpn(constants.tx.dust) < 0) {
|
||||
tx.outputs[tx.outputs.length - 2].value.iadd(left);
|
||||
left = new bn(0);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user