minerblock: ensure constant coinbase size.
This commit is contained in:
parent
09c2357552
commit
f2964e06fb
@ -550,6 +550,7 @@ MinerOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
if (typeof flags === 'string')
|
if (typeof flags === 'string')
|
||||||
flags = new Buffer(flags, 'utf8');
|
flags = new Buffer(flags, 'utf8');
|
||||||
assert(Buffer.isBuffer(flags));
|
assert(Buffer.isBuffer(flags));
|
||||||
|
assert(flags.length <= 20, 'Coinbase flags > 20 bytes.');
|
||||||
this.coinbaseFlags = flags;
|
this.coinbaseFlags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -116,9 +116,12 @@ MinerBlock.prototype.getRate = function() {
|
|||||||
|
|
||||||
MinerBlock.prototype._init = function _init() {
|
MinerBlock.prototype._init = function _init() {
|
||||||
var scale = consensus.WITNESS_SCALE_FACTOR;
|
var scale = consensus.WITNESS_SCALE_FACTOR;
|
||||||
|
var hash = encoding.ZERO_HASH;
|
||||||
var block = this.block;
|
var block = this.block;
|
||||||
var cb = this.coinbase;
|
var cb = this.coinbase;
|
||||||
var input, output, nonce;
|
var input, output, commit, padding;
|
||||||
|
|
||||||
|
assert(this.coinbaseFlags.length <= 20);
|
||||||
|
|
||||||
// Setup our block.
|
// Setup our block.
|
||||||
block.version = this.version;
|
block.version = this.version;
|
||||||
@ -136,7 +139,7 @@ MinerBlock.prototype._init = function _init() {
|
|||||||
|
|
||||||
// Let the world know this little
|
// Let the world know this little
|
||||||
// miner succeeded.
|
// miner succeeded.
|
||||||
input.script.set(1, this.coinbaseFlags);
|
input.script.set(1, encoding.ZERO_HASH160);
|
||||||
|
|
||||||
// Smaller nonce for good measure.
|
// Smaller nonce for good measure.
|
||||||
input.script.set(2, util.nonce().slice(0, 4));
|
input.script.set(2, util.nonce().slice(0, 4));
|
||||||
@ -147,42 +150,97 @@ MinerBlock.prototype._init = function _init() {
|
|||||||
|
|
||||||
input.script.compile();
|
input.script.compile();
|
||||||
|
|
||||||
|
// Set up the witness nonce.
|
||||||
|
if (this.witness) {
|
||||||
|
input.witness.set(0, block.createWitnessNonce());
|
||||||
|
input.witness.compile();
|
||||||
|
}
|
||||||
|
|
||||||
cb.inputs.push(input);
|
cb.inputs.push(input);
|
||||||
|
|
||||||
// Reward output.
|
// Reward output.
|
||||||
output = new Output();
|
output = new Output();
|
||||||
output.script.fromAddress(this.address);
|
output.script.fromPubkeyhash(encoding.ZERO_HASH160);
|
||||||
|
|
||||||
cb.outputs.push(output);
|
cb.outputs.push(output);
|
||||||
|
|
||||||
// If we're using segwit, we need to
|
// If we're using segwit, we
|
||||||
// set up the nonce and commitment.
|
// need to set up the commitment.
|
||||||
if (this.witness) {
|
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.
|
// Commitment output.
|
||||||
cb.outputs.push(new Output());
|
commit = new Output();
|
||||||
|
commit.script.fromCommitment(hash);
|
||||||
|
cb.outputs.push(commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.txs.push(cb);
|
block.txs.push(cb);
|
||||||
|
|
||||||
// Update commitments.
|
|
||||||
this.refresh();
|
|
||||||
|
|
||||||
// Initialize weight.
|
// Initialize weight.
|
||||||
this.weight = this.block.getWeight();
|
this.weight = block.getWeight();
|
||||||
|
|
||||||
// 4 extra bytes for varint tx count.
|
// 4 extra bytes for varint tx count.
|
||||||
this.weight += 4 * scale;
|
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.
|
// 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() {
|
MinerBlock.prototype.updateCommitment = function updateCommitment() {
|
||||||
var output = this.coinbase.outputs[1];
|
var output = this.coinbase.outputs[1];
|
||||||
var flags = this.coinbaseFlags;
|
|
||||||
var hash;
|
var hash;
|
||||||
|
|
||||||
// Recalculate witness merkle root.
|
// Recalculate witness merkle root.
|
||||||
@ -216,7 +273,7 @@ MinerBlock.prototype.updateCommitment = function updateCommitment() {
|
|||||||
|
|
||||||
// Update commitment.
|
// Update commitment.
|
||||||
output.script.clear();
|
output.script.clear();
|
||||||
output.script.fromCommitment(hash, flags);
|
output.script.fromCommitment(hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user