minerblock: ensure constant coinbase size.

This commit is contained in:
Christopher Jeffrey 2017-02-22 20:27:19 -08:00
parent 09c2357552
commit f2964e06fb
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 79 additions and 21 deletions

View File

@ -550,6 +550,7 @@ MinerOptions.prototype.fromOptions = function fromOptions(options) {
if (typeof flags === 'string')
flags = new Buffer(flags, 'utf8');
assert(Buffer.isBuffer(flags));
assert(flags.length <= 20, 'Coinbase flags > 20 bytes.');
this.coinbaseFlags = flags;
}

View File

@ -116,9 +116,12 @@ MinerBlock.prototype.getRate = function() {
MinerBlock.prototype._init = function _init() {
var scale = consensus.WITNESS_SCALE_FACTOR;
var hash = encoding.ZERO_HASH;
var block = this.block;
var cb = this.coinbase;
var input, output, nonce;
var input, output, commit, padding;
assert(this.coinbaseFlags.length <= 20);
// Setup our block.
block.version = this.version;
@ -136,7 +139,7 @@ MinerBlock.prototype._init = function _init() {
// Let the world know this little
// miner succeeded.
input.script.set(1, this.coinbaseFlags);
input.script.set(1, encoding.ZERO_HASH160);
// Smaller nonce for good measure.
input.script.set(2, util.nonce().slice(0, 4));
@ -147,42 +150,97 @@ MinerBlock.prototype._init = function _init() {
input.script.compile();
// Set up the witness nonce.
if (this.witness) {
input.witness.set(0, block.createWitnessNonce());
input.witness.compile();
}
cb.inputs.push(input);
// Reward output.
output = new Output();
output.script.fromAddress(this.address);
output.script.fromPubkeyhash(encoding.ZERO_HASH160);
cb.outputs.push(output);
// If we're using segwit, we need to
// set up the nonce and commitment.
// If we're using segwit, we
// need to set up the commitment.
if (this.witness) {
// Our witness nonce is the hash256
// of the previous block hash.
nonce = block.createWitnessNonce();
// Set up the witness nonce.
input.witness.set(0, nonce);
input.witness.compile();
// Commitment output.
cb.outputs.push(new Output());
commit = new Output();
commit.script.fromCommitment(hash);
cb.outputs.push(commit);
}
block.txs.push(cb);
// Update commitments.
this.refresh();
// Initialize weight.
this.weight = this.block.getWeight();
this.weight = block.getWeight();
// 4 extra bytes for varint tx count.
this.weight += 4 * scale;
// Padding for the CB height (constant size).
padding = 5 - input.script.code[0].getSize();
assert(padding >= 0);
this.weight += padding * scale;
// Reserved size.
// Without segwit:
// Block weight = 840
// Block stripped size = 210
// Block size = 210
// CB weight = 500
// CB stripped size = 125
// CB size = 125
// Sigops cost = 4
// With segwit:
// Block weight = 1064
// Block stripped size = 257
// Block size = 293
// CB weight = 724
// CB stripped size = 172
// CB size = 208
// Sigops cost = 4
if (!this.witness) {
assert.equal(this.weight, 840);
assert.equal(block.getBaseSize() + 4 + padding, 210);
assert.equal(block.getSize() + 4 + padding, 210);
assert.equal(cb.getWeight() + padding * scale, 500);
assert.equal(cb.getBaseSize() + padding, 125);
assert.equal(cb.getSize() + padding, 125);
} else {
assert.equal(this.weight, 1064);
assert.equal(block.getBaseSize() + 4 + padding, 257);
assert.equal(block.getSize() + 4 + padding, 293);
assert.equal(cb.getWeight() + padding * scale, 724);
assert.equal(cb.getBaseSize() + padding, 172);
assert.equal(cb.getSize() + padding, 208);
}
// Initialize sigops weight.
this.sigops = cb.getSigopsCost(null, this.flags);
this.sigops = 4;
// Setup coinbase flags (variable size).
input.script.set(1, this.coinbaseFlags);
input.script.compile();
// Setup output script (variable size).
output.script.clear();
output.script.fromAddress(this.address);
// Update commitments.
this.refresh();
// Ensure the variable size
// stuff didn't break anything.
assert(block.getWeight() <= this.weight,
'Coinbase exceeds reserved size!');
assert(cb.getSigopsCost(null, this.flags) <= this.sigops,
'Coinbase exceeds reserved sigops');
};
/**
@ -208,7 +266,6 @@ MinerBlock.prototype.refresh = function refresh() {
MinerBlock.prototype.updateCommitment = function updateCommitment() {
var output = this.coinbase.outputs[1];
var flags = this.coinbaseFlags;
var hash;
// Recalculate witness merkle root.
@ -216,7 +273,7 @@ MinerBlock.prototype.updateCommitment = function updateCommitment() {
// Update commitment.
output.script.clear();
output.script.fromCommitment(hash, flags);
output.script.fromCommitment(hash);
};
/**