Browse Source

Merge pull request #5004

9df9cf5 Make SCRIPT_VERIFY_STRICTENC compatible with BIP62 (Pieter Wuille)
0.10
Pieter Wuille 10 years ago
parent
commit
bf7b4fc6d3
No known key found for this signature in database
GPG Key ID: 57896D2FF8F0B657
  1. 1
      src/Makefile.test.include
  2. 76
      src/script/interpreter.cpp
  3. 25
      src/script/interpreter.h
  4. 113
      src/test/canonical_tests.cpp
  5. 48
      src/test/data/script_invalid.json
  6. 62
      src/test/data/script_valid.json
  7. 72
      src/test/script_tests.cpp
  8. 1
      src/test/transaction_tests.cpp

1
src/Makefile.test.include

@ -40,7 +40,6 @@ BITCOIN_TESTS =\
test/base58_tests.cpp \ test/base58_tests.cpp \
test/base64_tests.cpp \ test/base64_tests.cpp \
test/bloom_tests.cpp \ test/bloom_tests.cpp \
test/canonical_tests.cpp \
test/checkblock_tests.cpp \ test/checkblock_tests.cpp \
test/Checkpoints_tests.cpp \ test/Checkpoints_tests.cpp \
test/compress_tests.cpp \ test/compress_tests.cpp \

76
src/script/interpreter.cpp

@ -52,10 +52,7 @@ static inline void popstack(vector<valtype>& stack)
stack.pop_back(); stack.pop_back();
} }
bool IsCanonicalPubKey(const valtype &vchPubKey, unsigned int flags) { bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) {
if (!(flags & SCRIPT_VERIFY_STRICTENC))
return true;
if (vchPubKey.size() < 33) if (vchPubKey.size() < 33)
return error("Non-canonical public key: too short"); return error("Non-canonical public key: too short");
if (vchPubKey[0] == 0x04) { if (vchPubKey[0] == 0x04) {
@ -70,10 +67,7 @@ bool IsCanonicalPubKey(const valtype &vchPubKey, unsigned int flags) {
return true; return true;
} }
bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { bool static IsDERSignature(const valtype &vchSig) {
if (!(flags & SCRIPT_VERIFY_STRICTENC))
return true;
// See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 // 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> // 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 // Where R and S are not negative (their first byte has its highest bit not set), and not
@ -83,9 +77,6 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) {
return error("Non-canonical signature: too short"); return error("Non-canonical signature: too short");
if (vchSig.size() > 73) if (vchSig.size() > 73)
return error("Non-canonical signature: too long"); return error("Non-canonical signature: too long");
unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY));
if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE)
return error("Non-canonical signature: unknown hashtype byte");
if (vchSig[0] != 0x30) if (vchSig[0] != 0x30)
return error("Non-canonical signature: wrong type"); return error("Non-canonical signature: wrong type");
if (vchSig[1] != vchSig.size()-3) if (vchSig[1] != vchSig.size()-3)
@ -117,17 +108,54 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) {
if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80))
return error("Non-canonical signature: S value excessively padded"); return error("Non-canonical signature: S value excessively padded");
if (flags & SCRIPT_VERIFY_LOW_S) { return true;
// 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. bool static IsLowDERSignature(const valtype &vchSig) {
if (!CKey::CheckSignatureElement(S, nLenS, true)) if (!IsDERSignature(vchSig)) {
return error("Non-canonical signature: S value is unnecessarily high"); return false;
} }
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 (!CKey::CheckSignatureElement(S, nLenS, true))
return error("Non-canonical signature: S value is unnecessarily high");
return true; return true;
} }
bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
if (vchSig.size() == 0) {
return false;
}
unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY));
if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE)
return error("Non-canonical signature: unknown hashtype byte");
return true;
}
bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags) {
if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsDERSignature(vchSig)) {
return false;
} else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig)) {
return false;
} else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsDefinedHashtypeSignature(vchSig)) {
return false;
}
return true;
}
bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags) {
if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchSig)) {
return false;
}
return true;
}
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker) bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker)
{ {
CScript::const_iterator pc = script.begin(); CScript::const_iterator pc = script.begin();
@ -670,8 +698,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// Drop the signature, since there's no way for a signature to sign itself // Drop the signature, since there's no way for a signature to sign itself
scriptCode.FindAndDelete(CScript(vchSig)); scriptCode.FindAndDelete(CScript(vchSig));
bool fSuccess = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && if (!CheckSignatureEncoding(vchSig, flags)) {
checker.CheckSig(vchSig, vchPubKey, scriptCode); return false;
}
bool fSuccess = CheckPubKeyEncoding(vchPubKey, flags) && checker.CheckSig(vchSig, vchPubKey, scriptCode);
popstack(stack); popstack(stack);
popstack(stack); popstack(stack);
@ -730,9 +761,12 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
valtype& vchSig = stacktop(-isig); valtype& vchSig = stacktop(-isig);
valtype& vchPubKey = stacktop(-ikey); valtype& vchPubKey = stacktop(-ikey);
if (!CheckSignatureEncoding(vchSig, flags)) {
return false;
}
// Check signature // Check signature
bool fOk = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && bool fOk = CheckPubKeyEncoding(vchPubKey, flags) && checker.CheckSig(vchSig, vchPubKey, scriptCode);
checker.CheckSig(vchSig, vchPubKey, scriptCode);
if (fOk) { if (fOk) {
isig++; isig++;

25
src/script/interpreter.h

@ -28,14 +28,25 @@ enum
enum enum
{ {
SCRIPT_VERIFY_NONE = 0, SCRIPT_VERIFY_NONE = 0,
SCRIPT_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
SCRIPT_VERIFY_STRICTENC = (1U << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys
SCRIPT_VERIFY_LOW_S = (1U << 2), // enforce low S values (<n/2) in signatures (depends on STRICTENC)
SCRIPT_VERIFY_NULLDUMMY = (1U << 3), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length
};
bool IsCanonicalPubKey(const std::vector<unsigned char> &vchPubKey, unsigned int flags); // Evaluate P2SH subscripts (softfork safe, BIP16).
bool IsCanonicalSignature(const std::vector<unsigned char> &vchSig, unsigned int flags); SCRIPT_VERIFY_P2SH = (1U << 0),
// Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
// Passing a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) to checksig causes that pubkey to be
// skipped (not softfork safe: this flag can widen the validity of OP_CHECKSIG OP_NOT).
SCRIPT_VERIFY_STRICTENC = (1U << 1),
// Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1)
SCRIPT_VERIFY_DERSIG = (1U << 2),
// Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
// (softfork safe, BIP62 rule 5).
SCRIPT_VERIFY_LOW_S = (1U << 3),
// verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7).
SCRIPT_VERIFY_NULLDUMMY = (1U << 4),
};
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);

113
src/test/canonical_tests.cpp

@ -1,113 +0,0 @@
// Copyright (c) 2012-2013 The Bitcoin Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
// Unit tests for canonical signatures
//
#include "data/sig_noncanonical.json.h"
#include "data/sig_canonical.json.h"
#include "key.h"
#include "random.h"
#include "script/interpreter.h"
#include "util.h"
#include "utilstrencodings.h"
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
#include "json/json_spirit_writer_template.h"
#include <openssl/ecdsa.h>
using namespace std;
using namespace json_spirit;
// In script_tests.cpp
extern Array read_json(const std::string& jsondata);
BOOST_AUTO_TEST_SUITE(canonical_tests)
// OpenSSL-based test for canonical signature (without test for hashtype byte)
bool static IsCanonicalSignature_OpenSSL_inner(const std::vector<unsigned char>& vchSig)
{
if (vchSig.size() == 0)
return false;
const unsigned char *input = &vchSig[0];
ECDSA_SIG *psig = NULL;
d2i_ECDSA_SIG(&psig, &input, vchSig.size());
if (psig == NULL)
return false;
unsigned char buf[256];
unsigned char *pbuf = buf;
unsigned int nLen = i2d_ECDSA_SIG(psig, NULL);
if (nLen != vchSig.size()) {
ECDSA_SIG_free(psig);
return false;
}
nLen = i2d_ECDSA_SIG(psig, &pbuf);
ECDSA_SIG_free(psig);
return (memcmp(&vchSig[0], &buf[0], nLen) == 0);
}
// OpenSSL-based test for canonical signature
bool static IsCanonicalSignature_OpenSSL(const std::vector<unsigned char> &vchSignature) {
if (vchSignature.size() < 1)
return false;
if (vchSignature.size() > 127)
return false;
if (vchSignature[vchSignature.size() - 1] & 0x7C)
return false;
std::vector<unsigned char> vchSig(vchSignature);
vchSig.pop_back();
if (!IsCanonicalSignature_OpenSSL_inner(vchSig))
return false;
return true;
}
BOOST_AUTO_TEST_CASE(script_canon)
{
Array tests = read_json(std::string(json_tests::sig_canonical, json_tests::sig_canonical + sizeof(json_tests::sig_canonical)));
BOOST_FOREACH(Value &tv, tests) {
string test = tv.get_str();
if (IsHex(test)) {
std::vector<unsigned char> sig = ParseHex(test);
BOOST_CHECK_MESSAGE(IsCanonicalSignature(sig, SCRIPT_VERIFY_STRICTENC), test);
BOOST_CHECK_MESSAGE(IsCanonicalSignature_OpenSSL(sig), test);
}
}
}
BOOST_AUTO_TEST_CASE(script_noncanon)
{
Array tests = read_json(std::string(json_tests::sig_noncanonical, json_tests::sig_noncanonical + sizeof(json_tests::sig_noncanonical)));
BOOST_FOREACH(Value &tv, tests) {
string test = tv.get_str();
if (IsHex(test)) {
std::vector<unsigned char> sig = ParseHex(test);
BOOST_CHECK_MESSAGE(!IsCanonicalSignature(sig, SCRIPT_VERIFY_STRICTENC), test);
BOOST_CHECK_MESSAGE(!IsCanonicalSignature_OpenSSL(sig), test);
}
}
}
BOOST_AUTO_TEST_CASE(script_signstrict)
{
for (int i=0; i<100; i++) {
CKey key;
key.MakeNewKey(i & 1);
std::vector<unsigned char> sig;
uint256 hash = GetRandHash();
BOOST_CHECK(key.Sign(hash, sig)); // Generate a random signature.
BOOST_CHECK(key.GetPubKey().Verify(hash, sig)); // Check it.
sig.push_back(0x01); // Append a sighash type.
BOOST_CHECK(IsCanonicalSignature(sig, SCRIPT_VERIFY_STRICTENC | SCRIPT_VERIFY_LOW_S));
BOOST_CHECK(IsCanonicalSignature_OpenSSL(sig));
}
}
BOOST_AUTO_TEST_SUITE_END()

48
src/test/data/script_invalid.json

@ -444,18 +444,66 @@ nSequences are max.
"STRICTENC", "STRICTENC",
"P2PK with too little R padding" "P2PK with too little R padding"
], ],
[
"0x47 0x30440220001d0f82c127470cb38316c96b1719b33382353687a1146a776dee8259606905022062cd1fc8eacef819d68f0f41cc9ae9fdc2e29b70c3c7ad2c6c18f39b4e35c42701",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"DERSIG",
"P2PK NOT with bad sig with too much R padding"
],
[
"0x47 0x30440220005d727e2a82d6e8a98a6da6fbc281325644d1a40455e386fdb17883a8e6bc4d02202d15cca42ce136047a980d288e60c679d7e84cce18c3ceffb6bc81b9e9ba517801",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"",
"P2PK NOT with too much R padding but no DERSIG"
],
[
"0x47 0x30440220006e8bc4f82032b12bd594847c16d8b2986de734aa3b0528bd89d664d41e6d1c02200cfd582694891bcfa2e630e899bda257486eba00a007222fae71144dba07dc2901",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"DERSIG",
"P2PK NOT with too much R padding"
],
[ [
"0x48 0x304502206c43e065c8a8db3bbe69015afb86a51fb2fc8870defd41d436da2a197d9d6c12022100fcec35816ee2d84ec271ad159fcabf5dd712157051169e48ac328a7818cdb51e01", "0x48 0x304502206c43e065c8a8db3bbe69015afb86a51fb2fc8870defd41d436da2a197d9d6c12022100fcec35816ee2d84ec271ad159fcabf5dd712157051169e48ac328a7818cdb51e01",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
"LOW_S,STRICTENC", "LOW_S,STRICTENC",
"P2PK with high S" "P2PK with high S"
], ],
[
"0x47 0x304402203aab50cd7c30cc1e1475dee615b295bcee6ccf8aa8a7f6cda6b696c70d79cbb40220558e43fe7596c31146e2d077698d5a9c38351d8ba567549a2ae43ca97231c39501",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"STRICTENC",
"P2PK with hybrid pubkey"
],
[
"0x47 0x304402205745e8f846110c185ee1185c01843a108588b81463d2c34d4a3f2445529f12fe02206ee6a2657bbc4e2bb74bfc44c3a5c4f410ed6356ca68982465de6ca807c807c201",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"",
"P2PK NOT with hybrid pubkey but no STRICTENC"
],
[
"0x47 0x304402201f82b99a813c9c48c8dee8d2c43b8f637b72353fe9bdcc084537bc17e2ab770402200c43b96a5f7e115f0114eabda32e068145965cb6c7b5ef64833bb4fcf9fc1b3b05",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"STRICTENC",
"P2PK with undefined hashtype"
],
[
"0x47 0x30440220166848cd5b82a32b5944d90de3c35249354b43773c2ece1844ee8d1103e2f6c602203b6b046da4243c77adef80ada9201b27bbfdf7f9d5428f40434b060432afd62005",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
"STRICTENC",
"P2PK NOT with invalid sig and undefined hashtype"
],
[ [
"0x01 0x01 0x47 0x304402200e48ba1cf4d7182db94ffb57bd72ea31b5545dc0d1c512e665779b4fb2badc52022054b8388dfc074c708a75b62359b7be46402751ee40c0a111aef38a837b6ed09801 0x47 0x304402201c9820f59c49107bb30e6175cfc9ec95f897b03beb628b4bc854d2b80392aa0602200235d986ae418bcd111b8814f4c26a0ab5f475fb542a44884fc14912a97a252301 0x47 0x304402204cd7894c6f10a871f5b0c1f9c13228f8cdd4050248f0d0f498ee86be69ee3080022051bd2932c7d585eb600c7194235c74da820935f0d67972fd9545673aa1fd023301", "0x01 0x01 0x47 0x304402200e48ba1cf4d7182db94ffb57bd72ea31b5545dc0d1c512e665779b4fb2badc52022054b8388dfc074c708a75b62359b7be46402751ee40c0a111aef38a837b6ed09801 0x47 0x304402201c9820f59c49107bb30e6175cfc9ec95f897b03beb628b4bc854d2b80392aa0602200235d986ae418bcd111b8814f4c26a0ab5f475fb542a44884fc14912a97a252301 0x47 0x304402204cd7894c6f10a871f5b0c1f9c13228f8cdd4050248f0d0f498ee86be69ee3080022051bd2932c7d585eb600c7194235c74da820935f0d67972fd9545673aa1fd023301",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"NULLDUMMY", "NULLDUMMY",
"3-of-3 with nonzero dummy" "3-of-3 with nonzero dummy"
], ],
[
"0x01 0x01 0x47 0x304402201847fc3b8f7597768e7f543c58da1fca6e8e35eb28979431e6b637572ce6eaa4022048dd58608e040841d0bf52a70cfb70e1a9c8d2826fad068f4e9d2bf5c87766a501 0x47 0x30440220711311a72516affed73363763983d05c3d6a06a2eadf5d76b90b4354162ba94302204841a69e5955a7dc8e4ab3105fd0c86040c1dac6016297a51ddbf5079c28756801 0x47 0x30440220267e331a378191e7282fd10d61c97bf74bc97c233c5833d677936424ac08dee502201eee83d88b91988e1c4d9b979df2404aa190e0987a8ca09c4e5cd61da1d48ecc01",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
"NULLDUMMY",
"3-of-3 NOT with invalid sig with nonzero dummy"
],
["The End"] ["The End"]
] ]

62
src/test/data/script_valid.json

@ -572,22 +572,28 @@ nSequences are max.
"P2SH(2-of-3)" "P2SH(2-of-3)"
], ],
[ [
"0x47 0x304402200001cae94b795baaafb05db38cf24cd75560cab2c36c91e29fac7d0fd2a723a3022058e2e56e568ce7c4b2b106210d114e1faa079407a6ed4154f230667c7d3583bc01", "0x47 0x30440220001fff8863c84c0efc8eea5bffb7f388313f966f23a00ad3c0acc30ff5339684022016e6d78f51a3a1c362745931ca40b24f71cba2903dbfe5a6d392a9189127d83701",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"", "",
"P2PK with too much R padding but no STRICTENC" "P2PK with too much R padding but no DERSIG"
], ],
[ [
"0x48 0x304502206d01de7c2a40ac2bb1231ed97f3890a1782f421d4c28b97166deff317990288f0221005e720213b089355be2cf785d81a82c59307d30e1624f450ed9ca1ebbc11cca6d01", "0x48 0x304502202323d56f293842b544cacedd06baafb999196dfa1c2975314848c158ac606655022100514bd98186b8a3a1cc87f4aff76aed797781389f13f50d87bf95b2df6e488fcc01",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"", "",
"P2PK with too much S padding but no STRICTENC" "P2PK with too much S padding but no DERSIG"
], ],
[ [
"0x47 0x30440220f3d8889602147d60d26c1d3b21b8db183eac02bf6d2fec1424c0ef377ca6fd7b02202bae8bfe39d00a432d4538a592e338b0ffc44c17d4b7056043d55063cf91f5ef01", "0x47 0x30440220d31c24bb6c08a496e7698a08fd41975115d7b55bfaa31cb2d573e09481e59a6702206a691239996434076b78a4e1cf46fc8e993b468a9c77fb1832186aa8040a61a201",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"", "",
"P2PK with too little R padding but no STRICTENC" "P2PK with too little R padding but no DERSIG"
],
[
"0x47 0x30440220007c2cc7aef1801c2937447703c87ef2a3744209ad98da2abadd4ba8bb2e3ea00220503a275582c9f9e9ff30260c81b7f64b8b696f22105605cc8241fb76a797316201",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"",
"P2PK NOT with bad sig with too much R padding but no DERSIG"
], ],
[ [
"0x48 0x3045022021bf9184d94f208ac9f4757ebca9b1cbebf008cfc244fe5be1360b1b9aba0e92022100e55074f72f3a1bfddf2ea4ea7ba984f78822e136fe04c8f9c1363238e0233bd801", "0x48 0x3045022021bf9184d94f208ac9f4757ebca9b1cbebf008cfc244fe5be1360b1b9aba0e92022100e55074f72f3a1bfddf2ea4ea7ba984f78822e136fe04c8f9c1363238e0233bd801",
@ -596,10 +602,40 @@ nSequences are max.
"P2PK with high S but no LOW_S" "P2PK with high S but no LOW_S"
], ],
[ [
"0x48 0x304502205c3e81aaf2aad0673f349035b180eba783eba7797af91c979920dea6b17a16d6022100d1d46825c68da1b325f320a3503dad27bb818227f64a38d153554bfd360c0e5301", "0x47 0x304402202163bc732c21b7de0251297d3c6c2ece182782e85fc5e19d6036f1130a79051e022033827811634924ebba68767537d78dd7bd9109ae2a89a60587927abdc25eb06401",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"LOW_S", "",
"P2PK with high S but no STRICTENC" "P2PK with hybrid pubkey but no STRICTENC"
],
[
"0x47 0x3044022078033e4227aa05ded69d8da579966578e230d8a7fb44d5f1a0620c3853c24f78022006a2e3f4d872ac8dfdc529110aa37301d65a76255a4b6cce2992adacd4d2c4e201",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"STRICTENC",
"P2PK NOT with hybrid pubkey"
],
[
"0x47 0x3044022078d6c447887e88dcbe1bc5b613645280df6f4e5935648bc226e9d91da71b3216022047d6b7ef0949b228fc1b359afb8d50500268711354298217b983c26970790c7601",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"",
"P2PK NOT with invalid hybrid pubkey but no STRICTENC"
],
[
"0x47 0x304402207592427de20e315d644839754f2a5cca5b978b983a15e6da82109ede01722baa022032ceaf78590faa3f7743821e1b47b897ed1a57f6ee1c8a7519d23774d8de3c4401",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"STRICTENC",
"P2PK NOT with invalid hybrid pubkey"
],
[
"0x47 0x304402204649e9517ef0377a8f8270bd423053fd98ddff62d74ea553e9579558abbb75e4022044a2b2344469c12e35ed898987711272b634733dd0f5e051288eceb04bd4669e05",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"",
"P2PK with undefined hashtype but no STRICTENC"
],
[
"0x47 0x304402207f1cf1866a2df0bb4b8d84d0ade72aa3abb6aaab0639d608b23d9e10ead0c48202203caa97f22c3439443eea4b89f7f6729854df0f567a8184d6ecc6e8b6c68c3e9d05",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
"",
"P2PK NOT with invalid sig and undefined hashtype but no STRICTENC"
], ],
[ [
"0x01 0x01 0x47 0x3044022046ce33d1771b0127dd4c4cef8fdc3218ebdfa60e3793ed700292d8ebd93fb1f402201029d47a414db83e96e31443c2d8b552f971469c4800f5eff7df2f0648521aed01 0x47 0x304402205c53911ad55b054920043962bbda98cf6e57e2db1cd5611138251490baabaa8702201dc80dfceae6007e7772dc13ff6e7ca66a983cb017fe5d46d30118462d83bcf801 0x47 0x304402201937e44a4ec12364f9d32f9d25e7ecbc68aee9ef90069af80efef4c05f6ace9602206c515101c00c75710b32ff7ff8dbaf7c9a0be6e86ed14a0755b47626604f31fd01", "0x01 0x01 0x47 0x3044022046ce33d1771b0127dd4c4cef8fdc3218ebdfa60e3793ed700292d8ebd93fb1f402201029d47a414db83e96e31443c2d8b552f971469c4800f5eff7df2f0648521aed01 0x47 0x304402205c53911ad55b054920043962bbda98cf6e57e2db1cd5611138251490baabaa8702201dc80dfceae6007e7772dc13ff6e7ca66a983cb017fe5d46d30118462d83bcf801 0x47 0x304402201937e44a4ec12364f9d32f9d25e7ecbc68aee9ef90069af80efef4c05f6ace9602206c515101c00c75710b32ff7ff8dbaf7c9a0be6e86ed14a0755b47626604f31fd01",
@ -607,6 +643,12 @@ nSequences are max.
"", "",
"3-of-3 with nonzero dummy but no NULLDUMMY" "3-of-3 with nonzero dummy but no NULLDUMMY"
], ],
[
"0x01 0x01 0x47 0x30440220195038dbc6b2ae1199f86a6777824f7c5149789d85f655a3534a4422b8fba38c02204df9db87d2eb9fe06edc66870d9ac4c9ce673459f9d43cee0347ce4ffb02ee5a01 0x47 0x3044022010a45f30c6fa97a186eba9e6b595ab87d3dfcbf05dcaf1f1b8e3e7bf39515bb802203474e78d3d372e5f5c0f8c257ce8300c4bb8f37c51d4a894e11a91b5817da6ed01 0x47 0x30440220039cffd8e39850f95112662b1220b14b3c0d3d8a2772e13c947bfbf96345a64e02204154bfa77e2c0134d5434353bed82141e5da1cc479954aa288d5f0671480a04b01",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
"",
"3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY"
],
["The End"] ["The End"]
] ]

72
src/test/script_tests.cpp

@ -242,8 +242,9 @@ public:
return *this; return *this;
} }
Array GetJSON() const Array GetJSON()
{ {
DoPush();
Array array; Array array;
array.push_back(FormatScript(spendTx.vin[0].scriptSig)); array.push_back(FormatScript(spendTx.vin[0].scriptSig));
array.push_back(FormatScript(creditTx.vout[0].scriptPubKey)); array.push_back(FormatScript(creditTx.vout[0].scriptPubKey));
@ -319,40 +320,87 @@ BOOST_AUTO_TEST_CASE(script_build)
).Num(0).PushSig(keys.key1).Num(0).PushRedeem()); ).Num(0).PushSig(keys.key1).Num(0).PushRedeem());
good.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, good.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG,
"P2PK with too much R padding but no STRICTENC", 0 "P2PK with too much R padding but no DERSIG", 0
).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000")); ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
bad.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, bad.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG,
"P2PK with too much R padding", SCRIPT_VERIFY_STRICTENC "P2PK with too much R padding", SCRIPT_VERIFY_DERSIG
).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000")); ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
good.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, good.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG,
"P2PK with too much S padding but no STRICTENC", 0 "P2PK with too much S padding but no DERSIG", 0
).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100")); ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100"));
bad.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, bad.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG,
"P2PK with too much S padding", SCRIPT_VERIFY_STRICTENC "P2PK with too much S padding", SCRIPT_VERIFY_DERSIG
).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100")); ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100"));
good.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, good.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG,
"P2PK with too little R padding but no STRICTENC", 0 "P2PK with too little R padding but no DERSIG", 0
).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220")); ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
bad.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, bad.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG,
"P2PK with too little R padding", SCRIPT_VERIFY_STRICTENC "P2PK with too little R padding", SCRIPT_VERIFY_DERSIG
).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220")); ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
good.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG << OP_NOT,
"P2PK NOT with bad sig with too much R padding but no DERSIG", 0
).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10));
bad.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG << OP_NOT,
"P2PK NOT with bad sig with too much R padding", SCRIPT_VERIFY_DERSIG
).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10));
bad.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG << OP_NOT,
"P2PK NOT with too much R padding but no DERSIG", 0
).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
bad.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG << OP_NOT,
"P2PK NOT with too much R padding", SCRIPT_VERIFY_DERSIG
).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
good.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG, good.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG,
"P2PK with high S but no LOW_S", SCRIPT_VERIFY_STRICTENC "P2PK with high S but no LOW_S", 0
).PushSig(keys.key2, SIGHASH_ALL, 32, 33));
good.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG,
"P2PK with high S but no STRICTENC", SCRIPT_VERIFY_LOW_S
).PushSig(keys.key2, SIGHASH_ALL, 32, 33)); ).PushSig(keys.key2, SIGHASH_ALL, 32, 33));
bad.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG, bad.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG,
"P2PK with high S", SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC "P2PK with high S", SCRIPT_VERIFY_LOW_S
).PushSig(keys.key2, SIGHASH_ALL, 32, 33)); ).PushSig(keys.key2, SIGHASH_ALL, 32, 33));
good.push_back(TestBuilder(CScript() << keys.pubkey0H << OP_CHECKSIG,
"P2PK with hybrid pubkey but no STRICTENC", 0
).PushSig(keys.key0, SIGHASH_ALL));
bad.push_back(TestBuilder(CScript() << keys.pubkey0H << OP_CHECKSIG,
"P2PK with hybrid pubkey", SCRIPT_VERIFY_STRICTENC
).PushSig(keys.key0, SIGHASH_ALL));
bad.push_back(TestBuilder(CScript() << keys.pubkey0H << OP_CHECKSIG << OP_NOT,
"P2PK NOT with hybrid pubkey but no STRICTENC", 0
).PushSig(keys.key0, SIGHASH_ALL));
good.push_back(TestBuilder(CScript() << keys.pubkey0H << OP_CHECKSIG << OP_NOT,
"P2PK NOT with hybrid pubkey", SCRIPT_VERIFY_STRICTENC
).PushSig(keys.key0, SIGHASH_ALL));
good.push_back(TestBuilder(CScript() << keys.pubkey0H << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid hybrid pubkey but no STRICTENC", 0
).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10));
good.push_back(TestBuilder(CScript() << keys.pubkey0H << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid hybrid pubkey", SCRIPT_VERIFY_STRICTENC
).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10));
good.push_back(TestBuilder(CScript() << keys.pubkey1 << OP_CHECKSIG,
"P2PK with undefined hashtype but no STRICTENC", 0
).PushSig(keys.key1, 5));
bad.push_back(TestBuilder(CScript() << keys.pubkey1 << OP_CHECKSIG,
"P2PK with undefined hashtype", SCRIPT_VERIFY_STRICTENC
).PushSig(keys.key1, 5));
good.push_back(TestBuilder(CScript() << keys.pubkey1 << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid sig and undefined hashtype but no STRICTENC", 0
).PushSig(keys.key1, 5).DamagePush(10));
bad.push_back(TestBuilder(CScript() << keys.pubkey1 << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid sig and undefined hashtype", SCRIPT_VERIFY_STRICTENC
).PushSig(keys.key1, 5).DamagePush(10));
good.push_back(TestBuilder(CScript() << OP_3 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG, good.push_back(TestBuilder(CScript() << OP_3 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG,
"3-of-3 with nonzero dummy but no NULLDUMMY", 0 "3-of-3 with nonzero dummy but no NULLDUMMY", 0
).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2)); ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2));
bad.push_back(TestBuilder(CScript() << OP_3 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG, bad.push_back(TestBuilder(CScript() << OP_3 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG,
"3-of-3 with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY "3-of-3 with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY
).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2)); ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2));
good.push_back(TestBuilder(CScript() << OP_3 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG << OP_NOT,
"3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY", 0
).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10));
bad.push_back(TestBuilder(CScript() << OP_3 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG << OP_NOT,
"3-of-3 NOT with invalid sig with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY
).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10));
std::map<std::string, Array> tests_good; std::map<std::string, Array> tests_good;
std::map<std::string, Array> tests_bad; std::map<std::string, Array> tests_bad;

1
src/test/transaction_tests.cpp

@ -31,6 +31,7 @@ static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of
(string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE) (string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE)
(string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH) (string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH)
(string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC) (string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC)
(string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG)
(string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S) (string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S)
(string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY); (string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY);

Loading…
Cancel
Save