segwit mining.
This commit is contained in:
parent
b1d53adb6a
commit
1dc15922f6
@ -109,7 +109,7 @@ Block.prototype.getSigops = function getSigops(scriptHash, accurate) {
|
||||
return total;
|
||||
};
|
||||
|
||||
Block.prototype.getMerkleRoot = function getMerkleRoot() {
|
||||
Block.prototype.getMerkleRoot = function getMerkleRoot(enc) {
|
||||
var leaves = [];
|
||||
var i, root;
|
||||
|
||||
@ -121,10 +121,12 @@ Block.prototype.getMerkleRoot = function getMerkleRoot() {
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
return utils.toHex(root);
|
||||
return enc === 'hex'
|
||||
? utils.toHex(root)
|
||||
: root;
|
||||
};
|
||||
|
||||
Block.prototype.getCommitmentHash = function getCommitmentHash() {
|
||||
Block.prototype.getCommitmentHash = function getCommitmentHash(enc) {
|
||||
var leaves = [];
|
||||
var i, witnessNonce, witnessRoot, commitmentHash;
|
||||
|
||||
@ -143,7 +145,9 @@ Block.prototype.getCommitmentHash = function getCommitmentHash() {
|
||||
|
||||
commitmentHash = utils.dsha256(Buffer.concat([witnessRoot, witnessNonce]));
|
||||
|
||||
return utils.toHex(commitmentHash);
|
||||
return enc === 'hex'
|
||||
? utils.toHex(commitmentHash)
|
||||
: commitmentHash;
|
||||
};
|
||||
|
||||
Block.prototype.__defineGetter__('commitmentHash', function() {
|
||||
@ -215,7 +219,7 @@ Block.prototype._verify = function _verify(ret) {
|
||||
}
|
||||
|
||||
// Check merkle root
|
||||
if (this.getMerkleRoot() !== this.merkleRoot) {
|
||||
if (this.merkleRoot !== this.getMerkleRoot('hex')) {
|
||||
ret.reason = 'bad-txnmrkleroot';
|
||||
ret.score = 100;
|
||||
return false;
|
||||
|
||||
@ -566,7 +566,7 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
|
||||
}
|
||||
|
||||
if (block.version >= 5 && segwit) {
|
||||
if (block.commitmentHash !== block.getCommitmentHash()) {
|
||||
if (block.commitmentHash !== block.getCommitmentHash('hex')) {
|
||||
return done(new VerifyError(block,
|
||||
'invalid',
|
||||
'bad-blk-wit-length',
|
||||
@ -1571,6 +1571,7 @@ Chain.prototype.getLocator = function getLocator(start, callback, force) {
|
||||
var unlock = this._lock(getLocator, [start, callback], force);
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
if (start) {
|
||||
@ -1950,7 +1951,7 @@ Chain.prototype.computeBlockVersion = function computeBlockVersion(prev, callbac
|
||||
});
|
||||
};
|
||||
|
||||
Chain.prototype.isSegwitActive = function isSegwitActive(callback) {
|
||||
Chain.prototype.isSegwitActive = function isSegwitActive(callback, force) {
|
||||
var self = this;
|
||||
var unlock;
|
||||
|
||||
@ -1965,7 +1966,7 @@ Chain.prototype.isSegwitActive = function isSegwitActive(callback) {
|
||||
if (!this.tip)
|
||||
return utils.asyncify(callback)(null, false);
|
||||
|
||||
// unlock = this._lock(isSegwitActive, [callback]);
|
||||
// unlock = this._lock(isSegwitActive, [callback], force);
|
||||
// if (!unlock)
|
||||
// return;
|
||||
// callback = utils.wrap(callback, unlock);
|
||||
@ -2015,9 +2016,14 @@ Chain.prototype.isSegwitActive = function isSegwitActive(callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Chain.prototype.checkFinal = function checkFinal(prev, tx, flags, callback) {
|
||||
Chain.prototype.checkFinal = function checkFinal(prev, tx, flags, callback, force) {
|
||||
var height = prev.height + 1;
|
||||
|
||||
// var unlock = this._lock(checkFinal, [prev, tx, flags, callback], force);
|
||||
// if (!unlock)
|
||||
// return;
|
||||
// callback = utils.wrap(callback, unlock);
|
||||
|
||||
function check(err, ts) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
@ -2100,7 +2106,7 @@ Chain.prototype.evalLocks = function evalLocks(entry, minHeight, minTime, callba
|
||||
});
|
||||
};
|
||||
|
||||
Chain.prototype.checkLocks = function checkLocks(tx, flags, entry, callback) {
|
||||
Chain.prototype.checkLocks = function checkLocks(tx, flags, entry, callback, force) {
|
||||
var self = this;
|
||||
|
||||
// var unlock = this._lock(checkLocks, [tx, flags, entry, callback], force);
|
||||
|
||||
@ -28,6 +28,9 @@ function Miner(node, options) {
|
||||
this.options = options;
|
||||
this.address = this.options.address;
|
||||
this.coinbaseFlags = this.options.coinbaseFlags || 'mined by bcoin';
|
||||
|
||||
// Allow a dsha256 option in case someone
|
||||
// wants to pass in a faster linked in function.
|
||||
this.dsha256 = this.options.dsha256 || utils.dsha256;
|
||||
|
||||
this.node = node;
|
||||
@ -127,7 +130,7 @@ Miner.prototype.start = function start() {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
self.mempool.fillCoins(tx, function(err) {
|
||||
self.node.fillCoins(tx, function(err) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
@ -165,6 +168,9 @@ Miner.prototype.addTX = function addTX(tx) {
|
||||
if (this.block._txMap[tx.hash('hex')])
|
||||
return false;
|
||||
|
||||
if (!this.block.witness && tx.hasWitness())
|
||||
return false;
|
||||
|
||||
// Add the tx to our block
|
||||
this.block.txs.push(tx);
|
||||
this.block._txMap[tx.hash('hex')] = true;
|
||||
@ -185,8 +191,6 @@ Miner.prototype.createBlock = function createBlock(callback) {
|
||||
var self = this;
|
||||
var ts, target, coinbase, headers, block;
|
||||
|
||||
ts = Math.max(utils.now(), this.last.ts + 1);
|
||||
|
||||
// Find target
|
||||
this.last.ensureAncestors(function(err) {
|
||||
if (err) {
|
||||
@ -194,71 +198,111 @@ Miner.prototype.createBlock = function createBlock(callback) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
target = self.chain.getTarget(self.last, ts);
|
||||
// Calculate version with versionbits
|
||||
self.chain.computeBlockVersion(self.last, function(err, version) {
|
||||
if (err) {
|
||||
self.last.free();
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// Create a coinbase
|
||||
coinbase = bcoin.mtx();
|
||||
ts = Math.max(utils.now(), this.last.ts + 1);
|
||||
|
||||
coinbase.addInput({
|
||||
prevout: {
|
||||
hash: utils.toHex(constants.zeroHash),
|
||||
index: 0xffffffff
|
||||
},
|
||||
script: new bcoin.script([
|
||||
// Height (required in v2+ blocks)
|
||||
bcoin.script.array(self.last.height + 1),
|
||||
// extraNonce - incremented when
|
||||
// the nonce overflows.
|
||||
new Buffer([0]),
|
||||
// Add a nonce to ensure we don't
|
||||
// collide with a previous coinbase
|
||||
// of ours. This isn't really
|
||||
// necessary nowdays due to bip34
|
||||
// (used above).
|
||||
utils.nonce().toBuffer(),
|
||||
// Let the world know this little
|
||||
// miner succeeded.
|
||||
new Buffer(self.coinbaseFlags || 'mined by bcoin', 'ascii')
|
||||
]),
|
||||
witness: new bcoin.script.witness([]),
|
||||
sequence: 0xffffffff
|
||||
target = self.chain.getTarget(self.last, ts);
|
||||
|
||||
// Create a coinbase
|
||||
coinbase = bcoin.mtx();
|
||||
|
||||
coinbase.addInput({
|
||||
prevout: {
|
||||
hash: utils.toHex(constants.zeroHash),
|
||||
index: 0xffffffff
|
||||
},
|
||||
coin: null,
|
||||
script: new bcoin.script([
|
||||
// Height (required in v2+ blocks)
|
||||
bcoin.script.array(self.last.height + 1),
|
||||
// extraNonce - incremented when
|
||||
// the nonce overflows.
|
||||
bcoin.script.array(0),
|
||||
// Add a nonce to ensure we don't
|
||||
// collide with a previous coinbase
|
||||
// of ours. This isn't really
|
||||
// necessary nowdays due to bip34
|
||||
// (used above).
|
||||
bcoin.script.array(utils.nonce()),
|
||||
// Let the world know this little
|
||||
// miner succeeded.
|
||||
new Buffer(self.coinbaseFlags, 'ascii')
|
||||
]),
|
||||
witness: new bcoin.script.witness([]),
|
||||
sequence: 0xffffffff
|
||||
});
|
||||
|
||||
coinbase.addOutput({
|
||||
address: self.address,
|
||||
value: new bn(0)
|
||||
});
|
||||
|
||||
// Create our block
|
||||
headers = {
|
||||
version: version,
|
||||
prevBlock: self.last.hash,
|
||||
merkleRoot: utils.toHex(constants.zeroHash),
|
||||
ts: ts,
|
||||
bits: target,
|
||||
nonce: 0
|
||||
};
|
||||
|
||||
block = bcoin.block(headers, 'block');
|
||||
block._txMap = {};
|
||||
|
||||
block.txs.push(coinbase);
|
||||
|
||||
block.target = utils.fromCompact(target);
|
||||
block.extraNonce = new bn(0, 'le');
|
||||
|
||||
if (self.chain.segwitActive) {
|
||||
// Set up the witness nonce and
|
||||
// commitment output for segwit.
|
||||
block.witness = true;
|
||||
block.witnessNonce = utils.nonce().toBuffer();
|
||||
coinbase.inputs[0].witness.items[0] = block.witnessNonce;
|
||||
coinbase.addOutput({
|
||||
script: new bcoin.script([]),
|
||||
value: new bn(0)
|
||||
});
|
||||
}
|
||||
|
||||
// Update coinbase since our coinbase was added.
|
||||
self.updateCoinbase(block);
|
||||
|
||||
// Create our merkle root.
|
||||
self.updateMerkle(block);
|
||||
|
||||
self.last.free();
|
||||
|
||||
return callback(null, block);
|
||||
});
|
||||
|
||||
coinbase.addOutput({
|
||||
address: self.address,
|
||||
value: new bn(0)
|
||||
});
|
||||
|
||||
// Create our block
|
||||
headers = {
|
||||
version: 4,
|
||||
prevBlock: self.last.hash,
|
||||
merkleRoot: utils.toHex(constants.zeroHash),
|
||||
ts: ts,
|
||||
bits: target,
|
||||
nonce: 0
|
||||
};
|
||||
|
||||
block = bcoin.block(headers, 'block');
|
||||
block._txMap = {};
|
||||
|
||||
block.txs.push(coinbase);
|
||||
|
||||
block.target = utils.fromCompact(target);
|
||||
block.extraNonce = new bn(0, 'le');
|
||||
|
||||
// Update coinbase since our coinbase was added.
|
||||
self.updateCoinbase(block);
|
||||
|
||||
// Create our merkle root.
|
||||
self.updateMerkle(block);
|
||||
|
||||
self.last.free();
|
||||
|
||||
return callback(null, block);
|
||||
});
|
||||
};
|
||||
|
||||
Miner.prototype.updateCommitment = function updateCommitment(block) {
|
||||
var coinbase = block.txs[0];
|
||||
var hash;
|
||||
|
||||
assert(coinbase);
|
||||
|
||||
if (!block)
|
||||
block = this.block;
|
||||
|
||||
delete block._txMap[coinbase.hash('hex')];
|
||||
|
||||
hash = block.getCommitmentHash();
|
||||
coinbase.outputs[1].script = bcoin.script.createCommitment(hash);
|
||||
|
||||
block._txMap[coinbase.hash('hex')] = true;
|
||||
};
|
||||
|
||||
Miner.prototype.updateCoinbase = function updateCoinbase(block) {
|
||||
var coinbase = block.txs[0];
|
||||
var reward = bcoin.block.reward(this.last.height + 1);
|
||||
@ -280,37 +324,29 @@ Miner.prototype.updateMerkle = function updateMerkle(block) {
|
||||
if (!block)
|
||||
block = this.block;
|
||||
|
||||
// Always update commitment before updating merkle root.
|
||||
// The updated commitment output will change the merkle root.
|
||||
if (block.witness)
|
||||
this.updateCommitment(block);
|
||||
|
||||
block.ts = utils.now();
|
||||
block.merkleRoot = block.getMerkleRoot();
|
||||
block.merkleRoot = block.getMerkleRoot('hex');
|
||||
};
|
||||
|
||||
Miner.prototype.iterate = function iterate() {
|
||||
var self = this;
|
||||
|
||||
this.timeout = setTimeout(function() {
|
||||
var hash, res;
|
||||
|
||||
// Try to find a block: do one iteration of extraNonce
|
||||
if (!self.findNonce())
|
||||
return self.iterate();
|
||||
|
||||
hash = self.block.hash('hex');
|
||||
|
||||
// Make sure our block is valid
|
||||
if (!self.block.verify()) {
|
||||
utils.debug('%s did not verify.', hash);
|
||||
return self.emit('error', new Error(hash + ' did not verify.'));
|
||||
}
|
||||
|
||||
// Add our block to the chain
|
||||
self.chain.add(self.block, self.pool.peers.load, function(err, total) {
|
||||
if (err)
|
||||
self.chain.add(self.block, function(err) {
|
||||
if (err) {
|
||||
if (err.type === 'VerifyError')
|
||||
utils.debug('Miner: %s could not be added to chain.', block.rhash);
|
||||
return self.emit('error', err);
|
||||
|
||||
if (total === 0) {
|
||||
utils.debug('%s could not be added to chain.', hash);
|
||||
return self.emit('error',
|
||||
new Error(hash + ' could not be added to chain.'));
|
||||
}
|
||||
|
||||
// Emit our newly found block
|
||||
|
||||
@ -1700,6 +1700,13 @@ Script.prototype.isCommitment = function isCommitment() {
|
||||
&& utils.readU32BE(this.code[1], 0) === 0xaa21a9ed;
|
||||
};
|
||||
|
||||
Script.prototype.createCommitment = function createCommitment(hash) {
|
||||
return new Script([
|
||||
opcodes.OP_RETURN,
|
||||
Buffer.concat([new Buffer([0xaa, 0x21, 0xa9, 0xed]), hash])
|
||||
]);
|
||||
};
|
||||
|
||||
Script.prototype.getCommitmentHash = function getCommitmentHash() {
|
||||
if (!this.isCommitment())
|
||||
return;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user