Hush Full Node software. We were censored from Github, this is where all development happens now. https://hush.is
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

671 lines
24 KiB

/******************************************************************************
* Copyright © 2014-2019 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
/*
CCutils has low level functions that are universally useful for all contracts.
*/
#include "CCinclude.h"
#include "komodo_structs.h"
#ifdef TESTMODE
#define MIN_NON_NOTARIZED_CONFIRMS 2
#else
#define MIN_NON_NOTARIZED_CONFIRMS 101
#endif // TESTMODE
int32_t komodo_dpowconfs(int32_t height,int32_t numconfs);
struct komodo_state *komodo_stateptr(char *symbol,char *dest);
extern uint32_t KOMODO_DPOWCONFS;
6 years ago
void endiancpy(uint8_t *dest,uint8_t *src,int32_t len)
{
int32_t i,j=0;
#if defined(WORDS_BIGENDIAN)
for (i=31; i>=0; i--)
dest[j++] = src[i];
#else
memcpy(dest,src,len);
#endif
}
6 years ago
CC *MakeCCcond1of2(uint8_t evalcode,CPubKey pk1,CPubKey pk2)
{
std::vector<CC*> pks;
pks.push_back(CCNewSecp256k1(pk1));
6 years ago
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});
}
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk)
{
CTxOut vout;
CC *payoutCond = MakeCCcond1(evalcode,pk);
vout = CTxOut(nValue,CCPubKey(payoutCond));
cc_free(payoutCond);
return(vout);
}
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2)
6 years ago
{
CTxOut vout;
CC *payoutCond = MakeCCcond1of2(evalcode,pk1,pk2);
6 years ago
vout = CTxOut(nValue,CCPubKey(payoutCond));
cc_free(payoutCond);
return(vout);
}
// make three-eval (token+evalcode+evalcode2) 1of2 cryptocondition:
CC *MakeTokensCCcond1of2(uint8_t evalcode, uint8_t evalcode2, CPubKey pk1, CPubKey pk2)
{
// make 1of2 sigs cond
std::vector<CC*> pks;
pks.push_back(CCNewSecp256k1(pk1));
pks.push_back(CCNewSecp256k1(pk2));
std::vector<CC*> thresholds;
thresholds.push_back( CCNewEval(E_MARSHAL(ss << evalcode)) );
if( evalcode != EVAL_TOKENS ) // if evalCode == EVAL_TOKENS, it is actually MakeCCcond1of2()!
thresholds.push_back(CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS))); // this is eval token cc
if( evalcode2 != 0 )
thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode2))); // add optional additional evalcode
thresholds.push_back(CCNewThreshold(1, pks)); // this is 1 of 2 sigs cc
return CCNewThreshold(thresholds.size(), thresholds);
}
// overload to make two-eval (token+evalcode) 1of2 cryptocondition:
CC *MakeTokensCCcond1of2(uint8_t evalcode, CPubKey pk1, CPubKey pk2) {
return MakeTokensCCcond1of2(evalcode, 0, pk1, pk2);
}
// make three-eval (token+evalcode+evalcode2) cryptocondition:
CC *MakeTokensCCcond1(uint8_t evalcode, uint8_t evalcode2, CPubKey pk)
{
std::vector<CC*> pks;
pks.push_back(CCNewSecp256k1(pk));
std::vector<CC*> thresholds;
thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode)));
if (evalcode != EVAL_TOKENS) // if evalCode == EVAL_TOKENS, it is actually MakeCCcond1()!
thresholds.push_back(CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS))); // this is eval token cc
if (evalcode2 != 0)
thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode2))); // add optional additional evalcode
thresholds.push_back(CCNewThreshold(1, pks)); // signature
return CCNewThreshold(thresholds.size(), thresholds);
}
// overload to make two-eval (token+evalcode) cryptocondition:
CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk) {
return MakeTokensCCcond1(evalcode, 0, pk);
}
// make three-eval (token+evalcode+evalcode2) 1of2 cc vout:
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);
}
// 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);
}
// overload to make two-eval (token+evalcode) cc vout:
CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk) {
return MakeTokensCC1vout(evalcode, 0, nValue, pk);
}
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);
}
bool IsCCInput(CScript const& scriptSig)
{
CC *cond;
if ( (cond= GetCryptoCondition(scriptSig)) == 0 )
return false;
cc_free(cond);
return true;
}
6 years ago
// set additional 'unspendable' addr
void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr)
6 years ago
{
cp->unspendableEvalcode2 = evalcode;
6 years ago
cp->unspendablepk2 = pk;
memcpy(cp->unspendablepriv2,priv,32);
strcpy(cp->unspendableaddr2,coinaddr);
}
// set yet another additional 'unspendable' addr
void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr)
6 years ago
{
cp->unspendableEvalcode3 = evalcode;
6 years ago
cp->unspendablepk3 = pk;
memcpy(cp->unspendablepriv3,priv,32);
strcpy(cp->unspendableaddr3,coinaddr);
}
// set pubkeys, myprivkey and 1of2 cc addr for spending from 1of2 cryptocondition vout:
5 years ago
void CCaddr1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2,uint8_t *priv,char *coinaddr)
{
cp->coins1of2pk[0] = pk1;
cp->coins1of2pk[1] = pk2;
5 years ago
memcpy(cp->coins1of2priv,priv,32);
strcpy(cp->coins1of2addr,coinaddr);
}
// set pubkeys, myprivkey and 1of2 cc addr for spending from 1of2 token cryptocondition vout
// to get tokenaddr use GetTokensCCaddress()
void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *tokenaddr)
{
cp->tokens1of2pk[0] = pk1;
cp->tokens1of2pk[1] = pk2;
strcpy(cp->tokens1of2addr, tokenaddr);
}
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey)
{
CTxDestination address; txnouttype whichType;
if ( ExtractDestination(scriptPubKey,address) != 0 )
{
strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str());
return(true);
}
//fprintf(stderr,"ExtractDestination failed\n");
return(false);
}
bool GetCustomscriptaddress(char *destaddr,const CScript &scriptPubKey,uint8_t taddr,uint8_t prefix, uint8_t prefix2)
{
CTxDestination address; txnouttype whichType;
if ( ExtractDestination(scriptPubKey,address) != 0 )
{
strcpy(destaddr,(char *)CCustomBitcoinAddress(address,taddr,prefix,prefix2).ToString().c_str());
return(true);
}
//fprintf(stderr,"ExtractDestination failed\n");
return(false);
}
bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn,
CTransaction &txOut, std::vector<std::vector<unsigned char>> &preConditions, std::vector<std::vector<unsigned char>> &params)
{
uint256 blockHash;
if (myGetTransaction(tx.vin[nIn].prevout.hash, txOut, blockHash) && txOut.vout.size() > tx.vin[nIn].prevout.n)
{
CBlockIndex index;
if (eval->GetBlock(blockHash, index))
{
// read preconditions
CScript subScript = CScript();
preConditions.clear();
if (txOut.vout[tx.vin[nIn].prevout.n].scriptPubKey.IsPayToCryptoCondition(&subScript, preConditions))
{
// read any available parameters in the output transaction
params.clear();
if (tx.vout.size() > 0 && tx.vout[tx.vout.size() - 1].scriptPubKey.IsOpReturn())
{
if (tx.vout[tx.vout.size() - 1].scriptPubKey.GetOpretData(params) && params.size() == 1)
{
CScript scr = CScript(params[0].begin(), params[0].end());
// printf("Script decoding inner:\n%s\nouter:\n%s\n", scr.ToString().c_str(), tx.vout[tx.vout.size() - 1].scriptPubKey.ToString().c_str());
if (!scr.GetPushedData(scr.begin(), params))
{
return false;
}
else return true;
}
else return false;
}
else return true;
}
}
}
return false;
6 years ago
//fprintf(stderr,"ExtractDestination failed\n");
return(false);
}
6 years ago
bool pubkey2addr(char *destaddr,uint8_t *pubkey33)
{
std::vector<uint8_t>pk; int32_t i;
for (i=0; i<33; i++)
pk.push_back(pubkey33[i]);
return(Getscriptaddress(destaddr,CScript() << pk << OP_CHECKSIG));
}
CPubKey CCtxidaddr(char *txidaddr,uint256 txid)
{
uint8_t buf33[33]; CPubKey pk;
buf33[0] = 0x02;
endiancpy(&buf33[1],(uint8_t *)&txid,32);
pk = buf2pk(buf33);
6 years ago
Getscriptaddress(txidaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG);
return(pk);
}
CPubKey CCCustomtxidaddr(char *txidaddr,uint256 txid,uint8_t taddr,uint8_t prefix,uint8_t prefix2)
{
uint8_t buf33[33]; CPubKey pk;
buf33[0] = 0x02;
endiancpy(&buf33[1],(uint8_t *)&txid,32);
pk = buf2pk(buf33);
GetCustomscriptaddress(txidaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG,taddr,prefix,prefix2);
return(pk);
}
bool _GetCCaddress(char *destaddr,uint8_t evalcode,CPubKey pk)
6 years ago
{
CC *payoutCond;
destaddr[0] = 0;
if ( (payoutCond= MakeCCcond1(evalcode,pk)) != 0 )
6 years ago
{
Getscriptaddress(destaddr,CCPubKey(payoutCond));
cc_free(payoutCond);
6 years ago
}
return(destaddr[0] != 0);
}
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));
}
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);
}
// 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));
}
bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2)
6 years ago
{
CC *payoutCond;
destaddr[0] = 0;
if ( (payoutCond= MakeCCcond1of2(cp->evalcode,pk,pk2)) != 0 )
{
Getscriptaddress(destaddr,CCPubKey(payoutCond));
cc_free(payoutCond);
6 years ago
}
return(destaddr[0] != 0);
}
// get scriptPubKey adddress for three/dual eval token 1of2 cc vout
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);
}
bool ConstrainVout(CTxOut vout, int32_t CCflag, char *cmpaddr, int64_t nValue)
6 years ago
{
char destaddr[64];
if ( vout.scriptPubKey.IsPayToCryptoCondition() != CCflag )
6 years ago
{
fprintf(stderr,"constrain vout error isCC %d vs %d CCflag\n", vout.scriptPubKey.IsPayToCryptoCondition(), CCflag);
6 years ago
return(false);
6 years ago
}
else if ( cmpaddr != 0 && (Getscriptaddress(destaddr, vout.scriptPubKey) == 0 || strcmp(destaddr, cmpaddr) != 0) )
6 years ago
{
fprintf(stderr,"constrain vout error: check addr %s vs script addr %s\n", cmpaddr!=0?cmpaddr:"", destaddr!=0?destaddr:"");
6 years ago
return(false);
6 years ago
}
6 years ago
else if ( nValue != 0 && nValue != vout.nValue ) //(nValue == 0 && vout.nValue < 10000) || (
6 years ago
{
fprintf(stderr,"constrain vout error nValue %.8f vs %.8f\n",(double)nValue/COIN,(double)vout.nValue/COIN);
6 years ago
return(false);
6 years ago
}
6 years ago
else return(true);
}
6 years ago
bool PreventCC(Eval* eval,const CTransaction &tx,int32_t preventCCvins,int32_t numvins,int32_t preventCCvouts,int32_t numvouts)
6 years ago
{
int32_t i;
if ( preventCCvins >= 0 )
{
for (i=preventCCvins; i<numvins; i++)
{
if ( IsCCInput(tx.vin[i].scriptSig) != 0 )
return eval->Invalid("invalid CC vin");
}
}
if ( preventCCvouts >= 0 )
{
for (i=preventCCvouts; i<numvouts; i++)
{
if ( tx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 )
6 years ago
{
fprintf(stderr,"vout.%d is CC\n",i);
6 years ago
return eval->Invalid("invalid CC vout");
6 years ago
}
6 years ago
}
}
return(true);
}
5 years ago
bool priv2addr(char *coinaddr,uint8_t *buf33,uint8_t priv32[32])
{
CKey priv; CPubKey pk; int32_t i; uint8_t *src;
priv.SetKey32(priv32);
pk = priv.GetPubKey();
if ( buf33 != 0 )
{
src = (uint8_t *)pk.begin();
for (i=0; i<33; i++)
buf33[i] = src[i];
}
return(Getscriptaddress(coinaddr, CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG));
}
std::vector<uint8_t> Mypubkey()
{
extern uint8_t NOTARY_PUBKEY33[33];
std::vector<uint8_t> pubkey; int32_t i; uint8_t *dest,*pubkey33;
pubkey33 = NOTARY_PUBKEY33;
pubkey.resize(33);
dest = pubkey.data();
for (i=0; i<33; i++)
dest[i] = pubkey33[i];
return(pubkey);
}
bool Myprivkey(uint8_t myprivkey[])
{
5 years ago
char coinaddr[64],checkaddr[64]; std::string strAddress; char *dest; int32_t i,n; CBitcoinAddress address; CKeyID keyID; CKey vchSecret; uint8_t buf33[33];
if ( Getscriptaddress(coinaddr,CScript() << Mypubkey() << OP_CHECKSIG) != 0 )
{
n = (int32_t)strlen(coinaddr);
strAddress.resize(n+1);
dest = (char *)strAddress.data();
for (i=0; i<n; i++)
dest[i] = coinaddr[i];
dest[i] = 0;
if ( address.SetString(strAddress) != 0 && address.GetKeyID(keyID) != 0 )
{
#ifdef ENABLE_WALLET
if ( pwalletMain->GetKey(keyID,vchSecret) != 0 )
{
memcpy(myprivkey,vchSecret.begin(),32);
5 years ago
if ( 0 )
{
for (i=0; i<32; i++)
fprintf(stderr,"0x%02x, ",myprivkey[i]);
fprintf(stderr," found privkey for %s!\n",dest);
}
5 years ago
if ( priv2addr(checkaddr,buf33,myprivkey) != 0 )
{
if ( buf2pk(buf33) == Mypubkey() && strcmp(checkaddr,coinaddr) == 0 )
return(true);
else printf("mismatched privkey -> addr %s vs %s\n",checkaddr,coinaddr);
}
return(false);
}
#endif
}
}
fprintf(stderr,"privkey for the -pubkey= address is not in the wallet, importprivkey!\n");
return(false);
}
CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv)
6 years ago
{
if ( unspendablepriv != 0 )
memcpy(unspendablepriv,cp->CCpriv,32);
return(pubkey2pk(ParseHex(cp->CChexstr)));
}
void CCclearvars(struct CCcontract_info *cp)
6 years ago
{
cp->unspendableEvalcode2 = cp->unspendableEvalcode3 = 0;
6 years ago
cp->unspendableaddr2[0] = cp->unspendableaddr3[0] = 0;
6 years ago
}
int64_t CCduration(int32_t &numblocks,uint256 txid)
{
CTransaction tx; uint256 hashBlock; uint32_t txheight,txtime=0; char str[65]; CBlockIndex *pindex; int64_t duration = 0;
numblocks = 0;
6 years ago
if ( myGetTransaction(txid,tx,hashBlock) == 0 )
{
6 years ago
//fprintf(stderr,"CCduration cant find duration txid %s\n",uint256_str(str,txid));
return(0);
}
6 years ago
else if ( hashBlock == zeroid )
{
6 years ago
//fprintf(stderr,"CCduration no hashBlock for txid %s\n",uint256_str(str,txid));
6 years ago
return(0);
}
else if ( (pindex= komodo_getblockindex(hashBlock)) == 0 || (txtime= pindex->nTime) == 0 || (txheight= pindex->GetHeight()) <= 0 )
6 years ago
{
fprintf(stderr,"CCduration no txtime %u or txheight.%d %p for txid %s\n",txtime,txheight,pindex,uint256_str(str,txid));
6 years ago
return(0);
}
else if ( (pindex= chainActive.LastTip()) == 0 || pindex->nTime < txtime || pindex->GetHeight() <= txheight )
6 years ago
{
6 years ago
if ( pindex->nTime < txtime )
fprintf(stderr,"CCduration backwards timestamps %u %u for txid %s hts.(%d %d)\n",(uint32_t)pindex->nTime,txtime,uint256_str(str,txid),txheight,(int32_t)pindex->GetHeight());
6 years ago
return(0);
}
numblocks = (pindex->GetHeight() - txheight);
6 years ago
duration = (pindex->nTime - txtime);
//fprintf(stderr,"duration %d (%u - %u) numblocks %d (%d - %d)\n",(int32_t)duration,(uint32_t)pindex->nTime,txtime,numblocks,pindex->GetHeight(),txheight);
return(duration);
}
bool komodo_txnotarizedconfirmed(uint256 txid)
6 years ago
{
char str[65];
6 years ago
uint32_t confirms,notarized=0,txheight;
CTransaction tx;
uint256 hashBlock;
CBlockIndex *pindex;
char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp;
6 years ago
if ( myGetTransaction(txid,tx,hashBlock) == 0 )
{
fprintf(stderr,"komodo_txnotarizedconfirmed cant find txid %s\n",txid.ToString().c_str());
return(0);
}
else if ( hashBlock == zeroid )
{
fprintf(stderr,"komodo_txnotarizedconfirmed no hashBlock for txid %s\n",txid.ToString().c_str());
return(0);
}
else if ( (pindex= mapBlockIndex[hashBlock]) == 0 || (txheight= pindex->GetHeight()) <= 0 )
{
fprintf(stderr,"komodo_txnotarizedconfirmed no txheight.%d %p for txid %s\n",txheight,pindex,txid.ToString().c_str());
return(0);
}
else if ( (pindex= chainActive.LastTip()) == 0 || pindex->GetHeight() < txheight )
{
fprintf(stderr,"komodo_txnotarizedconfirmed backwards heights for txid %s hts.(%d %d)\n",txid.ToString().c_str(),txheight,(int32_t)pindex->GetHeight());
return(0);
}
confirms=1 + pindex->GetHeight() - txheight;
if ((sp= komodo_stateptr(symbol,dest)) != 0 && (notarized=sp->NOTARIZED_HEIGHT) > 0 && txheight > sp->NOTARIZED_HEIGHT) notarized=0;
#ifdef TESTMODE
notarized=0;
#endif //TESTMODE
if (notarized>0 && confirms > 1)
return (true);
else if (notarized==0 && confirms >= MIN_NON_NOTARIZED_CONFIRMS)
6 years ago
return (true);
return (false);
}
CPubKey check_signing_pubkey(CScript scriptSig)
{
bool found = false;
CPubKey pubkey;
auto findEval = [](CC *cond, struct CCVisitor _) {
bool r = false;
if (cc_typeId(cond) == CC_Secp256k1) {
*(CPubKey*)_.context=buf2pk(cond->publicKey);
r = true;
}
// false for a match, true for continue
return r ? 0 : 1;
};
CC *cond = GetCryptoCondition(scriptSig);
if (cond) {
CCVisitor visitor = { findEval, (uint8_t*)"", 0, &pubkey };
bool out = !cc_visit(cond, visitor);
cc_free(cond);
if (pubkey.IsValid()) {
return pubkey;
}
}
return CPubKey();
}
5 years ago
bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector<uint8_t> paramsNull,const CTransaction &ctx, unsigned int nIn)
5 years ago
{
CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector<uint8_t> origpubkey;
height = KOMODO_CONNECTING;
if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation
return(true);
if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE )
return eval->Invalid("CC are disabled or not active yet");
if ( (KOMODO_CONNECTING & (1<<30)) != 0 )
{
from_mempool = 1;
height &= ((1<<30) - 1);
}
if (cp->validate == NULL)
return eval->Invalid("validation not supported for eval code");
5 years ago
//fprintf(stderr,"KOMODO_CONNECTING.%d mempool.%d vs CCactive.%d\n",height,from_mempool,KOMODO_CCACTIVATE);
// there is a chance CC tx is valid in mempool, but invalid when in block, so we cant filter duplicate requests. if any of the vins are spent, for example
//txid = ctx.GetHash();
//if ( txid == cp->prevtxid )
// return(true);
//fprintf(stderr,"process CC %02x\n",cp->evalcode);
CCclearvars(cp);
if ( paramsNull.size() != 0 ) // Don't expect params
return eval->Invalid("Cannot have params");
//else if ( ctx.vout.size() == 0 ) // spend can go to z-addresses
// return eval->Invalid("no-vouts");
else if ( (*cp->validate)(cp,eval,ctx,nIn) != 0 )
{
//fprintf(stderr,"done CC %02x\n",cp->evalcode);
//cp->prevtxid = txid;
return(true);
}
//fprintf(stderr,"invalid CC %02x\n",cp->evalcode);
return(false);
}
extern struct CCcontract_info CCinfos[0x100];
5 years ago
extern std::string MYCCLIBNAME;
bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn);
5 years ago
5 years ago
bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector<uint8_t> paramsNull,const CTransaction &txTo,unsigned int nIn)
{
uint8_t evalcode; int32_t height,from_mempool; struct CCcontract_info *cp;
5 years ago
if ( ASSETCHAINS_CCLIB != MYCCLIBNAME )
{
5 years ago
fprintf(stderr,"-ac_cclib=%s vs myname %s\n",ASSETCHAINS_CCLIB.c_str(),MYCCLIBNAME.c_str());
5 years ago
return eval->Invalid("-ac_cclib name mismatches myname");
}
height = KOMODO_CONNECTING;
if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation
return(true);
if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE )
return eval->Invalid("CC are disabled or not active yet");
if ( (KOMODO_CONNECTING & (1<<30)) != 0 )
{
from_mempool = 1;
height &= ((1<<30) - 1);
}
evalcode = cond->code[0];
if ( evalcode >= EVAL_FIRSTUSER && evalcode <= EVAL_LASTUSER )
{
5 years ago
cp = &CCinfos[(int32_t)evalcode];
5 years ago
if ( cp->didinit == 0 )
{
5 years ago
if ( CClib_initcp(cp,evalcode) == 0 )
5 years ago
cp->didinit = 1;
else return eval->Invalid("unsupported CClib evalcode");
}
CCclearvars(cp);
if ( paramsNull.size() != 0 ) // Don't expect params
return eval->Invalid("Cannot have params");
else if ( CClib_validate(cp,height,eval,txTo,nIn) != 0 )
5 years ago
return(true);
return(false); //eval->Invalid("error in CClib_validate");
5 years ago
}
return eval->Invalid("cclib CC must have evalcode between 16 and 127");
}