diff --git a/lib/bcoin/miner.js b/lib/bcoin/miner.js index e20a5653..3d6df110 100644 --- a/lib/bcoin/miner.js +++ b/lib/bcoin/miner.js @@ -206,13 +206,15 @@ Miner.prototype.createBlock = function createBlock(tx) { }, script: [ // Height (required in v2+ blocks) - new bn(this.last.height + 1).toArray().reverse(), + bcoin.script.array(this.last.height + 1), // extraNonce - incremented when // the nonce overflows. [], // Add a nonce to ensure we don't // collide with a previous coinbase - // of ours. + // of ours. This isn't really + // necessary nowdays due to bip34 + // (used above). utils.nonce().toArray(), // Let the world know this little // miner succeeded. @@ -221,6 +223,9 @@ Miner.prototype.createBlock = function createBlock(tx) { seq: 0xffffffff }); + if (script.size(coinbase.inputs[0].script) > 100) + throw new Error('Coinbase script is too large'); + coinbase.output({ address: this.address, value: new bn(0) @@ -243,7 +248,7 @@ Miner.prototype.createBlock = function createBlock(tx) { block.txs.push(coinbase); block.target = utils.fromCompact(target); - block.extraNonce = new bn(0); + block.extraNonce = script.num(0); // Update coinbase since our coinbase was added. this.updateCoinbase(block); @@ -255,7 +260,7 @@ Miner.prototype.createBlock = function createBlock(tx) { }; Miner.prototype.updateCoinbase = function updateCoinbase(block) { - var coinbase = block.coinbase; + var coinbase = block.txs[0]; var reward = bcoin.block.reward(this.last.height + 1); assert(coinbase); @@ -334,16 +339,20 @@ Miner.prototype.findNonce = function findNonce() { var data = new Buffer(this.block.render()); var now; + // Track how long we've been at it. this._begin = utils.now(); // The heart and soul of the miner: match the target. while (this.block.nonce <= 0xffffffff) { // Hash and test against the next target - if (utils.testTarget(this.block.target, dsha256(data))) + if (utils.testTarget(this.block.target, utils.dsha256(data))) return true; // Increment the nonce to get a different hash this.block.nonce++; + + // Update the raw buffer (faster than + // constantly serializing the block) utils.writeU32(data, this.block.nonce, 76); // Send progress report every so often @@ -383,18 +392,6 @@ Miner.prototype.findNonce = function findNonce() { return false; }; -/** - * Utils - */ - -function sha256(data, enc) { - return crypto.createHash('sha256').update(data).digest(); -} - -function dsha256(data, enc) { - return Array.prototype.slice.call(sha256(sha256(data, enc))); -} - /** * Expose */ diff --git a/lib/bcoin/protocol/framer.js b/lib/bcoin/protocol/framer.js index 6ffdeca8..d6a0d63a 100644 --- a/lib/bcoin/protocol/framer.js +++ b/lib/bcoin/protocol/framer.js @@ -10,9 +10,6 @@ var constants = require('./constants'); var utils = bcoin.utils; var assert = utils.assert; -var writeU32 = utils.writeU32; -var writeAscii = utils.writeAscii; - /** * Framer */ @@ -37,15 +34,15 @@ Framer.prototype.header = function header(cmd, payload) { assert(payload.length <= 0xffffffff); // Magic value - writeU32(h, network.magic, 0); + utils.writeU32(h, network.magic, 0); // Command - len = writeAscii(h, cmd, 4); + len = utils.writeAscii(h, cmd, 4); for (i = 4 + len; i < 4 + 12; i++) h[i] = 0; // Payload length - writeU32(h, payload.length, 16); + utils.writeU32(h, payload.length, 16); // Checksum utils.copy(utils.checksum(payload), h, 20); @@ -112,7 +109,7 @@ Framer.prototype.version = function version(packet) { packet = {}; // Version - off += writeU32(p, constants.version, off); + off += utils.writeU32(p, constants.version, off); // Services off += utils.writeU64(p, constants.services.network, off); @@ -140,7 +137,7 @@ Framer.prototype.version = function version(packet) { } // Start height - off += writeU32(p, packet.height || 0, off); + off += utils.writeU32(p, packet.height || 0, off); // Relay p[off++] = packet.relay ? 1 : 0; @@ -162,7 +159,7 @@ Framer.prototype._inv = function _inv(command, items) { for (i = 0; i < items.length; i++) { // Type - off += writeU32(res, constants.inv[items[i].type], off); + off += utils.writeU32(res, constants.inv[items[i].type], off); // Hash hash = items[i].hash; @@ -209,10 +206,10 @@ Framer.prototype.filterLoad = function filterLoad(bloom, update) { utils.writeIntv(before, filter.length, 0); // Number of hash functions - writeU32(after, bloom.n, 0); + utils.writeU32(after, bloom.n, 0); // nTweak - writeU32(after, bloom.tweak, 4); + utils.writeU32(after, bloom.tweak, 4); // nFlags after[8] = constants.filterFlags[update]; @@ -240,7 +237,7 @@ Framer.prototype._getBlocks = function _getBlocks(cmd, hashes, stop) { if (cmd === 'getheaders' && !hashes) hashes = []; - writeU32(p, constants.version, 0); + utils.writeU32(p, constants.version, 0); off = 4 + utils.writeIntv(p, hashes.length, 4); p.length = off + 32 * (hashes.length + 1); @@ -284,13 +281,13 @@ Framer.tx = function tx(tx) { input = tx.inputs[i]; off += utils.copy(utils.toArray(input.out.hash, 'hex'), p, off, true); - off += writeU32(p, input.out.index, off); + off += utils.writeU32(p, input.out.index, off); s = bcoin.script.encode(input.script); off += utils.writeIntv(p, s.length, off); off += utils.copy(s, p, off, true); - off += writeU32(p, input.seq, off); + off += utils.writeU32(p, input.seq, off); } off += utils.writeIntv(p, tx.outputs.length, off); @@ -304,7 +301,7 @@ Framer.tx = function tx(tx) { off += utils.writeIntv(p, s.length, off); off += utils.copy(s, p, off, true); } - off += writeU32(p, tx.lock, off); + off += utils.writeU32(p, tx.lock, off); return p; }; @@ -331,19 +328,19 @@ Framer.block = function _block(block, type) { off += utils.copy(utils.toArray(block.merkleRoot, 'hex'), p, off, true); // timestamp - off += writeU32(p, block.ts, off); + off += utils.writeU32(p, block.ts, off); // bits - off += writeU32(p, block.bits, off); + off += utils.writeU32(p, block.bits, off); // nonce - off += writeU32(p, block.nonce, off); + off += utils.writeU32(p, block.nonce, off); assert.equal(off, 80); if (type === 'merkleblock') { // txn_count - off += writeU32(p, block.totalTX, off); + off += utils.writeU32(p, block.totalTX, off); // hash count off += utils.writeIntv(p, block.hashes.length, off); // hashes @@ -388,8 +385,7 @@ Framer.prototype.reject = function reject(details) { off += utils.writeIntv(p, message.length, off); off += utils.writeAscii(p, message, off); - p[off] = ccode; - off++; + off += utils.writeU8(p, ccode, off); off += utils.writeIntv(p, reason.length, off); off += utils.writeAscii(p, reason, off); diff --git a/lib/bcoin/protocol/parser.js b/lib/bcoin/protocol/parser.js index 98793f8d..c736a9a6 100644 --- a/lib/bcoin/protocol/parser.js +++ b/lib/bcoin/protocol/parser.js @@ -14,9 +14,6 @@ var assert = utils.assert; var constants = require('./constants'); var network = require('./network'); -var readU32 = utils.readU32; -var readU64 = utils.readU64; - /** * Parser */ @@ -78,7 +75,7 @@ Parser.prototype.parse = function parse(chunk) { this.packet.payload = chunk; - if (readU32(utils.checksum(this.packet.payload)) !== this.packet.checksum) + if (utils.readU32(utils.checksum(this.packet.payload)) !== this.packet.checksum) return this._error('Invalid checksum'); this.packet.payload = this.parsePayload(this.packet.cmd, this.packet.payload); @@ -92,7 +89,7 @@ Parser.prototype.parse = function parse(chunk) { Parser.prototype.parseHeader = function parseHeader(h) { var i, magic, cmd; - magic = readU32(h, 0); + magic = utils.readU32(h, 0); if (magic !== network.magic) { return this._error('Invalid magic value: ' + magic.toString(16)); @@ -105,12 +102,12 @@ Parser.prototype.parseHeader = function parseHeader(h) { return this._error('Not NULL-terminated cmd'); cmd = utils.stringify(h.slice(4, 4 + i)); - this.waiting = readU32(h, 16); + this.waiting = utils.readU32(h, 16); return { cmd: cmd, length: this.waiting, - checksum: readU32(h, 20) + checksum: utils.readU32(h, 20) }; }; @@ -153,7 +150,7 @@ Parser.prototype.parsePing = function parsePing(p) { return this._error('pong packet is too small'); return { - nonce: readU64(p, 0) + nonce: utils.readU64(p, 0) }; }; @@ -162,7 +159,7 @@ Parser.prototype.parsePong = function parsePong(p) { return this._error('ping packet is too small'); return { - nonce: readU64(p, 0) + nonce: utils.readU64(p, 0) }; }; @@ -172,8 +169,8 @@ Parser.prototype.parseVersion = function parseVersion(p) { if (p.length < 85) return this._error('version packet is too small'); - v = readU32(p, 0); - services = readU64(p, 4); + v = utils.readU32(p, 0); + services = utils.readU64(p, 4); // Timestamp ts = utils.read64(p, 12); @@ -185,7 +182,7 @@ Parser.prototype.parseVersion = function parseVersion(p) { from = this._parseAddr(p, 46); // Nonce, very dramatic - nonce = readU64(p, 72); + nonce = utils.readU64(p, 72); // User agent length result = utils.readIntv(p, 80); @@ -194,7 +191,7 @@ Parser.prototype.parseVersion = function parseVersion(p) { off += result.r; // Start height - height = readU32(p, off); + height = utils.readU32(p, off); off += 4; // Relay @@ -238,7 +235,7 @@ Parser.prototype.parseInvList = function parseInvList(p) { for (i = 0, off = 0; i < count; i++, off += 36) { items.push({ - type: constants.invByVal[readU32(p, off)], + type: constants.invByVal[utils.readU32(p, off)], hash: utils.toArray(p.slice(off + 4, off + 36)) }); } @@ -278,10 +275,10 @@ Parser.prototype.parseMerkleBlock = function parseMerkleBlock(p) { version: utils.read32(p, 0), prevBlock: utils.toArray(p.slice(4, 36)), merkleRoot: utils.toArray(p.slice(36, 68)), - ts: readU32(p, 68), - bits: readU32(p, 72), - nonce: readU32(p, 76), - totalTX: readU32(p, 80), + ts: utils.readU32(p, 68), + bits: utils.readU32(p, 72), + nonce: utils.readU32(p, 76), + totalTX: utils.readU32(p, 80), hashes: hashes, flags: flags, _raw: p.slice(0, 80), @@ -312,11 +309,11 @@ Parser.prototype.parseHeaders = function parseHeaders(p) { off += 32; header.merkleRoot = utils.toArray(p.slice(off, off + 32)); off += 32; - header.ts = readU32(p, off); + header.ts = utils.readU32(p, off); off += 4; - header.bits = readU32(p, off); + header.bits = utils.readU32(p, off); off += 4; - header.nonce = readU32(p, off); + header.nonce = utils.readU32(p, off); off += 4; r = utils.readIntv(p, off); header.totalTX = r.r; @@ -351,9 +348,9 @@ Parser.prototype.parseBlock = function parseBlock(p) { version: utils.read32(p, 0), prevBlock: utils.toArray(p.slice(4, 36)), merkleRoot: utils.toArray(p.slice(36, 68)), - ts: readU32(p, 68), - bits: readU32(p, 72), - nonce: readU32(p, 76), + ts: utils.readU32(p, 68), + bits: utils.readU32(p, 72), + nonce: utils.readU32(p, 76), totalTX: totalTX, txs: txs, _raw: p.slice(0, 80), @@ -378,10 +375,10 @@ Parser.prototype.parseTXIn = function parseTXIn(p) { size: off + scriptLen + 4, out: { hash: utils.toArray(p.slice(0, 32)), - index: readU32(p, 32) + index: utils.readU32(p, 32) }, script: bcoin.script.decode(utils.toArray(p.slice(off, off + scriptLen))), - seq: readU32(p, off + scriptLen) + seq: utils.readU32(p, off + scriptLen) }; }; @@ -464,7 +461,7 @@ Parser.prototype.parseTX = function parseTX(p) { version: utils.read32(p, 0), inputs: txIn, outputs: txOut, - lock: readU32(p, off), + lock: utils.readU32(p, off), _off: off + 4, _size: p.length }; @@ -486,7 +483,7 @@ Parser.prototype.parseReject = function parseReject(p) { message = utils.stringify(p.slice(off, off + messageLen)); off += messageLen; - ccode = p[off]; + ccode = utils.readU8(p, off); off++; reasonLen = utils.readIntv(p, off); @@ -516,7 +513,6 @@ Parser.prototype._parseAddr = function _parseAddr(p, off, full) { if (!off) off = 0; - // timestamp - LE if (full) { ts = utils.readU32(p, off); off += 4; @@ -524,15 +520,12 @@ Parser.prototype._parseAddr = function _parseAddr(p, off, full) { ts = 0; } - // NODE_NETWORK services - LE services = utils.readU64(p, off); off += 8; - // ipv6 - BE ip = utils.toArray(p.slice(off, off + 16)); off += 16; - // port - BE port = utils.readU16BE(p, off); off += 2; diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index b3fb14a1..4834a434 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -414,11 +414,11 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) { if (stack.length === 0) return false; if (script.num(stack[stack.length - 1]).cmpn(0) !== 0) - stack.push(script.numArray(stack[stack.length - 1])); + stack.push(script.array(stack[stack.length - 1])); break; } case 'depth': { - stack.push(script.numArray(stack.length)); + stack.push(script.array(stack.length)); break; } case 'drop': { @@ -551,7 +551,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) { case 'size': { if (stack.length < 1) return false; - stack.push(script.numArray(stack[stack.length - 1].length || 0)); + stack.push(script.array(stack[stack.length - 1].length || 0)); break; } case 'add1': @@ -588,7 +588,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) { } if (typeof n === 'boolean') n = script.num(+n); - stack.push(script.numArray(n)); + stack.push(script.array(n)); break; } case 'add': @@ -673,7 +673,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) { if (!res) return false; } else { - stack.push(script.numArray(n)); + stack.push(script.array(n)); } break; case 'within': @@ -944,9 +944,9 @@ script.num = function num(value, useNum) { // not have the high bit set. A number can't // justify having the last byte's low bits unset // unless they ran out of space for the sign bit - // in the second to last bit. This also takes - // care of negative We also fail on [0] to avoid - // negative zero (also avoids positive zero). + // in the second to last bit. We also fail on [0] + // to avoid negative zero (also avoids positive + // zero). if (!(value[value.length - 1] & 0x7f)) { if (value.length === 1 || !(value[value.length - 2] & 0x80)) { // We should technically fail here by @@ -984,7 +984,7 @@ script.num = function num(value, useNum) { return value; }; -script.numArray = function(value) { +script.array = function(value) { if (Array.isArray(value)) return value.slice(); diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index df3a0aed..c29bed90 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -559,7 +559,7 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) { if (options.scripthash) { if (options.lock != null) { script = [ - bcoin.script.numArray(options.lock), + bcoin.script.array(options.lock), 'checklocktimeverify', 'drop', 'codesep' diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index 974da2e5..62a1463e 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -1033,14 +1033,14 @@ utils.read64BE = function read64BE(arr, off) { return new bn(num); }; -utils.writeU8 = function readU8(dst, num, off) { +utils.writeU8 = function writeU8(dst, num, off) { num = +num; off = off >>> 0; dst[off] = num & 0xff; return 1; }; -utils.writeU16 = function readU16(dst, num, off) { +utils.writeU16 = function writeU16(dst, num, off) { num = +num; off = off >>> 0; dst[off] = num & 0xff; @@ -1048,7 +1048,7 @@ utils.writeU16 = function readU16(dst, num, off) { return 2; }; -utils.writeU16BE = function read16BE(dst, num, off) { +utils.writeU16BE = function write16BE(dst, num, off) { num = +num; off = off >>> 0; dst[off] = (num >>> 8) & 0xff;