allow larger PUSHDATA for CC fulfillment

This commit is contained in:
Scott Sadler
2018-04-06 02:55:47 -03:00
parent 561f3e18c1
commit e625be68a9
5 changed files with 116 additions and 3 deletions

View File

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

View File

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

View File

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

View File

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

View File

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