diff --git a/src/main.cpp b/src/main.cpp index 8306a2c11..5f8737b53 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3884,22 +3884,27 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned return (nFound >= nRequired); } -bool static IsCanonicalBlockSignature(const CBlock* pblock) +bool static IsCanonicalBlockSignature(const CBlock* pblock, bool checkLowS) { if (pblock->IsProofOfWork()) { return pblock->vchBlockSig.empty(); } - return IsLowDERSignature(pblock->vchBlockSig, NULL, false); + return checkLowS ? IsLowDERSignature(pblock->vchBlockSig, NULL, false) : IsDERSignature(pblock->vchBlockSig, NULL, false); } bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool fMayBanPeerIfInvalid) { - if (!IsCanonicalBlockSignature(pblock)) { - if (pfrom && pfrom->nVersion >= CANONICAL_BLOCK_SIG_VERSION) - return state.DoS(100, error("ProcessNewBlock(): bad block signature encoding"), - REJECT_INVALID, "bad-block-signature-encoding"); - return false; + if (!IsCanonicalBlockSignature(pblock, false)) { + if (pfrom && pfrom->nVersion >= CANONICAL_BLOCK_SIG_VERSION) + return state.DoS(100, error("ProcessNewBlock(): bad block signature encoding"), + REJECT_INVALID, "bad-block-signature-encoding"); + } + + if (!IsCanonicalBlockSignature(pblock, true)) { + if (pfrom && pfrom->nVersion >= CANONICAL_BLOCK_SIG_LOW_S_VERSION) + return state.DoS(100, error("ProcessNewBlock(): bad block signature encoding (low-s)"), + REJECT_INVALID, "bad-block-signature-encoding"); } { diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 8103bce4c..f134f21fb 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -176,30 +176,19 @@ bool IsLowDERSignature(const valtype &vchSig, ScriptError* serror, bool haveHash if (!IsValidSignatureEncoding(vchSig, haveHashType)) { return set_error(serror, SCRIPT_ERR_SIG_DER); } - unsigned int nLenR = vchSig[3]; - unsigned int nLenS = vchSig[5+nLenR]; - const unsigned char *S = &vchSig[6+nLenR]; - // If the S value is above the order of the curve divided by two, its - // complement modulo the order could have been used instead, which is - // one byte shorter when encoded correctly. - if (!CPubKey::CheckSignatureElement(S, nLenS, true)) - return set_error(serror, SCRIPT_ERR_SIG_HIGH_S); - - return true; -} - -/* -bool IsLowDERSignature(const valtype &vchSig, ScriptError* serror) { - if (!IsValidSignatureEncoding(vchSig)) { - return set_error(serror, SCRIPT_ERR_SIG_DER); - } - std::vector vchSigCopy(vchSig.begin(), vchSig.begin() + vchSig.size() - 1); + std::vector vchSigCopy(vchSig.begin(), vchSig.begin() + vchSig.size() - (haveHashType ? 1 : 0)); if (!CPubKey::CheckLowS(vchSigCopy)) { return set_error(serror, SCRIPT_ERR_SIG_HIGH_S); } return true; } -*/ + +bool IsDERSignature(const valtype &vchSig, ScriptError* serror, bool haveHashType) { + if (!IsValidSignatureEncoding(vchSig, haveHashType)) { + return set_error(serror, SCRIPT_ERR_SIG_DER); + } + return true; +} bool static IsDefinedHashtypeSignature(const valtype &vchSig) { if (vchSig.size() == 0) { diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 9753da667..57407cb07 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -162,6 +162,7 @@ public: bool IsCompressedOrUncompressedPubKey(const std::vector &vchPubKey); bool IsLowDERSignature(const std::vector &vchSig, ScriptError* serror, bool haveHashType = true); +bool IsDERSignature(const std::vector &vchSig, ScriptError* serror, bool haveHashType = true); bool EvalScript(std::vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL); bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL); diff --git a/src/version.h b/src/version.h index b1c661e7e..b3ae38a8b 100644 --- a/src/version.h +++ b/src/version.h @@ -17,8 +17,9 @@ static const int INIT_PROTO_VERSION = 209; //! In this version, 'getheaders' was introduced. static const int GETHEADERS_VERSION = 31800; -//! demand canonical block signatures starting from this version -static const int CANONICAL_BLOCK_SIG_VERSION = 60018; +//! reject blocks with non-canonical signatures starting from this version +static const int CANONICAL_BLOCK_SIG_VERSION = 60016; +static const int CANONICAL_BLOCK_SIG_LOW_S_VERSION = 60018; //! disconnect from peers older than this proto version static const int MIN_PEER_PROTO_VERSION = CANONICAL_BLOCK_SIG_VERSION;