Changeset View
Standalone View
src/test/script_tests.cpp
Show First 20 Lines • Show All 228 Lines • ▼ Show 20 Lines | KeyData() { | ||||
key2.Set(vchKey2, vchKey2 + 32, false); | key2.Set(vchKey2, vchKey2 + 32, false); | ||||
key2C.Set(vchKey2, vchKey2 + 32, true); | key2C.Set(vchKey2, vchKey2 + 32, true); | ||||
pubkey2 = key2.GetPubKey(); | pubkey2 = key2.GetPubKey(); | ||||
pubkey2C = key2C.GetPubKey(); | pubkey2C = key2C.GetPubKey(); | ||||
} | } | ||||
}; | }; | ||||
#include <secp256k1.h> | |||||
deadalnix: Never include in the middle of a file | |||||
extern "C" { | |||||
deadalnixUnsubmitted Done Inline Actionsyou don't need extern C deadalnix: you don't need extern C | |||||
/* | |||||
* nonce function that always returns | |||||
* k = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1. | |||||
* this nonce is special since kG is the point: | |||||
* x = 0x00000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63 | |||||
* y = 0xc0c686408d517dfd67c2367651380d00d126e4229631fd03f8ff35eef1a61e3c | |||||
* This lets us make really short ECDSA signatures (~60 bytes) which can be | |||||
* beefed up to ~64 bytes by padding garbage at the end. | |||||
*/ | |||||
static int nonce_function_half(unsigned char *nonce32, | |||||
const unsigned char *msg32, | |||||
const unsigned char *key32, | |||||
const unsigned char *algo16, void *data, | |||||
unsigned int counter) { | |||||
unsigned char noncehalf[32] = { | |||||
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0x57, 0x6e, 0x73, 0x57, 0xa4, | |||||
0x50, 0x1d, 0xdf, 0xe9, 0x2f, 0x46, 0x68, 0x1b, 0x20, 0xa1}; | |||||
memcpy(nonce32, noncehalf, 32); | |||||
return 1; | |||||
} | |||||
} | |||||
// create short ECDSA signature (<=60 bytes) using above nonce trick | |||||
// (based on CKey::SignECDSA) | |||||
bool SignECDSA_short(const CKey &key, const uint256 &hash, | |||||
std::vector<uint8_t> &vchSig) { | |||||
vchSig.resize(72); | |||||
size_t nSigLen = 72; | |||||
secp256k1_ecdsa_signature sig; | |||||
secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); | |||||
int ret = secp256k1_ecdsa_sign(ctx, &sig, hash.begin(), key.begin(), | |||||
nonce_function_half, nullptr); | |||||
secp256k1_context_destroy(ctx); | |||||
assert(ret); | |||||
secp256k1_ecdsa_signature_serialize_der(ctx, (uint8_t *)&vchSig[0], | |||||
&nSigLen, &sig); | |||||
assert(nSigLen <= 60); | |||||
vchSig.resize(nSigLen); | |||||
return true; | |||||
} | |||||
deadalnixUnsubmitted Done Inline ActionsI find it a bit unfortunate that this require to be added. This create a lot more dependencies. I don't really think it is require as you can do CHECKSIG NOT on a signature that is properly encoded as long as you odn't pass the NULLFAIL flag. deadalnix: I find it a bit unfortunate that this require to be added. This create a lot more dependencies. | |||||
markblundebergAuthorUnsubmitted Done Inline ActionsYes, the previous sigencoding diff added some tests to script_tests.json that did this sort of thing. These can be expanded if needed. markblundeberg: Yes, the previous sigencoding diff added some tests to script_tests.json that did this sort of… | |||||
class TestBuilder { | class TestBuilder { | ||||
private: | private: | ||||
//! Actually executed script | //! Actually executed script | ||||
CScript script; | CScript script; | ||||
//! The P2SH redeemscript | //! The P2SH redeemscript | ||||
CScript redeemscript; | CScript redeemscript; | ||||
CTransactionRef creditTx; | CTransactionRef creditTx; | ||||
CMutableTransaction spendTx; | CMutableTransaction spendTx; | ||||
Show All 16 Lines | void DoPush(const std::vector<uint8_t> &data) { | ||||
push = data; | push = data; | ||||
havePush = true; | havePush = true; | ||||
} | } | ||||
std::vector<uint8_t> DoSign(const CKey &key, const uint256 &hash, | std::vector<uint8_t> DoSign(const CKey &key, const uint256 &hash, | ||||
unsigned int lenR = 32, | unsigned int lenR = 32, | ||||
unsigned int lenS = 32) const { | unsigned int lenS = 32) const { | ||||
std::vector<uint8_t> vchSig, r, s; | std::vector<uint8_t> vchSig, r, s; | ||||
if (lenR == 21) { | |||||
// use above hack to make valid short R | |||||
SignECDSA_short(key, hash, vchSig); | |||||
// pad it to be length 6 + lenR + lenS -- this leaves garbage at | |||||
// end but ecdsa_signature_parse_der_lax doesn't care. | |||||
vchSig.resize(6 + lenR + lenS); | |||||
return vchSig; | |||||
} | |||||
uint32_t iter = 0; | uint32_t iter = 0; | ||||
do { | do { | ||||
key.SignECDSA(hash, vchSig, iter++); | key.SignECDSA(hash, vchSig, iter++); | ||||
if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) { | if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) { | ||||
NegateSignatureS(vchSig); | NegateSignatureS(vchSig); | ||||
} | } | ||||
r = std::vector<uint8_t>(vchSig.begin() + 4, | r = std::vector<uint8_t>(vchSig.begin() + 4, | ||||
vchSig.begin() + 4 + vchSig[3]); | vchSig.begin() + 4 + vchSig[3]); | ||||
s = std::vector<uint8_t>(vchSig.begin() + 6 + vchSig[3], | s = std::vector<uint8_t>(vchSig.begin() + 6 + vchSig[3], | ||||
vchSig.begin() + 6 + vchSig[3] + | vchSig.begin() + 6 + vchSig[3] + | ||||
vchSig[5 + vchSig[3]]); | vchSig[5 + vchSig[3]]); | ||||
} while (lenR != r.size() || lenS != s.size()); | } while (lenR != r.size() || lenS != s.size()); | ||||
return vchSig; | return vchSig; | ||||
} | } | ||||
std::vector<uint8_t> DoSignSchnorr(const CKey &key, | |||||
const uint256 &hash) const { | |||||
std::vector<uint8_t> vchSig; | |||||
// no need to iterate for size; schnorrs are always same size. | |||||
key.SignSchnorr(hash, vchSig); | |||||
return vchSig; | |||||
} | |||||
public: | public: | ||||
TestBuilder(const CScript &script_, const std::string &comment_, | TestBuilder(const CScript &script_, const std::string &comment_, | ||||
uint32_t flags_, bool P2SH = false, | uint32_t flags_, bool P2SH = false, | ||||
Amount nValue_ = Amount::zero()) | Amount nValue_ = Amount::zero()) | ||||
: script(script_), havePush(false), comment(comment_), flags(flags_), | : script(script_), havePush(false), comment(comment_), flags(flags_), | ||||
scriptError(SCRIPT_ERR_OK), nValue(nValue_) { | scriptError(SCRIPT_ERR_OK), nValue(nValue_) { | ||||
CScript scriptPubKey = script; | CScript scriptPubKey = script; | ||||
if (P2SH) { | if (P2SH) { | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | TestBuilder &PushSig(const CKey &key, | ||||
uint256 hash = SignatureHash(script, CTransaction(spendTx), 0, | uint256 hash = SignatureHash(script, CTransaction(spendTx), 0, | ||||
sigHashType, amount, nullptr, sigFlags); | sigHashType, amount, nullptr, sigFlags); | ||||
std::vector<uint8_t> vchSig = DoSign(key, hash, lenR, lenS); | std::vector<uint8_t> vchSig = DoSign(key, hash, lenR, lenS); | ||||
vchSig.push_back(static_cast<uint8_t>(sigHashType.getRawSigHashType())); | vchSig.push_back(static_cast<uint8_t>(sigHashType.getRawSigHashType())); | ||||
DoPush(vchSig); | DoPush(vchSig); | ||||
return *this; | return *this; | ||||
} | } | ||||
TestBuilder & | |||||
PushSigSchnorr(const CKey &key, SigHashType sigHashType = SigHashType(), | |||||
Amount amount = Amount::zero(), | |||||
uint32_t sigFlags = SCRIPT_ENABLE_SIGHASH_FORKID) { | |||||
uint256 hash = SignatureHash(script, CTransaction(spendTx), 0, | |||||
sigHashType, amount, nullptr, sigFlags); | |||||
std::vector<uint8_t> vchSig = DoSignSchnorr(key, hash); | |||||
vchSig.push_back(static_cast<uint8_t>(sigHashType.getRawSigHashType())); | |||||
DoPush(vchSig); | |||||
return *this; | |||||
} | |||||
TestBuilder &PushDataSig(const CKey &key, const std::vector<uint8_t> &data, | TestBuilder &PushDataSig(const CKey &key, const std::vector<uint8_t> &data, | ||||
unsigned int lenR = 32, unsigned int lenS = 32) { | unsigned int lenR = 32, unsigned int lenS = 32) { | ||||
std::vector<uint8_t> vchHash(32); | std::vector<uint8_t> vchHash(32); | ||||
CSHA256().Write(data.data(), data.size()).Finalize(vchHash.data()); | CSHA256().Write(data.data(), data.size()).Finalize(vchHash.data()); | ||||
DoPush(DoSign(key, uint256(vchHash), lenR, lenS)); | DoPush(DoSign(key, uint256(vchHash), lenR, lenS)); | ||||
return *this; | return *this; | ||||
} | } | ||||
TestBuilder &PushDataSigSchnorr(const CKey &key, | |||||
const std::vector<uint8_t> &data) { | |||||
std::vector<uint8_t> vchHash(32); | |||||
CSHA256().Write(data.data(), data.size()).Finalize(vchHash.data()); | |||||
DoPush(DoSignSchnorr(key, uint256(vchHash))); | |||||
return *this; | |||||
} | |||||
TestBuilder &Push(const CPubKey &pubkey) { | TestBuilder &Push(const CPubKey &pubkey) { | ||||
DoPush(std::vector<uint8_t>(pubkey.begin(), pubkey.end())); | DoPush(std::vector<uint8_t>(pubkey.begin(), pubkey.end())); | ||||
return *this; | return *this; | ||||
} | } | ||||
TestBuilder &PushRedeem() { | TestBuilder &PushRedeem() { | ||||
DoPush(std::vector<uint8_t>(redeemscript.begin(), redeemscript.end())); | DoPush(std::vector<uint8_t>(redeemscript.begin(), redeemscript.end())); | ||||
return *this; | return *this; | ||||
▲ Show 20 Lines • Show All 1,161 Lines • ▼ Show 20 Lines | tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) | ||||
<< OP_CHECKDATASIGVERIFY << OP_TRUE, | << OP_CHECKDATASIGVERIFY << OP_TRUE, | ||||
"CHECKDATASIGVERIFY with invalid hybrid pubkey", | "CHECKDATASIGVERIFY with invalid hybrid pubkey", | ||||
checkdatasigschnorrflags) | checkdatasigschnorrflags) | ||||
.PushDataSig(keys.key0, {}) | .PushDataSig(keys.key0, {}) | ||||
.DamagePush(10) | .DamagePush(10) | ||||
.Num(0) | .Num(0) | ||||
.ScriptError(SCRIPT_ERR_PUBKEYTYPE)); | .ScriptError(SCRIPT_ERR_PUBKEYTYPE)); | ||||
/* | |||||
* Tests that have Schnorr signatures in them: | |||||
*/ | |||||
deadalnixUnsubmitted Done Inline ActionsOther groups use // deadalnix: Other groups use // | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | |||||
"Schnorr P2PK", SCRIPT_ENABLE_SCHNORR) | |||||
.PushSigSchnorr(keys.key0)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | |||||
"Schnorr P2PK disabled", 0) | |||||
.PushSigSchnorr(keys.key0) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | |||||
"Schnorr P2PK disabled with STRICTENC", | |||||
SCRIPT_VERIFY_STRICTENC) | |||||
.PushSigSchnorr(keys.key0) | |||||
.ScriptError(SCRIPT_ERR_SIG_DER)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | |||||
"Schnorr P2PK, bad sig", SCRIPT_ENABLE_SCHNORR) | |||||
.PushSigSchnorr(keys.key0) | |||||
.DamagePush(10) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
deadalnixUnsubmitted Done Inline ActionsCheck that it works with another key + that it fails with mismatched public/private keys + check that it passes with strict encoding+schnorr. deadalnix: Check that it works with another key + that it fails with mismatched public/private keys +… | |||||
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 | |||||
<< ToByteVector(keys.pubkey1C.GetID()) | |||||
<< OP_EQUALVERIFY << OP_CHECKSIG, | |||||
"Schnorr P2PKH", SCRIPT_ENABLE_SCHNORR) | |||||
.PushSigSchnorr(keys.key1) | |||||
.Push(keys.pubkey1C)); | |||||
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 | |||||
<< ToByteVector(keys.pubkey1C.GetID()) | |||||
<< OP_EQUALVERIFY << OP_CHECKSIG, | |||||
"Schnorr P2PKH disabled", 0) | |||||
.PushSigSchnorr(keys.key1) | |||||
.Push(keys.pubkey1C) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 | |||||
<< ToByteVector(keys.pubkey2C.GetID()) | |||||
<< OP_EQUALVERIFY << OP_CHECKSIG, | |||||
"Schnorr P2PKH, bad pubkey", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.PushSigSchnorr(keys.key2) | |||||
.Push(keys.pubkey2C) | |||||
.DamagePush(5) | |||||
.ScriptError(SCRIPT_ERR_EQUALVERIFY)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, | |||||
"Schnorr P2SH(P2PK)", | |||||
SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SCHNORR, true) | |||||
.PushSigSchnorr(keys.key0) | |||||
.PushRedeem()); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, | |||||
"Schnorr P2SH(P2PK) disabled", SCRIPT_VERIFY_P2SH, true) | |||||
.PushSigSchnorr(keys.key0) | |||||
.PushRedeem() | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, | |||||
"Schnorr P2SH(P2PK), bad redeemscript", | |||||
SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SCHNORR, true) | |||||
.PushSigSchnorr(keys.key0) | |||||
.PushRedeem() | |||||
.DamagePush(10) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
deadalnixUnsubmitted Done Inline ActionsThis last one seems to be testing P2SH. It's not really necessary. It doesn't test anything related to schnorr. deadalnix: This last one seems to be testing P2SH. It's not really necessary. It doesn't test anything… | |||||
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 | |||||
<< ToByteVector(keys.pubkey0.GetID()) | |||||
<< OP_EQUALVERIFY << OP_CHECKSIG, | |||||
"Schnorr P2SH(P2PKH)", | |||||
SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SCHNORR, | |||||
true) | |||||
.PushSigSchnorr(keys.key0) | |||||
.Push(keys.pubkey0) | |||||
.PushRedeem()); | |||||
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 | |||||
<< ToByteVector(keys.pubkey0.GetID()) | |||||
<< OP_EQUALVERIFY << OP_CHECKSIG, | |||||
"Schnorr P2SH(P2PKH) disabled", | |||||
SCRIPT_VERIFY_P2SH, true) | |||||
.PushSigSchnorr(keys.key0) | |||||
.Push(keys.pubkey0) | |||||
.PushRedeem() | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) | |||||
<< ToByteVector(keys.pubkey1C) | |||||
<< ToByteVector(keys.pubkey2C) << OP_3 | |||||
<< OP_CHECKMULTISIG, | |||||
"Schnorr 3-of-3 illegal w/out schnorr flag", 0) | |||||
.Num(0) | |||||
.PushSigSchnorr(keys.key0) | |||||
.PushSigSchnorr(keys.key1) | |||||
.PushSigSchnorr(keys.key2) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) | |||||
<< ToByteVector(keys.pubkey1C) | |||||
<< ToByteVector(keys.pubkey2C) << OP_3 | |||||
<< OP_CHECKMULTISIG, | |||||
"Schnorr 3-of-3 illegal", SCRIPT_ENABLE_SCHNORR) | |||||
.Num(0) | |||||
.PushSigSchnorr(keys.key0) | |||||
.PushSigSchnorr(keys.key1) | |||||
.PushSigSchnorr(keys.key2) | |||||
.ScriptError(SCRIPT_ERR_SIG_BADLENGTH)); | |||||
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) | |||||
<< ToByteVector(keys.pubkey1C) | |||||
<< ToByteVector(keys.pubkey2C) << OP_3 | |||||
<< OP_CHECKMULTISIG, | |||||
"Schnorr-mixed 3-of-3 illegal", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.Num(0) | |||||
.PushSig(keys.key0) | |||||
.PushSig(keys.key1) | |||||
.PushSigSchnorr(keys.key2) | |||||
.ScriptError(SCRIPT_ERR_SIG_BADLENGTH)); | |||||
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) | |||||
<< ToByteVector(keys.pubkey1C) | |||||
<< ToByteVector(keys.pubkey2C) << OP_3 | |||||
<< OP_CHECKMULTISIG, | |||||
"Schnorr P2SH(2-of-3) illegal", | |||||
SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SCHNORR, | |||||
true) | |||||
.Num(0) | |||||
.PushSigSchnorr(keys.key1) | |||||
.PushSigSchnorr(keys.key2) | |||||
.PushRedeem() | |||||
.ScriptError(SCRIPT_ERR_SIG_BADLENGTH)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"ECDSA 1-of-1", 0) | |||||
.Num(0) | |||||
.PushSig(keys.key1)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"ECDSA 1-of-1 with schnorr flag", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.Num(0) | |||||
.PushSig(keys.key1)); | |||||
deadalnixUnsubmitted Done Inline ActionsYou should have 3 time the same pattern here: Without some order in there, it's impossible to figure out if you covered all bases. deadalnix: You should have 3 time the same pattern here:
1/ classic ECDSA with no… | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"Schnorr 1-of-1 illegal", SCRIPT_ENABLE_SCHNORR) | |||||
deadalnixUnsubmitted Done Inline ActionsPlease use more descriptive description. illegal doesn't help at all figuring out what this is about. It gets worse if you consider this not in isolation but in association with all the other tests that already exist. deadalnix: Please use more descriptive description. illegal doesn't help at all figuring out what this is… | |||||
.Num(0) | |||||
.PushSigSchnorr(keys.key1) | |||||
.ScriptError(SCRIPT_ERR_SIG_BADLENGTH)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"Schnorr 1-of-1 illegal w/out schnorr flag", 0) | |||||
.Num(0) | |||||
.PushSigSchnorr(keys.key1) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
deadalnixUnsubmitted Done Inline ActionsYou reverse the order of the tests compared to other tests cases. This is confusing. This end up being the test above without the schnorr flag, which is not clear from anything. deadalnix: You reverse the order of the tests compared to other tests cases. This is confusing. This end… | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"Schnorr 1-of-1 illegal with STRICTENC", | |||||
SCRIPT_ENABLE_SCHNORR | SCRIPT_VERIFY_STRICTENC) | |||||
.Num(0) | |||||
.PushSigSchnorr(keys.key1) | |||||
.ScriptError(SCRIPT_ERR_SIG_BADLENGTH)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << OP_1 | |||||
<< OP_CHECKMULTISIG, | |||||
"Schnorr 1-of-1 illegal with STRICTENC and no schnorrflag", | |||||
SCRIPT_VERIFY_STRICTENC) | |||||
.Num(0) | |||||
.PushSigSchnorr(keys.key1) | |||||
.ScriptError(SCRIPT_ERR_SIG_DER)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG, | |||||
"Schnorr P2PK with hybrid pubkey but no STRICTENC", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.PushSigSchnorr(keys.key0)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG, | |||||
"Schnorr P2PK with hybrid pubkey", | |||||
SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) | |||||
.PushSigSchnorr(keys.key0, SigHashType()) | |||||
.ScriptError(SCRIPT_ERR_PUBKEYTYPE)); | |||||
tests.push_back( | |||||
TestBuilder( | |||||
CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, | |||||
"Schnorr P2PK NOT with invalid hybrid pubkey but no STRICTENC", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.PushSigSchnorr(keys.key0) | |||||
.DamagePush(10)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, | |||||
"Schnorr P2PK with undefined hashtype", | |||||
SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) | |||||
.PushSigSchnorr(keys.key1, SigHashType(5)) | |||||
.ScriptError(SCRIPT_ERR_SIG_HASHTYPE)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << OP_DUP << OP_HASH160 | |||||
<< ToByteVector(keys.pubkey0.GetID()) | |||||
<< OP_EQUALVERIFY << OP_CHECKSIG, | |||||
"Schnorr P2PKH with invalid sighashtype", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.PushSigSchnorr(keys.key0, SigHashType(0x21), Amount::zero(), 0) | |||||
.Push(keys.pubkey0)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << OP_DUP << OP_HASH160 | |||||
<< ToByteVector(keys.pubkey0.GetID()) | |||||
<< OP_EQUALVERIFY << OP_CHECKSIG, | |||||
"Schnorr P2PKH with invalid sighashtype and STRICTENC", | |||||
SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) | |||||
.PushSigSchnorr(keys.key0, SigHashType(0x21), Amount::zero(), | |||||
SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) | |||||
.Push(keys.pubkey0) | |||||
// Should fail for STRICTENC | |||||
.ScriptError(SCRIPT_ERR_SIG_HASHTYPE)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG, | |||||
"Schnorr Standard CHECKDATASIG", checkdatasigschnorrflags) | |||||
.PushDataSigSchnorr(keys.key1, {}) | |||||
.Num(0)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG, | |||||
"Schnorr Standard CHECKDATASIG disabled", checkdatasigflags) | |||||
.PushDataSigSchnorr(keys.key1, {}) | |||||
.Num(0) | |||||
.ScriptError(SCRIPT_ERR_SIG_DER)); | |||||
tests.push_back( | |||||
TestBuilder( | |||||
CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG, | |||||
"Schnorr Standard CHECKDATASIG disabled but no NULLFAIL/STRICTENC", | |||||
SCRIPT_ENABLE_CHECKDATASIG) | |||||
.PushDataSigSchnorr(keys.key1, {}) | |||||
.Num(0) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG, | |||||
"Schnorr CHECKDATASIG with hybrid pubkey but no STRICTENC", | |||||
checkdatasigschnorrflags & ~SCRIPT_VERIFY_STRICTENC) | |||||
.PushDataSigSchnorr(keys.key0, {}) | |||||
.Num(0)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG, | |||||
"Schnorr CHECKDATASIG with hybrid pubkey", | |||||
checkdatasigschnorrflags) | |||||
.PushDataSigSchnorr(keys.key0, {}) | |||||
.Num(0) | |||||
.ScriptError(SCRIPT_ERR_PUBKEYTYPE)); | |||||
tests.push_back( | |||||
TestBuilder( | |||||
CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG | |||||
<< OP_NOT, | |||||
"Schnorr CHECKDATASIG with invalid hybrid pubkey but no STRICTENC", | |||||
SCRIPT_ENABLE_CHECKDATASIG | SCRIPT_ENABLE_SCHNORR) | |||||
.PushDataSigSchnorr(keys.key0, {}) | |||||
.DamagePush(10) | |||||
.Num(0)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG, | |||||
"Schnorr CHECKDATASIG with invalid hybrid pubkey", | |||||
checkdatasigschnorrflags) | |||||
.PushDataSigSchnorr(keys.key0, {}) | |||||
.DamagePush(10) | |||||
.Num(0) | |||||
.ScriptError(SCRIPT_ERR_PUBKEYTYPE)); | |||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) | |||||
<< OP_CHECKDATASIGVERIFY << OP_TRUE, | |||||
"Schnorr Standard CHECKDATASIGVERIFY", | |||||
checkdatasigschnorrflags) | |||||
.PushDataSigSchnorr(keys.key1, {}) | |||||
.Num(0)); | |||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) | |||||
<< OP_CHECKDATASIGVERIFY, | |||||
"Schnorr Standard CHECKDATASIGVERIFY disabled", | |||||
checkdatasigflags) | |||||
.PushDataSigSchnorr(keys.key1, {}) | |||||
.Num(0) | |||||
.ScriptError(SCRIPT_ERR_SIG_DER)); | |||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) | |||||
<< OP_CHECKDATASIGVERIFY, | |||||
"Schnorr Standard CHECKDATASIGVERIFY disabled " | |||||
"but no NULLFAIL/STRICTENC", | |||||
SCRIPT_ENABLE_CHECKDATASIG) | |||||
.PushDataSigSchnorr(keys.key1, {}) | |||||
.Num(0) | |||||
.ScriptError(SCRIPT_ERR_CHECKDATASIGVERIFY)); | |||||
tests.push_back( | |||||
TestBuilder( | |||||
CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIGVERIFY | |||||
<< OP_TRUE, | |||||
"Schnorr CHECKDATASIGVERIFY with hybrid pubkey but no STRICTENC", | |||||
checkdatasigschnorrflags & ~SCRIPT_VERIFY_STRICTENC) | |||||
.PushDataSigSchnorr(keys.key0, {}) | |||||
.Num(0)); | |||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) | |||||
<< OP_CHECKDATASIGVERIFY << OP_TRUE, | |||||
"Schnorr CHECKDATASIGVERIFY with hybrid pubkey", | |||||
checkdatasigschnorrflags) | |||||
.PushDataSigSchnorr(keys.key0, {}) | |||||
.Num(0) | |||||
.ScriptError(SCRIPT_ERR_PUBKEYTYPE)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) | |||||
<< OP_CHECKDATASIGVERIFY << OP_TRUE, | |||||
"Schnorr CHECKDATASIGVERIFY with invalid hybrid pubkey but " | |||||
"no STRICTENC", | |||||
SCRIPT_ENABLE_CHECKDATASIG | SCRIPT_ENABLE_SCHNORR) | |||||
.PushDataSigSchnorr(keys.key0, {}) | |||||
.DamagePush(10) | |||||
.Num(0) | |||||
.ScriptError(SCRIPT_ERR_CHECKDATASIGVERIFY)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) | |||||
<< OP_CHECKDATASIGVERIFY << OP_TRUE, | |||||
"Schnorr CHECKDATASIGVERIFY with invalid hybrid pubkey", | |||||
checkdatasigschnorrflags) | |||||
.PushDataSigSchnorr(keys.key0, {}) | |||||
.DamagePush(10) | |||||
.Num(0) | |||||
.ScriptError(SCRIPT_ERR_PUBKEYTYPE)); | |||||
// test putting valid short ECDSA sigs (same or close to schnorr length) | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | |||||
"64+1-byte ECDSA P2PK", 0) | |||||
.PushSig(keys.key0, SigHashType(), 21, 37)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | |||||
"64+1-byte ECDSA P2PK strict", SCRIPT_VERIFY_STRICTENC) | |||||
.PushSig(keys.key0, SigHashType(), 21, 37) | |||||
.ScriptError(SCRIPT_ERR_SIG_DER)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | |||||
"63+1-byte ECDSA P2PK with Schnorr flag", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.PushSig(keys.key0, SigHashType(), 21, 36)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | |||||
"64+1-byte ECDSA P2PK with Schnorr flag", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.PushSig(keys.key0, SigHashType(), 21, 37) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | |||||
"65+1-byte ECDSA P2PK with Schnorr flag", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.PushSig(keys.key0, SigHashType(), 21, 38)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | |||||
"64+1-byte ECDSA P2PK strict with Schnorr", | |||||
SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) | |||||
.PushSig(keys.key0, SigHashType(), 21, 37) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"63+1-byte ECDSA 1-of-1", 0) | |||||
.Num(0) | |||||
.PushSig(keys.key1, SigHashType(), 21, 36)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"64+1-byte ECDSA 1-of-1", 0) | |||||
.Num(0) | |||||
.PushSig(keys.key1, SigHashType(), 21, 37)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"65+1-byte ECDSA 1-of-1", 0) | |||||
.Num(0) | |||||
.PushSig(keys.key1, SigHashType(), 21, 38)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"63+1-byte ECDSA 1-of-1 with schnorr flag", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.Num(0) | |||||
.PushSig(keys.key1, SigHashType(), 21, 36)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"64+1-byte ECDSA 1-of-1 with schnorr flag", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.Num(0) | |||||
.PushSig(keys.key1, SigHashType(), 21, 37) | |||||
.ScriptError(SCRIPT_ERR_SIG_BADLENGTH)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"65+1-byte ECDSA 1-of-1 with schnorr flag", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.Num(0) | |||||
.PushSig(keys.key1, SigHashType(), 21, 38)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"64+1-byte ECDSA 1-of-1 strict", | |||||
SCRIPT_VERIFY_STRICTENC) | |||||
.Num(0) | |||||
.PushSig(keys.key1, SigHashType(), 21, 37) | |||||
.ScriptError(SCRIPT_ERR_SIG_DER)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << OP_1 | |||||
<< OP_CHECKMULTISIG, | |||||
"64+1-byte ECDSA 1-of-1 strict with schnorr flag", | |||||
SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) | |||||
.Num(0) | |||||
.PushSig(keys.key1, SigHashType(), 21, 37) | |||||
.ScriptError(SCRIPT_ERR_SIG_BADLENGTH)); | |||||
std::set<std::string> tests_set; | std::set<std::string> tests_set; | ||||
{ | { | ||||
UniValue json_tests = read_json(std::string( | UniValue json_tests = read_json(std::string( | ||||
json_tests::script_tests, | json_tests::script_tests, | ||||
json_tests::script_tests + sizeof(json_tests::script_tests))); | json_tests::script_tests + sizeof(json_tests::script_tests))); | ||||
for (unsigned int idx = 0; idx < json_tests.size(); idx++) { | for (unsigned int idx = 0; idx < json_tests.size(); idx++) { | ||||
▲ Show 20 Lines • Show All 755 Lines • Show Last 20 Lines |
Never include in the middle of a file