tests: use generators.
This commit is contained in:
parent
ed66e0b7cc
commit
44b78dd345
@ -14,7 +14,7 @@ var c = require('../lib/utils/spawn').cb;
|
|||||||
|
|
||||||
describe('Chain', function() {
|
describe('Chain', function() {
|
||||||
var chain, wallet, node, miner, walletdb;
|
var chain, wallet, node, miner, walletdb;
|
||||||
var competingTip, oldTip, tip1, tip2, cb1, cb2;
|
var tip1, tip2, cb1, cb2;
|
||||||
|
|
||||||
this.timeout(5000);
|
this.timeout(5000);
|
||||||
|
|
||||||
@ -24,254 +24,233 @@ describe('Chain', function() {
|
|||||||
miner = node.miner;
|
miner = node.miner;
|
||||||
node.on('error', function() {});
|
node.on('error', function() {});
|
||||||
|
|
||||||
function mineBlock(tip, tx, callback) {
|
var mineBlock = co(function* mineBlock(tip, tx) {
|
||||||
c(miner.createBlock(tip), function(err, attempt) {
|
var attempt = yield miner.createBlock(tip);
|
||||||
assert.ifError(err);
|
var redeemer;
|
||||||
if (tx) {
|
|
||||||
var redeemer = bcoin.mtx();
|
if (!tx)
|
||||||
redeemer.addOutput({
|
return attempt.mineSync();
|
||||||
address: wallet.receiveAddress.getAddress(),
|
|
||||||
value: utils.satoshi('25.0')
|
redeemer = bcoin.mtx();
|
||||||
});
|
|
||||||
redeemer.addOutput({
|
redeemer.addOutput({
|
||||||
address: wallet.changeAddress.getAddress(),
|
address: wallet.receiveAddress.getAddress(),
|
||||||
value: utils.satoshi('5.0')
|
value: 25 * 1e8
|
||||||
});
|
|
||||||
redeemer.addInput(tx, 0);
|
|
||||||
redeemer.setLocktime(chain.height);
|
|
||||||
return c(wallet.sign(redeemer), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
attempt.addTX(redeemer.toTX());
|
|
||||||
callback(null, attempt.mineSync());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
callback(null, attempt.mineSync());
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
redeemer.addOutput({
|
||||||
|
address: wallet.changeAddress.getAddress(),
|
||||||
|
value: 5 * 1e8
|
||||||
|
});
|
||||||
|
|
||||||
|
redeemer.addInput(tx, 0);
|
||||||
|
|
||||||
|
redeemer.setLocktime(chain.height);
|
||||||
|
|
||||||
|
yield wallet.sign(redeemer);
|
||||||
|
|
||||||
|
attempt.addTX(redeemer.toTX());
|
||||||
|
|
||||||
|
return attempt.mineSync();
|
||||||
|
});
|
||||||
|
|
||||||
function deleteCoins(tx) {
|
function deleteCoins(tx) {
|
||||||
|
var i;
|
||||||
|
|
||||||
if (tx.txs) {
|
if (tx.txs) {
|
||||||
deleteCoins(tx.txs);
|
deleteCoins(tx.txs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(tx)) {
|
if (Array.isArray(tx)) {
|
||||||
tx.forEach(deleteCoins);
|
for (i = 0; i < tx.length; i++)
|
||||||
|
deleteCoins(tx[i]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tx.inputs.forEach(function(input) {
|
|
||||||
input.coin = null;
|
for (i = 0; i < tx.inputs.length; i++)
|
||||||
});
|
tx.inputs[i].coin = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should open chain and miner', function(cb) {
|
it('should open chain and miner', cob(function *() {
|
||||||
miner.mempool = null;
|
miner.mempool = null;
|
||||||
constants.tx.COINBASE_MATURITY = 0;
|
constants.tx.COINBASE_MATURITY = 0;
|
||||||
c(node.open(), cb);
|
yield node.open();
|
||||||
});
|
}));
|
||||||
|
|
||||||
it('should open walletdb', function(cb) {
|
it('should open walletdb', cob(function *() {
|
||||||
c(walletdb.create({}), function(err, w) {
|
wallet = yield walletdb.create();
|
||||||
assert.ifError(err);
|
miner.address = wallet.getAddress();
|
||||||
wallet = w;
|
}));
|
||||||
miner.address = wallet.getAddress();
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should mine a block', function(cb) {
|
it('should mine a block', cob(function *() {
|
||||||
c(miner.mineBlock(), function(err, block) {
|
var block = yield miner.mineBlock();
|
||||||
assert.ifError(err);
|
assert(block);
|
||||||
assert(block);
|
}));
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should mine competing chains', function(cb) {
|
it('should mine competing chains', cob(function *() {
|
||||||
utils.forRangeSerial(0, 10, function(i, next) {
|
var i, block1, block2;
|
||||||
mineBlock(tip1, cb1, function(err, block1) {
|
|
||||||
assert.ifError(err);
|
|
||||||
cb1 = block1.txs[0];
|
|
||||||
mineBlock(tip2, cb2, function(err, block2) {
|
|
||||||
assert.ifError(err);
|
|
||||||
cb2 = block2.txs[0];
|
|
||||||
deleteCoins(block1);
|
|
||||||
c(chain.add(block1), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
deleteCoins(block2);
|
|
||||||
c(chain.add(block2), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert(chain.tip.hash === block1.hash('hex'));
|
|
||||||
competingTip = block2.hash('hex');
|
|
||||||
c(chain.db.get(block1.hash('hex')), function(err, entry1) {
|
|
||||||
assert.ifError(err);
|
|
||||||
c(chain.db.get(block2.hash('hex')), function(err, entry2) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert(entry1);
|
|
||||||
assert(entry2);
|
|
||||||
tip1 = entry1;
|
|
||||||
tip2 = entry2;
|
|
||||||
c(chain.db.isMainChain(block2.hash('hex')), function(err, result) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert(!result);
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, cb);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have correct balance', function(cb) {
|
for (i = 0; i < 10; i++) {
|
||||||
setTimeout(function() {
|
block1 = yield mineBlock(tip1, cb1);
|
||||||
c(wallet.getBalance(), function(err, balance) {
|
cb1 = block1.txs[0];
|
||||||
assert.equal(balance.unconfirmed, 0);
|
|
||||||
assert.equal(balance.confirmed, 500 * 1e8);
|
block2 = yield mineBlock(tip2, cb2);
|
||||||
assert.equal(balance.total, 500 * 1e8);
|
cb2 = block2.txs[0];
|
||||||
cb();
|
|
||||||
});
|
deleteCoins(block1);
|
||||||
}, 1000);
|
yield chain.add(block1);
|
||||||
});
|
|
||||||
|
deleteCoins(block2);
|
||||||
|
yield chain.add(block2);
|
||||||
|
|
||||||
|
assert(chain.tip.hash === block1.hash('hex'));
|
||||||
|
|
||||||
|
tip1 = yield chain.db.get(block1.hash('hex'));
|
||||||
|
tip2 = yield chain.db.get(block2.hash('hex'));
|
||||||
|
|
||||||
|
assert(tip1);
|
||||||
|
assert(tip2);
|
||||||
|
|
||||||
|
assert(!(yield tip2.isMainChain()));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should have correct balance', cob(function* () {
|
||||||
|
var balance;
|
||||||
|
|
||||||
|
yield spawn.timeout(100);
|
||||||
|
|
||||||
|
balance = yield wallet.getBalance();
|
||||||
|
assert.equal(balance.unconfirmed, 0);
|
||||||
|
assert.equal(balance.confirmed, 500 * 1e8);
|
||||||
|
assert.equal(balance.total, 500 * 1e8);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle a reorg', cob(function *() {
|
||||||
|
var entry, block, forked;
|
||||||
|
|
||||||
it('should handle a reorg', function(cb) {
|
|
||||||
assert.equal(walletdb.height, chain.height);
|
assert.equal(walletdb.height, chain.height);
|
||||||
assert.equal(chain.height, 10);
|
assert.equal(chain.height, 10);
|
||||||
oldTip = chain.tip;
|
|
||||||
c(chain.db.get(competingTip), function(err, entry) {
|
entry = yield chain.db.get(tip2.hash);
|
||||||
assert.ifError(err);
|
assert(entry);
|
||||||
assert(entry);
|
assert(chain.height === entry.height);
|
||||||
assert(chain.height === entry.height);
|
|
||||||
c(miner.mineBlock(entry), function(err, block) {
|
block = yield miner.mineBlock(entry);
|
||||||
assert.ifError(err);
|
assert(block);
|
||||||
assert(block);
|
|
||||||
var forked = false;
|
forked = false;
|
||||||
chain.once('reorganize', function() {
|
chain.once('reorganize', function() {
|
||||||
forked = true;
|
forked = true;
|
||||||
});
|
|
||||||
deleteCoins(block);
|
|
||||||
c(chain.add(block), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert(forked);
|
|
||||||
assert(chain.tip.hash === block.hash('hex'));
|
|
||||||
assert(chain.tip.chainwork.cmp(oldTip.chainwork) > 0);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('should have correct balance', function(cb) {
|
deleteCoins(block);
|
||||||
setTimeout(function() {
|
|
||||||
c(wallet.getBalance(), function(err, balance) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.equal(balance.unconfirmed, 500 * 1e8);
|
|
||||||
assert.equal(balance.confirmed, 550 * 1e8);
|
|
||||||
assert.equal(balance.total, 1050 * 1e8);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check main chain', function(cb) {
|
yield chain.add(block);
|
||||||
c(chain.db.isMainChain(oldTip), function(err, result) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert(!result);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should mine a block after a reorg', function(cb) {
|
assert(forked);
|
||||||
mineBlock(null, cb2, function(err, block) {
|
assert(chain.tip.hash === block.hash('hex'));
|
||||||
assert.ifError(err);
|
assert(chain.tip.chainwork.cmp(tip1.chainwork) > 0);
|
||||||
deleteCoins(block);
|
}));
|
||||||
c(chain.add(block), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
c(chain.db.get(block.hash('hex')), function(err, entry) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert(entry);
|
|
||||||
assert(chain.tip.hash === entry.hash);
|
|
||||||
c(chain.db.isMainChain(entry.hash), function(err, result) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert(result);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail to mine a block with coins on an alternate chain', function(cb) {
|
it('should have correct balance', cob(function *() {
|
||||||
mineBlock(null, cb1, function(err, block) {
|
var balance;
|
||||||
assert.ifError(err);
|
|
||||||
deleteCoins(block);
|
|
||||||
c(chain.add(block), function(err) {
|
|
||||||
assert(err);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should get coin', function(cb) {
|
yield spawn.timeout(100);
|
||||||
mineBlock(null, null, function(err, block) {
|
|
||||||
assert.ifError(err);
|
|
||||||
c(chain.add(block), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
mineBlock(null, block.txs[0], function(err, block) {
|
|
||||||
assert.ifError(err);
|
|
||||||
c(chain.add(block), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
var tx = block.txs[1];
|
|
||||||
var output = bcoin.coin.fromTX(tx, 1);
|
|
||||||
c(chain.db.getCoin(tx.hash('hex'), 1), function(err, coin) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.deepEqual(coin.toRaw(), output.toRaw());
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should get balance', function(cb) {
|
balance = yield wallet.getBalance();
|
||||||
setTimeout(function() {
|
assert.equal(balance.unconfirmed, 500 * 1e8);
|
||||||
c(wallet.getBalance(), function(err, balance) {
|
assert.equal(balance.confirmed, 550 * 1e8);
|
||||||
assert.ifError(err);
|
assert.equal(balance.total, 1050 * 1e8);
|
||||||
assert.equal(balance.unconfirmed, 500 * 1e8);
|
}));
|
||||||
assert.equal(balance.confirmed, 700 * 1e8);
|
|
||||||
assert.equal(balance.total, 1200 * 1e8);
|
|
||||||
assert(wallet.account.receiveDepth >= 8);
|
|
||||||
assert(wallet.account.changeDepth >= 7);
|
|
||||||
assert.equal(walletdb.height, chain.height);
|
|
||||||
assert.equal(walletdb.tip, chain.tip.hash);
|
|
||||||
c(wallet.getHistory(), function(err, txs) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.equal(txs.length, 44);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rescan for transactions', function(cb) {
|
it('should check main chain', cob(function *() {
|
||||||
|
var result = yield tip1.isMainChain();
|
||||||
|
assert(!result);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should mine a block after a reorg', cob(function *() {
|
||||||
|
var block, entry, result;
|
||||||
|
|
||||||
|
block = yield mineBlock(null, cb2);
|
||||||
|
deleteCoins(block);
|
||||||
|
yield chain.add(block);
|
||||||
|
|
||||||
|
entry = yield chain.db.get(block.hash('hex'));
|
||||||
|
assert(entry);
|
||||||
|
assert(chain.tip.hash === entry.hash);
|
||||||
|
|
||||||
|
result = yield entry.isMainChain();
|
||||||
|
assert(result);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should fail to mine a block with coins on an alternate chain', cob(function *() {
|
||||||
|
var block = yield mineBlock(null, cb1);
|
||||||
|
var err;
|
||||||
|
|
||||||
|
deleteCoins(block);
|
||||||
|
|
||||||
|
try {
|
||||||
|
yield chain.add(block);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(err);
|
||||||
|
assert.equal(err.reason, 'bad-txns-inputs-missingorspent');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should get coin', cob(function *() {
|
||||||
|
var block, tx, output, coin;
|
||||||
|
|
||||||
|
block = yield mineBlock();
|
||||||
|
yield chain.add(block);
|
||||||
|
block = yield mineBlock(null, block.txs[0]);
|
||||||
|
yield chain.add(block);
|
||||||
|
|
||||||
|
tx = block.txs[1];
|
||||||
|
output = bcoin.coin.fromTX(tx, 1);
|
||||||
|
|
||||||
|
coin = yield chain.db.getCoin(tx.hash('hex'), 1);
|
||||||
|
|
||||||
|
assert.deepEqual(coin.toRaw(), output.toRaw());
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should get balance', cob(function *() {
|
||||||
|
var balance, txs;
|
||||||
|
|
||||||
|
yield spawn.timeout(100);
|
||||||
|
|
||||||
|
balance = yield wallet.getBalance();
|
||||||
|
assert.equal(balance.unconfirmed, 500 * 1e8);
|
||||||
|
assert.equal(balance.confirmed, 700 * 1e8);
|
||||||
|
assert.equal(balance.total, 1200 * 1e8);
|
||||||
|
|
||||||
|
assert(wallet.account.receiveDepth >= 8);
|
||||||
|
assert(wallet.account.changeDepth >= 7);
|
||||||
|
|
||||||
|
assert.equal(walletdb.height, chain.height);
|
||||||
|
assert.equal(walletdb.tip, chain.tip.hash);
|
||||||
|
|
||||||
|
txs = yield wallet.getHistory();
|
||||||
|
assert.equal(txs.length, 44);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should rescan for transactions', cob(function *() {
|
||||||
var total = 0;
|
var total = 0;
|
||||||
c(walletdb.getAddressHashes(), function(err, hashes) {
|
var hashes = yield walletdb.getAddressHashes();
|
||||||
assert.ifError(err);
|
|
||||||
c(chain.db.scan(null, hashes, function(block, txs) {
|
|
||||||
total += txs.length;
|
|
||||||
return Promise.resolve(null);
|
|
||||||
}), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.equal(total, 25);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should cleanup', function(cb) {
|
yield chain.db.scan(null, hashes, function(block, txs) {
|
||||||
|
total += txs.length;
|
||||||
|
return Promise.resolve(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(total, 25);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should cleanup', cob(function *() {
|
||||||
constants.tx.COINBASE_MATURITY = 100;
|
constants.tx.COINBASE_MATURITY = 100;
|
||||||
c(node.close(), cb);
|
yield node.close();
|
||||||
});
|
}));
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,379 +8,356 @@ var crypto = require('../lib/crypto/crypto');
|
|||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var opcodes = constants.opcodes;
|
var opcodes = constants.opcodes;
|
||||||
var c = require('../lib/utils/spawn').cb;
|
var c = require('../lib/utils/spawn').cb;
|
||||||
|
var cob = require('../lib/utils/spawn').cob;
|
||||||
|
|
||||||
|
function dummy(prev, prevHash) {
|
||||||
|
if (!prevHash)
|
||||||
|
prevHash = constants.ONE_HASH.toString('hex');
|
||||||
|
|
||||||
|
return {
|
||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
describe('Mempool', function() {
|
describe('Mempool', function() {
|
||||||
|
var chain, mempool, walletdb;
|
||||||
|
var wallet, cached;
|
||||||
|
|
||||||
this.timeout(5000);
|
this.timeout(5000);
|
||||||
|
|
||||||
var chain = new bcoin.chain({
|
chain = new bcoin.chain({
|
||||||
name: 'mp-chain',
|
name: 'mp-chain',
|
||||||
db: 'memory'
|
db: 'memory'
|
||||||
});
|
});
|
||||||
|
|
||||||
var mempool = new bcoin.mempool({
|
mempool = new bcoin.mempool({
|
||||||
chain: chain,
|
chain: chain,
|
||||||
name: 'mempool-test',
|
name: 'mempool-test',
|
||||||
db: 'memory'
|
db: 'memory'
|
||||||
});
|
});
|
||||||
|
|
||||||
var walletdb = new bcoin.walletdb({
|
walletdb = new bcoin.walletdb({
|
||||||
name: 'mempool-wallet-test',
|
name: 'mempool-wallet-test',
|
||||||
db: 'memory',
|
db: 'memory',
|
||||||
verify: true
|
verify: true
|
||||||
});
|
});
|
||||||
|
|
||||||
var w, cached;
|
it('should open mempool', cob(function *() {
|
||||||
|
yield mempool.open();
|
||||||
|
chain.state.flags |= constants.flags.VERIFY_WITNESS;
|
||||||
|
}));
|
||||||
|
|
||||||
mempool.on('error', function() {});
|
it('should open walletdb', cob(function *() {
|
||||||
|
yield walletdb.open();
|
||||||
|
}));
|
||||||
|
|
||||||
it('should open mempool', function(cb) {
|
it('should open wallet', cob(function *() {
|
||||||
c(mempool.open(), function(err) {
|
wallet = yield walletdb.create();
|
||||||
assert.ifError(err);
|
}));
|
||||||
chain.state.flags |= constants.flags.VERIFY_WITNESS;
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should open walletdb', function(cb) {
|
it('should handle incoming orphans and TXs', cob(function *() {
|
||||||
c(walletdb.open(), cb);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should open wallet', function(cb) {
|
|
||||||
c(walletdb.create({}), function(err, wallet) {
|
|
||||||
assert.ifError(err);
|
|
||||||
w = wallet;
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle incoming orphans and TXs', function(cb) {
|
|
||||||
var kp = bcoin.keyring.generate();
|
var kp = bcoin.keyring.generate();
|
||||||
// Coinbase
|
var w = wallet;
|
||||||
var t1 = bcoin.mtx().addOutput(w, 50000).addOutput(w, 10000); // 10000 instead of 1000
|
var t1, t2, t3, t4, f1, fake, prev, sig, balance, txs;
|
||||||
var prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
|
||||||
var dummyInput = {
|
t1 = bcoin.mtx()
|
||||||
prevout: {
|
.addOutput(w.getAddress(), 50000)
|
||||||
hash: constants.ONE_HASH.toString('hex'),
|
.addOutput(w.getAddress(), 10000);
|
||||||
index: 0
|
|
||||||
},
|
prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
||||||
coin: {
|
t1.addInput(dummy(prev));
|
||||||
version: 1,
|
sig = t1.signature(0, prev, kp.privateKey, 'all', 0);
|
||||||
height: 0,
|
t1.inputs[0].script = new bcoin.script([sig]),
|
||||||
value: 70000,
|
|
||||||
script: prev,
|
|
||||||
coinbase: false,
|
|
||||||
hash: constants.ONE_HASH.toString('hex'),
|
|
||||||
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)]),
|
|
||||||
|
|
||||||
// balance: 51000
|
// balance: 51000
|
||||||
c(w.sign(t1), function(err, total) {
|
yield w.sign(t1);
|
||||||
assert.ifError(err);
|
t1 = t1.toTX();
|
||||||
t1 = t1.toTX();
|
|
||||||
var t2 = bcoin.mtx().addInput(t1, 0) // 50000
|
|
||||||
.addOutput(w, 20000)
|
|
||||||
.addOutput(w, 20000);
|
|
||||||
// balance: 49000
|
|
||||||
c(w.sign(t2), function(err, total) {
|
|
||||||
assert.ifError(err);
|
|
||||||
t2 = t2.toTX();
|
|
||||||
var t3 = bcoin.mtx().addInput(t1, 1) // 10000
|
|
||||||
.addInput(t2, 0) // 20000
|
|
||||||
.addOutput(w, 23000);
|
|
||||||
// balance: 47000
|
|
||||||
c(w.sign(t3), function(err, total) {
|
|
||||||
assert.ifError(err);
|
|
||||||
t3 = t3.toTX();
|
|
||||||
var t4 = bcoin.mtx().addInput(t2, 1) // 24000
|
|
||||||
.addInput(t3, 0) // 23000
|
|
||||||
.addOutput(w, 11000)
|
|
||||||
.addOutput(w, 11000);
|
|
||||||
// balance: 22000
|
|
||||||
c(w.sign(t4), function(err, total) {
|
|
||||||
assert.ifError(err);
|
|
||||||
t4 = t4.toTX();
|
|
||||||
var f1 = bcoin.mtx().addInput(t4, 1) // 11000
|
|
||||||
.addOutput(bcoin.address.fromData(new Buffer([])).toBase58(), 9000);
|
|
||||||
// balance: 11000
|
|
||||||
c(w.sign(f1), function(err, total) {
|
|
||||||
assert.ifError(err);
|
|
||||||
f1 = f1.toTX();
|
|
||||||
var fake = bcoin.mtx().addInput(t1, 1) // 1000 (already redeemed)
|
|
||||||
.addOutput(w, 6000); // 6000 instead of 500
|
|
||||||
// Script inputs but do not sign
|
|
||||||
c(w.template(fake), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
// Fake signature
|
|
||||||
fake.inputs[0].script.set(0, new Buffer([0,0,0,0,0,0,0,0,0]));
|
|
||||||
fake.inputs[0].script.compile();
|
|
||||||
fake = fake.toTX();
|
|
||||||
// balance: 11000
|
|
||||||
[t2, t3, t4, f1, fake].forEach(function(tx) {
|
|
||||||
tx.inputs.forEach(function(input) {
|
|
||||||
input.coin = null;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
c(mempool.addTX(fake), function(err) {
|
t2 = bcoin.mtx()
|
||||||
assert.ifError(err);
|
.addInput(t1, 0) // 50000
|
||||||
c(mempool.addTX(t4), function(err) {
|
.addOutput(w.getAddress(), 20000)
|
||||||
assert.ifError(err);
|
.addOutput(w.getAddress(), 20000);
|
||||||
var balance = mempool.getBalance();
|
|
||||||
assert.equal(balance, 0);
|
|
||||||
c(mempool.addTX(t1), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
var balance = mempool.getBalance();
|
|
||||||
assert.equal(balance, 60000);
|
|
||||||
c(mempool.addTX(t2), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
var balance = mempool.getBalance();
|
|
||||||
assert.equal(balance, 50000);
|
|
||||||
c(mempool.addTX(t3), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
var balance = mempool.getBalance();
|
|
||||||
assert.equal(balance, 22000);
|
|
||||||
c(mempool.addTX(f1), function(err) {
|
|
||||||
assert.ifError(err);
|
|
||||||
var balance = mempool.getBalance();
|
|
||||||
assert.equal(balance, 20000);
|
|
||||||
var txs = mempool.getHistory();
|
|
||||||
assert(txs.some(function(tx) {
|
|
||||||
return tx.hash('hex') === f1.hash('hex');
|
|
||||||
}));
|
|
||||||
|
|
||||||
cb();
|
// balance: 49000
|
||||||
});
|
yield w.sign(t2);
|
||||||
});
|
t2 = t2.toTX();
|
||||||
});
|
|
||||||
});
|
t3 = bcoin.mtx()
|
||||||
});
|
.addInput(t1, 1) // 10000
|
||||||
});
|
.addInput(t2, 0) // 20000
|
||||||
});
|
.addOutput(w.getAddress(), 23000);
|
||||||
});
|
|
||||||
});
|
// balance: 47000
|
||||||
});
|
yield w.sign(t3);
|
||||||
|
t3 = t3.toTX();
|
||||||
|
|
||||||
|
t4 = bcoin.mtx()
|
||||||
|
.addInput(t2, 1) // 24000
|
||||||
|
.addInput(t3, 0) // 23000
|
||||||
|
.addOutput(w.getAddress(), 11000)
|
||||||
|
.addOutput(w.getAddress(), 11000);
|
||||||
|
|
||||||
|
// balance: 22000
|
||||||
|
yield w.sign(t4);
|
||||||
|
t4 = t4.toTX();
|
||||||
|
|
||||||
|
f1 = bcoin.mtx()
|
||||||
|
.addInput(t4, 1) // 11000
|
||||||
|
.addOutput(new bcoin.address(), 9000);
|
||||||
|
|
||||||
|
// balance: 11000
|
||||||
|
yield w.sign(f1);
|
||||||
|
f1 = f1.toTX();
|
||||||
|
|
||||||
|
fake = bcoin.mtx()
|
||||||
|
.addInput(t1, 1) // 1000 (already redeemed)
|
||||||
|
.addOutput(w.getAddress(), 6000); // 6000 instead of 500
|
||||||
|
|
||||||
|
// Script inputs but do not sign
|
||||||
|
yield w.template(fake);
|
||||||
|
|
||||||
|
// Fake signature
|
||||||
|
fake.inputs[0].script.set(0, constants.ZERO_SIG);
|
||||||
|
fake.inputs[0].script.compile();
|
||||||
|
fake = fake.toTX();
|
||||||
|
// balance: 11000
|
||||||
|
|
||||||
|
[t2, t3, t4, f1, fake].forEach(function(tx) {
|
||||||
|
tx.inputs.forEach(function(input) {
|
||||||
|
input.coin = null;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle locktime', function(cb) {
|
yield mempool.addTX(fake);
|
||||||
|
yield mempool.addTX(t4);
|
||||||
|
|
||||||
|
balance = mempool.getBalance();
|
||||||
|
assert.equal(balance, 0);
|
||||||
|
|
||||||
|
yield mempool.addTX(t1);
|
||||||
|
|
||||||
|
balance = mempool.getBalance();
|
||||||
|
assert.equal(balance, 60000);
|
||||||
|
|
||||||
|
yield mempool.addTX(t2);
|
||||||
|
|
||||||
|
balance = mempool.getBalance();
|
||||||
|
assert.equal(balance, 50000);
|
||||||
|
|
||||||
|
yield mempool.addTX(t3);
|
||||||
|
|
||||||
|
balance = mempool.getBalance();
|
||||||
|
assert.equal(balance, 22000);
|
||||||
|
|
||||||
|
yield mempool.addTX(f1);
|
||||||
|
|
||||||
|
balance = mempool.getBalance();
|
||||||
|
assert.equal(balance, 20000);
|
||||||
|
|
||||||
|
txs = mempool.getHistory();
|
||||||
|
assert(txs.some(function(tx) {
|
||||||
|
return tx.hash('hex') === f1.hash('hex');
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle locktime', cob(function *() {
|
||||||
|
var w = wallet;
|
||||||
var kp = bcoin.keyring.generate();
|
var kp = bcoin.keyring.generate();
|
||||||
// Coinbase
|
var tx, prev, prevHash, sig;
|
||||||
var t1 = bcoin.mtx().addOutput(w, 50000).addOutput(w, 10000); // 10000 instead of 1000
|
|
||||||
var prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
tx = bcoin.mtx()
|
||||||
var prevHash = crypto.randomBytes(32).toString('hex');
|
.addOutput(w.getAddress(), 50000)
|
||||||
var dummyInput = {
|
.addOutput(w.getAddress(), 10000);
|
||||||
prevout: {
|
|
||||||
hash: prevHash,
|
prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
||||||
index: 0
|
prevHash = crypto.randomBytes(32).toString('hex');
|
||||||
},
|
|
||||||
coin: {
|
tx.addInput(dummy(prev, prevHash));
|
||||||
version: 1,
|
tx.setLocktime(200);
|
||||||
height: 0,
|
|
||||||
value: 70000,
|
|
||||||
script: prev,
|
|
||||||
coinbase: false,
|
|
||||||
hash: prevHash,
|
|
||||||
index: 0
|
|
||||||
},
|
|
||||||
script: new bcoin.script([]),
|
|
||||||
sequence: 0xffffffff
|
|
||||||
};
|
|
||||||
t1.addInput(dummyInput);
|
|
||||||
t1.setLocktime(200);
|
|
||||||
chain.tip.height = 200;
|
chain.tip.height = 200;
|
||||||
t1.inputs[0].script = new bcoin.script([t1.signature(0, prev, kp.privateKey, 'all', 0)]),
|
|
||||||
t1 = t1.toTX();
|
|
||||||
c(mempool.addTX(t1), function(err) {
|
|
||||||
chain.tip.height = 0;
|
|
||||||
assert.ifError(err);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle invalid locktime', function(cb) {
|
sig = tx.signature(0, prev, kp.privateKey, 'all', 0);
|
||||||
|
tx.inputs[0].script = new bcoin.script([sig]),
|
||||||
|
|
||||||
|
tx = tx.toTX();
|
||||||
|
|
||||||
|
yield mempool.addTX(tx);
|
||||||
|
chain.tip.height = 0;
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle invalid locktime', cob(function *() {
|
||||||
|
var w = wallet;
|
||||||
var kp = bcoin.keyring.generate();
|
var kp = bcoin.keyring.generate();
|
||||||
// Coinbase
|
var tx, prev, prevHash, sig, err;
|
||||||
var t1 = bcoin.mtx().addOutput(w, 50000).addOutput(w, 10000); // 10000 instead of 1000
|
|
||||||
var prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
tx = bcoin.mtx()
|
||||||
var prevHash = crypto.randomBytes(32).toString('hex');
|
.addOutput(w.getAddress(), 50000)
|
||||||
var dummyInput = {
|
.addOutput(w.getAddress(), 10000);
|
||||||
prevout: {
|
|
||||||
hash: prevHash,
|
prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
||||||
index: 0
|
prevHash = crypto.randomBytes(32).toString('hex');
|
||||||
},
|
|
||||||
coin: {
|
tx.addInput(dummy(prev, prevHash));
|
||||||
version: 1,
|
tx.setLocktime(200);
|
||||||
height: 0,
|
|
||||||
value: 70000,
|
|
||||||
script: prev,
|
|
||||||
coinbase: false,
|
|
||||||
hash: prevHash,
|
|
||||||
index: 0
|
|
||||||
},
|
|
||||||
script: new bcoin.script([]),
|
|
||||||
sequence: 0xffffffff
|
|
||||||
};
|
|
||||||
t1.addInput(dummyInput);
|
|
||||||
t1.setLocktime(200);
|
|
||||||
chain.tip.height = 200 - 1;
|
chain.tip.height = 200 - 1;
|
||||||
t1.inputs[0].script = new bcoin.script([t1.signature(0, prev, kp.privateKey, 'all', 0)]),
|
|
||||||
t1 = t1.toTX();
|
|
||||||
c(mempool.addTX(t1), function(err) {
|
|
||||||
chain.tip.height = 0;
|
|
||||||
assert(err);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not cache a malleated wtx with mutated sig', function(cb) {
|
sig = tx.signature(0, prev, kp.privateKey, 'all', 0);
|
||||||
|
tx.inputs[0].script = new bcoin.script([sig]),
|
||||||
|
tx = tx.toTX();
|
||||||
|
|
||||||
|
try {
|
||||||
|
yield mempool.addTX(tx);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(err);
|
||||||
|
|
||||||
|
chain.tip.height = 0;
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not cache a malleated wtx with mutated sig', cob(function *() {
|
||||||
|
var w = wallet;
|
||||||
var kp = bcoin.keyring.generate();
|
var kp = bcoin.keyring.generate();
|
||||||
|
var tx, prev, prevHash, prevs, sig, tx, err;
|
||||||
|
|
||||||
kp.witness = true;
|
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();
|
|
||||||
c(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) {
|
tx = bcoin.mtx()
|
||||||
var kp = bcoin.keyring.generate();
|
.addOutput(w.getAddress(), 50000)
|
||||||
// Coinbase
|
.addOutput(w.getAddress(), 10000);
|
||||||
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();
|
|
||||||
c(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) {
|
prev = new bcoin.script([0, kp.keyHash]);
|
||||||
|
prevHash = crypto.randomBytes(32).toString('hex');
|
||||||
|
|
||||||
|
tx.addInput(dummy(prev, prevHash));
|
||||||
|
|
||||||
|
prevs = bcoin.script.fromPubkeyhash(kp.keyHash);
|
||||||
|
|
||||||
|
sig = tx.signature(0, prevs, kp.privateKey, 'all', 1);
|
||||||
|
sig[sig.length - 1] = 0;
|
||||||
|
tx.inputs[0].witness = new bcoin.witness([sig, kp.publicKey]);
|
||||||
|
tx = tx.toTX();
|
||||||
|
|
||||||
|
try {
|
||||||
|
yield mempool.addTX(tx);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(err);
|
||||||
|
assert(!mempool.hasReject(tx.hash()));
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not cache a malleated tx with unnecessary witness', cob(function *() {
|
||||||
|
var w = wallet;
|
||||||
var kp = bcoin.keyring.generate();
|
var kp = bcoin.keyring.generate();
|
||||||
|
var tx, prev, prevHash, sig, tx, err;
|
||||||
|
|
||||||
|
tx = bcoin.mtx()
|
||||||
|
.addOutput(w.getAddress(), 50000)
|
||||||
|
.addOutput(w.getAddress(), 10000);
|
||||||
|
|
||||||
|
prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
||||||
|
prevHash = crypto.randomBytes(32).toString('hex');
|
||||||
|
|
||||||
|
tx.addInput(dummy(prev, prevHash));
|
||||||
|
|
||||||
|
sig = tx.signature(0, prev, kp.privateKey, 'all', 0);
|
||||||
|
tx.inputs[0].script = new bcoin.script([sig]);
|
||||||
|
tx.inputs[0].witness.push(new Buffer(0));
|
||||||
|
tx = tx.toTX();
|
||||||
|
|
||||||
|
try {
|
||||||
|
yield mempool.addTX(tx);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(err);
|
||||||
|
assert(!mempool.hasReject(tx.hash()));
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not cache a malleated wtx with wit removed', cob(function *() {
|
||||||
|
var w = wallet;
|
||||||
|
var kp = bcoin.keyring.generate();
|
||||||
|
var tx, prev, prevHash, tx, err;
|
||||||
|
|
||||||
kp.witness = true;
|
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();
|
|
||||||
c(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) {
|
tx = bcoin.mtx()
|
||||||
|
.addOutput(w.getAddress(), 50000)
|
||||||
|
.addOutput(w.getAddress(), 10000);
|
||||||
|
|
||||||
|
prev = new bcoin.script([0, kp.keyHash]);
|
||||||
|
prevHash = crypto.randomBytes(32).toString('hex');
|
||||||
|
|
||||||
|
tx.addInput(dummy(prev, prevHash));
|
||||||
|
|
||||||
|
tx = tx.toTX();
|
||||||
|
|
||||||
|
try {
|
||||||
|
yield mempool.addTX(tx);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(err);
|
||||||
|
assert(err.malleated);
|
||||||
|
assert(!mempool.hasReject(tx.hash()));
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should cache non-malleated tx without sig', cob(function *() {
|
||||||
|
var w = wallet;
|
||||||
var kp = bcoin.keyring.generate();
|
var kp = bcoin.keyring.generate();
|
||||||
// Coinbase
|
var tx, prev, prevHash, tx, err;
|
||||||
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();
|
|
||||||
c(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) {
|
tx = bcoin.mtx()
|
||||||
var t1 = bcoin.mtx().addOutput(w, 50000);
|
.addOutput(w.getAddress(), 50000)
|
||||||
var dummyInput = {
|
.addOutput(w.getAddress(), 10000);
|
||||||
|
|
||||||
|
prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
||||||
|
prevHash = crypto.randomBytes(32).toString('hex');
|
||||||
|
|
||||||
|
tx.addInput(dummy(prev, prevHash));
|
||||||
|
|
||||||
|
tx = tx.toTX();
|
||||||
|
|
||||||
|
try {
|
||||||
|
yield mempool.addTX(tx);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(err);
|
||||||
|
assert(!err.malleated);
|
||||||
|
assert(mempool.hasReject(tx.hash()));
|
||||||
|
cached = tx;
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should clear reject cache', cob(function *() {
|
||||||
|
var w = wallet;
|
||||||
|
var tx, input, tx, block;
|
||||||
|
|
||||||
|
tx = bcoin.mtx()
|
||||||
|
.addOutput(w.getAddress(), 50000);
|
||||||
|
|
||||||
|
input = {
|
||||||
prevout: {
|
prevout: {
|
||||||
hash: constants.NULL_HASH,
|
hash: constants.NULL_HASH,
|
||||||
index: 0xffffffff
|
index: 0xffffffff
|
||||||
@ -389,19 +366,20 @@ describe('Mempool', function() {
|
|||||||
script: new bcoin.script(),
|
script: new bcoin.script(),
|
||||||
sequence: 0xffffffff
|
sequence: 0xffffffff
|
||||||
};
|
};
|
||||||
t1.addInput(dummyInput);
|
|
||||||
var tx = t1.toTX();
|
|
||||||
var block = new bcoin.block();
|
|
||||||
block.txs.push(tx);
|
|
||||||
assert(mempool.hasReject(cached.hash()));
|
|
||||||
c(mempool.addBlock(block), function(err) {
|
|
||||||
assert(!err);
|
|
||||||
assert(!mempool.hasReject(cached.hash()));
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should destroy mempool', function(cb) {
|
tx.addInput(input);
|
||||||
c(mempool.close(), cb);
|
|
||||||
});
|
tx = tx.toTX();
|
||||||
|
|
||||||
|
block = new bcoin.block();
|
||||||
|
block.txs.push(tx);
|
||||||
|
|
||||||
|
assert(mempool.hasReject(cached.hash()));
|
||||||
|
yield mempool.addBlock(block);
|
||||||
|
assert(!mempool.hasReject(cached.hash()));
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should destroy mempool', cob(function *() {
|
||||||
|
yield mempool.close();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|||||||
1666
test/wallet-test.js
1666
test/wallet-test.js
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user