bip152: comments.

This commit is contained in:
Christopher Jeffrey 2017-01-15 23:42:39 -08:00
parent 60897be916
commit 9affb11b22
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -26,8 +26,14 @@ var Block = require('../primitives/block');
* @exports CompactBlock
* @constructor
* @extends AbstractBlock
* @param {NakedBlock} options
* @param {Object} options
* @property {Buffer|null} keyNonce - Nonce for siphash key.
* @property {Number[]} ids - Short IDs.
* @property {Object[]} ptx - Prefilled transactions.
* @property {TX[]} available - Available transaction vector.
* @property {Object} idMap - Map of short ids to indexes.
* @property {Number} count - Transactions resolved.
* @property {Buffer|null} sipKey - Siphash key.
*/
function CompactBlock(options) {
@ -51,9 +57,11 @@ function CompactBlock(options) {
util.inherits(CompactBlock, AbstractBlock);
CompactBlock.prototype._verify = function _verify(ret) {
return this.verifyHeaders(ret);
};
/**
* Inject properties from options object.
* @private
* @param {Object} options
*/
CompactBlock.prototype.fromOptions = function fromOptions(options) {
this.parseOptions(options);
@ -83,15 +91,39 @@ CompactBlock.prototype.fromOptions = function fromOptions(options) {
return this;
};
/**
* Instantiate compact block from options.
* @param {Object} options
* @returns {CompactBlock}
*/
CompactBlock.fromOptions = function fromOptions(options) {
return new CompactBlock().fromOptions(options);
};
/**
* Verify the block headers.
* @alias CompactBlock#verify
* @param {Object?} ret - Return object, may be
* set with properties `reason` and `score`.
* @returns {Boolean}
*/
CompactBlock.prototype._verify = function _verify(ret) {
return this.verifyHeaders(ret);
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
CompactBlock.prototype.fromRaw = function fromRaw(data) {
var br = new BufferReader(data);
var i, count, index, tx;
this.version = br.readU32(); // Technically signed
this.version = br.readU32();
this.prevBlock = br.readHash('hex');
this.merkleRoot = br.readHash('hex');
this.ts = br.readU32();
@ -126,33 +158,75 @@ CompactBlock.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Instantiate a block from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {CompactBlock}
*/
CompactBlock.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new CompactBlock().fromRaw(data);
};
/**
* Serialize compact block with witness data.
* @returns {Buffer}
*/
CompactBlock.prototype.toRaw = function toRaw() {
return this.frameRaw(true);
};
/**
* Serialize compact block without witness data.
* @returns {Buffer}
*/
CompactBlock.prototype.toNormal = function toNormal() {
return this.frameRaw(false);
};
/**
* Write serialized block to a buffer
* writer (includes witness data).
* @param {BufferWriter} bw
*/
CompactBlock.prototype.toWriter = function toWriter(bw) {
return this.writeRaw(bw, true);
};
/**
* Write serialized block to a buffer
* writer (excludes witness data).
* @param {BufferWriter} bw
*/
CompactBlock.prototype.toNormalWriter = function toNormalWriter(bw) {
return this.writeRaw(bw, false);
};
/**
* Serialize compact block.
* @private
* @param {Boolean} witness
* @returns {Buffer}
*/
CompactBlock.prototype.frameRaw = function frameRaw(witness) {
var size = this.getSize();
return this.writeRaw(new StaticWriter(size), witness).render();
};
/**
* Calculate block serialization size.
* @param {Boolean} witness
* @returns {Number}
*/
CompactBlock.prototype.getSize = function getSize(witness) {
var size = 0;
var i, ptx;
@ -175,6 +249,13 @@ CompactBlock.prototype.getSize = function getSize(witness) {
return size;
};
/**
* Serialize block to buffer writer.
* @private
* @param {BufferWriter} bw
* @param {Boolean} witness
*/
CompactBlock.prototype.writeRaw = function writeRaw(bw, witness) {
var i, id, lo, hi, ptx;
@ -207,10 +288,23 @@ CompactBlock.prototype.writeRaw = function writeRaw(bw, witness) {
return bw;
};
/**
* Convert block to a TXRequest
* containing missing indexes.
* @returns {TXRequest}
*/
CompactBlock.prototype.toRequest = function toRequest() {
return TXRequest.fromCompact(this);
};
/**
* Attempt to fill missing transactions from mempool.
* @param {Boolean} witness
* @param {Mempool} mempool
* @returns {Boolean}
*/
CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) {
var have = {};
var hashes = mempool.getSnapshot();
@ -254,6 +348,12 @@ CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) {
return false;
};
/**
* Attempt to fill missing transactions from TXResponse.
* @param {TXResponse} res
* @returns {Boolean}
*/
CompactBlock.prototype.fillMissing = function fillMissing(res) {
var offset = 0;
var i;
@ -271,6 +371,12 @@ CompactBlock.prototype.fillMissing = function fillMissing(res) {
return offset === res.txs.length;
};
/**
* Calculate a transaction short ID.
* @param {Hash} hash
* @returns {Number}
*/
CompactBlock.prototype.sid = function sid(hash) {
var lo, hi;
@ -285,16 +391,32 @@ CompactBlock.prototype.sid = function sid(hash) {
return hi * 0x100000000 + lo;
};
/**
* Test whether an index is available.
* @param {Number} index
* @returns {Boolean}
*/
CompactBlock.prototype.hasIndex = function hasIndex(index) {
return this.available[index] != null;
};
/**
* Initialize the siphash key.
* @private
*/
CompactBlock.prototype.initKey = function initKey() {
var data = util.concat(this.abbr(), this.keyNonce);
var hash = crypto.sha256(data);
this.sipKey = hash.slice(0, 16);
};
/**
* Initialize compact block and short id map.
* @private
*/
CompactBlock.prototype.init = function init() {
var i, last, ptx, offset, id;
@ -340,6 +462,12 @@ CompactBlock.prototype.init = function init() {
}
};
/**
* Convert completely filled compact
* block to a regular block.
* @returns {Block}
*/
CompactBlock.prototype.toBlock = function toBlock() {
var block = new Block();
var i, tx;
@ -364,6 +492,15 @@ CompactBlock.prototype.toBlock = function toBlock() {
return block;
};
/**
* Inject properties from block.
* @private
* @param {Block} block
* @param {Boolean} witness
* @param {Buffer?} nonce
* @returns {CompactBlock}
*/
CompactBlock.prototype.fromBlock = function fromBlock(block, witness, nonce) {
var i, tx, hash, id;
@ -400,10 +537,23 @@ CompactBlock.prototype.fromBlock = function fromBlock(block, witness, nonce) {
return this;
};
/**
* Instantiate compact block from a block.
* @param {Block} block
* @param {Boolean} witness
* @param {Buffer?} nonce
* @returns {CompactBlock}
*/
CompactBlock.fromBlock = function fromBlock(block, witness, nonce) {
return new CompactBlock().fromBlock(block, witness, nonce);
};
/**
* Convert block to headers.
* @returns {Headers}
*/
CompactBlock.prototype.toHeaders = function toHeaders() {
return Headers.fromBlock(this);
};
@ -412,6 +562,9 @@ CompactBlock.prototype.toHeaders = function toHeaders() {
* Represents a BlockTransactionsRequest (bip152): `getblocktxn` packet.
* @see https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
* @constructor
* @param {Object} options
* @property {Hash} hash
* @property {Number[]} indexes
*/
function TXRequest(options) {
@ -425,6 +578,13 @@ function TXRequest(options) {
this.fromOptions(options);
}
/**
* Inject properties from options.
* @private
* @param {Object} options
* @returns {TXRequest}
*/
TXRequest.prototype.fromOptions = function fromOptions(options) {
this.hash = options.hash;
@ -434,10 +594,23 @@ TXRequest.prototype.fromOptions = function fromOptions(options) {
return this;
};
/**
* Instantiate request from options.
* @param {Object} options
* @returns {TXRequest}
*/
TXRequest.fromOptions = function fromOptions(options) {
return new TXRequest().fromOptions(options);
};
/**
* Inject properties from compact block.
* @private
* @param {CompactBlock} block
* @returns {TXRequest}
*/
TXRequest.prototype.fromCompact = function fromCompact(block) {
var i;
@ -451,10 +624,23 @@ TXRequest.prototype.fromCompact = function fromCompact(block) {
return this;
};
/**
* Instantiate request from compact block.
* @param {CompactBlock} block
* @returns {TXRequest}
*/
TXRequest.fromCompact = function fromCompact(block) {
return new TXRequest().fromCompact(block);
};
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
* @returns {TXRequest}
*/
TXRequest.prototype.fromReader = function fromReader(br) {
var i, count, index, offset;
@ -481,18 +667,42 @@ TXRequest.prototype.fromReader = function fromReader(br) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
* @returns {TXRequest}
*/
TXRequest.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
/**
* Instantiate request from buffer reader.
* @param {BufferReader} br
* @returns {TXRequest}
*/
TXRequest.fromReader = function fromReader(br) {
return new TXRequest().fromReader(br);
};
/**
* Instantiate request from serialized data.
* @param {Buffer} data
* @returns {TXRequest}
*/
TXRequest.fromRaw = function fromRaw(data) {
return new TXRequest().fromRaw(data);
};
/**
* Calculate request serialization size.
* @returns {Number}
*/
TXRequest.prototype.getSize = function getSize() {
var size = 0;
var i, index;
@ -508,6 +718,11 @@ TXRequest.prototype.getSize = function getSize() {
return size;
};
/**
* Write serialized request to buffer writer.
* @param {BufferWriter} bw
*/
TXRequest.prototype.toWriter = function toWriter(bw) {
var i, index;
@ -523,6 +738,11 @@ TXRequest.prototype.toWriter = function toWriter(bw) {
return bw;
};
/**
* Serialize request.
* @returns {Buffer}
*/
TXRequest.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
@ -531,6 +751,9 @@ TXRequest.prototype.toRaw = function toRaw() {
* Represents BlockTransactions (bip152): `blocktxn` packet.
* @see https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
* @constructor
* @param {Object} options
* @property {Hash} hash
* @property {TX[]} txs
*/
function TXResponse(options) {
@ -544,6 +767,13 @@ function TXResponse(options) {
this.fromOptions(options);
}
/**
* Inject properties from options.
* @private
* @param {Object} options
* @returns {TXResponse}
*/
TXResponse.prototype.fromOptions = function fromOptions(options) {
this.hash = options.hash;
@ -553,10 +783,23 @@ TXResponse.prototype.fromOptions = function fromOptions(options) {
return this;
};
/**
* Instantiate response from options.
* @param {Object} options
* @returns {TXResponse}
*/
TXResponse.fromOptions = function fromOptions(options) {
return new TXResponse().fromOptions(options);
};
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
* @returns {TXResponse}
*/
TXResponse.prototype.fromReader = function fromReader(br) {
var i, count;
@ -570,18 +813,44 @@ TXResponse.prototype.fromReader = function fromReader(br) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
* @returns {TXResponse}
*/
TXResponse.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
/**
* Instantiate response from buffer reader.
* @param {BufferReader} br
* @returns {TXResponse}
*/
TXResponse.fromReader = function fromReader(br) {
return new TXResponse().fromReader(br);
};
/**
* Instantiate response from serialized data.
* @param {Buffer} data
* @returns {TXResponse}
*/
TXResponse.fromRaw = function fromRaw(data) {
return new TXResponse().fromRaw(data);
};
/**
* Inject properties from block.
* @private
* @param {Block} block
* @returns {TXResponse}
*/
TXResponse.prototype.fromBlock = function fromBlock(block, req) {
var i, index;
@ -589,34 +858,69 @@ TXResponse.prototype.fromBlock = function fromBlock(block, req) {
for (i = 0; i < req.indexes.length; i++) {
index = req.indexes[i];
if (index >= block.txs.length)
return this;
break;
this.txs.push(block.txs[index]);
}
return this;
};
/**
* Instantiate response from block.
* @param {Block} block
* @returns {TXResponse}
*/
TXResponse.fromBlock = function fromBlock(block, req) {
return new TXResponse().fromBlock(block, req);
};
/**
* Serialize response with witness data.
* @returns {Buffer}
*/
TXResponse.prototype.toRaw = function toRaw() {
return this.frameRaw(true);
};
/**
* Serialize response without witness data.
* @returns {Buffer}
*/
TXResponse.prototype.toNormal = function toNormal() {
return this.frameRaw(false);
};
/**
* Write serialized response to a buffer
* writer (includes witness data).
* @param {BufferWriter} bw
*/
TXResponse.prototype.toWriter = function toWriter(bw) {
return this.writeRaw(bw, true);
};
/**
* Write serialized response to a buffer
* writer (excludes witness data).
* @param {BufferWriter} bw
*/
TXResponse.prototype.toNormalWriter = function toNormalWriter(bw) {
return this.writeRaw(bw, false);
};
/**
* Calculate request serialization size.
* @returns {Number}
*/
TXResponse.prototype.getSize = function getSize(witness) {
var size = 0;
var i, tx;
@ -635,6 +939,13 @@ TXResponse.prototype.getSize = function getSize(witness) {
return size;
};
/**
* Write serialized response to buffer writer.
* @private
* @param {BufferWriter} bw
* @param {Boolean} witness
*/
TXResponse.prototype.writeRaw = function writeRaw(bw, witness) {
var i, tx;
@ -653,13 +964,25 @@ TXResponse.prototype.writeRaw = function writeRaw(bw, witness) {
return bw;
};
/**
* Serialize response with witness data.
* @private
* @param {Boolean} witness
* @returns {Buffer}
*/
TXResponse.prototype.frameRaw = function frameRaw(witness) {
var size = this.getSize();
return this.writeRaw(new StaticWriter(size), witness).render();
};
/*
* Helpers
/**
* Represents a prefilled TX.
* @constructor
* @param {Number} index
* @param {TX} tx
* @property {Number} index
* @property {TX} tx
*/
function PrefilledTX(index, tx) {