Delete more CCs #381
This commit is contained in:
@@ -18,41 +18,6 @@
|
||||
#ifndef CC_INCLUDE_H
|
||||
#define CC_INCLUDE_H
|
||||
|
||||
/*! \file CCinclude.h
|
||||
\brief Cryptoconditions
|
||||
|
||||
CCs for teh lulz
|
||||
|
||||
*/
|
||||
|
||||
/// \mainpage Brief introduction into cryptocondition contracts
|
||||
/// There are only a very few types in bitcoin: pay to pubkey, pay to pubkey hash and pay to script hash (p2pk, p2pkh, p2sh).
|
||||
/// There are actually more that are possible, but those three are 99%+ of bitcoin transactions.
|
||||
/// So you can pay to a pubkey, or to its hash or to a script's hash. The last is how most of the more complex scripts are invoked. To spend a p2sh vout, you need to provide the redeemscript,
|
||||
/// this script's hash is what the p2sh address was.
|
||||
/// All of the above are the standard bitcoin vout types and there should be plenty of materials about it.
|
||||
///
|
||||
/// Cryptoconditions (CC) contracts created a fourth type of vout, the CC vout. This is using the cryptoconditions standard and it is even a different signature mechanism,
|
||||
/// ed25519 instead of secp256k1. It is basically a big extension to the bitcoin script. There is a special opcode that is added that says it is a CC script.
|
||||
///
|
||||
/// But it gets more interesting. Each CC script has an evalcode.
|
||||
/// This is just an arbitrary number but what it does is allows to create a self-contained universe of CC utxo that all have the same evalcode and that is
|
||||
/// how a faucet CC contract differentiates itself from a dice CC contract, the eval code is different.
|
||||
///
|
||||
/// One effect from using a different eval code is that even if the rest of the CC script is the same, the bitcoin address that is calculated is different.
|
||||
/// What this means is that for each pubkey, there is a unique address for each different eval code!
|
||||
/// And this allows efficient segregation of one CC contracts transactions from another.
|
||||
/// The final part that will make it all clear how the funds can be locked inside the contract.
|
||||
/// This is what makes a contract, a contract.
|
||||
/// I put both the privkey and pubkey for a randomly chosen address and associate it with each CC contract.
|
||||
/// That means anybody can sign outputs for that privkey.
|
||||
/// However, it is a CC output, so in addition to the signature, whatever constraints a CC contract implements must also be satistifed.
|
||||
/// This allows funds to be locked and yet anybody is able to spend it, assuming they satisfy the CC's rules.
|
||||
///
|
||||
/// One other technical note is that Hush has the insight-explorer extensions built in
|
||||
/// so it can lookup directly all transactions to any address.
|
||||
/// This is a key performance boosting thing as if it wasnt there, trying to get all the utxo for an address not in the wallet is quite time consuming.
|
||||
///
|
||||
|
||||
#include <cc/eval.h>
|
||||
#include <script/cc.h>
|
||||
@@ -949,11 +914,6 @@ extern void CCLogPrintStr(const char *category, int level, const std::string &st
|
||||
template <class T>
|
||||
void CCLogPrintStream(const char *category, int level, const char *functionName, T print_to_stream)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
print_to_stream(stream);
|
||||
if (functionName != NULL)
|
||||
stream << functionName << " ";
|
||||
CCLogPrintStr(category, level, stream.str());
|
||||
}
|
||||
/// Macro for logging messages using bitcoin LogAcceptCategory and LogPrintStr functions.
|
||||
/// Supports error, info and three levels of debug messages.
|
||||
|
||||
@@ -30,151 +30,31 @@
|
||||
// for tokens to be used there should be at least one 't' tx with other contract's custom opret
|
||||
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, vscript_t vopretNonfungible)
|
||||
{
|
||||
/* CScript opret;
|
||||
uint8_t evalcode = EVAL_TOKENS;
|
||||
funcid = 'c'; // override the param
|
||||
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << origpubkey << name << description; \
|
||||
if (!vopretNonfungible.empty()) {
|
||||
ss << (uint8_t)OPRETID_NONFUNGIBLEDATA;
|
||||
ss << vopretNonfungible;
|
||||
}); */
|
||||
|
||||
std::vector<std::pair<uint8_t, vscript_t>> oprets;
|
||||
|
||||
if(!vopretNonfungible.empty())
|
||||
oprets.push_back(std::make_pair(OPRETID_NONFUNGIBLEDATA, vopretNonfungible));
|
||||
return EncodeTokenCreateOpRet(funcid, origpubkey, name, description, oprets);
|
||||
return CScript();
|
||||
}
|
||||
|
||||
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, std::vector<std::pair<uint8_t, vscript_t>> oprets)
|
||||
{
|
||||
CScript opret;
|
||||
uint8_t evalcode = EVAL_TOKENS;
|
||||
funcid = 'c'; // override the param
|
||||
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << origpubkey << name << description;
|
||||
for (auto o : oprets) {
|
||||
if (o.first != 0) {
|
||||
ss << (uint8_t)o.first;
|
||||
ss << o.second;
|
||||
}
|
||||
});
|
||||
return(opret);
|
||||
return CScript();
|
||||
}
|
||||
|
||||
/*
|
||||
// opret 'i' for imported tokens
|
||||
CScript EncodeTokenImportOpRet(std::vector<uint8_t> origpubkey, std::string name, std::string description, uint256 srctokenid, std::vector<std::pair<uint8_t, vscript_t>> oprets)
|
||||
{
|
||||
CScript opret;
|
||||
uint8_t evalcode = EVAL_TOKENS;
|
||||
uint8_t funcid = 'i';
|
||||
|
||||
srctokenid = revuint256(srctokenid); // do not forget this
|
||||
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << origpubkey << name << description << srctokenid;
|
||||
for (auto o : oprets) {
|
||||
if (o.first != 0) {
|
||||
ss << (uint8_t)o.first;
|
||||
ss << o.second;
|
||||
}
|
||||
});
|
||||
return(opret);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, std::pair<uint8_t, vscript_t> opretWithId)
|
||||
{
|
||||
std::vector<std::pair<uint8_t, vscript_t>> oprets;
|
||||
oprets.push_back(opretWithId);
|
||||
return EncodeTokenOpRet(tokenid, voutPubkeys, oprets);
|
||||
return CScript();
|
||||
}
|
||||
|
||||
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, std::vector<std::pair<uint8_t, vscript_t>> oprets)
|
||||
{
|
||||
CScript opret;
|
||||
uint8_t tokenFuncId = 't';
|
||||
uint8_t evalCodeInOpret = EVAL_TOKENS;
|
||||
|
||||
tokenid = revuint256(tokenid);
|
||||
|
||||
uint8_t ccType = 0;
|
||||
if (voutPubkeys.size() >= 0 && voutPubkeys.size() <= 2)
|
||||
ccType = voutPubkeys.size();
|
||||
else {
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "EncodeTokenOpRet voutPubkeys.size()=" << voutPubkeys.size() << " not supported" << std::endl);
|
||||
}
|
||||
|
||||
//vopret_t vpayload;
|
||||
//GetOpReturnData(payload, vpayload);
|
||||
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalCodeInOpret << tokenFuncId << tokenid << ccType;
|
||||
if (ccType >= 1) ss << voutPubkeys[0];
|
||||
if (ccType == 2) ss << voutPubkeys[1];
|
||||
for (auto o : oprets) {
|
||||
if (o.first != 0) {
|
||||
ss << (uint8_t)o.first;
|
||||
ss << o.second;
|
||||
}
|
||||
});
|
||||
|
||||
// bad opret cases (tries to attach payload without re-serialization):
|
||||
|
||||
// error "64: scriptpubkey":
|
||||
// if (payload.size() > 0)
|
||||
// opret += payload;
|
||||
|
||||
// error "64: scriptpubkey":
|
||||
// CScript opretPayloadNoOpcode(vpayload);
|
||||
// return opret + opretPayloadNoOpcode;
|
||||
|
||||
// error "sig_aborted":
|
||||
// opret.resize(opret.size() + vpayload.size());
|
||||
// CScript::iterator it = opret.begin() + opret.size();
|
||||
// for (int i = 0; i < vpayload.size(); i++, it++)
|
||||
// *it = vpayload[i];
|
||||
|
||||
return opret;
|
||||
return CScript();
|
||||
}
|
||||
|
||||
// overload for compatibility
|
||||
//CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector<CPubKey> voutPubkeys, CScript payload)
|
||||
//{
|
||||
// return EncodeTokenOpRet(tokenid, voutPubkeys, payload);
|
||||
//}
|
||||
|
||||
// overload for fungible tokens (no additional data in opret):
|
||||
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description) {
|
||||
//vopret_t vopretNonfungibleDummy;
|
||||
std::vector<std::pair<uint8_t, vscript_t>> opretsDummy;
|
||||
return DecodeTokenCreateOpRet(scriptPubKey, origpubkey, name, description, opretsDummy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description, std::vector<std::pair<uint8_t, vscript_t>> &oprets)
|
||||
{
|
||||
vscript_t vopret, vblob;
|
||||
uint8_t dummyEvalcode, funcid, opretId = 0;
|
||||
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
oprets.clear();
|
||||
|
||||
if (vopret.size() > 2 && vopret.begin()[0] == EVAL_TOKENS && vopret.begin()[1] == 'c')
|
||||
{
|
||||
if (E_UNMARSHAL(vopret, ss >> dummyEvalcode; ss >> funcid; ss >> origpubkey; ss >> name; ss >> description;
|
||||
while (!ss.eof()) {
|
||||
ss >> opretId;
|
||||
if (!ss.eof()) {
|
||||
ss >> vblob;
|
||||
oprets.push_back(std::make_pair(opretId, vblob));
|
||||
}
|
||||
}))
|
||||
{
|
||||
return(funcid);
|
||||
}
|
||||
}
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenCreateOpRet() incorrect token create opret" << std::endl);
|
||||
return (uint8_t)0;
|
||||
}
|
||||
|
||||
@@ -183,99 +63,6 @@ uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t>
|
||||
// for 'c' returns only funcid. NOTE: nonfungible data is not returned
|
||||
uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<std::pair<uint8_t, vscript_t>> &oprets)
|
||||
{
|
||||
vscript_t vopret, vblob, dummyPubkey, vnonfungibleDummy;
|
||||
uint8_t funcId = 0, *script, dummyEvalCode, dummyFuncId, ccType, opretId = 0;
|
||||
std::string dummyName; std::string dummyDescription;
|
||||
uint256 dummySrcTokenId;
|
||||
CPubKey voutPubkey1, voutPubkey2;
|
||||
|
||||
vscript_t voldstyledata;
|
||||
bool foundOldstyle = false;
|
||||
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
script = (uint8_t *)vopret.data();
|
||||
tokenid = zeroid;
|
||||
oprets.clear();
|
||||
|
||||
if (script != NULL && vopret.size() > 2)
|
||||
{
|
||||
evalCodeTokens = script[0];
|
||||
if (evalCodeTokens != EVAL_TOKENS) {
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() incorrect evalcode in tokens opret" << std::endl);
|
||||
return (uint8_t)0;
|
||||
}
|
||||
|
||||
funcId = script[1];
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "DecodeTokenOpRet() decoded funcId=" << (char)(funcId ? funcId : ' ') << std::endl);
|
||||
|
||||
switch (funcId)
|
||||
{
|
||||
case 'c':
|
||||
return DecodeTokenCreateOpRet(scriptPubKey, dummyPubkey, dummyName, dummyDescription, oprets);
|
||||
|
||||
case 't':
|
||||
|
||||
// compatibility with old-style rogue or assets data (with no opretid):
|
||||
// try to unmarshal old-style rogue or assets data:
|
||||
foundOldstyle = E_UNMARSHAL(vopret, ss >> dummyEvalCode; ss >> dummyFuncId; ss >> tokenid; ss >> ccType;
|
||||
if (ccType >= 1) ss >> voutPubkey1;
|
||||
if (ccType == 2) ss >> voutPubkey2;
|
||||
if (!ss.eof()) {
|
||||
ss >> voldstyledata;
|
||||
}) && voldstyledata.size() >= 2 &&
|
||||
(voldstyledata.begin()[0] == 0x11 /*EVAL_ROGUE*/ && IS_CHARINSTR(voldstyledata.begin()[1], "RHQKG") ||
|
||||
voldstyledata.begin()[0] == EVAL_ASSETS && IS_CHARINSTR(voldstyledata.begin()[1], "sbSBxo")) ;
|
||||
|
||||
if (foundOldstyle || // fix for compatibility with old style data (no opretid)
|
||||
E_UNMARSHAL(vopret, ss >> dummyEvalCode; ss >> dummyFuncId; ss >> tokenid; ss >> ccType;
|
||||
if (ccType >= 1) ss >> voutPubkey1;
|
||||
if (ccType == 2) ss >> voutPubkey2;
|
||||
while (!ss.eof()) {
|
||||
ss >> opretId;
|
||||
if (!ss.eof()) {
|
||||
ss >> vblob;
|
||||
oprets.push_back(std::make_pair(opretId, vblob));
|
||||
}
|
||||
}))
|
||||
{
|
||||
if (!(ccType >= 0 && ccType <= 2)) { //incorrect ccType
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() incorrect ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
|
||||
return (uint8_t)0;
|
||||
}
|
||||
|
||||
// add verification pubkeys:
|
||||
voutPubkeys.clear();
|
||||
if (voutPubkey1.IsValid())
|
||||
voutPubkeys.push_back(voutPubkey1);
|
||||
if (voutPubkey2.IsValid())
|
||||
voutPubkeys.push_back(voutPubkey2);
|
||||
|
||||
tokenid = revuint256(tokenid);
|
||||
|
||||
if (foundOldstyle) { //patch for old-style opret data with no opretid
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "DecodeTokenOpRet() found old-style rogue/asset data, evalcode=" << (int)voldstyledata.begin()[0] << " funcid=" << (char)voldstyledata.begin()[1] << " for tokenid=" << revuint256(tokenid).GetHex() << std::endl);
|
||||
uint8_t opretIdRestored;
|
||||
if (voldstyledata.begin()[0] == 0x11 /*EVAL_ROGUE*/)
|
||||
opretIdRestored = OPRETID_ROGUEGAMEDATA;
|
||||
else // EVAL_ASSETS
|
||||
opretIdRestored = OPRETID_ASSETSDATA;
|
||||
|
||||
oprets.push_back(std::make_pair(opretIdRestored, voldstyledata));
|
||||
}
|
||||
|
||||
return(funcId);
|
||||
}
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() bad opret format," << " ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
|
||||
return (uint8_t)0;
|
||||
|
||||
default:
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() illegal funcid=" << (int)funcId << std::endl);
|
||||
return (uint8_t)0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() empty opret, could not parse" << std::endl);
|
||||
}
|
||||
return (uint8_t)0;
|
||||
}
|
||||
|
||||
@@ -328,27 +115,20 @@ CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk) {
|
||||
CTxOut MakeTokensCC1of2vout(uint8_t evalcode, uint8_t evalcode2, CAmount nValue, CPubKey pk1, CPubKey pk2)
|
||||
{
|
||||
CTxOut vout;
|
||||
CC *payoutCond = MakeTokensCCcond1of2(evalcode, evalcode2, pk1, pk2);
|
||||
vout = CTxOut(nValue, CCPubKey(payoutCond));
|
||||
cc_free(payoutCond);
|
||||
return(vout);
|
||||
}
|
||||
// overload to make two-eval (token+evalcode) 1of2 cc vout:
|
||||
CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2) {
|
||||
return MakeTokensCC1of2vout(evalcode, 0, nValue, pk1, pk2);
|
||||
return CTxOut();
|
||||
}
|
||||
|
||||
// make three-eval (token+evalcode+evalcode2) cc vout:
|
||||
CTxOut MakeTokensCC1vout(uint8_t evalcode, uint8_t evalcode2, CAmount nValue, CPubKey pk)
|
||||
{
|
||||
CTxOut vout;
|
||||
CC *payoutCond = MakeTokensCCcond1(evalcode, evalcode2, pk);
|
||||
vout = CTxOut(nValue, CCPubKey(payoutCond));
|
||||
cc_free(payoutCond);
|
||||
return(vout);
|
||||
return CTxOut();
|
||||
}
|
||||
// overload to make two-eval (token+evalcode) cc vout:
|
||||
CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk) {
|
||||
return MakeTokensCC1vout(evalcode, 0, nValue, pk);
|
||||
return CTxOut();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,25 +41,6 @@ void endiancpy(uint8_t *dest,uint8_t *src,int32_t len)
|
||||
#endif
|
||||
}
|
||||
|
||||
CC *MakeCCcond1of2(uint8_t evalcode,CPubKey pk1,CPubKey pk2)
|
||||
{
|
||||
std::vector<CC*> pks;
|
||||
pks.push_back(CCNewSecp256k1(pk1));
|
||||
pks.push_back(CCNewSecp256k1(pk2));
|
||||
CC *condCC = CCNewEval(E_MARSHAL(ss << evalcode));
|
||||
CC *Sig = CCNewThreshold(1, pks);
|
||||
return CCNewThreshold(2, {condCC, Sig});
|
||||
}
|
||||
|
||||
CC *MakeCCcond1(uint8_t evalcode,CPubKey pk)
|
||||
{
|
||||
std::vector<CC*> pks;
|
||||
pks.push_back(CCNewSecp256k1(pk));
|
||||
CC *condCC = CCNewEval(E_MARSHAL(ss << evalcode));
|
||||
CC *Sig = CCNewThreshold(1, pks);
|
||||
return CCNewThreshold(2, {condCC, Sig});
|
||||
}
|
||||
|
||||
int32_t has_opret(const CTransaction &tx, uint8_t evalcode)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -73,83 +54,31 @@ int32_t has_opret(const CTransaction &tx, uint8_t evalcode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool getCCopret(const CScript &scriptPubKey, CScript &opret)
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vParams = std::vector<std::vector<unsigned char>>();
|
||||
CScript dummy; bool ret = false;
|
||||
if ( scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) != 0 )
|
||||
{
|
||||
ret = true;
|
||||
if ( vParams.size() == 1)
|
||||
{
|
||||
opret = CScript(vParams[0].begin()+6, vParams[0].end());
|
||||
//fprintf(stderr, "vparams.%s\n", HexStr(vParams[0].begin(), vParams[0].end()).c_str());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool makeCCopret(CScript &opret, std::vector<std::vector<unsigned char>> &vData)
|
||||
{
|
||||
if ( opret.empty() )
|
||||
return false;
|
||||
vData.push_back(std::vector<unsigned char>(opret.begin(), opret.end()));
|
||||
return true;
|
||||
}
|
||||
|
||||
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue, CPubKey pk, std::vector<std::vector<unsigned char>>* vData)
|
||||
{
|
||||
CTxOut vout;
|
||||
CC *payoutCond = MakeCCcond1(evalcode,pk);
|
||||
vout = CTxOut(nValue,CCPubKey(payoutCond));
|
||||
if ( vData )
|
||||
{
|
||||
//std::vector<std::vector<unsigned char>> vtmpData = std::vector<std::vector<unsigned char>>(vData->begin(), vData->end());
|
||||
std::vector<CPubKey> vPubKeys = std::vector<CPubKey>();
|
||||
//vPubKeys.push_back(pk);
|
||||
COptCCParams ccp = COptCCParams(COptCCParams::VERSION, evalcode, 1, 1, vPubKeys, ( * vData));
|
||||
vout.scriptPubKey << ccp.AsVector() << OP_DROP;
|
||||
}
|
||||
cc_free(payoutCond);
|
||||
return(vout);
|
||||
}
|
||||
|
||||
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2, std::vector<std::vector<unsigned char>>* vData)
|
||||
{
|
||||
CTxOut vout;
|
||||
CC *payoutCond = MakeCCcond1of2(evalcode,pk1,pk2);
|
||||
vout = CTxOut(nValue,CCPubKey(payoutCond));
|
||||
if ( vData )
|
||||
{
|
||||
//std::vector<std::vector<unsigned char>> vtmpData = std::vector<std::vector<unsigned char>>(vData->begin(), vData->end());
|
||||
std::vector<CPubKey> vPubKeys = std::vector<CPubKey>();
|
||||
// skip pubkeys. These need to maybe be optional and we need some way to get them out that is easy!
|
||||
//vPubKeys.push_back(pk1);
|
||||
//vPubKeys.push_back(pk2);
|
||||
COptCCParams ccp = COptCCParams(COptCCParams::VERSION, evalcode, 1, 2, vPubKeys, ( * vData));
|
||||
vout.scriptPubKey << ccp.AsVector() << OP_DROP;
|
||||
}
|
||||
cc_free(payoutCond);
|
||||
return(vout);
|
||||
}
|
||||
|
||||
CC* GetCryptoCondition(CScript const& scriptSig)
|
||||
{
|
||||
auto pc = scriptSig.begin();
|
||||
opcodetype opcode;
|
||||
std::vector<unsigned char> ffbin;
|
||||
if (scriptSig.GetOp(pc, opcode, ffbin))
|
||||
return cc_readFulfillmentBinary((uint8_t*)ffbin.data(), ffbin.size()-1);
|
||||
else return(0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool IsCCInput(CScript const& scriptSig)
|
||||
{
|
||||
CC *cond;
|
||||
if ( (cond= GetCryptoCondition(scriptSig)) == 0 )
|
||||
return false;
|
||||
cc_free(cond);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime, int64_t &actualtxfee)
|
||||
@@ -308,68 +237,34 @@ CPubKey CCCustomtxidaddr(char *txidaddr,uint256 txid,uint8_t taddr,uint8_t prefi
|
||||
|
||||
bool _GetCCaddress(char *destaddr,uint8_t evalcode,CPubKey pk)
|
||||
{
|
||||
CC *payoutCond;
|
||||
destaddr[0] = 0;
|
||||
if ( (payoutCond= MakeCCcond1(evalcode,pk)) != 0 )
|
||||
{
|
||||
Getscriptaddress(destaddr,CCPubKey(payoutCond));
|
||||
cc_free(payoutCond);
|
||||
}
|
||||
return(destaddr[0] != 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk)
|
||||
{
|
||||
destaddr[0] = 0;
|
||||
if ( pk.size() == 0 )
|
||||
pk = GetUnspendable(cp,0);
|
||||
return(_GetCCaddress(destaddr,cp->evalcode,pk));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool _GetTokensCCaddress(char *destaddr, uint8_t evalcode, uint8_t evalcode2, CPubKey pk)
|
||||
{
|
||||
CC *payoutCond;
|
||||
destaddr[0] = 0;
|
||||
if ((payoutCond = MakeTokensCCcond1(evalcode, evalcode2, pk)) != 0)
|
||||
{
|
||||
Getscriptaddress(destaddr, CCPubKey(payoutCond));
|
||||
cc_free(payoutCond);
|
||||
}
|
||||
return(destaddr[0] != 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get scriptPubKey adddress for three/dual eval token cc vout
|
||||
bool GetTokensCCaddress(struct CCcontract_info *cp, char *destaddr, CPubKey pk)
|
||||
{
|
||||
destaddr[0] = 0;
|
||||
if (pk.size() == 0)
|
||||
pk = GetUnspendable(cp, 0);
|
||||
return(_GetTokensCCaddress(destaddr, cp->evalcode, cp->additionalTokensEvalcode2, pk));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2)
|
||||
{
|
||||
CC *payoutCond;
|
||||
destaddr[0] = 0;
|
||||
if ( (payoutCond= MakeCCcond1of2(cp->evalcode,pk,pk2)) != 0 )
|
||||
{
|
||||
Getscriptaddress(destaddr,CCPubKey(payoutCond));
|
||||
cc_free(payoutCond);
|
||||
}
|
||||
return(destaddr[0] != 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey pk, CPubKey pk2)
|
||||
{
|
||||
CC *payoutCond;
|
||||
destaddr[0] = 0;
|
||||
if ((payoutCond = MakeTokensCCcond1of2(cp->evalcode, cp->additionalTokensEvalcode2, pk, pk2)) != 0) // if additionalTokensEvalcode2 not set then it is dual-eval cc else three-eval cc
|
||||
{
|
||||
Getscriptaddress(destaddr, CCPubKey(payoutCond));
|
||||
cc_free(payoutCond);
|
||||
}
|
||||
return(destaddr[0] != 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConstrainVout(CTxOut vout, int32_t CCflag, char *cmpaddr, int64_t nValue)
|
||||
|
||||
@@ -84,25 +84,5 @@ UniValue custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
|
||||
bool custom_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
|
||||
{
|
||||
char expectedaddress[64]; CPubKey pk;
|
||||
CScript opret; int32_t numvout = 0;
|
||||
if ( has_opret(tx, EVAL_CUSTOM) == 0 )
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vParams = std::vector<std::vector<unsigned char>>();
|
||||
if ( getCCopret(tx.vout[0].scriptPubKey,opret) )
|
||||
numvout = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
opret = tx.vout[1].scriptPubKey;
|
||||
numvout = 2;
|
||||
}
|
||||
if ( tx.vout.size() != numvout ) // make sure the tx only has appropriate outputs
|
||||
return eval->Invalid("invalid number of vouts");
|
||||
else if ( custom_opretdecode(pk,opret) != '1' ) // verify opreturn payload
|
||||
return eval->Invalid("invalid opreturn");
|
||||
GetCCaddress(cp,expectedaddress,pk);
|
||||
if ( IsCClibvout(cp,tx,0,expectedaddress) == COIN ) // make sure amount and destination matches
|
||||
return(true);
|
||||
else return eval->Invalid("invalid vout0 amount");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -20,30 +20,18 @@
|
||||
|
||||
bool IsCryptoConditionsEnabled()
|
||||
{
|
||||
return 0 != ASSETCHAINS_CC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool IsSupportedCryptoCondition(const CC *cond)
|
||||
{
|
||||
int mask = cc_typeMask(cond);
|
||||
|
||||
if (mask & ~CCEnabledTypes) return false;
|
||||
|
||||
// Also require that the condition have at least one signable node
|
||||
if (!(mask & CCSigningNodes)) return false;
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool IsSignedCryptoCondition(const CC *cond)
|
||||
{
|
||||
if (!cc_isFulfilled(cond)) return false;
|
||||
if (1 << cc_typeId(cond) & CCSigningNodes) return true;
|
||||
if (cc_typeId(cond) == CC_Threshold)
|
||||
for (int i=0; i<cond->size; i++)
|
||||
if (IsSignedCryptoCondition(cond->subconditions[i])) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -87,19 +75,13 @@ CC* CCNewEval(std::vector<unsigned char> code)
|
||||
|
||||
CScript CCPubKey(const CC *cond)
|
||||
{
|
||||
unsigned char buf[1000];
|
||||
size_t len = cc_conditionBinary(cond, buf);
|
||||
return CScript() << std::vector<unsigned char>(buf, buf+len) << OP_CHECKCRYPTOCONDITION;
|
||||
return CScript();
|
||||
}
|
||||
|
||||
|
||||
CScript CCSig(const CC *cond)
|
||||
{
|
||||
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;
|
||||
return CScript();
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CCSigVec(const CC *cond)
|
||||
@@ -114,20 +96,6 @@ std::vector<unsigned char> CCSigVec(const CC *cond)
|
||||
std::string CCShowStructure(CC *cond)
|
||||
{
|
||||
std::string out;
|
||||
if (cc_isAnon(cond)) {
|
||||
out = "A" + std::to_string(cc_typeId(cond));
|
||||
}
|
||||
else if (cc_typeId(cond) == CC_Threshold) {
|
||||
out += "(" + std::to_string(cond->threshold) + " of ";
|
||||
for (int i=0; i<cond->size; i++) {
|
||||
out += CCShowStructure(cond->subconditions[i]);
|
||||
if (i < cond->size - 1) out += ",";
|
||||
}
|
||||
out += ")";
|
||||
}
|
||||
else {
|
||||
out = std::to_string(cc_typeId(cond));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user