Changeset View
Changeset View
Standalone View
Standalone View
src/test/script_tests.cpp
Show First 20 Lines • Show All 227 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: This dependency addition is a bit unfortunate.
An alternative is to produce valid DER encoded… | |||||
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. | |||||
deadalnixUnsubmitted Not Done Inline ActionsPlease mention a source for this. It is a well know point G' on the curve such as 2*G' = G. deadalnix: Please mention a source for this. It is a well know point G' on the curve such as 2*G' = G. | |||||
*/ | |||||
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; | |||||
} | |||||
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: | |||||
*/ | |||||
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)); | |||||
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)); | |||||
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", SCRIPT_ENABLE_SCHNORR) | |||||
.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-mixed 3-of-3 illegal", | |||||
SCRIPT_ENABLE_SCHNORR) | |||||
.Num(0) | |||||
.PushSig(keys.key0) | |||||
.PushSig(keys.key1) | |||||
.PushSigSchnorr(keys.key2) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
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_EVAL_FALSE)); | |||||
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)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"Schnorr 1-of-1 illegal", SCRIPT_ENABLE_SCHNORR) | |||||
.Num(0) | |||||
.PushSigSchnorr(keys.key1) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) | |||||
<< OP_1 << OP_CHECKMULTISIG, | |||||
"Schnorr 1-of-1 illegal disabled", 0) | |||||
.Num(0) | |||||
.PushSigSchnorr(keys.key1) | |||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | |||||
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_DER)); | |||||
tests.push_back( | |||||
TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << OP_1 | |||||
<< OP_CHECKMULTISIG, | |||||
"Schnorr 1-of-1 illegal disabled with STRICTENC", | |||||
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)); | |||||
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_DER)); | |||||
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 |
This dependency addition is a bit unfortunate.
An alternative is to produce valid DER encoded signatures that do not check out. The interpreter should accept these as long as the NULLFAIL flag is not provided.