|
|
|
@ -227,7 +227,10 @@ const char* GetOpName(opcodetype opcode)
@@ -227,7 +227,10 @@ const char* GetOpName(opcodetype opcode)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsCanonicalPubKey(const valtype &vchPubKey) { |
|
|
|
|
bool IsCanonicalPubKey(const valtype &vchPubKey, unsigned int flags) { |
|
|
|
|
if (!(flags & SCRIPT_VERIFY_STRICTENC)) |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
if (vchPubKey.size() < 33) |
|
|
|
|
return error("Non-canonical public key: too short"); |
|
|
|
|
if (vchPubKey[0] == 0x04) { |
|
|
|
@ -242,7 +245,10 @@ bool IsCanonicalPubKey(const valtype &vchPubKey) {
@@ -242,7 +245,10 @@ bool IsCanonicalPubKey(const valtype &vchPubKey) {
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsCanonicalSignature(const valtype &vchSig) { |
|
|
|
|
bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { |
|
|
|
|
if (!(flags & SCRIPT_VERIFY_STRICTENC)) |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
// See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
|
|
|
|
|
// A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype>
|
|
|
|
|
// Where R and S are not negative (their first byte has its highest bit not set), and not
|
|
|
|
@ -286,6 +292,11 @@ bool IsCanonicalSignature(const valtype &vchSig) {
@@ -286,6 +292,11 @@ bool IsCanonicalSignature(const valtype &vchSig) {
|
|
|
|
|
if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) |
|
|
|
|
return error("Non-canonical signature: S value excessively padded"); |
|
|
|
|
|
|
|
|
|
if (flags & SCRIPT_VERIFY_EVEN_S) { |
|
|
|
|
if (S[nLenS-1] & 1) |
|
|
|
|
return error("Non-canonical signature: S value odd"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -302,7 +313,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
@@ -302,7 +313,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
|
|
|
|
if (script.size() > 10000) |
|
|
|
|
return false; |
|
|
|
|
int nOpCount = 0; |
|
|
|
|
bool fStrictEncodings = flags & SCRIPT_VERIFY_STRICTENC; |
|
|
|
|
|
|
|
|
|
try |
|
|
|
|
{ |
|
|
|
@ -841,9 +851,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
@@ -841,9 +851,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
|
|
|
|
// Drop the signature, since there's no way for a signature to sign itself
|
|
|
|
|
scriptCode.FindAndDelete(CScript(vchSig)); |
|
|
|
|
|
|
|
|
|
bool fSuccess = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey))); |
|
|
|
|
if (fSuccess) |
|
|
|
|
fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags); |
|
|
|
|
bool fSuccess = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && |
|
|
|
|
CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags); |
|
|
|
|
|
|
|
|
|
popstack(stack); |
|
|
|
|
popstack(stack); |
|
|
|
@ -903,9 +912,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
@@ -903,9 +912,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
|
|
|
|
valtype& vchPubKey = stacktop(-ikey); |
|
|
|
|
|
|
|
|
|
// Check signature
|
|
|
|
|
bool fOk = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey))); |
|
|
|
|
if (fOk) |
|
|
|
|
fOk = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags); |
|
|
|
|
bool fOk = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && |
|
|
|
|
CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags); |
|
|
|
|
|
|
|
|
|
if (fOk) { |
|
|
|
|
isig++; |
|
|
|
|