Merge pull request #119 from kleetus/remove_verify
Removed verifyScript and related methods that we don't currently use.
This commit is contained in:
commit
d7c16e11a3
|
@ -8,49 +8,6 @@ var BaseTransaction = chainlib.Transaction;
|
||||||
var BaseDatabase = chainlib.DB;
|
var BaseDatabase = chainlib.DB;
|
||||||
var levelup = chainlib.deps.levelup;
|
var levelup = chainlib.deps.levelup;
|
||||||
|
|
||||||
Transaction.prototype.validate = function(db, poolTransactions, callback) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if (!(db instanceof BaseDatabase)) {
|
|
||||||
throw new Error('First argument is expected to be an instance of Database');
|
|
||||||
}
|
|
||||||
|
|
||||||
// coinbase is valid
|
|
||||||
if (this.isCoinbase()) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
var verified = this.verify();
|
|
||||||
if(verified !== true) {
|
|
||||||
return callback(new Error(verified));
|
|
||||||
}
|
|
||||||
|
|
||||||
async.series(
|
|
||||||
[
|
|
||||||
self._validateInputs.bind(self, db, poolTransactions),
|
|
||||||
self._validateOutputs.bind(self),
|
|
||||||
self._checkSufficientInputs.bind(self)
|
|
||||||
],
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype._validateInputs = function(db, poolTransactions, callback) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// Verify inputs are unspent
|
|
||||||
async.each(self.inputs, function(input, next) {
|
|
||||||
async.series(
|
|
||||||
[
|
|
||||||
self._populateInput.bind(self, db, input, poolTransactions),
|
|
||||||
self._checkSpent.bind(self, db, input, poolTransactions),
|
|
||||||
self._checkScript.bind(self, db, input, self.inputs.indexOf(input))
|
|
||||||
],
|
|
||||||
next
|
|
||||||
);
|
|
||||||
}, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype.populateInputs = function(db, poolTransactions, callback) {
|
Transaction.prototype.populateInputs = function(db, poolTransactions, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -103,32 +60,6 @@ Transaction.prototype._checkSpent = function(db, input, poolTransactions, callba
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Transaction.prototype._checkScript = function(db, input, index, callback) {
|
|
||||||
if (input.output.script) {
|
|
||||||
var scriptPubkey = input.output._scriptBuffer;
|
|
||||||
var txTo = this.toBuffer();
|
|
||||||
var valid = db.bitcoind.verifyScript(scriptPubkey, txTo, index);
|
|
||||||
if(valid) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return callback(new Error('Script does not validate'));
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype._validateOutputs = function(callback) {
|
|
||||||
setImmediate(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype._checkSufficientInputs = function(callback) {
|
|
||||||
var inputTotal = this._getInputAmount();
|
|
||||||
var outputTotal = this._getOutputAmount();
|
|
||||||
if(inputTotal < outputTotal) {
|
|
||||||
return callback(new Error('Insufficient inputs'));
|
|
||||||
} else {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.manyToBuffer = function(transactions) {
|
Transaction.manyToBuffer = function(transactions) {
|
||||||
return BaseTransaction.manyToBuffer(transactions);
|
return BaseTransaction.manyToBuffer(transactions);
|
||||||
};
|
};
|
||||||
|
|
|
@ -171,44 +171,6 @@ struct async_tx_data {
|
||||||
Eternal<Function> callback;
|
Eternal<Function> callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify Scripts
|
|
||||||
*/
|
|
||||||
NAN_METHOD(VerifyScript) {
|
|
||||||
NanScope();
|
|
||||||
|
|
||||||
if (!node::Buffer::HasInstance(args[0])) {
|
|
||||||
return NanThrowTypeError("First argument should be a Buffer.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!node::Buffer::HasInstance(args[1])) {
|
|
||||||
return NanThrowTypeError("Second argument should be a Buffer.");
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char *scriptPubKey = (unsigned char *) node::Buffer::Data(args[0]);
|
|
||||||
unsigned int scriptPubKeyLen = (unsigned int) node::Buffer::Length(args[0]);
|
|
||||||
|
|
||||||
const unsigned char *txTo = (unsigned char *) node::Buffer::Data(args[1]);
|
|
||||||
unsigned int txToLen = (unsigned int)node::Buffer::Length(args[1]);
|
|
||||||
|
|
||||||
unsigned int nIn = args[2]->NumberValue();
|
|
||||||
unsigned int flags = args[3]->NumberValue();
|
|
||||||
|
|
||||||
bitcoinconsensus_error* err;
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
int valid = bitcoinconsensus_verify_script(scriptPubKey, scriptPubKeyLen, txTo, txToLen, nIn, flags, err);
|
|
||||||
|
|
||||||
if (!valid && err) {
|
|
||||||
NanThrowError("The transaction was not valid");
|
|
||||||
}
|
|
||||||
|
|
||||||
NanReturnValue(NanNew<Number>(valid));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
@ -1666,7 +1628,6 @@ init(Handle<Object> target) {
|
||||||
NODE_SET_METHOD(target, "getBlockIndex", GetBlockIndex);
|
NODE_SET_METHOD(target, "getBlockIndex", GetBlockIndex);
|
||||||
NODE_SET_METHOD(target, "getMempoolOutputs", GetMempoolOutputs);
|
NODE_SET_METHOD(target, "getMempoolOutputs", GetMempoolOutputs);
|
||||||
NODE_SET_METHOD(target, "addMempoolUncheckedTransaction", AddMempoolUncheckedTransaction);
|
NODE_SET_METHOD(target, "addMempoolUncheckedTransaction", AddMempoolUncheckedTransaction);
|
||||||
NODE_SET_METHOD(target, "verifyScript", VerifyScript);
|
|
||||||
NODE_SET_METHOD(target, "sendTransaction", SendTransaction);
|
NODE_SET_METHOD(target, "sendTransaction", SendTransaction);
|
||||||
NODE_SET_METHOD(target, "estimateFee", EstimateFee);
|
NODE_SET_METHOD(target, "estimateFee", EstimateFee);
|
||||||
NODE_SET_METHOD(target, "startTxMon", StartTxMon);
|
NODE_SET_METHOD(target, "startTxMon", StartTxMon);
|
||||||
|
|
|
@ -27,7 +27,6 @@ NAN_METHOD(IsSpent);
|
||||||
NAN_METHOD(GetBlockIndex);
|
NAN_METHOD(GetBlockIndex);
|
||||||
NAN_METHOD(GetMempoolOutputs);
|
NAN_METHOD(GetMempoolOutputs);
|
||||||
NAN_METHOD(AddMempoolUncheckedTransaction);
|
NAN_METHOD(AddMempoolUncheckedTransaction);
|
||||||
NAN_METHOD(VerifyScript);
|
|
||||||
NAN_METHOD(SendTransaction);
|
NAN_METHOD(SendTransaction);
|
||||||
NAN_METHOD(EstimateFee);
|
NAN_METHOD(EstimateFee);
|
||||||
NAN_METHOD(StartTxMon);
|
NAN_METHOD(StartTxMon);
|
||||||
|
|
|
@ -12,97 +12,6 @@ var chainlib = require('chainlib');
|
||||||
var levelup = chainlib.deps.levelup;
|
var levelup = chainlib.deps.levelup;
|
||||||
|
|
||||||
describe('Bitcoin Transaction', function() {
|
describe('Bitcoin Transaction', function() {
|
||||||
describe('#validate', function() {
|
|
||||||
it('should give an error if verify() fails', function(done) {
|
|
||||||
var tx = new Transaction();
|
|
||||||
tx.verify = sinon.stub().returns('invalid tx');
|
|
||||||
tx.validate(db, [], function(err) {
|
|
||||||
should.exist(err);
|
|
||||||
err.message.should.equal('invalid tx');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('should give an error if one if the async series functions fails', function(done) {
|
|
||||||
var tx = new Transaction();
|
|
||||||
tx._validateInputs = sinon.stub().callsArg(2);
|
|
||||||
tx._validateOutputs = sinon.stub().callsArgWith(0, new Error('output validation error'));
|
|
||||||
tx._checkSufficientInputs = sinon.stub().callsArg(0);
|
|
||||||
tx.verify = sinon.stub().returns(true);
|
|
||||||
tx.validate(db, [], function(err) {
|
|
||||||
should.exist(err);
|
|
||||||
err.message.should.equal('output validation error');
|
|
||||||
tx._validateInputs.calledOnce.should.equal(true);
|
|
||||||
tx._validateOutputs.calledOnce.should.equal(true);
|
|
||||||
tx._checkSufficientInputs.called.should.equal(false);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('should call all the functions if there is no error', function(done) {
|
|
||||||
var tx = new Transaction();
|
|
||||||
tx._validateInputs = sinon.stub().callsArg(2);
|
|
||||||
tx._validateOutputs = sinon.stub().callsArg(0);
|
|
||||||
tx._checkSufficientInputs = sinon.stub().callsArg(0);
|
|
||||||
tx.verify = sinon.stub().returns(true);
|
|
||||||
tx.validate(db, [], function(err) {
|
|
||||||
should.not.exist(err);
|
|
||||||
tx._validateInputs.calledOnce.should.equal(true);
|
|
||||||
tx._validateOutputs.calledOnce.should.equal(true);
|
|
||||||
tx._checkSufficientInputs.calledOnce.should.equal(true);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('#_validateInputs', function() {
|
|
||||||
it('should call all the functions and complete when no errors', function(done) {
|
|
||||||
var tx = new Transaction();
|
|
||||||
tx.inputs = ['input'];
|
|
||||||
sinon.stub(tx, '_populateInput', function(db, input, poolTransactions, callback) {
|
|
||||||
return callback(null, input, 'populateInput');
|
|
||||||
});
|
|
||||||
sinon.stub(tx, '_checkSpent', function(db, input, poolTransactions, callback) {
|
|
||||||
return callback();
|
|
||||||
});
|
|
||||||
sinon.stub(tx, '_checkScript', function(db, input, index, callback) {
|
|
||||||
return callback();
|
|
||||||
});
|
|
||||||
|
|
||||||
tx._validateInputs('db', [], function(err) {
|
|
||||||
should.not.exist(err);
|
|
||||||
tx._populateInput.calledOnce.should.equal(true);
|
|
||||||
tx._populateInput.calledWith('db', 'input');
|
|
||||||
tx._checkSpent.calledOnce.should.equal(true);
|
|
||||||
tx._populateInput.calledWith('db', 'input');
|
|
||||||
tx._checkScript.calledOnce.should.equal(true);
|
|
||||||
tx._populateInput.calledWith('input');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('should halt on an error', function(done) {
|
|
||||||
var tx = new Transaction();
|
|
||||||
tx.inputs = ['input'];
|
|
||||||
sinon.stub(tx, '_populateInput', function(db, input, poolTransactions, callback) {
|
|
||||||
return callback();
|
|
||||||
});
|
|
||||||
sinon.stub(tx, '_checkSpent', function(db, input, poolTransactions, callback) {
|
|
||||||
return callback(new Error('error'));
|
|
||||||
});
|
|
||||||
sinon.stub(tx, '_checkScript', function(input, callback) {
|
|
||||||
return callback();
|
|
||||||
});
|
|
||||||
|
|
||||||
tx._validateInputs('db', [], function(err) {
|
|
||||||
should.exist(err);
|
|
||||||
err.message.should.equal('error');
|
|
||||||
tx._populateInput.calledOnce.should.equal(true);
|
|
||||||
tx._populateInput.calledWith('input');
|
|
||||||
tx._checkSpent.calledOnce.should.equal(true);
|
|
||||||
tx._populateInput.calledWith('input');
|
|
||||||
tx._checkScript.called.should.equal(false);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#populateInputs', function() {
|
describe('#populateInputs', function() {
|
||||||
it('will call _populateInput with transactions', function() {
|
it('will call _populateInput with transactions', function() {
|
||||||
var tx = new Transaction();
|
var tx = new Transaction();
|
||||||
|
@ -213,99 +122,4 @@ describe('Bitcoin Transaction', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('#_checkScript', function() {
|
|
||||||
it('should not have an error with a valid script', function(done) {
|
|
||||||
var prevTx = new Transaction();
|
|
||||||
prevTx.fromString(transactionData[0].hex);
|
|
||||||
var tx = new Transaction();
|
|
||||||
tx.fromString(transactionData[1].hex);
|
|
||||||
var input = tx.inputs[0];
|
|
||||||
input.output = prevTx.outputs[0];
|
|
||||||
var db = {
|
|
||||||
bitcoind: {
|
|
||||||
verifyScript: sinon.stub().returns(true)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
tx._checkScript(db, input, 0, function(err) {
|
|
||||||
should.not.exist(err);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('should have an error when signature is missing', function(done) {
|
|
||||||
var prevTx = new Transaction();
|
|
||||||
prevTx.fromString(transactionData[0].hex);
|
|
||||||
var tx = new Transaction();
|
|
||||||
tx.fromString(transactionData[2].hex);
|
|
||||||
var input = tx.inputs[0];
|
|
||||||
input.output = prevTx.outputs[0];
|
|
||||||
var db = {
|
|
||||||
bitcoind: {
|
|
||||||
verifyScript: sinon.stub().returns(false)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
tx._checkScript(db, input, 0, function(err) {
|
|
||||||
should.exist(err);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('#_checkSufficientInputs', function() {
|
|
||||||
var inputs = [
|
|
||||||
{
|
|
||||||
outputIndex: 0,
|
|
||||||
output: {
|
|
||||||
satoshis: 1000
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
outputIndex: 0,
|
|
||||||
output: {
|
|
||||||
satoshis: 2000
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
outputIndex: 1,
|
|
||||||
output: {
|
|
||||||
satoshis: 3000
|
|
||||||
}
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
var outputs = [
|
|
||||||
{
|
|
||||||
satoshis: 4000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
satoshis: 3000
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
it('should give an error if inputs are less than outputs', function(done) {
|
|
||||||
var tx = new Transaction();
|
|
||||||
tx.inputs = inputs;
|
|
||||||
tx.outputs = outputs;
|
|
||||||
tx._checkSufficientInputs(function(err) {
|
|
||||||
should.exist(err);
|
|
||||||
err.message.should.equal('Insufficient inputs');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('should not give an error if inputs are greater than or equal to outputs', function(done) {
|
|
||||||
inputs[2].output = {
|
|
||||||
satoshis: 8000
|
|
||||||
};
|
|
||||||
|
|
||||||
var tx = new Transaction();
|
|
||||||
tx.inputs = inputs;
|
|
||||||
tx.outputs = outputs;
|
|
||||||
tx._checkSufficientInputs(function(err) {
|
|
||||||
should.not.exist(err);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue