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.network.requireStandard;
|
||||||
this.rejectAbsurdFees = this.options.rejectAbsurdFees !== false;
|
this.rejectAbsurdFees = this.options.rejectAbsurdFees !== false;
|
||||||
this.prematureWitness = !!this.options.prematureWitness;
|
this.prematureWitness = !!this.options.prematureWitness;
|
||||||
|
this.paranoid = !!this.options.paranoid;
|
||||||
|
|
||||||
this.maxSize = options.maxSize || constants.mempool.MAX_MEMPOOL_SIZE;
|
this.maxSize = options.maxSize || constants.mempool.MAX_MEMPOOL_SIZE;
|
||||||
this.expiryTime = options.expiryTime || constants.mempool.MEMPOOL_EXPIRY;
|
this.expiryTime = options.expiryTime || constants.mempool.MEMPOOL_EXPIRY;
|
||||||
@ -866,16 +867,16 @@ Mempool.prototype.verify = function verify(entry, callback) {
|
|||||||
'bad-txns-nonstandard-inputs',
|
'bad-txns-nonstandard-inputs',
|
||||||
0));
|
0));
|
||||||
}
|
}
|
||||||
// if (self.chain.state.hasWitness()) {
|
if (self.chain.state.hasWitness()) {
|
||||||
// if (!tx.hasStandardWitness(true, ret)) {
|
if (!tx.hasStandardWitness(ret)) {
|
||||||
// ret = new VerifyError(tx,
|
ret = new VerifyError(tx,
|
||||||
// 'nonstandard',
|
'nonstandard',
|
||||||
// ret.reason,
|
ret.reason,
|
||||||
// ret.score);
|
ret.score);
|
||||||
// ret.malleated = ret.score > 0;
|
ret.malleated = ret.score > 0;
|
||||||
// return callback(ret);
|
return callback(ret);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tx.getSigopsWeight(flags) > constants.tx.MAX_SIGOPS_WEIGHT) {
|
if (tx.getSigopsWeight(flags) > constants.tx.MAX_SIGOPS_WEIGHT) {
|
||||||
@ -954,6 +955,9 @@ Mempool.prototype.verify = function verify(entry, callback) {
|
|||||||
// Standard verification
|
// Standard verification
|
||||||
self.checkInputs(tx, flags1, function(error) {
|
self.checkInputs(tx, flags1, function(error) {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
|
if (!self.paranoid)
|
||||||
|
return callback();
|
||||||
|
|
||||||
return self.checkResult(tx, mandatory, function(err, result) {
|
return self.checkResult(tx, mandatory, function(err, result) {
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(err.type !== 'VerifyError',
|
assert(err.type !== 'VerifyError',
|
||||||
@ -1192,8 +1196,7 @@ Mempool.prototype.getDepends = function getDepends(tx) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Mempool.prototype.storeOrphan = function storeOrphan(tx) {
|
Mempool.prototype.storeOrphan = function storeOrphan(tx) {
|
||||||
var prevout = {};
|
var missing = {};
|
||||||
var missing = [];
|
|
||||||
var i, hash, input, prev;
|
var i, hash, input, prev;
|
||||||
|
|
||||||
if (tx.getWeight() > constants.tx.MAX_WEIGHT) {
|
if (tx.getWeight() > constants.tx.MAX_WEIGHT) {
|
||||||
@ -1211,26 +1214,26 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx) {
|
|||||||
|
|
||||||
if (this.hasReject(input.prevout.hash)) {
|
if (this.hasReject(input.prevout.hash)) {
|
||||||
this.logger.debug('Not storing orphan %s (rejected parents).', tx.rhash);
|
this.logger.debug('Not storing orphan %s (rejected parents).', tx.rhash);
|
||||||
|
this.rejects.add(tx.hash());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
missing.push(input.prevout.hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hash = tx.hash('hex');
|
hash = tx.hash('hex');
|
||||||
|
|
||||||
for (i = 0; i < tx.inputs.length; i++) {
|
for (i = 0; i < tx.inputs.length; i++) {
|
||||||
input = tx.inputs[i];
|
input = tx.inputs[i];
|
||||||
if (!input.coin)
|
if (input.coin)
|
||||||
prevout[input.prevout.hash] = true;
|
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++) {
|
for (i = 0; i < missing.length; i++) {
|
||||||
prev = prevout[i];
|
prev = missing[i];
|
||||||
if (!this.waiting[prev])
|
if (!this.waiting[prev])
|
||||||
this.waiting[prev] = [];
|
this.waiting[prev] = [];
|
||||||
this.waiting[prev].push(hash);
|
this.waiting[prev].push(hash);
|
||||||
|
|||||||
@ -1374,13 +1374,13 @@ TX.prototype.hasStandardInputs = function hasStandardInputs() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TX.prototype.hasStandardWitness = function hasStandardWitness(strict, ret) {
|
TX.prototype.hasStandardWitness = function hasStandardWitness(ret) {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = new VerifyResult();
|
ret = new VerifyResult();
|
||||||
|
|
||||||
result = this._hasStandardWitness();
|
result = this.getWitnessStandard();
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case BAD_WITNESS:
|
case BAD_WITNESS:
|
||||||
@ -1392,12 +1392,9 @@ TX.prototype.hasStandardWitness = function hasStandardWitness(strict, ret) {
|
|||||||
ret.score = 100;
|
ret.score = 100;
|
||||||
return false;
|
return false;
|
||||||
case BAD_NONSTD_P2WSH:
|
case BAD_NONSTD_P2WSH:
|
||||||
if (strict) {
|
ret.reason = 'bad-witness-nonstandard';
|
||||||
ret.reason = 'bad-witness-nonstandard';
|
ret.score = 0;
|
||||||
ret.score = 0;
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1410,7 +1407,7 @@ TX.prototype.hasStandardWitness = function hasStandardWitness(strict, ret) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TX.prototype._hasStandardWitness = function _hasStandardWitness() {
|
TX.prototype.getWitnessStandard = function getWitnessStandard() {
|
||||||
var ret = BAD_OKAY;
|
var ret = BAD_OKAY;
|
||||||
var i, j, input, prev, hash, redeem, m, n;
|
var i, j, input, prev, hash, redeem, m, n;
|
||||||
|
|
||||||
|
|||||||
@ -28,12 +28,16 @@ describe('Mempool', function() {
|
|||||||
verify: true
|
verify: true
|
||||||
});
|
});
|
||||||
|
|
||||||
var w;
|
var w, cached;
|
||||||
|
|
||||||
mempool.on('error', function() {});
|
mempool.on('error', function() {});
|
||||||
|
|
||||||
it('should open mempool', function(cb) {
|
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) {
|
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) {
|
it('should destroy mempool', function(cb) {
|
||||||
mempool.close(cb);
|
mempool.close(cb);
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user