diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -203,17 +203,6 @@ } } -static bool IsDefinedHashtypeSignature(const valtype &vchSig) { - if (vchSig.size() == 0) { - return false; - } - if (!GetHashType(vchSig).hasSupportedBaseType()) { - return false; - } - - return true; -} - bool CheckSignatureEncoding(const std::vector &vchSig, uint32_t flags, ScriptError *serror) { // Empty signature. Not strictly DER encoded, but allowed to provide a @@ -232,7 +221,7 @@ return false; } if ((flags & SCRIPT_VERIFY_STRICTENC) != 0) { - if (!IsDefinedHashtypeSignature(vchSig)) { + if (!GetHashType(vchSig).isDefined()) { return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE); } bool usesForkId = GetHashType(vchSig).hasForkId(); diff --git a/src/script/sighashtype.h b/src/script/sighashtype.h --- a/src/script/sighashtype.h +++ b/src/script/sighashtype.h @@ -26,7 +26,7 @@ * c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73 for an * example where an unsupported base sig hash of 0 was used. */ -enum class BaseSigHashType : uint32_t { +enum class BaseSigHashType : uint8_t { UNSUPPORTED = 0, ALL = SIGHASH_ALL, NONE = SIGHASH_NONE, @@ -67,8 +67,9 @@ uint32_t getForkValue() const { return sigHash >> 8; } - bool hasSupportedBaseType() const { - BaseSigHashType baseType = getBaseType(); + bool isDefined() const { + auto baseType = + BaseSigHashType(sigHash & ~(SIGHASH_FORKID | SIGHASH_ANYONECANPAY)); return baseType >= BaseSigHashType::ALL && baseType <= BaseSigHashType::SINGLE; } diff --git a/src/test/script_sighashtype_tests.cpp b/src/test/script_sighashtype_tests.cpp --- a/src/test/script_sighashtype_tests.cpp +++ b/src/test/script_sighashtype_tests.cpp @@ -12,10 +12,10 @@ BOOST_FIXTURE_TEST_SUITE(script_sighashtype_tests, BasicTestingSetup) static void CheckSigHashType(SigHashType t, BaseSigHashType baseType, - bool hasSupportedBaseType, uint32_t forkValue, - bool hasForkId, bool hasAnyoneCanPay) { + bool isDefined, uint32_t forkValue, bool hasForkId, + bool hasAnyoneCanPay) { BOOST_CHECK(t.getBaseType() == baseType); - BOOST_CHECK_EQUAL(t.hasSupportedBaseType(), hasSupportedBaseType); + BOOST_CHECK_EQUAL(t.isDefined(), isDefined); BOOST_CHECK_EQUAL(t.getForkValue(), forkValue); BOOST_CHECK_EQUAL(t.hasForkId(), hasForkId); BOOST_CHECK_EQUAL(t.hasAnyoneCanPay(), hasAnyoneCanPay); @@ -44,38 +44,36 @@ .withForkId(hasForkId) .withAnyoneCanPay(hasAnyoneCanPay); - bool hasSupportedBaseType = - baseType != BaseSigHashType::UNSUPPORTED; - CheckSigHashType(t, baseType, hasSupportedBaseType, - forkValue, hasForkId, hasAnyoneCanPay); + bool isDefined = baseType != BaseSigHashType::UNSUPPORTED; + CheckSigHashType(t, baseType, isDefined, forkValue, + hasForkId, hasAnyoneCanPay); // Also check all possible alterations. CheckSigHashType(t.withForkId(hasForkId), baseType, - hasSupportedBaseType, forkValue, hasForkId, + isDefined, forkValue, hasForkId, hasAnyoneCanPay); CheckSigHashType(t.withForkId(!hasForkId), baseType, - hasSupportedBaseType, forkValue, - !hasForkId, hasAnyoneCanPay); + isDefined, forkValue, !hasForkId, + hasAnyoneCanPay); CheckSigHashType(t.withAnyoneCanPay(hasAnyoneCanPay), - baseType, hasSupportedBaseType, forkValue, - hasForkId, hasAnyoneCanPay); + baseType, isDefined, forkValue, hasForkId, + hasAnyoneCanPay); CheckSigHashType(t.withAnyoneCanPay(!hasAnyoneCanPay), - baseType, hasSupportedBaseType, forkValue, - hasForkId, !hasAnyoneCanPay); + baseType, isDefined, forkValue, hasForkId, + !hasAnyoneCanPay); for (BaseSigHashType newBaseType : baseTypes) { - bool hasSupportedNewBaseType = + bool isNewDefined = newBaseType != BaseSigHashType::UNSUPPORTED; CheckSigHashType(t.withBaseType(newBaseType), - newBaseType, hasSupportedNewBaseType, - forkValue, hasForkId, hasAnyoneCanPay); + newBaseType, isNewDefined, forkValue, + hasForkId, hasAnyoneCanPay); } for (uint32_t newForkValue : forkValues) { CheckSigHashType(t.withForkValue(newForkValue), - baseType, hasSupportedBaseType, - newForkValue, hasForkId, - hasAnyoneCanPay); + baseType, isDefined, newForkValue, + hasForkId, hasAnyoneCanPay); } } } @@ -86,50 +84,32 @@ BOOST_AUTO_TEST_CASE(sighash_serialization_test) { std::set forkValues{0, 1, 0xab1fe9, 0xc81eea, 0xffffff}; - // Test all possible base sig hash values. - for (uint32_t baseType = 0; baseType <= 0x1f; baseType++) { + // Test all possible sig hash values embeded in signatures. + for (uint32_t sigHashType = 0x00; sigHashType <= 0xff; sigHashType++) { for (uint32_t forkValue : forkValues) { - bool hasSupportedBaseType = - (baseType != 0) && (baseType <= SIGHASH_SINGLE); + uint32_t rawType = sigHashType | (forkValue << 8); + + uint32_t baseType = rawType & 0x1f; + bool hasForkId = (rawType & SIGHASH_FORKID) != 0; + bool hasAnyoneCanPay = (rawType & SIGHASH_ANYONECANPAY) != 0; - uint32_t rawType = baseType | (forkValue << 8); + uint32_t noflag = + sigHashType & ~(SIGHASH_FORKID | SIGHASH_ANYONECANPAY); + bool isDefined = (noflag != 0) && (noflag <= SIGHASH_SINGLE); SigHashType tbase(rawType); - SigHashType tforkid(rawType | SIGHASH_FORKID); - SigHashType tanyonecanspend(rawType | SIGHASH_ANYONECANPAY); - SigHashType tboth(rawType | SIGHASH_FORKID | SIGHASH_ANYONECANPAY); // Check deserialization. - CheckSigHashType(tbase, BaseSigHashType(baseType), - hasSupportedBaseType, forkValue, false, false); - CheckSigHashType(tforkid, BaseSigHashType(baseType), - hasSupportedBaseType, forkValue, true, false); - CheckSigHashType(tanyonecanspend, BaseSigHashType(baseType), - hasSupportedBaseType, forkValue, false, true); - CheckSigHashType(tboth, BaseSigHashType(baseType), - hasSupportedBaseType, forkValue, true, true); + CheckSigHashType(tbase, BaseSigHashType(baseType), isDefined, + forkValue, hasForkId, hasAnyoneCanPay); // Check raw value. BOOST_CHECK_EQUAL(tbase.getRawSigHashType(), rawType); - BOOST_CHECK_EQUAL(tforkid.getRawSigHashType(), - rawType | SIGHASH_FORKID); - BOOST_CHECK_EQUAL(tanyonecanspend.getRawSigHashType(), - rawType | SIGHASH_ANYONECANPAY); - BOOST_CHECK_EQUAL(tboth.getRawSigHashType(), - rawType | SIGHASH_FORKID | SIGHASH_ANYONECANPAY); // Check serialization/deserialization. uint32_t unserializedOutput; (CDataStream(SER_DISK, 0) << tbase) >> unserializedOutput; BOOST_CHECK_EQUAL(unserializedOutput, rawType); - (CDataStream(SER_DISK, 0) << tforkid) >> unserializedOutput; - BOOST_CHECK_EQUAL(unserializedOutput, rawType | SIGHASH_FORKID); - (CDataStream(SER_DISK, 0) << tanyonecanspend) >> unserializedOutput; - BOOST_CHECK_EQUAL(unserializedOutput, - rawType | SIGHASH_ANYONECANPAY); - (CDataStream(SER_DISK, 0) << tboth) >> unserializedOutput; - BOOST_CHECK_EQUAL(unserializedOutput, - rawType | SIGHASH_FORKID | SIGHASH_ANYONECANPAY); } } }