diff --git a/lib/crypto/signature.js b/lib/crypto/signature.js index a179afe5c..cf9b897c2 100644 --- a/lib/crypto/signature.js +++ b/lib/crypto/signature.js @@ -4,6 +4,7 @@ var BN = require('./bn'); var _ = require('lodash'); var $ = require('../util/preconditions'); var BufferUtil = require('../util/buffer'); +var JSUtil = require('../util/js'); var Signature = function Signature(r, s) { if (!(this instanceof Signature)) { @@ -285,7 +286,12 @@ Signature.prototype.hasLowS = function() { * Translated from bitcoind's IsDefinedHashtypeSignature */ Signature.prototype.hasDefinedHashtype = function() { - if (this.nhashtype < Signature.SIGHASH_ALL || this.nhashtype > Signature.SIGHASH_SINGLE) { + if (!JSUtil.isNaturalNumber(this.nhashtype)) { + return false; + } + // accept with or without Signature.SIGHASH_ANYONECANPAY by ignoring the bit + var temp = this.nhashtype & ~Signature.SIGHASH_ANYONECANPAY; + if (temp < Signature.SIGHASH_ALL || temp > Signature.SIGHASH_SINGLE) { return false; } return true; diff --git a/test/crypto/signature.js b/test/crypto/signature.js index 359c96d2d..dc005491b 100644 --- a/test/crypto/signature.js +++ b/test/crypto/signature.js @@ -1,5 +1,6 @@ 'use strict'; +var _ = require('lodash'); var should = require('chai').should(); var bitcore = require('../..'); var BN = bitcore.crypto.BN; @@ -293,4 +294,35 @@ describe('Signature', function() { }); }); + describe('#hasDefinedHashtype', function() { + it('should reject invalid sighash types and accept valid ones', function() { + var sig = new Signature(); + sig.hasDefinedHashtype().should.equal(false); + var testCases = [ + [undefined, false], + [null, false], + [0, false], + [1.1, false], + [-1, false], + [-1.1, false], + ['', false], + ['1', false], + [Signature.SIGHASH_ANYONECANPAY, false], + [Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_ALL, true], + [Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_NONE, true], + [Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_SINGLE, true], + [Signature.SIGHASH_ALL, true], + [Signature.SIGHASH_NONE, true], + [Signature.SIGHASH_SINGLE, true], + [Signature.SIGHASH_SINGLE + 1, false], + [(Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_SINGLE) + 1, false], + [(Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_ALL) - 1, false], + ]; + _.each(testCases, function(testCase) { + sig.nhashtype = testCase[0]; + sig.hasDefinedHashtype().should.equal(testCase[1]); + }); + }); + }); + });