bip152: comments.
This commit is contained in:
parent
60897be916
commit
9affb11b22
@ -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) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user