diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index bc358dcbe..e2b477330 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -46,350 +46,14 @@ By using -addressindex=1, it allows tracking of all the CC addresses */ std::string FinalizeCCTx(uint64_t CCmask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector pubkeys) { - UniValue sigData = FinalizeCCTxExt(false, CCmask, cp, mtx, mypk, txfee, opret, pubkeys); - return sigData[JSON_HEXTX].getValStr(); + return std::string(""); } // extended version that supports signInfo object with conds to vins map for remote cc calls UniValue FinalizeCCTxExt(bool remote, uint64_t CCmask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector pubkeys) { - auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - CTransaction vintx; std::string hex; CPubKey globalpk; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0; - int64_t utxovalues[CC_MAXVINS],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0,normalvins=0,ccvins=0; - int32_t i,flag,mgret,utxovout,n,err = 0; - char myaddr[64], destaddr[64], unspendable[64], mytokensaddr[64], mysingletokensaddr[64], unspendabletokensaddr[64],CC1of2CCaddr[64]; - uint8_t *privkey = NULL, myprivkey[32] = { '\0' }, unspendablepriv[32] = { '\0' }, /*tokensunspendablepriv[32],*/ *msg32 = 0; - CC *mycond=0, *othercond=0, *othercond2=0,*othercond4=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond=0, *condCC2=0,*mytokenscond = NULL, *mysingletokenscond = NULL, *othertokenscond = NULL; - CPubKey unspendablepk /*, tokensunspendablepk*/; - struct CCcontract_info *cpTokens, tokensC; - UniValue sigData(UniValue::VARR),result(UniValue::VOBJ); - const UniValue sigDataNull = NullUniValue; - - globalpk = GetUnspendable(cp,0); - n = mtx.vout.size(); - for (i=0; i CC_MAXVINS ) - { - fprintf(stderr,"FinalizeCCTx: %d is too many vins\n",n); - result.push_back(Pair(JSON_HEXTX, "0")); - return result; - } - - //Myprivkey(myprivkey); // for NSPV mode we need to add myprivkey for the explicitly defined mypk param -#ifdef ENABLE_WALLET - // get privkey for mypk - CKeyID keyID = mypk.GetID(); - CKey vchSecret; - if (pwalletMain->GetKey(keyID, vchSecret)) - memcpy(myprivkey, vchSecret.begin(), sizeof(myprivkey)); -#endif - - GetCCaddress(cp,myaddr,mypk); - mycond = MakeCCcond1(cp->evalcode,mypk); - - // to spend from single-eval evalcode 'unspendable' cc addr - unspendablepk = GetUnspendable(cp, unspendablepriv); - GetCCaddress(cp, unspendable, unspendablepk); - othercond = MakeCCcond1(cp->evalcode, unspendablepk); - GetCCaddress1of2(cp,CC1of2CCaddr,unspendablepk,unspendablepk); - - //fprintf(stderr,"evalcode.%d (%s)\n",cp->evalcode,unspendable); - - // tokens support: - // to spend from dual/three-eval mypk vout - GetTokensCCaddress(cp, mytokensaddr, mypk); - // NOTE: if additionalEvalcode2 is not set it is a dual-eval (not three-eval) cc cond: - mytokenscond = MakeTokensCCcond1(cp->evalcode, cp->additionalTokensEvalcode2, mypk); - - // to spend from single-eval EVAL_TOKENS mypk - cpTokens = CCinit(&tokensC, EVAL_TOKENS); - GetCCaddress(cpTokens, mysingletokensaddr, mypk); - mysingletokenscond = MakeCCcond1(EVAL_TOKENS, mypk); - - // to spend from dual/three-eval EVAL_TOKEN+evalcode 'unspendable' pk: - GetTokensCCaddress(cp, unspendabletokensaddr, unspendablepk); // it may be a three-eval cc, if cp->additionalEvalcode2 is set - othertokenscond = MakeTokensCCcond1(cp->evalcode, cp->additionalTokensEvalcode2, unspendablepk); - - //Reorder vins so that for multiple normal vins all other except vin0 goes to the end - //This is a must to avoid hardfork change of validation in every CC, because there could be maximum one normal vin at the begining with current validation. - for (i=0; i1 && ccvins) - { - for(i=1;i= totaloutputs+2*txfee ) - { - change = totalinputs - (totaloutputs+txfee); - mtx.vout.push_back(CTxOut(change,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - } - if ( opret.size() > 0 ) - mtx.vout.push_back(CTxOut(0,opret)); - PrecomputedTransactionData txdata(mtx); - n = mtx.vin.size(); - for (i=0; i %s\n",utxovout,dstr(vintx.vout[utxovout].nValue),addr); - } - if ( NSPV_SignTx(mtx,i,vintx.vout[utxovout].nValue,vintx.vout[utxovout].scriptPubKey,0) == 0 ) - fprintf(stderr,"NSPV signing error for vini.%d of %llx\n",i,(long long)vinimask); - } - } - else - { - Getscriptaddress(destaddr,vintx.vout[utxovout].scriptPubKey); - //fprintf(stderr,"FinalizeCCTx() vin.%d is CC %.8f -> (%s) vs %s\n",i,(double)utxovalues[i]/COIN,destaddr,mysingletokensaddr); - //std::cerr << "FinalizeCCtx() searching destaddr=" << destaddr << " for vin[" << i << "] satoshis=" << utxovalues[i] << std::endl; - if( strcmp(destaddr, myaddr) == 0 ) - { -//fprintf(stderr, "FinalizeCCTx() matched cc myaddr (%s)\n", myaddr); - privkey = myprivkey; - cond = mycond; - } - else if (strcmp(destaddr, mytokensaddr) == 0) // if this is TokensCC1vout - { - privkey = myprivkey; - cond = mytokenscond; -//fprintf(stderr,"FinalizeCCTx() matched dual-eval TokensCC1vout my token addr.(%s)\n",mytokensaddr); - } - else if (strcmp(destaddr, mysingletokensaddr) == 0) // if this is TokensCC1vout - { - privkey = myprivkey; - cond = mysingletokenscond; -//fprintf(stderr, "FinalizeCCTx() matched single-eval token CC1vout my token addr.(%s)\n", mytokensaddr); - } - else if ( strcmp(destaddr,unspendable) == 0 ) - { - privkey = unspendablepriv; - cond = othercond; -//fprintf(stderr,"FinalizeCCTx evalcode(%d) matched unspendable CC addr.(%s)\n",cp->evalcode,unspendable); - } - else if (strcmp(destaddr, unspendabletokensaddr) == 0) - { - privkey = unspendablepriv; - cond = othertokenscond; -//fprintf(stderr,"FinalizeCCTx() matched unspendabletokensaddr dual/three-eval CC addr.(%s)\n",unspendabletokensaddr); - } - // check if this is the 2nd additional evalcode + 'unspendable' cc addr: - else if ( strcmp(destaddr, cp->unspendableaddr2) == 0) - { -//fprintf(stderr,"FinalizeCCTx() matched %s unspendable2!\n",cp->unspendableaddr2); - privkey = cp->unspendablepriv2; - if( othercond2 == 0 ) - othercond2 = MakeCCcond1(cp->unspendableEvalcode2, cp->unspendablepk2); - cond = othercond2; - } - // check if this is 3rd additional evalcode + 'unspendable' cc addr: - else if ( strcmp(destaddr,cp->unspendableaddr3) == 0 ) - { -//fprintf(stderr,"FinalizeCCTx() matched %s unspendable3!\n",cp->unspendableaddr3); - privkey = cp->unspendablepriv3; - if( othercond3 == 0 ) - othercond3 = MakeCCcond1(cp->unspendableEvalcode3, cp->unspendablepk3); - cond = othercond3; - } - // check if this is spending from 1of2 cc coins addr: - else if (strcmp(cp->coins1of2addr, destaddr) == 0) - { -//fprintf(stderr,"FinalizeCCTx() matched %s unspendable1of2!\n",cp->coins1of2addr); - privkey = cp->coins1of2priv;//myprivkey; - if (othercond1of2 == 0) - othercond1of2 = MakeCCcond1of2(cp->evalcode, cp->coins1of2pk[0], cp->coins1of2pk[1]); - cond = othercond1of2; - } - else if ( strcmp(CC1of2CCaddr,destaddr) == 0 ) - { -//fprintf(stderr,"FinalizeCCTx() matched %s CC1of2CCaddr!\n",CC1of2CCaddr); - privkey = unspendablepriv; - if (condCC2 == 0) - condCC2 = MakeCCcond1of2(cp->evalcode,unspendablepk,unspendablepk); - cond = condCC2; - } - // check if this is spending from 1of2 cc tokens addr: - else if (strcmp(cp->tokens1of2addr, destaddr) == 0) - { -//fprintf(stderr,"FinalizeCCTx() matched %s cp->tokens1of2addr!\n", cp->tokens1of2addr); - privkey = cp->tokens1of2priv;//myprivkey; - if (othercond1of2tokens == 0) - // NOTE: if additionalEvalcode2 is not set then it is dual-eval cc else three-eval cc - // TODO: verify evalcodes order if additionalEvalcode2 is not 0 - othercond1of2tokens = MakeTokensCCcond1of2(cp->evalcode, cp->additionalTokensEvalcode2, cp->tokens1of2pk[0], cp->tokens1of2pk[1]); - cond = othercond1of2tokens; - } - else - { - flag = 0; - if ( pubkeys != NULL_pubkeys ) - { - char coinaddr[64]; - GetCCaddress1of2(cp,coinaddr,globalpk,pubkeys[i]); - //fprintf(stderr,"%s + %s -> %s vs %s\n",HexStr(globalpk).c_str(),HexStr(pubkeys[i]).c_str(),coinaddr,destaddr); - if ( strcmp(destaddr,coinaddr) == 0 ) - { - privkey = cp->CCpriv; - if ( othercond4 != 0 ) - cc_free(othercond4); - othercond4 = MakeCCcond1of2(cp->evalcode,globalpk,pubkeys[i]); - cond = othercond4; - flag = 1; - } - } //else privkey = myprivkey; - - if ( flag == 0 ) - { - fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr); - memset(myprivkey,0,32); - return sigDataNull; - } - } - uint256 sighash = SignatureHash(CCPubKey(cond), mtx, i, SIGHASH_ALL,utxovalues[i],consensusBranchId, &txdata); - if ( 0 ) - { - int32_t z; - for (z=0; z<32; z++) - fprintf(stderr,"%02x",privkey[z]); - fprintf(stderr," privkey, "); - for (z=0; z<32; z++) - fprintf(stderr,"%02x",((uint8_t *)sighash.begin())[z]); - fprintf(stderr," sighash [%d] %.8f %x\n",i,(double)utxovalues[i]/COIN,consensusBranchId); - } - - if (!remote) // we have privkey in the wallet - { - if (cc_signTreeSecp256k1Msg32(cond, privkey, sighash.begin()) != 0) - { - mtx.vin[i].scriptSig = CCSig(cond); - } - else - { - fprintf(stderr, "vini.%d has CC signing error address.(%s) %s\n", i, destaddr, EncodeHexTx(mtx).c_str()); - memset(myprivkey, 0, sizeof(myprivkey)); - return sigDataNull; - } - } - else // no privkey locally - remote call - { - // serialize cc: - UniValue ccjson; - ccjson.read(cc_conditionToJSONString(cond)); - if (ccjson.empty()) - { - fprintf(stderr, "vini.%d can't serialize CC.(%s) %s\n", i, destaddr, EncodeHexTx(mtx).c_str()); - memset(myprivkey, 0, sizeof(myprivkey)); - return sigDataNull; - } - - AddSigData2UniValue(sigData, i, ccjson, std::string(), vintx.vout[utxovout].nValue); // store vin i with scriptPubKey - } - } - } else fprintf(stderr,"FinalizeCCTx2 couldnt find %s mgret.%d\n",mtx.vin[i].prevout.hash.ToString().c_str(),mgret); - } - if ( mycond != 0 ) - cc_free(mycond); - if ( condCC2 != 0 ) - cc_free(condCC2); - if ( othercond != 0 ) - cc_free(othercond); - if ( othercond2 != 0 ) - cc_free(othercond2); - if ( othercond3 != 0 ) - cc_free(othercond3); - if ( othercond4 != 0 ) - cc_free(othercond4); - if ( othercond1of2 != 0 ) - cc_free(othercond1of2); - if ( othercond1of2tokens != 0 ) - cc_free(othercond1of2tokens); - if ( mytokenscond != 0 ) - cc_free(mytokenscond); - if ( mysingletokenscond != 0 ) - cc_free(mysingletokenscond); - if ( othertokenscond != 0 ) - cc_free(othertokenscond); - memset(myprivkey,0,sizeof(myprivkey)); - std::string strHex = EncodeHexTx(mtx); - if ( strHex.size() > 0 ) - result.push_back(Pair(JSON_HEXTX, strHex)); - else { - result.push_back(Pair(JSON_HEXTX, "0")); - } - if (sigData.size() > 0) result.push_back(Pair(JSON_SIGDATA,sigData)); + UniValue result(UniValue::VOBJ); return result; } @@ -399,187 +63,47 @@ void NSPV_CCtxids(std::vector &txids,char *coinaddr,bool ccflag, uint8_ void SetCCunspents(std::vector > &unspentOutputs,char *coinaddr,bool ccflag) { - int32_t type=0,i,n; char *ptr; std::string addrstr; uint160 hashBytes; std::vector > addresses; - if ( HUSH_NSPV_SUPERLITE ) - { - NSPV_CCunspents(unspentOutputs,coinaddr,ccflag); - return; - } - n = (int32_t)strlen(coinaddr); - addrstr.resize(n+1); - ptr = (char *)addrstr.data(); - for (i=0; i<=n; i++) - ptr[i] = coinaddr[i]; - CBitcoinAddress address(addrstr); - if ( address.GetIndexKey(hashBytes, type, ccflag) == 0 ) - return; - addresses.push_back(std::make_pair(hashBytes,type)); - for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) - { - if ( GetAddressUnspent((*it).first, (*it).second, unspentOutputs) == 0 ) - return; - } + return; } void SetCCtxids(std::vector > &addressIndex,char *coinaddr,bool ccflag) { - int32_t type=0,i,n; char *ptr; std::string addrstr; uint160 hashBytes; std::vector > addresses; - if ( HUSH_NSPV_SUPERLITE ) - { - NSPV_CCtxids(addressIndex,coinaddr,ccflag); - return; - } - n = (int32_t)strlen(coinaddr); - addrstr.resize(n+1); - ptr = (char *)addrstr.data(); - for (i=0; i<=n; i++) - ptr[i] = coinaddr[i]; - CBitcoinAddress address(addrstr); - if ( address.GetIndexKey(hashBytes, type, ccflag) == 0 ) - return; - addresses.push_back(std::make_pair(hashBytes,type)); - for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) - { - if ( GetAddressIndex((*it).first, (*it).second, addressIndex) == 0 ) - return; - } + return; } void SetCCtxids(std::vector &txids,char *coinaddr,bool ccflag, uint8_t evalcode, uint256 filtertxid, uint8_t func) { - int32_t type=0,i,n; char *ptr; std::string addrstr; uint160 hashBytes; std::vector > addresses; - std::vector > addressIndex; - if ( HUSH_NSPV_SUPERLITE ) - { - NSPV_CCtxids(txids,coinaddr,ccflag,evalcode,filtertxid,func); - return; - } - n = (int32_t)strlen(coinaddr); - addrstr.resize(n+1); - ptr = (char *)addrstr.data(); - for (i=0; i<=n; i++) - ptr[i] = coinaddr[i]; - CBitcoinAddress address(addrstr); - if ( address.GetIndexKey(hashBytes, type, ccflag) == 0 ) - return; - addresses.push_back(std::make_pair(hashBytes,type)); - for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) - { - if ( GetAddressIndex((*it).first, (*it).second, addressIndex) == 0 ) - return; - for (std::vector >::const_iterator it1=addressIndex.begin(); it1!=addressIndex.end(); it1++) - { - if (it1->second>=0) txids.push_back(it1->first.txhash); - } - } + return; } int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout,int32_t CCflag) { - uint256 txid; std::vector > unspentOutputs; - SetCCunspents(unspentOutputs,coinaddr,CCflag!=0?true:false); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - if ( txid == utxotxid && utxovout == it->first.index ) - return(it->second.satoshis); - } return(0); } int64_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag,int32_t lockflag) { - CCoins coins; - //fprintf(stderr,"CCgettxoud %s/v%d\n",txid.GetHex().c_str(),vout); - if ( mempoolflag != 0 ) - { - if ( lockflag != 0 ) - { - LOCK(mempool.cs); - CCoinsViewMemPool view(pcoinsTip, mempool); - if (!view.GetCoins(txid, coins)) - return(-1); - else if ( myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) != 0 ) - return(-1); - } - else - { - CCoinsViewMemPool view(pcoinsTip, mempool); - if (!view.GetCoins(txid, coins)) - return(-1); - else if ( myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) != 0 ) - return(-1); - } - } - else - { - if (!pcoinsTip->GetCoins(txid, coins)) - return(-1); - } - if ( vout < coins.vout.size() ) - return(coins.vout[vout].nValue); - else return(-1); + return(-1); } int32_t CCgetspenttxid(uint256 &spenttxid,int32_t &vini,int32_t &height,uint256 txid,int32_t vout) { - CSpentIndexKey key(txid, vout); - CSpentIndexValue value; - if ( !GetSpentIndex(key, value) ) - return(-1); - spenttxid = value.txid; - vini = (int32_t)value.inputIndex; - height = value.blockHeight; return(0); } int64_t CCaddress_balance(char *coinaddr,int32_t CCflag) { - int64_t sum = 0; std::vector > unspentOutputs; - SetCCunspents(unspentOutputs,coinaddr,CCflag!=0?true:false); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - sum += it->second.satoshis; - } - return(sum); + return 0; } int64_t CCfullsupply(uint256 tokenid) { - uint256 hashBlock; int32_t numvouts; CTransaction tx; std::vector origpubkey; std::string name,description; - if ( myGetTransaction(tokenid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 ) - { - if (DecodeTokenCreateOpRet(tx.vout[numvouts-1].scriptPubKey,origpubkey,name,description)) - { - return(tx.vout[1].nValue); - } - } return(0); } int64_t CCtoken_balance(char *coinaddr,uint256 reftokenid) { - int64_t price,sum = 0; int32_t numvouts; CTransaction tx; uint256 tokenid,txid,hashBlock; - std::vector vopretExtra; - std::vector > unspentOutputs; - uint8_t evalCode; - - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size()) > 0 ) - { - char str[65]; - std::vector voutTokenPubkeys; - std::vector> oprets; - if ( reftokenid==txid || (DecodeTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCode, tokenid, voutTokenPubkeys, oprets) != 0 && reftokenid == tokenid)) - { - sum += it->second.satoshis; - } - } - } - return(sum); + return 0; } int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *belowp,struct CC_utxo utxos[],int32_t numunspents,int64_t value)