chain: do not consider potentially malleated blocks invalid.
This commit is contained in:
parent
9dfe86e612
commit
8e1b2ea8e9
@ -285,13 +285,27 @@ Chain.prototype.isGenesis = function isGenesis(block) {
|
|||||||
|
|
||||||
Chain.prototype.verify = co(function* verify(block, prev) {
|
Chain.prototype.verify = co(function* verify(block, prev) {
|
||||||
var ret = new VerifyResult();
|
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)) {
|
if (!block.verify(ret)) {
|
||||||
throw new VerifyError(block,
|
err = new VerifyError(block,
|
||||||
'invalid',
|
'invalid',
|
||||||
ret.reason,
|
ret.reason,
|
||||||
ret.score);
|
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.
|
// 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()) {
|
if (state.hasWitness()) {
|
||||||
commitmentHash = block.commitmentHash;
|
commitmentHash = block.commitmentHash;
|
||||||
if (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) {
|
if (!block.witnessNonce) {
|
||||||
throw new VerifyError(block,
|
err = new VerifyError(block,
|
||||||
'invalid',
|
'invalid',
|
||||||
'bad-witness-merkle-size',
|
'bad-witness-merkle-size',
|
||||||
100);
|
100);
|
||||||
|
err.malleated = true;
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commitmentHash !== block.getCommitmentHash('hex')) {
|
if (commitmentHash !== block.getCommitmentHash('hex')) {
|
||||||
throw new VerifyError(block,
|
err = new VerifyError(block,
|
||||||
'invalid',
|
'invalid',
|
||||||
'bad-witness-merkle-match',
|
'bad-witness-merkle-match',
|
||||||
100);
|
100);
|
||||||
|
err.malleated = true;
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,10 +393,12 @@ Chain.prototype.verify = co(function* verify(block, prev) {
|
|||||||
// witness data cannot contain it.
|
// witness data cannot contain it.
|
||||||
if (!commitmentHash) {
|
if (!commitmentHash) {
|
||||||
if (block.hasWitness()) {
|
if (block.hasWitness()) {
|
||||||
throw new VerifyError(block,
|
err = new VerifyError(block,
|
||||||
'invalid',
|
'invalid',
|
||||||
'unexpected-witness',
|
'unexpected-witness',
|
||||||
100);
|
100);
|
||||||
|
err.malleated = true;
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -842,7 +869,8 @@ Chain.prototype.reconnect = co(function* reconnect(entry) {
|
|||||||
view = yield this.verifyContext(block, prev);
|
view = yield this.verifyContext(block, prev);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.type === 'VerifyError') {
|
if (e.type === 'VerifyError') {
|
||||||
this.invalid[entry.hash] = true;
|
if (!e.malleated)
|
||||||
|
this.invalid[entry.hash] = true;
|
||||||
this.emit('invalid', block, entry.height);
|
this.emit('invalid', block, entry.height);
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@ -897,7 +925,8 @@ Chain.prototype.setBestChain = co(function* setBestChain(entry, block, prev) {
|
|||||||
block.setHeight(-1);
|
block.setHeight(-1);
|
||||||
|
|
||||||
if (e.type === 'VerifyError') {
|
if (e.type === 'VerifyError') {
|
||||||
this.invalid[entry.hash] = true;
|
if (!e.malleated)
|
||||||
|
this.invalid[entry.hash] = true;
|
||||||
this.emit('invalid', block, entry.height);
|
this.emit('invalid', block, entry.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1082,7 +1111,8 @@ Chain.prototype._add = co(function* add(block) {
|
|||||||
// blocks coming in, not the resolving
|
// blocks coming in, not the resolving
|
||||||
// orphans.
|
// orphans.
|
||||||
if (initial && !block.verify(ret)) {
|
if (initial && !block.verify(ret)) {
|
||||||
this.invalid[hash] = true;
|
if (ret.reason === 'high-hash')
|
||||||
|
this.invalid[hash] = true;
|
||||||
this.emit('invalid', block, block.getCoinbaseHeight());
|
this.emit('invalid', block, block.getCoinbaseHeight());
|
||||||
throw new VerifyError(block, 'invalid', ret.reason, ret.score);
|
throw new VerifyError(block, 'invalid', ret.reason, ret.score);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user