many changes: * fix CC malleability * extra validations for CCs such as requiring a signature and limiting types * different SIGHASH types for CC
This commit is contained in:
@@ -950,27 +950,19 @@ bool EvalScript(
|
||||
if (stack.size() < 2)
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
|
||||
valtype& vchFulfillment = stacktop(-2);
|
||||
valtype& vchCondition = stacktop(-1);
|
||||
|
||||
CC *cond = cc_readFulfillmentBinary((unsigned char*)vchFulfillment.data(),
|
||||
vchFulfillment.size());
|
||||
if (!cond) {
|
||||
int fResult = checker.CheckCryptoCondition(stacktop(-1), stacktop(-2), script, consensusBranchId);
|
||||
if (fResult == -1) {
|
||||
return set_error(serror, SCRIPT_ERR_CRYPTOCONDITION_INVALID_FULFILLMENT);
|
||||
}
|
||||
|
||||
bool fSuccess = checker.CheckCryptoCondition(cond, vchCondition, script, consensusBranchId);
|
||||
|
||||
cc_free(cond);
|
||||
|
||||
|
||||
popstack(stack);
|
||||
popstack(stack);
|
||||
|
||||
stack.push_back(fSuccess ? vchTrue : vchFalse);
|
||||
stack.push_back(fResult == 1 ? vchTrue : vchFalse);
|
||||
|
||||
if (opcode == OP_CHECKCRYPTOCONDITIONVERIFY)
|
||||
{
|
||||
if (fSuccess)
|
||||
if (fResult == 1)
|
||||
popstack(stack);
|
||||
else
|
||||
return set_error(serror, SCRIPT_ERR_CRYPTOCONDITION_VERIFY);
|
||||
@@ -1295,18 +1287,33 @@ bool TransactionSignatureChecker::CheckSig(
|
||||
}
|
||||
|
||||
|
||||
bool TransactionSignatureChecker::CheckCryptoCondition(const CC *cond, const std::vector<unsigned char>& condBin, const CScript& scriptCode, uint32_t consensusBranchId) const
|
||||
int TransactionSignatureChecker::CheckCryptoCondition(
|
||||
const std::vector<unsigned char>& condBin,
|
||||
const std::vector<unsigned char>& ffillBin,
|
||||
const CScript& scriptCode,
|
||||
uint32_t consensusBranchId) const
|
||||
{
|
||||
if (!IsAcceptableCryptoCondition(cond)) return false;
|
||||
// Hash type is one byte tacked on to the end of the fulfillment
|
||||
if (ffillBin.empty())
|
||||
return false;
|
||||
|
||||
CC *cond = cc_readFulfillmentBinary((unsigned char*)ffillBin.data(), ffillBin.size()-1);
|
||||
if (!cond) return -1;
|
||||
|
||||
if (!IsSupportedCryptoCondition(cond)) return 0;
|
||||
if (!IsSignedCryptoCondition(cond)) return 0;
|
||||
|
||||
uint256 sighash;
|
||||
int nHashType = ffillBin.back();
|
||||
try {
|
||||
sighash = SignatureHash(scriptCode, *txTo, nIn, SIGHASH_ALL, amount, consensusBranchId, this->txdata);
|
||||
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId, this->txdata);
|
||||
} catch (logic_error ex) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return cc_verify(cond, (const unsigned char*)&sighash, 32, 0,
|
||||
condBin.data(), condBin.size(), GetCCEval(), (void*)this);
|
||||
int out = cc_verify(cond, (const unsigned char*)&sighash, 32, 0,
|
||||
condBin.data(), condBin.size(), GetCCEval(), (void*)this);
|
||||
cc_free(cond);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -128,7 +128,11 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool CheckCryptoCondition(const CC *cond, const std::vector<unsigned char>& condBin, const CScript& scriptCode, uint32_t consensusBranchId) const
|
||||
virtual int CheckCryptoCondition(
|
||||
const std::vector<unsigned char>& condBin,
|
||||
const std::vector<unsigned char>& ffillBin,
|
||||
const CScript& scriptCode,
|
||||
uint32_t consensusBranchId) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -152,7 +156,11 @@ public:
|
||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, uint32_t consensusBranchId) const;
|
||||
bool CheckLockTime(const CScriptNum& nLockTime) const;
|
||||
bool CheckCryptoCondition(const CC *cond, const std::vector<unsigned char>& condBin, const CScript& scriptCode, uint32_t consensusBranchId) const;
|
||||
int CheckCryptoCondition(
|
||||
const std::vector<unsigned char>& condBin,
|
||||
const std::vector<unsigned char>& ffillBin,
|
||||
const CScript& scriptCode,
|
||||
uint32_t consensusBranchId) const;
|
||||
VerifyEval GetCCEval() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -250,8 +250,9 @@ bool CScript::MayAcceptCryptoCondition() const
|
||||
if (!(opcode > OP_0 && opcode < OP_PUSHDATA1)) return false;
|
||||
CC *cond = cc_readConditionBinary(data.data(), data.size());
|
||||
if (!cond) return false;
|
||||
bool accept = IsAcceptableCryptoCondition(cond);
|
||||
return accept;
|
||||
bool out = IsSupportedCryptoCondition(cond);
|
||||
cc_free(cond);
|
||||
return out;
|
||||
}
|
||||
|
||||
bool CScript::IsPushOnly() const
|
||||
|
||||
Reference in New Issue
Block a user