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:
Scott Sadler
2018-03-31 23:20:03 -03:00
parent 9ef101bc21
commit 563581aff4
21 changed files with 215 additions and 116 deletions

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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