diff --git a/src/cc/CCHeir.h b/src/cc/CCHeir.h index 18d1f08bb..8399474a7 100644 --- a/src/cc/CCHeir.h +++ b/src/cc/CCHeir.h @@ -34,8 +34,8 @@ class TokenHelper; //template UniValue HeirAdd(uint256 fundingtxid, uint64_t txfee, int64_t amount); //template UniValue HeirClaim(uint256 fundingtxid, uint64_t txfee, int64_t nValue); -std::string HeirFundCoinCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 assetid); -std::string HeirFundTokenCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 assetid); +UniValue HeirFundCoinCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 assetid); +UniValue HeirFundTokenCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 assetid); UniValue HeirClaimCoinCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount); UniValue HeirClaimTokenCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount); UniValue HeirAddCoinCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount); diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index c42a4799e..14a500222 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -162,6 +162,7 @@ CScript EncodeAssetOpRet(uint8_t assetFuncId, uint256 tokenid, uint256 assetid2, bool DecodeAssetCreateOpRet(const CScript &scriptPubKey, std::vector &origpubkey, std::string &name, std::string &description); uint8_t DecodeAssetOpRet(const CScript &scriptPubKey, uint8_t &evalCodeInOpret, uint256 &tokenid, uint256 &assetid2, int64_t &price, std::vector &origpubkey); +CScript EncodeTokenOpRet(uint256 tokenid, std::vector voutPubkeys, CScript payload); CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector voutPubkeys, CScript payload); uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector &origpubkey, std::string &name, std::string &description); uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCode, uint256 &tokenid, std::vector &voutPubkeys, std::vector &vopretExtra); diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 242b0a38e..d1dcf0b1f 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -51,14 +51,11 @@ CScript EncodeTokenCreateOpRet(uint8_t funcid,std::vector origpubkey,st } // this is for other contracts which use tokens and build customized extra payloads to token's opret: -CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector voutPubkeys, CScript payload) +CScript EncodeTokenOpRet(uint256 tokenid, std::vector voutPubkeys, CScript payload) { CScript opret; - - if (evalCodeInOpret != EVAL_TOKENS) { - std::cerr << "EncodeTokenOpRet() evalCode should be EVAL_TOKENS!" << std::endl; - return opret; // return empty - } + uint8_t tokenFuncId = 't'; + uint8_t evalCodeInOpret = EVAL_TOKENS; tokenid = revuint256(tokenid); @@ -93,6 +90,11 @@ CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 t return opret; } +// overload for compatibility +CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector voutPubkeys, CScript payload) +{ + return EncodeTokenOpRet(tokenid, voutPubkeys, payload); +} uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey,std::vector &origpubkey,std::string &name,std::string &description) { @@ -405,35 +407,59 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *c std::cerr << "IsTokensvout() vopretExtra=" << HexStr(vopretExtra) << std::endl; //std::cerr << "IsTokensvout() vcontractOpret=" << HexStr(vcontractOpret) << std::endl;; - if (vopretExtra.size() < 2 /*|| vopretExtra.size() != vopretExtra.begin()[0]*/) { + uint8_t evalCodeInOpret; + if (vopretExtra.size() >= 2 /*|| vopretExtra.size() != vopretExtra.begin()[0] <-- shold we check this?*/) { std::cerr << "IsTokensvout() empty or incorrect contract opret" << std::endl; - return 0; + evalCodeInOpret = vopretExtra.begin()[1]; + } + else { + // if payload is empty maybe it is a claim to non-payload-one-token-eval vout? + evalCodeInOpret = EVAL_TOKENS; } - uint8_t evalCodeInOpret = vopretExtra.begin()[1]; - - if (voutPubkeys.size() >= 1 && voutPubkeys.size() <= 2) { - CTxOut testVout; + // maybe this is dual-eval 1 pubkey or 1of2 pubkey vout? + if (voutPubkeys.size() >= 1 && voutPubkeys.size() <= 2) { + CTxOut testDualVout; if (voutPubkeys.size() == 1) - testVout = MakeTokensCC1vout(evalCodeInOpret, tx.vout[v].nValue, voutPubkeys[0]); + testDualVout = MakeTokensCC1vout(evalCodeInOpret, tx.vout[v].nValue, voutPubkeys[0]); else // voutPubkeys.size() == 2 - testVout = MakeTokensCC1of2vout(evalCodeInOpret, tx.vout[v].nValue, voutPubkeys[0], voutPubkeys[1]); + testDualVout = MakeTokensCC1of2vout(evalCodeInOpret, tx.vout[v].nValue, voutPubkeys[0], voutPubkeys[1]); - if (tx.vout[v].scriptPubKey == testVout.scriptPubKey) { - std::cerr << indentStr << "IsTokensvout() vout is EVAL_TOKENS, returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + if (tx.vout[v].scriptPubKey == testDualVout.scriptPubKey) { + if(voutPubkeys.size() == 1) + std::cerr << indentStr << "IsTokensvout() this is dual-eval token vout, eval2=" << evalCodeInOpret << ", returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + else + std::cerr << indentStr << "IsTokensvout() this is dual-eval token 1of2 vout or change, eval2=" << evalCodeInOpret << ", returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; return tx.vout[v].nValue; } } - // maybe it is token change? + // maybe this is claim to single-eval token? + if (voutPubkeys.size() == 1) { + CTxOut testTokenVout1; + testTokenVout1 = MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[0]); + + if (tx.vout[v].scriptPubKey == testTokenVout1.scriptPubKey) { + std::cerr << indentStr << "IsTokensvout() this is single-eval token vout, returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + } + + // maybe it is single-eval or dual-eval token change? std::vector vinPubkeys; ExtractTokensVinPubkeys(tx, vinPubkeys); for(std::vector::iterator it = vinPubkeys.begin(); it != vinPubkeys.end(); it++) { - CTxOut testVout = MakeTokensCC1vout(evalCodeInOpret, tx.vout[v].nValue, *it); + CTxOut testTokenVout1 = MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, *it); + CTxOut testDualVout1 = MakeTokensCC1vout(evalCodeInOpret, tx.vout[v].nValue, *it); - if (tx.vout[v].scriptPubKey == testVout.scriptPubKey) { - std::cerr << indentStr << "IsTokensvout() vout is EVAL_TOKENS change, returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + if (tx.vout[v].scriptPubKey == testTokenVout1.scriptPubKey) { + std::cerr << indentStr << "IsTokensvout() this is single-eval token change, returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + + if (tx.vout[v].scriptPubKey == testDualVout1.scriptPubKey) { + std::cerr << indentStr << "IsTokensvout() this is dual-eval token change, vout eval2=" << (int)evalCodeInOpret << ", returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; return tx.vout[v].nValue; } } diff --git a/src/cc/heir.cpp b/src/cc/heir.cpp index c87f8155d..a1f8adfd3 100644 --- a/src/cc/heir.cpp +++ b/src/cc/heir.cpp @@ -619,8 +619,9 @@ template int64_t LifetimeHeirContractFunds(struct CCcontract_info * and also for setting spending plan for the funds' owner and heir * @return fundingtxid handle for subsequent references to this heir funding plan */ -template std::string HeirFund(uint64_t txfee, int64_t amount, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) +template UniValue HeirFund(uint64_t txfee, int64_t amount, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) { + UniValue result(UniValue::VOBJ); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); struct CCcontract_info *cp, C; @@ -664,24 +665,38 @@ template std::string HeirFund(uint64_t txfee, int64_t amount, voutTokenPubkeys.push_back(heirPubkey); // add change for txfee and opreturn vouts and sign tx: - return (FinalizeCCTx(0, cp, mtx, myPubkey, txfee, - Helper::makeCreateOpRet(tokenid, voutTokenPubkeys, myPubkey, heirPubkey, inactivityTimeSec, heirName))); + std::string rawhextx = FinalizeCCTx(0, cp, mtx, myPubkey, txfee, + Helper::makeCreateOpRet(tokenid, voutTokenPubkeys, myPubkey, heirPubkey, inactivityTimeSec, heirName)); + if (!rawhextx.empty()) { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hextx", rawhextx)); + } + else { + std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "sign error")); + } + } + else { // TODO: need result return unification with heiradd and claim + std::cerr << "HeirFund() could not find owner cc inputs" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "could not find owner cc inputs")); } - else // TODO: need result return unification with heiradd and claim - std::cerr << "HeirFund() could not find owner inputs" << std::endl; - } - else + else { std::cerr << "HeirFund() could not find normal inputs" << std::endl; - return std::string(""); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "could not find normal inputs")); + } + return result; } // if no these callers - it could not link -std::string HeirFundCoinCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid){ +UniValue HeirFundCoinCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid){ return HeirFund(txfee, funds, heirName, heirPubkey, inactivityTimeSec, tokenid); } -std::string HeirFundTokenCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) { +UniValue HeirFundTokenCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) { return HeirFund(txfee, funds, heirName, heirPubkey, inactivityTimeSec, tokenid); } @@ -735,8 +750,8 @@ template UniValue HeirAdd(uint256 fundingtxid, uint64_t txfee, in mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); // txfee 1, txfee 2 - for miners std::cerr << "HeirAdd() adding markeraddr=" << markeraddr << '\n'; */ - // add cryptocondition to spend this funded amount for either pk - mtx.vout.push_back(Helper::make1of2Vout(amount, ownerPubkey, heirPubkey)); + // add cryptocondition to spend this funded amount for either pk + mtx.vout.push_back(Helper::make1of2Vout(amount, ownerPubkey, heirPubkey)); if (inputs > amount) change = (inputs - amount); // -txfee <-- txfee pays user @@ -756,8 +771,16 @@ template UniValue HeirAdd(uint256 fundingtxid, uint64_t txfee, in std::string rawhextx = (FinalizeCCTx(0, cp, mtx, myPubkey, txfee, Helper::makeAddOpRet(tokenid, voutTokenPubkeys, fundingtxid, hasHeirSpendingBegun))); - result.push_back(Pair("result", "success")); - result.push_back(Pair("hextx", rawhextx)); + if (!rawhextx.empty()) { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hextx", rawhextx)); + } + else { + std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "sign error")); + } + } else { std::cerr << "HeirAdd cannot find owner cc inputs" << std::endl; @@ -772,7 +795,7 @@ template UniValue HeirAdd(uint256 fundingtxid, uint64_t txfee, in } } else { - fprintf(stderr, "HeirAdd() can't find any heir CC funding tx's\n"); + fprintf(stderr, "HeirAdd can't find any heir CC funding tx's\n"); result.push_back(Pair("result", "error")); result.push_back(Pair("error", "can't find any heir CC funding transactions")); @@ -858,7 +881,7 @@ template UniValue HeirClaim(uint256 fundingtxid, uint64_t txfee }*/ // add vout with amount to claiming address - mtx.vout.push_back(Helper::makeClaimerVout(amount, myPubkey)); // vout[0] + mtx.vout.push_back(Helper::makeUserVout(amount, myPubkey)); // vout[0] // calc and add change vout: if (inputs > amount) diff --git a/src/cc/heir_validate.h b/src/cc/heir_validate.h index 8f08a1588..e9710a471 100644 --- a/src/cc/heir_validate.h +++ b/src/cc/heir_validate.h @@ -43,9 +43,9 @@ public: static CTxOut makeUserVout(int64_t amount, CPubKey myPubkey) { return CTxOut(amount, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG); } - static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) { +/* static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) { return CTxOut(amount, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG); - } + } */ static bool GetCoinsOrTokensCCaddress1of2(char *coinaddr, CPubKey ownerPubkey, CPubKey heirPubkey) { struct CCcontract_info *cpHeir, heirC; cpHeir = CCinit(&heirC, EVAL_HEIR); @@ -64,20 +64,20 @@ public: static uint8_t getMyEval() { return EVAL_TOKENS; } static int64_t addOwnerInputs(uint256 tokenid, CMutableTransaction& mtx, CPubKey ownerPubkey, int64_t total, int32_t maxinputs) { struct CCcontract_info *cpHeir, heirC; - cpHeir = CCinit(&heirC, EVAL_HEIR); + cpHeir = CCinit(&heirC, EVAL_TOKENS); return AddTokenCCInputs(cpHeir, mtx, ownerPubkey, tokenid, total, maxinputs); } static CScript makeCreateOpRet(uint256 tokenid, std::vector voutTokenPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName) { - return EncodeTokenOpRet((uint8_t)'t', EVAL_TOKENS, tokenid, voutTokenPubkeys, + return EncodeTokenOpRet(tokenid, voutTokenPubkeys, EncodeHeirCreateOpRet((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName)); } static CScript makeAddOpRet(uint256 tokenid, std::vector voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) { - return EncodeTokenOpRet((uint8_t)'t', EVAL_TOKENS, tokenid, voutTokenPubkeys, + return EncodeTokenOpRet(tokenid, voutTokenPubkeys, EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan)); } static CScript makeClaimOpRet(uint256 tokenid, std::vector voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) { - return EncodeTokenOpRet((uint8_t)'t', EVAL_TOKENS, tokenid, voutTokenPubkeys, + return EncodeTokenOpRet(tokenid, voutTokenPubkeys, EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan)); } @@ -85,11 +85,11 @@ public: return MakeTokensCC1of2vout(EVAL_HEIR, amount, ownerPubkey, heirPubkey); } static CTxOut makeUserVout(int64_t amount, CPubKey myPubkey) { - return MakeTokensCC1vout(EVAL_HEIR, amount, myPubkey); - } - static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) { - return MakeTokensCC1vout(EVAL_HEIR, amount, myPubkey); + return MakeCC1vout(EVAL_TOKENS, amount, myPubkey); // yes EVAL_TOKENS } +/* static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) { + return MakeCC1vout(EVAL_TOKENS, amount, myPubkey); // yes EVAL_TOKENS + } */ static bool GetCoinsOrTokensCCaddress1of2(char *coinaddr, CPubKey ownerPubkey, CPubKey heirPubkey) { struct CCcontract_info *cpHeir, heirC; cpHeir = CCinit(&heirC, EVAL_HEIR); @@ -477,7 +477,7 @@ public: CScript ownerScript; CScript heirScript; - if (m_checkNormals) { + if (m_checkNormals) { //not used, incorrect check, too strict ownerScript = CoinHelper::makeUserVout(vout.nValue, ownerPubkey).scriptPubKey; heirScript = CoinHelper::makeUserVout(vout.nValue, heirPubkey).scriptPubKey; std::cerr << "CMyPubkeyVoutValidator::validateVout() vout.scriptPubKey=" << vout.scriptPubKey.ToString() << " makeUserVout(coin,owner)=" << CoinHelper::makeUserVout(vout.nValue, ownerPubkey).scriptPubKey.ToString() << " makeUserVout(coin,heir)=" << CoinHelper::makeUserVout(vout.nValue, heirPubkey).scriptPubKey.ToString() << std::endl; @@ -537,7 +537,7 @@ public: int64_t durationSec = CCduration(numblocks, m_latesttxid); // recreate scriptPubKey for heir and compare it with that of the vout: - if (vout.scriptPubKey == Helper::makeClaimerVout(vout.nValue, heirPubkey).scriptPubKey) { + if (vout.scriptPubKey == Helper::makeUserVout(vout.nValue, heirPubkey).scriptPubKey) { // this is the heir is trying to spend if (!m_isHeirSpendingBegan && durationSec <= inactivityTime) { message = "heir is not allowed yet to spend funds"; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 847ddd921..82870c941 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -7454,13 +7454,13 @@ UniValue heirfund(const UniValue& params, bool fHelp) inactivitytime = atof((char*)params[4].get_str().c_str()); - hex = HeirFundCoinCaller(txfee, amount, name, pubkey2pk(pubkey), inactivitytime, zeroid); - if (hex.size() > 0) { + result = HeirFundCoinCaller(txfee, amount, name, pubkey2pk(pubkey), inactivitytime, zeroid); +/* if (hex.size() > 0) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); } else - ERR_RESULT("couldn't create heir fund"); + ERR_RESULT("couldn't create heir fund");*/ return result; } @@ -7573,13 +7573,13 @@ UniValue heirfundtokens(const UniValue& params, bool fHelp) assetid = Parseuint256((char*)params[5].get_str().c_str()); - hex = HeirFundTokenCaller(txfee, amount, name, pubkey2pk(pubkey), inactivitytime, assetid); - if (hex.size() > 0) { + result = HeirFundTokenCaller(txfee, amount, name, pubkey2pk(pubkey), inactivitytime, assetid); +/* if (hex.size() > 0) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); } else - ERR_RESULT("couldn't create heir fund"); + ERR_RESULT("couldn't create heir fund");*/ return result;