more accurate segwit4 verification. misc.
This commit is contained in:
parent
0a7f118528
commit
a3720bd42d
2
bin/node
2
bin/node
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
var bcoin = require('bcoin')({ debug: true });
|
var bcoin = require('bcoin')({ debug: true, debugFile: true });
|
||||||
var utils = bcoin.utils;
|
var utils = bcoin.utils;
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
var bcoin = require('bcoin')({ debug: true });
|
var bcoin = require('bcoin')({ debug: true, debugFile: true });
|
||||||
var utils = bcoin.utils;
|
var utils = bcoin.utils;
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
|
|
||||||
|
|||||||
@ -148,9 +148,8 @@ Block.prototype.getMerkleRoot = function getMerkleRoot(enc) {
|
|||||||
|
|
||||||
Block.prototype.getCommitmentHash = function getCommitmentHash(enc) {
|
Block.prototype.getCommitmentHash = function getCommitmentHash(enc) {
|
||||||
var leaves = [];
|
var leaves = [];
|
||||||
var i, witnessNonce, witnessRoot, commitmentHash;
|
var witnessNonce = this.witnessNonce;
|
||||||
|
var i, witnessRoot, commitmentHash;
|
||||||
witnessNonce = this.txs[0].inputs[0].witness.items[0];
|
|
||||||
|
|
||||||
if (!witnessNonce)
|
if (!witnessNonce)
|
||||||
return;
|
return;
|
||||||
@ -170,6 +169,24 @@ Block.prototype.getCommitmentHash = function getCommitmentHash(enc) {
|
|||||||
: commitmentHash;
|
: commitmentHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Block.prototype.__defineGetter__('witnessNonce', function() {
|
||||||
|
var coinbase = this.txs[0];
|
||||||
|
|
||||||
|
if (!coinbase)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (coinbase.inputs.length !== 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (coinbase.inputs[0].witness.items.length !== 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (coinbase.inputs[0].witness.items[0].length !== 32)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return coinbase.inputs[0].witness.items[0];
|
||||||
|
});
|
||||||
|
|
||||||
Block.prototype.__defineGetter__('commitmentHash', function() {
|
Block.prototype.__defineGetter__('commitmentHash', function() {
|
||||||
var coinbase, i, commitment, commitmentHash;
|
var coinbase, i, commitment, commitmentHash;
|
||||||
|
|
||||||
@ -178,6 +195,9 @@ Block.prototype.__defineGetter__('commitmentHash', function() {
|
|||||||
|
|
||||||
coinbase = this.txs[0];
|
coinbase = this.txs[0];
|
||||||
|
|
||||||
|
if (!coinbase)
|
||||||
|
return;
|
||||||
|
|
||||||
for (i = 0; i < coinbase.outputs.length; i++) {
|
for (i = 0; i < coinbase.outputs.length; i++) {
|
||||||
commitment = coinbase.outputs[i].script;
|
commitment = coinbase.outputs[i].script;
|
||||||
if (commitment.isCommitment()) {
|
if (commitment.isCommitment()) {
|
||||||
@ -211,7 +231,7 @@ Block.prototype._verify = function _verify(ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// First TX must be a coinbase
|
// First TX must be a coinbase
|
||||||
if (!this.txs.length || !this.txs[0].isCoinbase()) {
|
if (this.txs.length === 0 || !this.txs[0].isCoinbase()) {
|
||||||
ret.reason = 'bad-cb-missing';
|
ret.reason = 'bad-cb-missing';
|
||||||
ret.score = 100;
|
ret.score = 100;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -405,7 +405,7 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
|
|||||||
var flags = constants.flags.MANDATORY_VERIFY_FLAGS;
|
var flags = constants.flags.MANDATORY_VERIFY_FLAGS;
|
||||||
var lockFlags = constants.flags.MANDATORY_LOCKTIME_FLAGS;
|
var lockFlags = constants.flags.MANDATORY_LOCKTIME_FLAGS;
|
||||||
var height, ts, i, tx, coinbaseHeight;
|
var height, ts, i, tx, coinbaseHeight;
|
||||||
var medianTime, segwit;
|
var medianTime, segwit, commitmentHash;
|
||||||
var ret = {};
|
var ret = {};
|
||||||
|
|
||||||
function done(err, result) {
|
function done(err, result) {
|
||||||
@ -492,12 +492,14 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
|
|||||||
|
|
||||||
// Segregrated witness is now usable
|
// Segregrated witness is now usable
|
||||||
if (network.type === 'segnet3' && height >= network.segwitHeight) {
|
if (network.type === 'segnet3' && height >= network.segwitHeight) {
|
||||||
if (block.version >= 5 && prev.isUpgraded(5)) {
|
if (block.version >= 5) {
|
||||||
flags |= constants.flags.VERIFY_WITNESS;
|
if (prev.isUpgraded(5)) {
|
||||||
segwit = true;
|
flags |= constants.flags.VERIFY_WITNESS;
|
||||||
self.segwitActive = true;
|
segwit = true;
|
||||||
} else if (block.version >= 5) {
|
self.segwitActive = true;
|
||||||
self.segwitActive = false;
|
} else {
|
||||||
|
self.segwitActive = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,13 +538,24 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (segwit) {
|
if (segwit) {
|
||||||
if (block.commitmentHash !== block.getCommitmentHash('hex')) {
|
commitmentHash = block.commitmentHash;
|
||||||
return done(new VerifyError(block,
|
if (commitmentHash) {
|
||||||
'invalid',
|
if (!block.witnessNonce) {
|
||||||
'bad-blk-wit-length',
|
return done(new VerifyError(block,
|
||||||
100));
|
'invalid',
|
||||||
|
'bad-witness-merkle-size',
|
||||||
|
100));
|
||||||
|
}
|
||||||
|
if (commitmentHash !== block.getCommitmentHash('hex')) {
|
||||||
|
return done(new VerifyError(block,
|
||||||
|
'invalid',
|
||||||
|
'bad-witness-merkle-match',
|
||||||
|
100));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (!commitmentHash) {
|
||||||
if (block.hasWitness()) {
|
if (block.hasWitness()) {
|
||||||
return done(new VerifyError(block,
|
return done(new VerifyError(block,
|
||||||
'invalid',
|
'invalid',
|
||||||
|
|||||||
@ -31,6 +31,9 @@ function Environment(options) {
|
|||||||
|
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
|
||||||
|
this._ensured = false;
|
||||||
|
this._debug = null;
|
||||||
|
|
||||||
this.isBrowser =
|
this.isBrowser =
|
||||||
(typeof process !== 'undefined' && process.browser)
|
(typeof process !== 'undefined' && process.browser)
|
||||||
|| typeof window !== 'undefined';
|
|| typeof window !== 'undefined';
|
||||||
@ -46,9 +49,6 @@ function Environment(options) {
|
|||||||
|
|
||||||
this.debugFile = options.debugFile;
|
this.debugFile = options.debugFile;
|
||||||
|
|
||||||
if (options.debugFile == null)
|
|
||||||
this.debugFile = true;
|
|
||||||
|
|
||||||
if (process.env.BCOIN_DEBUGFILE != null) {
|
if (process.env.BCOIN_DEBUGFILE != null) {
|
||||||
if (process.env.BCOIN_DEBUGFILE === '0'
|
if (process.env.BCOIN_DEBUGFILE === '0'
|
||||||
|| process.env.BCOIN_DEBUGFILE === '1') {
|
|| process.env.BCOIN_DEBUGFILE === '1') {
|
||||||
@ -66,11 +66,6 @@ function Environment(options) {
|
|||||||
if (process.env.BCOIN_PROFILE != null)
|
if (process.env.BCOIN_PROFILE != null)
|
||||||
this.profile = +process.env.BCOIN_PROFILE === 1;
|
this.profile = +process.env.BCOIN_PROFILE === 1;
|
||||||
|
|
||||||
this.fresh = options.fresh;
|
|
||||||
|
|
||||||
if (process.env.BCOIN_FRESH != null)
|
|
||||||
this.fresh = +process.env.BCOIN_FRESH === 1;
|
|
||||||
|
|
||||||
this.useWorkers = options.useWorkers;
|
this.useWorkers = options.useWorkers;
|
||||||
|
|
||||||
if (process.env.BCOIN_USE_WORKERS != null)
|
if (process.env.BCOIN_USE_WORKERS != null)
|
||||||
@ -127,13 +122,13 @@ function Environment(options) {
|
|||||||
this.chain = require('./chain')(this);
|
this.chain = require('./chain')(this);
|
||||||
this.mempool = require('./mempool')(this);
|
this.mempool = require('./mempool')(this);
|
||||||
this.keypair = require('./keypair')(this);
|
this.keypair = require('./keypair')(this);
|
||||||
|
this.hd = require('./hd')(this);
|
||||||
this.address = require('./address')(this);
|
this.address = require('./address')(this);
|
||||||
|
this.wallet = require('./wallet')(this);
|
||||||
this.walletdb = require('./walletdb')(this);
|
this.walletdb = require('./walletdb')(this);
|
||||||
this.provider = this.walletdb.provider;
|
this.provider = this.walletdb.provider;
|
||||||
this.wallet = require('./wallet')(this);
|
|
||||||
this.peer = require('./peer')(this);
|
this.peer = require('./peer')(this);
|
||||||
this.pool = require('./pool')(this);
|
this.pool = require('./pool')(this);
|
||||||
this.hd = require('./hd')(this);
|
|
||||||
this.miner = require('./miner')(this);
|
this.miner = require('./miner')(this);
|
||||||
this.minerblock = this.miner.minerblock;
|
this.minerblock = this.miner.minerblock;
|
||||||
this.http = require('./http')(this);
|
this.http = require('./http')(this);
|
||||||
@ -151,9 +146,6 @@ Environment.prototype.ensurePrefix = function ensurePrefix() {
|
|||||||
|
|
||||||
this._ensured = true;
|
this._ensured = true;
|
||||||
|
|
||||||
if (this.fresh && this.prefix.indexOf('bcoin') !== -1)
|
|
||||||
this.rimraf(this.prefix);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.statSync(this.prefix);
|
fs.statSync(this.prefix);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -161,31 +153,26 @@ Environment.prototype.ensurePrefix = function ensurePrefix() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Environment.prototype.rimraf = function rimraf(file) {
|
|
||||||
var cp;
|
|
||||||
|
|
||||||
if (this.isBrowser)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cp = require('child_' + 'process');
|
|
||||||
|
|
||||||
assert(typeof file === 'string');
|
|
||||||
assert(file !== '/');
|
|
||||||
assert(file !== process.env.HOME);
|
|
||||||
|
|
||||||
cp.execFileSync('rm', ['-rf', file], { stdio: 'ignore' });
|
|
||||||
};
|
|
||||||
|
|
||||||
Environment.prototype.debug = function debug() {
|
Environment.prototype.debug = function debug() {
|
||||||
var args = Array.prototype.slice.call(arguments);
|
var args = Array.prototype.slice.call(arguments);
|
||||||
var msg;
|
var msg;
|
||||||
|
|
||||||
|
if (this.isBrowser) {
|
||||||
|
if (this.debugLogs) {
|
||||||
|
msg = typeof args[0] === 'object'
|
||||||
|
? args[0]
|
||||||
|
: utils.format(args, false).slice(0, -1);
|
||||||
|
console.error(msg);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.debugLogs) {
|
if (this.debugLogs) {
|
||||||
msg = utils.format(args, true);
|
msg = utils.format(args, true);
|
||||||
process.stderr.write(msg);
|
process.stderr.write(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.debugFile && !this.isBrowser) {
|
if (this.debugFile) {
|
||||||
if (!this._debug) {
|
if (!this._debug) {
|
||||||
this.ensurePrefix();
|
this.ensurePrefix();
|
||||||
this._debug = fs.createWriteStream(this.debugFile, { flags: 'a' });
|
this._debug = fs.createWriteStream(this.debugFile, { flags: 'a' });
|
||||||
|
|||||||
@ -44,6 +44,7 @@ function Miner(options) {
|
|||||||
|
|
||||||
this.running = false;
|
this.running = false;
|
||||||
this.timeout = null;
|
this.timeout = null;
|
||||||
|
this.loaded = false;
|
||||||
|
|
||||||
this.block = null;
|
this.block = null;
|
||||||
|
|
||||||
@ -53,7 +54,10 @@ function Miner(options) {
|
|||||||
utils.inherits(Miner, EventEmitter);
|
utils.inherits(Miner, EventEmitter);
|
||||||
|
|
||||||
Miner.prototype.open = function open(callback) {
|
Miner.prototype.open = function open(callback) {
|
||||||
return utils.nextTick(callback);
|
if (this.loaded)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
return this.once('open', callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Miner.prototype.close =
|
Miner.prototype.close =
|
||||||
@ -105,6 +109,13 @@ Miner.prototype._init = function _init() {
|
|||||||
stat.height,
|
stat.height,
|
||||||
stat.best);
|
stat.best);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.chain.open(function(err) {
|
||||||
|
if (err)
|
||||||
|
return self.emit('error', err);
|
||||||
|
self.loaded = true;
|
||||||
|
self.emit('open');
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Miner.prototype.start = function start() {
|
Miner.prototype.start = function start() {
|
||||||
@ -263,7 +274,7 @@ function MinerBlock(options) {
|
|||||||
|
|
||||||
this.coinbase.addInput({
|
this.coinbase.addInput({
|
||||||
prevout: {
|
prevout: {
|
||||||
hash: utils.toHex(constants.zeroHash),
|
hash: constants.nullHash,
|
||||||
index: 0xffffffff
|
index: 0xffffffff
|
||||||
},
|
},
|
||||||
coin: null,
|
coin: null,
|
||||||
@ -283,7 +294,7 @@ function MinerBlock(options) {
|
|||||||
// miner succeeded.
|
// miner succeeded.
|
||||||
new Buffer(options.coinbaseFlags, 'ascii')
|
new Buffer(options.coinbaseFlags, 'ascii')
|
||||||
]),
|
]),
|
||||||
witness: new bcoin.script.witness([]),
|
witness: new bcoin.script.witness(),
|
||||||
sequence: 0xffffffff
|
sequence: 0xffffffff
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -296,10 +307,11 @@ function MinerBlock(options) {
|
|||||||
this.block = new bcoin.block({
|
this.block = new bcoin.block({
|
||||||
version: options.version,
|
version: options.version,
|
||||||
prevBlock: this.tip.hash,
|
prevBlock: this.tip.hash,
|
||||||
merkleRoot: constants.zeroHash,
|
merkleRoot: constants.nullHash,
|
||||||
ts: Math.max(utils.now(), this.tip.ts + 1),
|
ts: Math.max(utils.now(), this.tip.ts + 1),
|
||||||
bits: options.target,
|
bits: options.target,
|
||||||
nonce: 0
|
nonce: 0,
|
||||||
|
height: this.height
|
||||||
});
|
});
|
||||||
|
|
||||||
this.block.txs.push(this.coinbase);
|
this.block.txs.push(this.coinbase);
|
||||||
@ -311,7 +323,7 @@ function MinerBlock(options) {
|
|||||||
this.witnessNonce = utils.dsha256(new Buffer(this.tip.hash, 'hex'));
|
this.witnessNonce = utils.dsha256(new Buffer(this.tip.hash, 'hex'));
|
||||||
this.coinbase.inputs[0].witness.items[0] = this.witnessNonce;
|
this.coinbase.inputs[0].witness.items[0] = this.witnessNonce;
|
||||||
this.coinbase.addOutput({
|
this.coinbase.addOutput({
|
||||||
script: new bcoin.script([]),
|
script: new bcoin.script(),
|
||||||
value: new bn(0)
|
value: new bn(0)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -478,8 +490,10 @@ MinerBlock.prototype.mineAsync = function mine(callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
MinerBlock.prototype.destroy = function destroy() {
|
MinerBlock.prototype.destroy = function destroy() {
|
||||||
clearTimeout(this.timeout);
|
if (this.timeout) {
|
||||||
this.timeout = null;
|
clearTimeout(this.timeout);
|
||||||
|
this.timeout = null;
|
||||||
|
}
|
||||||
this.block = null;
|
this.block = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -18,12 +18,6 @@ if (bcoin.profile && !bcoin.isBrowser) {
|
|||||||
fs = require('f' + 's');
|
fs = require('f' + 's');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profiler) {
|
|
||||||
utils.nextTick(function() {
|
|
||||||
bcoin.debug('Starting node with profiler enabled.');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Profile
|
* Profile
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -708,7 +708,18 @@ utils.format = function format(args, color) {
|
|||||||
|
|
||||||
utils.print = function print() {
|
utils.print = function print() {
|
||||||
var args = Array.prototype.slice.call(arguments);
|
var args = Array.prototype.slice.call(arguments);
|
||||||
return process.stdout.write(utils.format(args, true));
|
var msg;
|
||||||
|
|
||||||
|
if (utils.isBrowser) {
|
||||||
|
msg = typeof args[0] === 'object'
|
||||||
|
? args[0]
|
||||||
|
: utils.format(args, false).slice(0, -1);
|
||||||
|
console.log(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = utils.format(args, true);
|
||||||
|
process.stdout.write(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
utils.merge = function merge(target) {
|
utils.merge = function merge(target) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user