test: add more mempool tests.
This commit is contained in:
parent
d18482507a
commit
72597c9faf
@ -99,6 +99,7 @@ function Mempool(options) {
|
||||
: this.network.requireStandard;
|
||||
this.rejectAbsurdFees = this.options.rejectAbsurdFees !== false;
|
||||
this.prematureWitness = !!this.options.prematureWitness;
|
||||
this.paranoid = !!this.options.paranoid;
|
||||
|
||||
this.maxSize = options.maxSize || constants.mempool.MAX_MEMPOOL_SIZE;
|
||||
this.expiryTime = options.expiryTime || constants.mempool.MEMPOOL_EXPIRY;
|
||||
@ -866,16 +867,16 @@ Mempool.prototype.verify = function verify(entry, callback) {
|
||||
'bad-txns-nonstandard-inputs',
|
||||
0));
|
||||
}
|
||||
// if (self.chain.state.hasWitness()) {
|
||||
// if (!tx.hasStandardWitness(true, ret)) {
|
||||
// ret = new VerifyError(tx,
|
||||
// 'nonstandard',
|
||||
// ret.reason,
|
||||
// ret.score);
|
||||
// ret.malleated = ret.score > 0;
|
||||
// return callback(ret);
|
||||
// }
|
||||
// }
|
||||
if (self.chain.state.hasWitness()) {
|
||||
if (!tx.hasStandardWitness(ret)) {
|
||||
ret = new VerifyError(tx,
|
||||
'nonstandard',
|
||||
ret.reason,
|
||||
ret.score);
|
||||
ret.malleated = ret.score > 0;
|
||||
return callback(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tx.getSigopsWeight(flags) > constants.tx.MAX_SIGOPS_WEIGHT) {
|
||||
@ -954,6 +955,9 @@ Mempool.prototype.verify = function verify(entry, callback) {
|
||||
// Standard verification
|
||||
self.checkInputs(tx, flags1, function(error) {
|
||||
if (!error) {
|
||||
if (!self.paranoid)
|
||||
return callback();
|
||||
|
||||
return self.checkResult(tx, mandatory, function(err, result) {
|
||||
if (err) {
|
||||
assert(err.type !== 'VerifyError',
|
||||
@ -1192,8 +1196,7 @@ Mempool.prototype.getDepends = function getDepends(tx) {
|
||||
*/
|
||||
|
||||
Mempool.prototype.storeOrphan = function storeOrphan(tx) {
|
||||
var prevout = {};
|
||||
var missing = [];
|
||||
var missing = {};
|
||||
var i, hash, input, prev;
|
||||
|
||||
if (tx.getWeight() > constants.tx.MAX_WEIGHT) {
|
||||
@ -1211,26 +1214,26 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx) {
|
||||
|
||||
if (this.hasReject(input.prevout.hash)) {
|
||||
this.logger.debug('Not storing orphan %s (rejected parents).', tx.rhash);
|
||||
this.rejects.add(tx.hash());
|
||||
return;
|
||||
}
|
||||
|
||||
missing.push(input.prevout.hash);
|
||||
}
|
||||
|
||||
hash = tx.hash('hex');
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
if (!input.coin)
|
||||
prevout[input.prevout.hash] = true;
|
||||
if (input.coin)
|
||||
continue;
|
||||
missing[input.prevout.hash] = true;
|
||||
}
|
||||
|
||||
prevout = Object.keys(prevout);
|
||||
missing = Object.keys(missing);
|
||||
|
||||
assert(prevout.length > 0);
|
||||
assert(missing.length > 0);
|
||||
|
||||
for (i = 0; i < prevout.length; i++) {
|
||||
prev = prevout[i];
|
||||
for (i = 0; i < missing.length; i++) {
|
||||
prev = missing[i];
|
||||
if (!this.waiting[prev])
|
||||
this.waiting[prev] = [];
|
||||
this.waiting[prev].push(hash);
|
||||
|
||||
@ -1374,13 +1374,13 @@ TX.prototype.hasStandardInputs = function hasStandardInputs() {
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
TX.prototype.hasStandardWitness = function hasStandardWitness(strict, ret) {
|
||||
TX.prototype.hasStandardWitness = function hasStandardWitness(ret) {
|
||||
var result;
|
||||
|
||||
if (!ret)
|
||||
ret = new VerifyResult();
|
||||
|
||||
result = this._hasStandardWitness();
|
||||
result = this.getWitnessStandard();
|
||||
|
||||
switch (result) {
|
||||
case BAD_WITNESS:
|
||||
@ -1392,12 +1392,9 @@ TX.prototype.hasStandardWitness = function hasStandardWitness(strict, ret) {
|
||||
ret.score = 100;
|
||||
return false;
|
||||
case BAD_NONSTD_P2WSH:
|
||||
if (strict) {
|
||||
ret.reason = 'bad-witness-nonstandard';
|
||||
ret.score = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
ret.reason = 'bad-witness-nonstandard';
|
||||
ret.score = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1410,7 +1407,7 @@ TX.prototype.hasStandardWitness = function hasStandardWitness(strict, ret) {
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
TX.prototype._hasStandardWitness = function _hasStandardWitness() {
|
||||
TX.prototype.getWitnessStandard = function getWitnessStandard() {
|
||||
var ret = BAD_OKAY;
|
||||
var i, j, input, prev, hash, redeem, m, n;
|
||||
|
||||
|
||||
@ -28,12 +28,16 @@ describe('Mempool', function() {
|
||||
verify: true
|
||||
});
|
||||
|
||||
var w;
|
||||
var w, cached;
|
||||
|
||||
mempool.on('error', function() {});
|
||||
|
||||
it('should open mempool', function(cb) {
|
||||
mempool.open(cb);
|
||||
mempool.open(function(err) {
|
||||
assert.ifError(err);
|
||||
chain.state.flags |= constants.flags.VERIFY_WITNESS;
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
it('should open walletdb', function(cb) {
|
||||
@ -233,6 +237,169 @@ describe('Mempool', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should not cache a malleated wtx with mutated sig', function(cb) {
|
||||
var kp = bcoin.keyring.generate();
|
||||
kp.witness = true;
|
||||
// Coinbase
|
||||
var t1 = bcoin.mtx().addOutput(w, 50000).addOutput(w, 10000); // 10000 instead of 1000
|
||||
var prev = new bcoin.script([0, kp.keyHash]);
|
||||
var prevHash = crypto.randomBytes(32).toString('hex');
|
||||
var dummyInput = {
|
||||
prevout: {
|
||||
hash: prevHash,
|
||||
index: 0
|
||||
},
|
||||
coin: {
|
||||
version: 1,
|
||||
height: 0,
|
||||
value: 70000,
|
||||
script: prev,
|
||||
coinbase: false,
|
||||
hash: prevHash,
|
||||
index: 0
|
||||
},
|
||||
script: new bcoin.script([]),
|
||||
sequence: 0xffffffff
|
||||
};
|
||||
t1.addInput(dummyInput);
|
||||
var prevs = bcoin.script.fromPubkeyhash(kp.keyHash);
|
||||
var sig = new bcoin.witness([t1.signature(0, prevs, kp.privateKey, 'all', 1), kp.publicKey]);
|
||||
var sig2 = new bcoin.witness([t1.signature(0, prevs, kp.privateKey, 'all', 1), kp.publicKey]);
|
||||
sig2.items[0][sig2.items[0].length - 1] = 0;
|
||||
t1.inputs[0].witness = sig2;
|
||||
var tx = t1.toTX();
|
||||
mempool.addTX(tx, function(err) {
|
||||
assert(err);
|
||||
assert(!mempool.hasReject(tx.hash()));
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not cache a malleated tx with unnecessary witness', function(cb) {
|
||||
var kp = bcoin.keyring.generate();
|
||||
// Coinbase
|
||||
var t1 = bcoin.mtx().addOutput(w, 50000).addOutput(w, 10000); // 10000 instead of 1000
|
||||
var prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
||||
var prevHash = crypto.randomBytes(32).toString('hex');
|
||||
var dummyInput = {
|
||||
prevout: {
|
||||
hash: prevHash,
|
||||
index: 0
|
||||
},
|
||||
coin: {
|
||||
version: 1,
|
||||
height: 0,
|
||||
value: 70000,
|
||||
script: prev,
|
||||
coinbase: false,
|
||||
hash: prevHash,
|
||||
index: 0
|
||||
},
|
||||
script: new bcoin.script([]),
|
||||
sequence: 0xffffffff
|
||||
};
|
||||
t1.addInput(dummyInput);
|
||||
t1.inputs[0].script = new bcoin.script([t1.signature(0, prev, kp.privateKey, 'all', 0)]),
|
||||
t1.inputs[0].witness.push(new Buffer(0));
|
||||
var tx = t1.toTX();
|
||||
mempool.addTX(tx, function(err) {
|
||||
assert(err);
|
||||
assert(!mempool.hasReject(tx.hash()));
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not cache a malleated wtx with wit removed', function(cb) {
|
||||
var kp = bcoin.keyring.generate();
|
||||
kp.witness = true;
|
||||
// Coinbase
|
||||
var t1 = bcoin.mtx().addOutput(w, 50000).addOutput(w, 10000); // 10000 instead of 1000
|
||||
var prev = new bcoin.script([0, kp.keyHash]);
|
||||
var prevHash = crypto.randomBytes(32).toString('hex');
|
||||
var dummyInput = {
|
||||
prevout: {
|
||||
hash: prevHash,
|
||||
index: 0
|
||||
},
|
||||
coin: {
|
||||
version: 1,
|
||||
height: 0,
|
||||
value: 70000,
|
||||
script: prev,
|
||||
coinbase: false,
|
||||
hash: prevHash,
|
||||
index: 0
|
||||
},
|
||||
script: new bcoin.script([]),
|
||||
sequence: 0xffffffff
|
||||
};
|
||||
t1.addInput(dummyInput);
|
||||
var tx = t1.toTX();
|
||||
mempool.addTX(tx, function(err) {
|
||||
assert(err);
|
||||
assert(err.malleated);
|
||||
assert(!mempool.hasReject(tx.hash()));
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
it('should cache non-malleated tx without sig', function(cb) {
|
||||
var kp = bcoin.keyring.generate();
|
||||
// Coinbase
|
||||
var t1 = bcoin.mtx().addOutput(w, 50000).addOutput(w, 10000); // 10000 instead of 1000
|
||||
var prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
||||
var prevHash = crypto.randomBytes(32).toString('hex');
|
||||
var dummyInput = {
|
||||
prevout: {
|
||||
hash: prevHash,
|
||||
index: 0
|
||||
},
|
||||
coin: {
|
||||
version: 1,
|
||||
height: 0,
|
||||
value: 70000,
|
||||
script: prev,
|
||||
coinbase: false,
|
||||
hash: prevHash,
|
||||
index: 0
|
||||
},
|
||||
script: new bcoin.script([]),
|
||||
sequence: 0xffffffff
|
||||
};
|
||||
t1.addInput(dummyInput);
|
||||
var tx = t1.toTX();
|
||||
mempool.addTX(tx, function(err) {
|
||||
assert(err);
|
||||
assert(!err.malleated);
|
||||
assert(mempool.hasReject(tx.hash()));
|
||||
cached = tx;
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
it('should clear reject cache', function(cb) {
|
||||
var t1 = bcoin.mtx().addOutput(w, 50000);
|
||||
var dummyInput = {
|
||||
prevout: {
|
||||
hash: constants.NULL_HASH,
|
||||
index: 0xffffffff
|
||||
},
|
||||
coin: null,
|
||||
script: new bcoin.script(),
|
||||
sequence: 0xffffffff
|
||||
};
|
||||
t1.addInput(dummyInput);
|
||||
var tx = t1.toTX();
|
||||
var block = new bcoin.block();
|
||||
block.txs.push(tx);
|
||||
assert(mempool.hasReject(cached.hash()));
|
||||
mempool.addBlock(block, function(err) {
|
||||
assert(!err);
|
||||
assert(!mempool.hasReject(cached.hash()));
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
it('should destroy mempool', function(cb) {
|
||||
mempool.close(cb);
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user