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)
|
CScript CCPubKey(const CC *cond)
|
||||||
{
|
{
|
||||||
@@ -43,8 +80,8 @@ CScript CCPubKey(const CC *cond)
|
|||||||
|
|
||||||
CScript CCSig(const CC *cond)
|
CScript CCSig(const CC *cond)
|
||||||
{
|
{
|
||||||
unsigned char buf[1000];
|
unsigned char buf[10000];
|
||||||
size_t len = cc_fulfillmentBinary(cond, buf, 1000);
|
size_t len = cc_fulfillmentBinary(cond, buf, 10000);
|
||||||
auto ffill = std::vector<unsigned char>(buf, buf+len);
|
auto ffill = std::vector<unsigned char>(buf, buf+len);
|
||||||
ffill.push_back(1); // SIGHASH_ALL
|
ffill.push_back(1); // SIGHASH_ALL
|
||||||
return CScript() << ffill;
|
return CScript() << ffill;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef KOMODO_CC_H
|
#ifndef KOMODO_CC_H
|
||||||
#define KOMODO_CC_H
|
#define KOMODO_CC_H
|
||||||
|
|
||||||
|
#include "pubkey.h"
|
||||||
#include "script/script.h"
|
#include "script/script.h"
|
||||||
#include "cryptoconditions/include/cryptoconditions.h"
|
#include "cryptoconditions/include/cryptoconditions.h"
|
||||||
|
|
||||||
@@ -32,6 +33,15 @@ bool IsSupportedCryptoCondition(const CC *cond);
|
|||||||
bool IsSignedCryptoCondition(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
|
* 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(
|
bool VerifyScript(
|
||||||
const CScript& scriptSig,
|
const CScript& scriptSig,
|
||||||
const CScript& scriptPubKey,
|
const CScript& scriptPubKey,
|
||||||
@@ -1387,7 +1418,12 @@ bool VerifyScript(
|
|||||||
}
|
}
|
||||||
|
|
||||||
vector<vector<unsigned char> > stack, stackCopy;
|
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
|
// serror is set
|
||||||
return false;
|
return false;
|
||||||
if (flags & SCRIPT_VERIFY_P2SH)
|
if (flags & SCRIPT_VERIFY_P2SH)
|
||||||
|
|||||||
@@ -19,6 +19,9 @@
|
|||||||
|
|
||||||
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
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
|
// Maximum script length in bytes
|
||||||
static const int MAX_SCRIPT_SIZE = 10000;
|
static const int MAX_SCRIPT_SIZE = 10000;
|
||||||
|
|
||||||
|
|||||||
@@ -199,3 +199,30 @@ TEST_F(CCTest, testCryptoConditionsDisabled)
|
|||||||
ASSETCHAINS_CC = 0;
|
ASSETCHAINS_CC = 0;
|
||||||
ASSERT_FALSE(Verify(cond));
|
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