diff --git a/lib/behaviors/hasHashBehavior.js b/lib/behaviors/hasHashBehavior.js new file mode 100644 index 000000000..9681f6096 --- /dev/null +++ b/lib/behaviors/hasHashBehavior.js @@ -0,0 +1,77 @@ +'use strict'; + +const hash256 = require('bcrypto/lib/hash256'); +const util = require('../utils/util'); + +class HasHashBehavior { + + constructor() { + this._hash = null; + this._hhash = null; + this._rhash = null; + this._whash = null; + } + + /** + * Clear any cached values (abstract). + */ + + _refresh() { + this._hash = null; + this._hhash = null; + this._rhash = null; + this._whash = null; + } + + /** + * Clear any cached values. + */ + + refresh() { + return this._refresh(); + } + + /** + * Get little-endian block hash. + * @returns {Hash} + */ + + rhash() { + return util.revHex(this.hash()); + } + + /** + * Hash the block headers. + * @param {Function} serializedBufferProviderFunc + * @param {String?} enc - Can be `'hex'` or `null`. + * @returns {Hash|Buffer} hash + */ + + setHash(serializedBufferProviderFunc, enc) { + let h = this._hash; + + if (!h) { + h = hash256.digest(serializedBufferProviderFunc()); + if (!this.mutable) + this._hash = h; + } + + if (enc === 'hex') { + let hex = this._hhash; + if (!hex) { + hex = h.toString('hex'); + if (!this.mutable) + this._hhash = hex; + } + h = hex; + } + + return h; + } +} + +/* + * Expose + */ + +module.exports = HasHashBehavior; diff --git a/lib/primitives/abstractblock.js b/lib/primitives/abstractblock.js index 5cc7a63c4..227912038 100644 --- a/lib/primitives/abstractblock.js +++ b/lib/primitives/abstractblock.js @@ -13,6 +13,7 @@ const bio = require('bufio'); const util = require('../utils/util'); const InvItem = require('./invitem'); const consensus = require('../protocol/consensus'); +const HasHashBehavior = require('../behaviors/hasHashBehavior'); /** * Abstract Block @@ -27,13 +28,14 @@ const consensus = require('../protocol/consensus'); * @property {Number} nonce */ -class AbstractBlock { +class AbstractBlock extends HasHashBehavior { /** * Create an abstract block. * @constructor */ constructor() { + super(); this.version = 1; this.prevBlock = consensus.ZERO_HASH; this.merkleRoot = consensus.ZERO_HASH; @@ -42,9 +44,6 @@ class AbstractBlock { this.nonce = 0; this.mutable = false; - - this._hash = null; - this._hhash = null; } /** @@ -111,23 +110,6 @@ class AbstractBlock { return false; } - /** - * Clear any cached values (abstract). - */ - - _refresh() { - this._hash = null; - this._hhash = null; - } - - /** - * Clear any cached values. - */ - - refresh() { - return this._refresh(); - } - /** * Hash the block headers. * @param {String?} enc - Can be `'hex'` or `null`. @@ -135,25 +117,7 @@ class AbstractBlock { */ hash(enc) { - let h = this._hash; - - if (!h) { - h = hash256.digest(this.toHead()); - if (!this.mutable) - this._hash = h; - } - - if (enc === 'hex') { - let hex = this._hhash; - if (!hex) { - hex = h.toString('hex'); - if (!this.mutable) - this._hhash = hex; - } - h = hex; - } - - return h; + return super.setHash(this.toHead.bind(this), enc); } /** @@ -238,14 +202,6 @@ class AbstractBlock { throw new Error('Abstract method.'); } - /** - * Get little-endian block hash. - * @returns {Hash} - */ - - rhash() { - return util.revHex(this.hash()); - } /** * Convert the block to an inv item. diff --git a/lib/primitives/tx.js b/lib/primitives/tx.js index fe4c0b069..a53d35df4 100644 --- a/lib/primitives/tx.js +++ b/lib/primitives/tx.js @@ -26,6 +26,7 @@ const ScriptError = require('../script/scripterror'); const {encoding} = bio; const {hashType} = Script; const {inspectSymbol} = require('../utils'); +const HasHashBehavior = require('../behaviors/hasHashBehavior'); /** * TX @@ -37,7 +38,7 @@ const {inspectSymbol} = require('../utils'); * @property {Number} locktime */ -class TX { +class TX extends HasHashBehavior { /** * Create a transaction. * @constructor @@ -45,6 +46,7 @@ class TX { */ constructor(options) { + super(); this.version = 1; this.inputs = []; this.outputs = []; @@ -52,10 +54,6 @@ class TX { this.mutable = false; - this._hash = null; - this._hhash = null; - this._whash = null; - this._raw = null; this._offset = -1; this._block = false; @@ -153,9 +151,7 @@ class TX { */ refresh() { - this._hash = null; - this._hhash = null; - this._whash = null; + super.refresh(); this._raw = null; this._size = -1; @@ -176,25 +172,7 @@ class TX { */ hash(enc) { - let h = this._hash; - - if (!h) { - h = hash256.digest(this.toNormal()); - if (!this.mutable) - this._hash = h; - } - - if (enc === 'hex') { - let hex = this._hhash; - if (!hex) { - hex = h.toString('hex'); - if (!this.mutable) - this._hhash = hex; - } - h = hex; - } - - return h; + return super.setHash(this.toNormal.bind(this), enc); } /** @@ -2016,15 +1994,6 @@ class TX { return false; } - /** - * Get little-endian tx hash. - * @returns {Hash} - */ - - rhash() { - return util.revHex(this.hash()); - } - /** * Get little-endian wtx hash. * @returns {Hash}