Implement replay protection using FORKID scheme

modeled off of the BCH and BTG implementations
with a few tweaks (forkid signing is ignored below fork height)
moved joinsplit signature verifications into ConnectBlock()
as it has now become height dependent
This commit is contained in:
jc 2018-02-18 20:12:57 -05:00
parent d6dc745a5f
commit ac0231d2ba
No known key found for this signature in database
GPG Key ID: E87FC0C8A375F3CF
19 changed files with 2312 additions and 2319 deletions

View File

@ -1019,30 +1019,39 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
if (txin.prevout.IsNull())
return state.DoS(10, error("CheckTransaction(): prevout is null"),
REJECT_INVALID, "bad-txns-prevout-null");
}
if (tx.vjoinsplit.size() > 0) {
// Empty output script.
CScript scriptCode;
uint256 dataToBeSigned;
try {
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL|SIGHASH_FORKID);
} catch (std::logic_error ex) {
return state.DoS(100, error("CheckTransaction(): error computing signature hash"),
REJECT_INVALID, "error-computing-signature-hash");
}
return true;
}
BOOST_STATIC_ASSERT(crypto_sign_PUBLICKEYBYTES == 32);
bool CheckJoinSplitSigs(const CTransaction& tx, CValidationState &state, const unsigned int flags)
{
if (tx.vjoinsplit.size() > 0) {
// Empty output script.
CScript scriptCode;
uint256 dataToBeSigned;
int hashtype = SIGHASH_ALL;
if(flags & SCRIPT_VERIFY_FORKID)
hashtype |= SIGHASH_FORKID;
// We rely on libsodium to check that the signature is canonical.
// https://github.com/jedisct1/libsodium/commit/62911edb7ff2275cccd74bf1c8aefcc4d76924e0
if (crypto_sign_verify_detached(&tx.joinSplitSig[0],
dataToBeSigned.begin(), 32,
tx.joinSplitPubKey.begin()
) != 0) {
try {
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, hashtype);
} catch (std::logic_error ex) {
return state.DoS(100, error("CheckTransaction(): error computing signature hash"),
REJECT_INVALID, "error-computing-signature-hash");
}
return state.DoS(100, error("CheckTransaction(): invalid joinsplit signature"),
REJECT_INVALID, "bad-txns-invalid-joinsplit-signature");
}
BOOST_STATIC_ASSERT(crypto_sign_PUBLICKEYBYTES == 32);
// We rely on libsodium to check that the signature is canonical.
// https://github.com/jedisct1/libsodium/commit/62911edb7ff2275cccd74bf1c8aefcc4d76924e0
if (crypto_sign_verify_detached(&tx.joinSplitSig[0],
dataToBeSigned.begin(), 32,
tx.joinSplitPubKey.begin()
) != 0) {
return state.DoS(100, error("CheckTransaction(): invalid joinsplit signature"),
REJECT_INVALID, "bad-txns-invalid-joinsplit-signature");
}
}
@ -1793,6 +1802,9 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons
return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
}
}
if(!CheckJoinSplitSigs(tx, state, flags))
return false;
}
}
@ -2134,6 +2146,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return true;
}
unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
if(isForkEnabled(pindex->nHeight))
flags |= SCRIPT_VERIFY_FORKID;
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
// unless those are already completely spent.
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
@ -2143,8 +2159,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
REJECT_INVALID, "bad-txns-BIP30");
}
unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
// DERSIG (BIP66) is also always enforced, but does not have a flag.
CBlockUndo blockundo;

View File

@ -343,6 +343,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state, libzcash::ProofVerifier& verifier);
bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidationState &state);
bool CheckJoinSplitSigs(const CTransaction& tx, CValidationState &state, const unsigned int flags);
/** Check for standard transaction types
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
@ -609,4 +610,9 @@ inline uint64_t bytes2uint64(char *array)
}
#endif
inline bool isForkEnabled(int nHeight)
{
return nHeight > forkStartHeight;
}
#endif // BITCOIN_MAIN_H

View File

@ -809,17 +809,11 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
static map<string, int> mapSigHashValues =
boost::assign::map_list_of
(string("ALL"), int(SIGHASH_ALL))
(string("ALL|SIGHASH_FORKID"), int(SIGHASH_ALL|SIGHASH_FORKID))
(string("ALL|ANYONECANPAY|SIGHASH_FORKID"), int(SIGHASH_ALL|SIGHASH_FORKID))
(string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))
(string("NONE"), int(SIGHASH_NONE))
(string("NONE|SIGHASH_FORKID"), int(SIGHASH_NONE|SIGHASH_FORKID))
(string("NONE|ANYONECANPAY|SIGHASH_FORKID"), int(SIGHASH_NONE|SIGHASH_FORKID|SIGHASH_ANYONECANPAY))
(string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY))
(string("SINGLE"), int(SIGHASH_SINGLE))
(string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY))
(string("SINGLE|SIGHASH_FORKID"), int(SIGHASH_SINGLE|SIGHASH_FORKID))
(string("SINGLE|ANYONECANPAY|SIGHASH_FORKID"), int(SIGHASH_SINGLE|SIGHASH_FORKID|SIGHASH_ANYONECANPAY))
;
string strHashType = params[3].get_str();
if (mapSigHashValues.count(strHashType))
@ -827,11 +821,10 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
else
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
if (!(nHashType & SIGHASH_FORKID))
throw JSONRPCError(RPC_INVALID_PARAMETER, "Signature must use SIGHASH_FORKID");
nHashType |= SIGHASH_FORKID;
}
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
bool fHashSingle = ((nHashType & ~SIGHASH_FLAGS_MASK) == SIGHASH_SINGLE);
// Script verification errors
UniValue vErrors(UniValue::VARR);

View File

@ -185,7 +185,7 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
if (vchSig.size() == 0) {
return false;
}
unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY|SIGHASH_FORKID));
unsigned char nHashType = GetHashType(vchSig) & (~(SIGHASH_ANYONECANPAY|SIGHASH_FORKID));
if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE)
return false;
@ -195,15 +195,12 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
bool static UsesForkId(uint32_t nHashType) {
return nHashType & SIGHASH_FORKID;
}
bool static UsesForkId(const valtype &vchSig) {
uint32_t nHashType = GetHashType(vchSig);
return UsesForkId(nHashType);
}
bool static AllowsNonForkId(unsigned int flags) {
return flags & SCRIPT_ALLOW_NON_FORKID;
}
bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
// Empty signature. Not strictly DER encoded, but allowed to provide a
// compact way to provide an invalid signature for use with CHECK(MULTI)SIG
@ -214,18 +211,12 @@ bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, Sc
return set_error(serror, SCRIPT_ERR_SIG_DER);
} else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig, serror)) {
return false;
} else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsDefinedHashtypeSignature(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE);
} else if ((flags & SCRIPT_VERIFY_FORKID) != 0 && !UsesForkId(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE);
}
if ((flags & SCRIPT_VERIFY_STRICTENC) != 0) {
if(!IsDefinedHashtypeSignature(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE);
}
bool requiresForkId = !AllowsNonForkId(flags);
bool usesForkId = UsesForkId(vchSig);
if (requiresForkId && !usesForkId)
return set_error(serror, SCRIPT_ERR_ILLEGAL_FORKID);
}
return true;
return true;
}
bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
@ -866,7 +857,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// serror is set
return false;
}
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script);
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script, flags);
popstack(stack);
popstack(stack);
@ -924,7 +915,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
}
// Check signature
bool fOk = checker.CheckSig(vchSig, vchPubKey, script);
bool fOk = checker.CheckSig(vchSig, vchPubKey, script, flags);
if (fOk) {
isig++;
@ -1089,11 +1080,8 @@ public:
};
} // anon namespace
//
// https://github.com/BTCGPU/BTCGPU/blob/bd007ae79c934f8c99d2247115637f8684ed861a/src/script/interpreter.cpp#L1204
// forkid
//
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, const int forkid)
{
if (nIn >= txTo.vin.size() && nIn != NOT_AN_INPUT) {
throw logic_error("input index is out of range");
@ -1102,23 +1090,21 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
throw logic_error(" no matching output for SIGHASH_SINGLE");
throw logic_error("no matching output for SIGHASH_SINGLE");
}
}
int nForkHashType = nHashType;
if (UsesForkId(nHashType))
nForkHashType |= forkid << 8;
// Wrapper to serialize only the necessary parts of the transaction being signed
CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType);
// Serialize and hash
CHashWriter ss(SER_GETHASH, 0);
ss << txTmp << (nHashType & ~SIGHASH_FORKID);
// This ensures Two Way Replay Protection
//
// see instead: https://github.com/BTCGPU/BTCGPU/blob/bd007ae79c934f8c99d2247115637f8684ed861a/src/script/interpreter.cpp#L1276
//
// if (nHashType & SIGHASH_FORKID) {
// ss << std::string("btcp");
// }
ss << txTmp << nForkHashType;
return ss.GetHash();
}
@ -1127,7 +1113,7 @@ bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned cha
return pubkey.Verify(sighash, vchSig);
}
bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode, const unsigned int flags) const
{
CPubKey pubkey(vchPubKey);
if (!pubkey.IsValid())
@ -1142,7 +1128,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
uint256 sighash;
try {
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, (flags & SCRIPT_VERIFY_FORKID) ? FORKID_IN_USE : 0);
} catch (logic_error ex) {
return false;
}
@ -1198,11 +1184,6 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
}
// If SIGHASH_FORKID is enabled, we also ensure strict encoding.
if (flags & SCRIPT_ENABLE_SIGHASH_FORKID) {
flags |= SCRIPT_VERIFY_STRICTENC;
}
// Do not allow spends of P2WPKH-P2SH and P2WSH-P2SH UTXOs
// To a non-segwit aware node these outputs are trivially spendable
// Detect them here and evaluate to false

View File

@ -32,11 +32,14 @@ enum
SIGHASH_ANYONECANPAY = 0x80,
};
/** Fork IDs **/
static const int SIGHASH_FLAGS_MASK = SIGHASH_FORKID | SIGHASH_ANYONECANPAY;
static const int SIGHASH_BASE_MASK = ~SIGHASH_FLAGS_MASK;
enum
{
FORKID_BCC = 0,
FORKID_NONE = 0,
FORKID_BTCP = 42,
FORKID_BTCGPU = 79
};
static const int FORKID_IN_USE = FORKID_BTCP;
@ -97,20 +100,16 @@ enum
// See BIP65 for details.
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9),
// Do we accept signature using SIGHASH_FORKID
SCRIPT_ENABLE_SIGHASH_FORKID = (1U << 16),
// Allow NON_FORKID in legacy tests and blocks under BTG hard fork height
SCRIPT_ALLOW_NON_FORKID = (1U << 17),
// Require that all signatures sign the forkid
SCRIPT_VERIFY_FORKID = (1U << 17)
};
//
// TODO: add forkId
//
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, const int forkid=FORKID_NONE);
class BaseSignatureChecker
{
public:
virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, const unsigned int flags) const
{
return false;
}
@ -134,7 +133,7 @@ protected:
public:
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const;
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, const unsigned int flags) const;
bool CheckLockTime(const CScriptNum& nLockTime) const;
};

View File

@ -52,9 +52,6 @@ typedef enum ScriptError_t
/* softfork safeness */
SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS,
/* SIGHASH_FORKID */
SCRIPT_ERR_ILLEGAL_FORKID,
/* SEGWIT LOCKED */
SCRIPT_ERR_SEGWIT_LOCKED,

View File

@ -27,7 +27,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
uint256 hash;
try {
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, FORKID_IN_USE);
} catch (logic_error ex) {
return false;
}
@ -189,7 +189,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC
if (sigs.count(pubkey))
continue; // Already got a sig for this pubkey
if (checker.CheckSig(sig, pubkey, scriptPubKey))
if (checker.CheckSig(sig, pubkey, scriptPubKey, SCRIPT_VERIFY_FORKID))
{
sigs[pubkey] = sig;
break;
@ -274,9 +274,9 @@ CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecke
Solver(scriptPubKey, txType, vSolutions);
vector<valtype> stack1;
EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC|SCRIPT_ENABLE_SIGHASH_FORKID, BaseSignatureChecker());
EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC|SCRIPT_VERIFY_FORKID, BaseSignatureChecker());
vector<valtype> stack2;
EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC|SCRIPT_ENABLE_SIGHASH_FORKID, BaseSignatureChecker());
EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC|SCRIPT_VERIFY_FORKID, BaseSignatureChecker());
return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2);
}
@ -288,7 +288,7 @@ class DummySignatureChecker : public BaseSignatureChecker
public:
DummySignatureChecker() {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, const unsigned int flags) const
{
return true;
}

View File

@ -37,10 +37,7 @@ extern unsigned nMaxDatacarrierBytes;
* details.
*/
//
// TODO https://github.com/BTCGPU/BTCGPU/blob/bd007ae79c934f8c99d2247115637f8684ed861a/src/script/standard.h#L43
//
static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SIGHASH_FORKID;
static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH;
/**
* Standard script verification flags that standard transactions will comply

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -28,7 +28,7 @@ BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
CScript
sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn)
{
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL|SIGHASH_FORKID);
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL);
CScript result;
result << OP_0; // CHECKMULTISIG bug workaround
@ -36,7 +36,7 @@ sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction,
{
vector<unsigned char> vchSig;
BOOST_CHECK(key.Sign(hash, vchSig));
vchSig.push_back((unsigned char)SIGHASH_ALL | SIGHASH_FORKID);
vchSig.push_back((unsigned char)SIGHASH_ALL);
result << vchSig;
}
return result;
@ -312,7 +312,7 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
for (int i = 0; i < 3; i++)
{
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL | SIGHASH_FORKID), strprintf("SignSignature %d", i));
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
}
}

View File

@ -86,8 +86,8 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams)
BOOST_CHECK_THROW(CallRPC("signrawtransaction null"), runtime_error);
BOOST_CHECK_THROW(CallRPC("signrawtransaction ff00"), runtime_error);
BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx));
BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx+" null null NONE|ANYONECANPAY|SIGHASH_FORKID"));
BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx+" [] [] NONE|ANYONECANPAY|SIGHASH_FORKID"));
BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx+" null null NONE|ANYONECANPAY"));
BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx+" [] [] NONE|ANYONECANPAY"));
BOOST_CHECK_THROW(CallRPC(string("signrawtransaction ")+rawtx+" null null badenum"), runtime_error);
// Only check failure cases for sendrawtransaction, there's no network to send to...

View File

@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(sign)
}
for (int i = 0; i < 8; i++)
{
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL| SIGHASH_FORKID), strprintf("SignSignature %d", i));
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
}
// All of the above should be OK, and the txTos have valid signatures
// Check to make sure signature verification fails if we use the wrong ScriptSig:
@ -115,7 +115,7 @@ BOOST_AUTO_TEST_CASE(sign)
{
CScript sigSave = txTo[i].vin[0].scriptSig;
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID, false)();
bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false)();
if (i == j)
BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
else
@ -238,7 +238,7 @@ BOOST_AUTO_TEST_CASE(set)
}
for (int i = 0; i < 4; i++)
{
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL | SIGHASH_FORKID), strprintf("SignSignature %d", i));
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i));
}
}
@ -378,9 +378,9 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txTo.vin[i].prevout.hash = txFrom.GetHash();
}
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0,SIGHASH_ALL| SIGHASH_FORKID));
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1,SIGHASH_ALL| SIGHASH_FORKID));
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2,SIGHASH_ALL| SIGHASH_FORKID));
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0,SIGHASH_ALL));
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1,SIGHASH_ALL));
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2,SIGHASH_ALL));
// SignSignature doesn't know how to sign these. We're
// not testing validating signatures, so just create

View File

@ -34,7 +34,7 @@ using namespace std;
// Uncomment if you want to output updated JSON tests.
// #define UPDATE_JSON_TESTS
static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID;
static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
unsigned int ParseScriptFlags(string strFlags);
string FormatScriptFlags(unsigned int flags);
@ -234,10 +234,9 @@ public:
return *this;
}
TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL| SIGHASH_FORKID, unsigned int lenR = 32, unsigned int lenS = 32)
TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32)
{
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType);
std::vector<unsigned char> vchSig, r, s;
uint32_t iter = 0;
do {
@ -249,7 +248,6 @@ public:
s = std::vector<unsigned char>(vchSig.begin() + 6 + vchSig[3], vchSig.begin() + 6 + vchSig[3] + vchSig[5 + vchSig[3]]);
} while (lenR != r.size() || lenS != s.size());
vchSig.push_back(static_cast<unsigned char>(nHashType));
DoPush(vchSig);
return *this;
}
@ -272,7 +270,6 @@ public:
std::vector<unsigned char> datain = ParseHex(hexin);
std::vector<unsigned char> dataout = ParseHex(hexout);
assert(pos + datain.size() <= push.size());
BOOST_CHECK_MESSAGE(std::vector<unsigned char>(push.begin() + pos, push.begin() + pos + datain.size()) == datain, comment);
push.erase(push.begin() + pos, push.begin() + pos + datain.size());
push.insert(push.begin() + pos, dataout.begin(), dataout.end());
@ -342,23 +339,23 @@ BOOST_AUTO_TEST_CASE(script_build)
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK anyonecanpay", 0
).PushSig(keys.key1, SIGHASH_ALL|SIGHASH_ANYONECANPAY | SIGHASH_FORKID));
).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK anyonecanpay marked with normal hashtype", 0
).PushSig(keys.key1, SIGHASH_ALL|SIGHASH_ANYONECANPAY| SIGHASH_FORKID).EditPush(70, "C1", "03"));
).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY).EditPush(70, "81", "01"));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
"P2SH(P2PK)", SCRIPT_VERIFY_P2SH|SCRIPT_ENABLE_SIGHASH_FORKID, true
"P2SH(P2PK)", SCRIPT_VERIFY_P2SH, true
).PushSig(keys.key0).PushRedeem());
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
"P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH |SCRIPT_ENABLE_SIGHASH_FORKID, true
"P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true
).PushSig(keys.key0).PushRedeem().DamagePush(10));
good.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
"P2SH(P2PKH), bad sig but no VERIFY_P2SH", 0, true
).PushSig(keys.key0).DamagePush(10).PushRedeem());
bad.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
"P2SH(P2PKH), bad sig", SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SIGHASH_FORKID, true
"P2SH(P2PKH), bad sig", SCRIPT_VERIFY_P2SH, true
).PushSig(keys.key0).DamagePush(10).PushRedeem());
good.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
@ -369,34 +366,34 @@ BOOST_AUTO_TEST_CASE(script_build)
).Num(0).PushSig(keys.key0).PushSig(keys.key1).Num(0));
good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
"P2SH(2-of-3)", SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SIGHASH_FORKID, true
"P2SH(2-of-3)", SCRIPT_VERIFY_P2SH, true
).Num(0).PushSig(keys.key1).PushSig(keys.key2).PushRedeem());
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
"P2SH(2-of-3), 1 sig", SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SIGHASH_FORKID, true
"P2SH(2-of-3), 1 sig", SCRIPT_VERIFY_P2SH, true
).Num(0).PushSig(keys.key1).Num(0).PushRedeem());
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too much R padding", 0
).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_FORKID, 31, 32).EditPush(1, "43021F", "44022000"));
).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too much S padding", 0
).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_FORKID).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() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too little R padding", 0
).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_FORKID, 33, 32).EditPush(1, "45022100", "440220"));
).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with bad sig with too much R padding", 0
).PushSig(keys.key2, SIGHASH_ALL | SIGHASH_FORKID, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10));
).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with too much R padding", 0
).PushSig(keys.key2, SIGHASH_ALL | SIGHASH_FORKID, 31, 32).EditPush(1, "43021F", "44022000"));
).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 1", 0
).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_FORKID, 33, 32).EditPush(1, "45022100", "440220"));
).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
"BIP66 example 2", 0
).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_FORKID, 33, 32).EditPush(1, "45022100", "440220"));
).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 3", 0
).Num(0));
@ -411,73 +408,73 @@ BOOST_AUTO_TEST_CASE(script_build)
).Num(1));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
"BIP66 example 7", 0
).Num(0).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_FORKID, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 8", 0
).Num(0).PushSig(keys.key1, SIGHASH_ALL| SIGHASH_FORKID, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
"BIP66 example 9", 0
).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL | SIGHASH_FORKID, 33, 32).EditPush(1, "45022100", "440220"));
).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 10", 0
).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL | SIGHASH_FORKID, 33, 32).EditPush(1, "45022100", "440220"));
).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
"BIP66 example 11", 0
).Num(0).PushSig(keys.key1, SIGHASH_ALL| SIGHASH_FORKID, 33, 32).EditPush(1, "45022100", "440220").Num(0));
).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 12", 0
).Num(0).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_FORKID, 33, 32).EditPush(1, "45022100", "440220").Num(0));
).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with multi-byte hashtype", 0
).PushSig(keys.key2, SIGHASH_ALL| SIGHASH_FORKID).EditPush(70, "41", "101"));
).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101"));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with high S but no LOW_S", 0
).PushSig(keys.key2, SIGHASH_ALL | SIGHASH_FORKID, 32, 33));
).PushSig(keys.key2, SIGHASH_ALL, 32, 33));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with high S", SCRIPT_VERIFY_LOW_S | SCRIPT_ENABLE_SIGHASH_FORKID
).PushSig(keys.key2, SIGHASH_ALL | SIGHASH_FORKID, 32, 33));
"P2PK with high S", SCRIPT_VERIFY_LOW_S
).PushSig(keys.key2, SIGHASH_ALL, 32, 33));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
"P2PK with hybrid pubkey but no STRICTENC", 0
).PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID));
).PushSig(keys.key0, SIGHASH_ALL));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
"P2PK with hybrid pubkey", SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID
).PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID));
"P2PK with hybrid pubkey", SCRIPT_VERIFY_STRICTENC
).PushSig(keys.key0, SIGHASH_ALL));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with hybrid pubkey but no STRICTENC", 0
).PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID));
).PushSig(keys.key0, SIGHASH_ALL));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with hybrid pubkey", SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID
).PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID));
"P2PK NOT with hybrid pubkey", SCRIPT_VERIFY_STRICTENC
).PushSig(keys.key0, SIGHASH_ALL));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid hybrid pubkey but no STRICTENC", 0
).PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID).DamagePush(10));
).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid hybrid pubkey", SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID
).PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID).DamagePush(10));
"P2PK NOT with invalid hybrid pubkey", SCRIPT_VERIFY_STRICTENC
).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10));
good.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"1-of-2 with the second 1 hybrid pubkey and no STRICTENC", 0
).Num(0).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_FORKID));
).Num(0).PushSig(keys.key1, SIGHASH_ALL));
good.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"1-of-2 with the second 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID
).Num(0).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_FORKID));
"1-of-2 with the second 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC
).Num(0).PushSig(keys.key1, SIGHASH_ALL));
bad.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0H) << OP_2 << OP_CHECKMULTISIG,
"1-of-2 with the first 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID
).Num(0).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_FORKID));
"1-of-2 with the first 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC
).Num(0).PushSig(keys.key1, SIGHASH_ALL));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK with undefined hashtype but no STRICTENC", 0
).PushSig(keys.key1, 5));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK with undefined hashtype", SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID
"P2PK with undefined hashtype", SCRIPT_VERIFY_STRICTENC
).PushSig(keys.key1, 5));
good.push_back(TestBuilder(CScript() << ToByteVector(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() << ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid sig and undefined hashtype", SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID
"P2PK NOT with invalid sig and undefined hashtype", SCRIPT_VERIFY_STRICTENC
).PushSig(keys.key1, 5).DamagePush(10));
good.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
@ -497,7 +494,7 @@ BOOST_AUTO_TEST_CASE(script_build)
"2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY", 0
).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs pushed using OP_DUP", SCRIPT_VERIFY_SIGPUSHONLY | SCRIPT_ENABLE_SIGHASH_FORKID
"2-of-2 with two identical keys and sigs pushed using OP_DUP", SCRIPT_VERIFY_SIGPUSHONLY
).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", 0
@ -506,23 +503,23 @@ BOOST_AUTO_TEST_CASE(script_build)
"P2SH(P2PK) with non-push scriptSig", SCRIPT_VERIFY_SIGPUSHONLY
).PushSig(keys.key2).PushRedeem());
good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs pushed", SCRIPT_VERIFY_SIGPUSHONLY | SCRIPT_ENABLE_SIGHASH_FORKID
"2-of-2 with two identical keys and sigs pushed", SCRIPT_VERIFY_SIGPUSHONLY
).Num(0).PushSig(keys.key1).PushSig(keys.key1));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SIGHASH_FORKID
"P2PK with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH
).Num(11).PushSig(keys.key0));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SIGHASH_FORKID
"P2PK with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH
).Num(11).PushSig(keys.key0));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2SH with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SIGHASH_FORKID, true
"P2SH with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH, true
).Num(11).PushSig(keys.key0).PushRedeem());
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2SH with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SIGHASH_FORKID, true
"P2SH with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true
).Num(11).PushSig(keys.key0).PushRedeem());
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2SH with CLEANSTACK", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SIGHASH_FORKID, true
"P2SH with CLEANSTACK", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true
).PushSig(keys.key0).PushRedeem());
@ -589,7 +586,6 @@ BOOST_AUTO_TEST_CASE(script_valid)
for (size_t idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
string strTest = test.write();
if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments)
{
if (test.size() != 1) {
@ -665,7 +661,7 @@ BOOST_AUTO_TEST_CASE(script_PushData)
CScript
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction)
{
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL | SIGHASH_FORKID);
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL);
CScript result;
//
@ -681,7 +677,7 @@ sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transac
{
vector<unsigned char> vchSig;
BOOST_CHECK(key.Sign(hash, vchSig));
vchSig.push_back((unsigned char)SIGHASH_ALL | SIGHASH_FORKID);
vchSig.push_back((unsigned char)SIGHASH_ALL);
result << vchSig;
}
return result;
@ -860,17 +856,17 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
// A couple of partially-signed versions:
vector<unsigned char> sig1;
uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL | SIGHASH_FORKID);
uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL);
BOOST_CHECK(keys[0].Sign(hash1, sig1));
sig1.push_back(SIGHASH_ALL| SIGHASH_FORKID);
sig1.push_back(SIGHASH_ALL);
vector<unsigned char> sig2;
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE | SIGHASH_FORKID);
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE);
BOOST_CHECK(keys[1].Sign(hash2, sig2));
sig2.push_back(SIGHASH_NONE| SIGHASH_FORKID);
sig2.push_back(SIGHASH_NONE);
vector<unsigned char> sig3;
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE | SIGHASH_FORKID);
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE);
BOOST_CHECK(keys[2].Sign(hash3, sig3));
sig3.push_back(SIGHASH_SINGLE | SIGHASH_FORKID);
sig3.push_back(SIGHASH_SINGLE);
// Not fussy about order (or even existence) of placeholders or signatures:
CScript partial1a = CScript() << OP_0 << sig1 << OP_0;
@ -885,7 +881,6 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
CScript complete23 = CScript() << OP_0 << sig2 << sig3;
combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial1b);
BOOST_CHECK(combined == partial1a);
combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial2a);
BOOST_CHECK(combined == complete12);

View File

@ -20,7 +20,6 @@
#include <univalue.h>
extern UniValue read_json(const std::string& jsondata);
// Old script.cpp SignatureHash function
@ -70,7 +69,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
}
// Blank out other inputs completely, not recommended for open transactions
if ((nHashType & 0x1f) == SIGHASH_ANYONECANPAY)
if (nHashType & SIGHASH_ANYONECANPAY)
{
txTmp.vin[0] = txTmp.vin[nIn];
txTmp.vin.resize(1);
@ -99,9 +98,8 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
tx.vout.clear();
tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0;
int ins = (insecure_rand() % 4) + 1;
int outs = fSingle ? ins + 1 : (insecure_rand() % 4) + 1;
int outs = fSingle ? ins : (insecure_rand() % 4) + 1;
int joinsplits = (insecure_rand() % 4);
for (int in = 0; in < ins; in++) {
tx.vin.push_back(CTxIn());
CTxIn &txin = tx.vin.back();
@ -155,16 +153,6 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
}
BOOST_FIXTURE_TEST_SUITE(sighash_tests, BasicTestingSetup)
//
// NB Any change in the data created below will require that you define this,
// and
// $ ./test_bitcoin -t sighash_tests > data/sighash.json
// $ make -C .. bitcoin_test
//
// the first step rebuilds the json, the second step result in
// data/sighash.json.h being recreated and used in a recompile
//
// #define PRINT_SIGHASH_JSON
BOOST_AUTO_TEST_CASE(sighash_test)
{
@ -180,18 +168,16 @@ BOOST_AUTO_TEST_CASE(sighash_test)
nRandomTests = 500;
#endif
for (int i=0; i<nRandomTests; i++) {
int nHashType = (insecure_rand() % 3) + 1;
int nHashType = insecure_rand();
CMutableTransaction txTo;
RandomTransaction(txTo, (nHashType == SIGHASH_SINGLE));
RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
CScript scriptCode;
RandomScript(scriptCode);
int nIn = insecure_rand() % txTo.vin.size();
uint256 sh, sho;
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
sh = SignatureHash(scriptCode, txTo, nIn, nHashType);
#if defined(PRINT_SIGHASH_JSON)
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << txTo;

View File

@ -418,16 +418,13 @@ BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
jsdesc->nullifiers[0] = GetRandHash();
jsdesc->nullifiers[1] = GetRandHash();
BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state));
BOOST_CHECK(!CheckJoinSplitSigs(newTx, state, 0));
BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-joinsplit-signature");
// Empty output script.
CScript scriptCode;
CTransaction signTx(newTx);
//
// NB SIGHASH_ALL | SIGHASH_FORKID
//
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, 0x41);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
assert(crypto_sign_detached(&newTx.joinSplitSig[0], NULL,
dataToBeSigned.begin(), 32,

View File

@ -962,7 +962,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL | SIGHASH_FORKID, FORKID_IN_USE);
// Add the signature
if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
@ -1105,4 +1105,3 @@ UniValue AsyncRPCOperation_sendmany::getStatus() const {
obj.push_back(Pair("params", contextinfo_ ));
return obj;
}

View File

@ -2829,7 +2829,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL | SIGHASH_FORKID);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL | SIGHASH_FORKID, FORKID_IN_USE);
// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,