do not accept mutable txs anywhere except wallet.

This commit is contained in:
Christopher Jeffrey 2016-08-17 16:45:42 -07:00
parent 4203999b81
commit 4b85715ec2
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
10 changed files with 53 additions and 29 deletions

View File

@ -236,7 +236,9 @@ Block.prototype.hasWitness = function hasWitness() {
*/
Block.prototype.addTX = function addTX(tx) {
var index = this.txs.push(tx) - 1;
var index;
assert(!tx.mutable, 'Cannot add mutable TX to block.');
index = this.txs.push(tx) - 1;
tx.setBlock(this, index);
return index;
};

View File

@ -517,8 +517,7 @@ Mempool.prototype.addTX = function addTX(tx, callback, force) {
if (!unlock)
return;
if (tx.mutable)
tx = tx.toTX();
assert(!tx.mutable, 'Cannot add mutable TX to mempool.');
callback = utils.wrap(callback, unlock);
callback = utils.asyncify(callback);

View File

@ -505,8 +505,7 @@ MinerBlock.prototype.updateMerkle = function updateMerkle() {
MinerBlock.prototype.addTX = function addTX(tx) {
var cost;
if (tx.mutable)
tx = tx.toTX();
assert(!tx.mutable, 'Cannot add mutable TX to block.');
cost = this.block.getCost() + tx.getCost();
@ -550,26 +549,28 @@ MinerBlock.prototype.findNonce = function findNonce() {
// The heart and soul of the miner: match the target.
while (block.nonce <= 0xffffffff) {
// Hash and test against the next target
if (rcmp(utils.hash256(data), target) <= 0)
// Hash and test against the next target.
if (rcmp(utils.hash256(data), target) <= 0) {
this.block.mutable = false;
return true;
}
// Increment the nonce to get a different hash
block.nonce++;
// Update the raw buffer (faster than
// constantly serializing the block)
// constantly serializing the headers).
data.writeUInt32LE(block.nonce, 76, true);
// Send progress report every so often
// Send progress report every so often.
if (block.nonce % 500000 === 0)
this.sendStatus();
}
// Keep track of our iterations
// Keep track of our iterations.
this.iterations++;
// Send progress report
// Send progress report.
this.sendStatus();
// If we took more a second or more (likely),

View File

@ -2212,10 +2212,8 @@ function BroadcastItem(pool, item, callback) {
this.id = this.pool.uid++;
this.msg = null;
if (item instanceof bcoin.tx) {
if (item.mutable)
item = item.toTX();
}
if (item instanceof bcoin.tx)
assert(!item.mutable, 'Cannot broadcast mutable TX.');
if (item.toInv) {
this.msg = item;

View File

@ -587,16 +587,17 @@ TXDB.prototype._verify = function _verify(tx, info, callback) {
return callback(null, false);
}
self._removeConflict(spent.hash, tx, function(err, rtx, rinfo) {
self._removeConflict(spent.hash, tx, function(err, tx, info) {
if (err)
return next(err);
// Spender was not removed, the current
// transaction is not elligible to be added.
if (!rtx)
if (!tx)
return callback(null, false);
self.emit('conflict', rtx, rinfo);
// Emit the _removed_ transaction.
self.emit('conflict', tx, info);
next();
});
@ -687,8 +688,7 @@ TXDB.prototype.add = function add(tx, info, callback) {
callback = utils.wrap(callback, unlock);
if (tx.mutable)
tx = tx.toTX();
assert(!tx.mutable, 'Cannot add mutable TX to wallet.');
// Attempt to confirm tx before adding it.
this._confirm(tx, info, function(err, existing) {

View File

@ -1473,6 +1473,8 @@ WalletDB.prototype.removeBlock = function removeBlock(entry, callback, force) {
WalletDB.prototype.addTX = function addTX(tx, callback, force) {
var self = this;
assert(!tx.mutable, 'Cannot add mutable TX to wallet.');
// Note:
// Atomicity doesn't matter here. If we crash,
// the automatic rescan will get the database

View File

@ -48,7 +48,7 @@ describe('Chain', function() {
redeemer.setLocktime(chain.height);
return wallet.sign(redeemer, function(err) {
assert.ifError(err);
attempt.addTX(redeemer);
attempt.addTX(redeemer.toTX());
callback(null, attempt.mineSync());
});
}

View File

@ -92,6 +92,7 @@ describe('HTTP', function() {
.addOutput(addr, 50460);
t1.addInput(dummyInput);
t1 = t1.toTX();
wallet.once('balance', function(b) {
balance = b;

View File

@ -75,18 +75,21 @@ describe('Mempool', function() {
// balance: 51000
w.sign(t1, function(err, total) {
assert.ifError(err);
t1 = t1.toTX();
var t2 = bcoin.mtx().addInput(t1, 0) // 50000
.addOutput(w, 20000)
.addOutput(w, 20000);
// balance: 49000
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
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)
@ -94,11 +97,13 @@ describe('Mempool', function() {
// balance: 22000
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
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
@ -107,6 +112,7 @@ describe('Mempool', function() {
// 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) {
@ -114,14 +120,6 @@ describe('Mempool', function() {
});
});
// Just for debugging
t1.hint = 't1';
t2.hint = 't2';
t3.hint = 't3';
t4.hint = 't4';
f1.hint = 'f1';
fake.hint = 'fake';
mempool.addTX(fake, function(err) {
assert.ifError(err);
mempool.addTX(t4, function(err) {
@ -191,6 +189,7 @@ describe('Mempool', function() {
t1.setLocktime(200);
chain.tip.height = 200;
t1.inputs[0].script = new bcoin.script([t1.createSignature(0, prev, kp.privateKey, 'all', 0)]),
t1 = t1.toTX();
mempool.addTX(t1, function(err) {
chain.tip.height = 0;
assert.ifError(err);
@ -225,6 +224,7 @@ describe('Mempool', function() {
t1.setLocktime(200);
chain.tip.height = 200 - 1;
t1.inputs[0].script = new bcoin.script([t1.createSignature(0, prev, kp.privateKey, 'all', 0)]),
t1 = t1.toTX();
mempool.addTX(t1, function(err) {
chain.tip.height = 0;
assert(err);

View File

@ -206,6 +206,7 @@ describe('Wallet', function() {
// balance: 51000
w.sign(t1, function(err) {
assert.ifError(err);
t1 = t1.toTX();
var t2 = bcoin.mtx().addInput(t1, 0) // 50000
.addOutput(w, 24000)
.addOutput(w, 24000);
@ -213,12 +214,14 @@ describe('Wallet', function() {
// balance: 49000
w.sign(t2, function(err) {
assert.ifError(err);
t2 = t2.toTX();
var t3 = bcoin.mtx().addInput(t1, 1) // 1000
.addInput(t2, 0) // 24000
.addOutput(w, 23000);
// balance: 47000
w.sign(t3, function(err) {
assert.ifError(err);
t3 = t3.toTX();
var t4 = bcoin.mtx().addInput(t2, 1) // 24000
.addInput(t3, 0) // 23000
.addOutput(w, 11000)
@ -226,11 +229,13 @@ describe('Wallet', function() {
// balance: 22000
w.sign(t4, function(err) {
assert.ifError(err);
t4 = t4.toTX();
var f1 = bcoin.mtx().addInput(t4, 1) // 11000
.addOutput(f, 10000);
// balance: 11000
w.sign(f1, function(err) {
assert.ifError(err);
f1 = f1.toTX();
var fake = bcoin.mtx().addInput(t1, 1) // 1000 (already redeemed)
.addOutput(w, 500);
// Script inputs but do not sign
@ -240,6 +245,7 @@ describe('Wallet', function() {
fake.inputs[0].script.set(0, FAKE_SIG);
fake.inputs[0].script.compile();
// balance: 11000
fake = fake.toTX();
// Fake TX should temporarly change output
walletdb.addTX(fake, function(err) {
@ -319,6 +325,7 @@ describe('Wallet', function() {
assert.ifError(err);
dw.sign(t1, function(err) {
assert.ifError(err);
t1 = t1.toTX();
dw.getBalance(function(err, balance) {
assert.ifError(err);
assert.equal(balance.total, 11000);
@ -361,6 +368,7 @@ describe('Wallet', function() {
.addOutput(w1, 5460);
t1.addInput(dummyInput);
t1 = t1.toTX();
walletdb.addTX(t1, function(err) {
assert.ifError(err);
@ -371,6 +379,7 @@ describe('Wallet', function() {
assert.ifError(err);
w1.sign(t2, function(err) {
assert.ifError(err);
t2 = t2.toTX();
assert(t2.verify());
@ -409,6 +418,7 @@ describe('Wallet', function() {
.addOutput(w1, 5460);
t1.addInput(dummyInput);
t1 = t1.toTX();
walletdb.addTX(t1, function(err) {
assert.ifError(err);
@ -419,6 +429,7 @@ describe('Wallet', function() {
assert.ifError(err);
w1.sign(t2, function(err) {
assert.ifError(err);
t2 = t2.toTX();
assert(t2.verify());
assert.equal(t2.getInputValue(), 16380);
@ -472,6 +483,7 @@ describe('Wallet', function() {
.addOutput(w1, 5460);
t1.addInput(dummyInput);
t1 = t1.toTX();
// Coinbase
var t2 = bcoin.mtx()
@ -481,6 +493,7 @@ describe('Wallet', function() {
.addOutput(w2, 5460);
t2.addInput(dummyInput);
t2 = t2.toTX();
walletdb.addTX(t1, function(err) {
assert.ifError(err);
@ -644,6 +657,7 @@ describe('Wallet', function() {
utx.addOutput({ address: addr, value: 5460 * 10 });
utx.addInput(dummyInput);
utx = utx.toTX();
// Simulate a confirmation
utx.ps = 0;
@ -682,6 +696,7 @@ describe('Wallet', function() {
w2.sign(send, function(err) {
assert.ifError(err);
send = send.toTX();
assert(send.verify(flags));
assert.equal(w1.changeDepth, 1);
@ -776,6 +791,7 @@ describe('Wallet', function() {
.addOutput(account.receiveAddress, 5460);
t1.addInput(dummyInput);
t1 = t1.toTX();
walletdb.addTX(t1, function(err) {
assert.ifError(err);
@ -843,6 +859,7 @@ describe('Wallet', function() {
.addOutput(account.receiveAddress, 5460);
t1.addInput(dummyInput);
t1 = t1.toTX();
walletdb.addTX(t1, function(err) {
assert.ifError(err);
@ -864,6 +881,7 @@ describe('Wallet', function() {
t1.ps = 0xdeadbeef;
t1.addInput(dummyInput);
t1 = t1.toTX();
walletdb.addTX(t1, function(err) {
assert.ifError(err);
@ -896,6 +914,7 @@ describe('Wallet', function() {
.addOutput(w1, 5460);
t1.addInput(dummyInput);
t1 = t1.toTX();
walletdb.addTX(t1, function(err) {
assert.ifError(err);
@ -934,6 +953,7 @@ describe('Wallet', function() {
.addOutput(w1, 5460);
t1.addInput(dummyInput);
t1 = t1.toTX();
walletdb.addTX(t1, function(err) {
assert.ifError(err);
@ -973,6 +993,7 @@ describe('Wallet', function() {
.addOutput(w1, 5460);
t1.addInput(dummyInput);
t1 = t1.toTX();
walletdb.addTX(t1, function(err) {
assert.ifError(err);