allow larger PUSHDATA for CC fulfillment
This commit is contained in:
@@ -32,6 +32,43 @@ bool IsSignedCryptoCondition(const CC *cond)
|
||||
}
|
||||
|
||||
|
||||
static unsigned char* CopyPubKey(CPubKey pkIn)
|
||||
{
|
||||
unsigned char* pk = (unsigned char*) malloc(33);
|
||||
memcpy(pk, pkIn.begin(), 33); // TODO: compressed?
|
||||
return pk;
|
||||
}
|
||||
|
||||
|
||||
CC* CCNewThreshold(int t, std::vector<CC*> v)
|
||||
{
|
||||
CC *cond = cc_new(CC_Threshold);
|
||||
cond->threshold = t;
|
||||
cond->size = v.size();
|
||||
cond->subconditions = (CC**) calloc(v.size(), sizeof(CC*));
|
||||
memcpy(cond->subconditions, v.data(), v.size() * sizeof(CC*));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
CC* CCNewSecp256k1(CPubKey k)
|
||||
{
|
||||
CC *cond = cc_new(CC_Secp256k1);
|
||||
cond->publicKey = CopyPubKey(k);
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
CC* CCNewEval(std::string method, std::vector<unsigned char> paramsBin)
|
||||
{
|
||||
CC *cond = cc_new(CC_Eval);
|
||||
strcpy(cond->method, method.data());
|
||||
cond->paramsBin = (unsigned char*) malloc(paramsBin.size());
|
||||
memcpy(cond->paramsBin, paramsBin.data(), paramsBin.size());
|
||||
cond->paramsBinLength = paramsBin.size();
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
CScript CCPubKey(const CC *cond)
|
||||
{
|
||||
@@ -43,8 +80,8 @@ CScript CCPubKey(const CC *cond)
|
||||
|
||||
CScript CCSig(const CC *cond)
|
||||
{
|
||||
unsigned char buf[1000];
|
||||
size_t len = cc_fulfillmentBinary(cond, buf, 1000);
|
||||
unsigned char buf[10000];
|
||||
size_t len = cc_fulfillmentBinary(cond, buf, 10000);
|
||||
auto ffill = std::vector<unsigned char>(buf, buf+len);
|
||||
ffill.push_back(1); // SIGHASH_ALL
|
||||
return CScript() << ffill;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef KOMODO_CC_H
|
||||
#define KOMODO_CC_H
|
||||
|
||||
#include "pubkey.h"
|
||||
#include "script/script.h"
|
||||
#include "cryptoconditions/include/cryptoconditions.h"
|
||||
|
||||
@@ -32,6 +33,15 @@ bool IsSupportedCryptoCondition(const CC *cond);
|
||||
bool IsSignedCryptoCondition(const CC *cond);
|
||||
|
||||
|
||||
/*
|
||||
* Construct crypto conditions
|
||||
*/
|
||||
CC* CCNewPreimage(std::vector<unsigned char> preimage);
|
||||
CC* CCNewEval(std::string method, std::vector<unsigned char> paramsBin);
|
||||
CC* CCNewSecp256k1(CPubKey k);
|
||||
CC* CCNewThreshold(int t, std::vector<CC*> v);
|
||||
|
||||
|
||||
/*
|
||||
* Turn a condition into a scriptPubKey
|
||||
*/
|
||||
|
||||
@@ -1372,6 +1372,37 @@ bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) con
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allow larger opcode in case of crypto condition scriptSig
|
||||
*/
|
||||
bool EvalCryptoConditionSig(
|
||||
vector<vector<unsigned char> >& stack,
|
||||
const CScript& scriptSig,
|
||||
ScriptError* serror)
|
||||
{
|
||||
CScript::const_iterator pc = scriptSig.begin();
|
||||
opcodetype opcode;
|
||||
valtype vchPushValue;
|
||||
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
|
||||
|
||||
if (!scriptSig.GetOp(pc, opcode, vchPushValue))
|
||||
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
|
||||
|
||||
if (opcode == 0 || opcode > OP_PUSHDATA4)
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
|
||||
if (pc != scriptSig.end())
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
|
||||
if (vchPushValue.size() > MAX_SCRIPT_CRYPTOCONDITION_FULFILLMENT_SIZE)
|
||||
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
|
||||
|
||||
stack.push_back(vchPushValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool VerifyScript(
|
||||
const CScript& scriptSig,
|
||||
const CScript& scriptPubKey,
|
||||
@@ -1387,7 +1418,12 @@ bool VerifyScript(
|
||||
}
|
||||
|
||||
vector<vector<unsigned char> > stack, stackCopy;
|
||||
if (!EvalScript(stack, scriptSig, flags, checker, consensusBranchId, serror))
|
||||
if (IsCryptoConditionsEnabled() && scriptPubKey.IsPayToCryptoCondition()) {
|
||||
if (!EvalCryptoConditionSig(stack, scriptSig, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
}
|
||||
else if (!EvalScript(stack, scriptSig, flags, checker, consensusBranchId, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
if (flags & SCRIPT_VERIFY_P2SH)
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
|
||||
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
||||
|
||||
// Max size of pushdata in a CC sig in bytes
|
||||
static const unsigned int MAX_SCRIPT_CRYPTOCONDITION_FULFILLMENT_SIZE = 2048;
|
||||
|
||||
// Maximum script length in bytes
|
||||
static const int MAX_SCRIPT_SIZE = 10000;
|
||||
|
||||
|
||||
@@ -199,3 +199,30 @@ TEST_F(CCTest, testCryptoConditionsDisabled)
|
||||
ASSETCHAINS_CC = 0;
|
||||
ASSERT_FALSE(Verify(cond));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(CCTest, testLargeCondition)
|
||||
{
|
||||
CC *cond;
|
||||
ScriptError error;
|
||||
CMutableTransaction mtxTo;
|
||||
|
||||
auto Verify = [&] (const CC *cond) {
|
||||
CAmount amount;
|
||||
CTransaction txTo(mtxTo);
|
||||
PrecomputedTransactionData txdata(txTo);
|
||||
auto checker = ServerTransactionSignatureChecker(&txTo, 0, amount, false, txdata);
|
||||
return VerifyScript(CCSig(cond), CCPubKey(cond), 0, checker, 0, &error);
|
||||
};
|
||||
|
||||
std::vector<CC*> ccs;
|
||||
for (int i=0; i<18; i++) {
|
||||
ccs.push_back(CCNewSecp256k1(notaryKey.GetPubKey()));
|
||||
}
|
||||
cond = CCNewThreshold(16, ccs);
|
||||
CCSign(mtxTo, cond);
|
||||
EXPECT_EQ("(16 of 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,A5,A5)",
|
||||
CCShowStructure(CCPrune(cond)));
|
||||
EXPECT_EQ(1744, CCSig(cond).size());
|
||||
ASSERT_TRUE(Verify(cond));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user