chain: do not consider potentially malleated blocks invalid.

This commit is contained in:
Christopher Jeffrey 2016-10-20 12:42:05 -07:00
parent 9dfe86e612
commit 8e1b2ea8e9
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -285,13 +285,27 @@ Chain.prototype.isGenesis = function isGenesis(block) {
Chain.prototype.verify = co(function* verify(block, prev) {
var ret = new VerifyResult();
var i, height, ts, tx, medianTime, commitmentHash, ancestors, state;
var i, err, height, ts, tx, medianTime;
var commitmentHash, ancestors, state;
if (!block.verify(ret)) {
throw new VerifyError(block,
err = new VerifyError(block,
'invalid',
ret.reason,
ret.score);
// High hash is the only thing an
// adversary couldn't mutate in
// otherwise valid non-contextual
// checks. The block timestamp
// can't be mutated, but our
// adjusted time might be off.
// We may be able to accept the
// block later.
if (ret.reason !== 'high-hash')
err.malleated = true;
throw err;
}
// Skip the genesis block. Skip all blocks in spv mode.
@ -349,17 +363,28 @@ Chain.prototype.verify = co(function* verify(block, prev) {
if (state.hasWitness()) {
commitmentHash = block.commitmentHash;
if (commitmentHash) {
// These are totally malleable. Someone
// may have even accidentally sent us
// the non-witness version of the block.
// We don't want to consider this block
// "invalid" if either of these checks
// fail.
if (!block.witnessNonce) {
throw new VerifyError(block,
err = new VerifyError(block,
'invalid',
'bad-witness-merkle-size',
100);
err.malleated = true;
throw err;
}
if (commitmentHash !== block.getCommitmentHash('hex')) {
throw new VerifyError(block,
err = new VerifyError(block,
'invalid',
'bad-witness-merkle-match',
100);
err.malleated = true;
throw err;
}
}
}
@ -368,10 +393,12 @@ Chain.prototype.verify = co(function* verify(block, prev) {
// witness data cannot contain it.
if (!commitmentHash) {
if (block.hasWitness()) {
throw new VerifyError(block,
err = new VerifyError(block,
'invalid',
'unexpected-witness',
100);
err.malleated = true;
throw err;
}
}
@ -842,7 +869,8 @@ Chain.prototype.reconnect = co(function* reconnect(entry) {
view = yield this.verifyContext(block, prev);
} catch (e) {
if (e.type === 'VerifyError') {
this.invalid[entry.hash] = true;
if (!e.malleated)
this.invalid[entry.hash] = true;
this.emit('invalid', block, entry.height);
}
throw e;
@ -897,7 +925,8 @@ Chain.prototype.setBestChain = co(function* setBestChain(entry, block, prev) {
block.setHeight(-1);
if (e.type === 'VerifyError') {
this.invalid[entry.hash] = true;
if (!e.malleated)
this.invalid[entry.hash] = true;
this.emit('invalid', block, entry.height);
}
@ -1082,7 +1111,8 @@ Chain.prototype._add = co(function* add(block) {
// blocks coming in, not the resolving
// orphans.
if (initial && !block.verify(ret)) {
this.invalid[hash] = true;
if (ret.reason === 'high-hash')
this.invalid[hash] = true;
this.emit('invalid', block, block.getCoinbaseHeight());
throw new VerifyError(block, 'invalid', ret.reason, ret.score);
}