From 63a9c4476291fff95da82ef8d91e4f3fdce586f9 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Tue, 19 Apr 2016 11:39:55 -0700 Subject: [PATCH] asserts. consistency. --- lib/bcoin/abstractblock.js | 10 ++++- lib/bcoin/chain.js | 2 +- lib/bcoin/coin.js | 10 +++-- lib/bcoin/compactblock.js | 2 +- lib/bcoin/input.js | 12 ++++-- lib/bcoin/output.js | 6 ++- lib/bcoin/script.js | 80 +++++++++++++++++++++++++++++++++++--- lib/bcoin/tx.js | 25 ++++++------ 8 files changed, 115 insertions(+), 32 deletions(-) diff --git a/lib/bcoin/abstractblock.js b/lib/bcoin/abstractblock.js index 0be5ce46..880cb656 100644 --- a/lib/bcoin/abstractblock.js +++ b/lib/bcoin/abstractblock.js @@ -8,6 +8,7 @@ module.exports = function(bcoin) { var utils = bcoin.utils; +var assert = utils.assert; var network = bcoin.protocol.network; /** @@ -35,7 +36,14 @@ function AbstractBlock(data) { if (!(this instanceof AbstractBlock)) return new AbstractBlock(data); - this.type = null; + assert(data, 'Block data is required.'); + assert(typeof data.version === 'number'); + assert(typeof data.prevBlock === 'string'); + assert(typeof data.merkleRoot === 'string'); + assert(typeof data.ts === 'number'); + assert(typeof data.bits === 'number'); + assert(typeof data.nonce === 'number'); + this.version = data.version; this.prevBlock = data.prevBlock; this.merkleRoot = data.merkleRoot; diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 97cef441..528c2fd7 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -1501,7 +1501,7 @@ Chain.prototype.add = function add(block, callback, force) { // fully validated here. They are deserialized, // validated, and emitted. Hopefully the deserialized // blocks get cleaned up by the GC quickly. - if (block.type === 'compactblock') { + if (block.compact) { try { block = block.toBlock(); } catch (e) { diff --git a/lib/bcoin/coin.js b/lib/bcoin/coin.js index 3aeace74..709aa349 100644 --- a/lib/bcoin/coin.js +++ b/lib/bcoin/coin.js @@ -41,6 +41,8 @@ function Coin(tx, index) { if (!(this instanceof Coin)) return new Coin(tx, index); + assert(tx, 'Coin data is required.'); + if (tx instanceof bcoin.tx) { this.version = tx.version; this.height = tx.height; @@ -53,7 +55,6 @@ function Coin(tx, index) { this.index = index; } else { options = tx; - assert(typeof options.script !== 'string'); this.version = options.version; this.height = options.height; this.value = options.value; @@ -63,12 +64,13 @@ function Coin(tx, index) { this.index = options.index; } - assert(!this.hash || typeof this.hash === 'string'); assert(typeof this.version === 'number'); assert(utils.isFinite(this.height)); assert(bn.isBN(this.value)); assert(this.script instanceof bcoin.script); assert(typeof this.coinbase === 'boolean'); + assert(!this.hash || typeof this.hash === 'string'); + assert(!this.index || typeof this.index === 'number'); } utils.inherits(Coin, bcoin.output); @@ -147,7 +149,7 @@ Coin.prototype.toJSON = function toJSON() { version: this.version, height: this.height, value: utils.btc(this.value), - script: this.script.encode().toString('hex'), + script: this.script.toRaw('hex'), coinbase: this.coinbase, hash: this.hash ? utils.revHex(this.hash) : null, index: this.index @@ -166,7 +168,7 @@ Coin._fromJSON = function _fromJSON(json) { version: json.version, height: json.height, value: utils.satoshi(json.value), - script: bcoin.script.parseScript(new Buffer(json.script, 'hex')), + script: bcoin.script._fromRaw(json.script, 'hex')), coinbase: json.coinbase, hash: json.hash ? utils.revHex(json.hash) : null, index: json.index diff --git a/lib/bcoin/compactblock.js b/lib/bcoin/compactblock.js index 18d05284..7a53aead 100644 --- a/lib/bcoin/compactblock.js +++ b/lib/bcoin/compactblock.js @@ -54,7 +54,7 @@ function CompactBlock(data) { bcoin.abstractblock.call(this, data); - this.type = 'compactblock'; + this.compact = true; this.coinbaseHeight = data.coinbaseHeight; } diff --git a/lib/bcoin/input.js b/lib/bcoin/input.js index 6ce16a45..8bd6565f 100644 --- a/lib/bcoin/input.js +++ b/lib/bcoin/input.js @@ -35,6 +35,8 @@ function Input(options, mutable) { if (!(this instanceof Input)) return new Input(options); + assert(options, 'Input data is required.'); + this.mutable = !!mutable; this.prevout = options.prevout; this.script = bcoin.script(options.script, this.mutable); @@ -44,8 +46,10 @@ function Input(options, mutable) { if (options.coin) this.coin = bcoin.coin(options.coin); + assert(typeof this.prevout === 'object'); assert(typeof this.prevout.hash === 'string'); assert(typeof this.prevout.index === 'number'); + assert(typeof this.sequence === 'number'); } Input.prototype.__defineGetter__('type', function() { @@ -260,8 +264,8 @@ Input.prototype.toJSON = function toJSON() { index: this.prevout.index }, coin: this.coin ? this.coin.toJSON() : null, - script: this.script.encode().toString('hex'), - witness: bcoin.protocol.framer.witness(this.witness).toString('hex'), + script: this.script.toRaw('hex'), + witness: this.witness.toRaw('hex'), sequence: this.sequence }; }; @@ -280,8 +284,8 @@ Input._fromJSON = function _fromJSON(json) { index: json.prevout.index }, coin: json.coin ? bcoin.coin._fromJSON(json.coin) : null, - script: bcoin.script.parseScript(new Buffer(json.script, 'hex')), - witness: bcoin.protocol.parser.parseWitness(new Buffer(json.witness, 'hex')), + script: bcoin.script._fromRaw(json.script, 'hex'), + witness: bcoin.witness._fromRaw(json.witness, 'hex'), sequence: json.sequence }; }; diff --git a/lib/bcoin/output.js b/lib/bcoin/output.js index c973e633..6320dea3 100644 --- a/lib/bcoin/output.js +++ b/lib/bcoin/output.js @@ -30,6 +30,8 @@ function Output(options, mutable) { if (!(this instanceof Output)) return new Output(options); + assert(options, 'Output data is required.'); + value = options.value; if (typeof value === 'number') { @@ -139,7 +141,7 @@ Output.prototype.inspect = function inspect() { Output.prototype.toJSON = function toJSON() { return { value: utils.btc(this.value), - script: this.script.encode().toString('hex') + script: this.script.toRaw('hex') }; }; @@ -153,7 +155,7 @@ Output.prototype.toJSON = function toJSON() { Output._fromJSON = function _fromJSON(json) { return { value: utils.satoshi(json.value), - script: bcoin.script.parseScript(new Buffer(json.script, 'hex')) + script: bcoin.script._fromRaw(json.script, 'hex')) }; }; diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 23d5f241..f0587673 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -63,6 +63,8 @@ function Witness(items, mutable) { this.items = items; this.redeem = null; + + assert(Array.isArray(items)); } /** @@ -196,6 +198,44 @@ Witness.prototype.indexOf = function indexOf(data) { return utils.indexOf(this.items, data); }; +/** + * Encode the witness to a Buffer. + * @param {String} enc - Encoding, either `'hex'` or `null`. + * @returns {Buffer|String} Serialized script. + */ + +Witness.prototype.toRaw = function toRaw(enc) { + var data = bcoin.protocol.framer.witness(this); + if (enc === 'hex') + data = data.toString('hex'); + return data; +}; + +/** + * Create a witness from a serialized buffer. + * @param {Buffer|String} data - Serialized witness. + * @param {String?} enc - Either `"hex"` or `null`. + * @returns {Object} Naked witness object. + */ + +Witness._fromRaw = function _fromRaw(data, enc) { + if (enc === 'hex') + data = new Buffer(data, 'hex'); + + return bcoin.protocol.parser.parseWitness(data); +}; + +/** + * Create a Witness from a serialized buffer. + * @param {Buffer|String} data - Serialized witness. + * @param {String?} enc - Either `"hex"` or `null`. + * @returns {Witness} + */ + +Witness.fromRaw = function fromRaw(data, enc) { + return new Witness(Witness._fromRaw(data, enc)); +}; + /** * Parse a formatted script * string into a witness object. _Must_ @@ -882,6 +922,9 @@ function Script(code, mutable) { this.raw = null; this.redeem = null; + + assert(Array.isArray(code)); + assert(!this.raw || Buffer.isBuffer(this.raw)); } /** @@ -919,6 +962,19 @@ Script.prototype.encode = function encode() { return this.raw; }; +/** + * Encode the script to a Buffer. See {@link Script#encode}. + * @param {String} enc - Encoding, either `'hex'` or `null`. + * @returns {Buffer|String} Serialized script. + */ + +Script.prototype.toRaw = function toRaw(enc) { + var data = this.encode(); + if (enc === 'hex') + data = data.toString('hex'); + return data; +}; + /** * Get the script's "subscript" starting at a separator. * Remove all OP_CODESEPARATORs if present. This bizarre @@ -4005,15 +4061,27 @@ Script.sign = function sign(msg, key, type) { * representation of a Script object (the same * properties, but it is not instantiated -- suitable * as an options object for Script). - * @param {Buffer} buf - Serialized script. + * @param {Buffer|String} data - Serialized script. + * @param {String?} enc - Either `"hex"` or `null`. * @returns {Object} Naked script object. */ -Script.parseScript = function parseScript(buf) { - return { - code: Script.decode(buf), - raw: buf - }; +Script._fromRaw = function _fromRaw(data, enc) { + if (enc === 'hex') + data = new Buffer(data, 'hex'); + + return Script.parseScript(data); +}; + +/** + * Create a script from a serialized buffer. + * @param {Buffer|String} data - Serialized script. + * @param {String?} enc - Either `"hex"` or `null`. + * @returns {Script} + */ + +Script.fromRaw = function fromRaw(data, enc) { + return new Script(Script._fromRaw(data, enc)); }; /** diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 7894d831..c37d2317 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -59,15 +59,18 @@ function TX(data, block, index) { if (!(this instanceof TX)) return new TX(data, block, index); - if (!data) - data = {}; + assert(data, 'TX data is required.'); + assert(typeof data.version === 'number'); + assert(Array.isArray(data.inputs)); + assert(Array.isArray(data.outputs)); + assert(typeof data.locktime === 'number'); this.type = 'tx'; - this.version = data.version != null ? data.version : 1; - this.flag = data.flag || 1; + this.version = data.version; + this.flag = data.flag; this.inputs = []; this.outputs = []; - this.locktime = data.locktime || 0; + this.locktime = data.locktime; this.ts = data.ts || 0; this.block = data.block || null; this.index = data.index != null ? data.index : -1; @@ -80,15 +83,11 @@ function TX(data, block, index) { this._size = data._size || 0; this._witnessSize = data._witnessSize || 0; - if (data.inputs) { - for (i = 0; i < data.inputs.length; i++) - this.inputs.push(new bcoin.input(data.inputs[i])); - } + for (i = 0; i < data.inputs.length; i++) + this.inputs.push(new bcoin.input(data.inputs[i])); - if (data.outputs) { - for (i = 0; i < data.outputs.length; i++) - this.outputs.push(new bcoin.output(data.outputs[i])); - } + for (i = 0; i < data.outputs.length; i++) + this.outputs.push(new bcoin.output(data.outputs[i])); if (block && this.ts === 0) { if (block.type === 'merkleblock') {