From eaf8a98e988242f1c5a233b799aeac21f2ec3d3e Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 13 Jun 2021 15:36:31 +0300 Subject: [PATCH 001/348] fix coinbase cc v2 vouts not validated issue --- src/main.cpp | 53 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index cbadd81609d..5f00330167f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2785,18 +2785,15 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) UpdateCoins(tx, inputs, txundo, nHeight); } -bool CScriptCheck::operator()() { - if (vout!=0) - { +bool CScriptCheck::operator()() +{ + if (vout != 0) { ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, evalcodeChecker, *txdata); - if (checker.CheckCryptoCondition(scriptPubKey.GetCCV2SPK(),&error)!=1) - { + if (checker.CheckCryptoCondition(scriptPubKey.GetCCV2SPK(), &error) != 1) { return ::error("CScriptCheck(): %s:%d CC validation failed: %s", ptxTo->GetHash().ToString(), n, ScriptErrorString(error)); } - } - else - { - const CScript &scriptSig = ptxTo->vin[n].scriptSig; + } else { + const CScript& scriptSig = ptxTo->vin[n].scriptSig; ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, evalcodeChecker, *txdata); if (!VerifyScript(scriptSig, scriptPubKey, nFlags, checker, consensusBranchId, &error)) { return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), n, ScriptErrorString(error)); @@ -2999,30 +2996,28 @@ bool ContextualCheckOutputs( std::shared_ptr evalcodeChecker, std::vector *pvChecks) { - if (!tx.IsCoinBase()) - { - if (pvChecks) - pvChecks->reserve(tx.vout.size()); + if (pvChecks) + pvChecks->reserve(tx.vout.size()); - if (fScriptChecks) { - for (unsigned int i = 0; i < tx.vout.size(); i++) { - if (tx.vout[i].scriptPubKey.IsPayToCCV2() ) + if (fScriptChecks) + { + for (unsigned int i = 0; i < tx.vout.size(); i++) + { + if (tx.vout[i].scriptPubKey.IsPayToCCV2() ) + { + CScriptCheck check(tx.vout[i].scriptPubKey, tx.vout[i].nValue, tx, i, evalcodeChecker, &txdata); + if (pvChecks) { - CScriptCheck check(tx.vout[i].scriptPubKey, tx.vout[i].nValue, tx, i, evalcodeChecker, &txdata); - if (pvChecks) - { - pvChecks->push_back(CScriptCheck()); - check.swap(pvChecks->back()); - } - else if (!check()) - { - return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError()))); - } + pvChecks->push_back(CScriptCheck()); + check.swap(pvChecks->back()); + } + else if (!check()) + { + return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError()))); } } } } - return true; } @@ -3856,6 +3851,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::vector vChecks; if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) return false; + } + + { // check tx outputs including coinbases + std::vector vChecks; if (!ContextualCheckOutputs(tx, state, fExpensiveChecks, txdata[i], evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) return false; control.Add(vChecks); From 74cb4e16beaaa7558026fbfdbde769ca5500b9df Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 13 Jun 2021 15:38:08 +0300 Subject: [PATCH 002/348] in token v2 validation moved up check for evalcodes in spk --- src/cc/CCtokens.cpp | 111 +++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 13986bcef4f..8a5cc6fb45b 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -536,12 +536,12 @@ CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcon // this is just for log messages indentation fur debugging recursive calls: std::string indentStr = std::string().append(tokenValIndentSize, '.'); - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "CheckTokensvout()" << " entered for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensV2::CheckTokensvout()" << " entered for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); int32_t n = tx.vout.size(); // just check boundaries: if (n == 0 || v < 0 || v >= n) { - LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "CheckTokensvout()" << " incorrect params: (n == 0 or v < 0 or v >= n)" << " v=" << v << " n=" << n << " returning error" << std::endl); + LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "TokensV2::CheckTokensvout()" << " incorrect params: (n == 0 or v < 0 or v >= n)" << " v=" << v << " n=" << n << " returning error" << std::endl); errorStr = "out of bounds"; return -1; } @@ -551,59 +551,60 @@ CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcon CScript dummy; if (tx.vout[v].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams)) { - CScript opret; - bool isLastVoutOpret; - if (GetCCDropAsOpret(tx.vout[v].scriptPubKey, opret)) - { - isLastVoutOpret = false; - } - else - { - isLastVoutOpret = true; - opret = tx.vout.back().scriptPubKey; - } - - uint256 tokenIdOpret; - std::vector oprets; - std::vector vpksdummy; - - // token opret most important checks (tokenid == reftokenid, tokenid is non-zero, tx is 'tokenbase'): - uint8_t funcId = TokensV2::DecodeTokenOpRet(opret, tokenIdOpret, vpksdummy, oprets); - if (funcId == 0) { - // bad opreturn - // errorStr = "can't decode opreturn data"; - // return -1; - return 0; // not token vout, skip - } + if (tx.vout[v].scriptPubKey.SpkHasEvalcodeCCV2(EVAL_TOKENSV2)) // it's token output, check it + { + CScript opret; + bool isLastVoutOpret; + if (GetCCDropAsOpret(tx.vout[v].scriptPubKey, opret)) + { + isLastVoutOpret = false; + } + else + { + isLastVoutOpret = true; + opret = tx.vout.back().scriptPubKey; + } - // basic checks: - if (IsTokenCreateFuncid(funcId)) { - // set returned tokend to tokenbase txid: - reftokenid = tx.GetHash(); - } - else if (IsTokenTransferFuncid(funcId)) { - // set returned tokenid to tokenid in opreturn: - reftokenid = tokenIdOpret; - } - else { - errorStr = "funcid not supported"; - return -1; - } - - if (reftokenid.IsNull()) { - errorStr = "null tokenid"; - return -1; - } + uint256 tokenIdOpret; + std::vector oprets; + std::vector vpksdummy; - // skip token marker (token global address) - if (IsTokenMarkerVout(tx.vout[v])) - return 0; + // token opret most important checks (tokenid == reftokenid, tokenid is non-zero, tx is 'tokenbase'): + uint8_t funcId = TokensV2::DecodeTokenOpRet(opret, tokenIdOpret, vpksdummy, oprets); + if (funcId == 0) { + // bad opreturn + errorStr = "can't decode opreturn data"; + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensV2::CheckTokensvout()" << " skipping vout with non token opret for txid=" << tx.GetHash().GetHex() << " v=" << v << " isLastVoutOpret=" << isLastVoutOpret << std::endl); + return -1; // not token vout, skip + } + + // basic checks: + if (IsTokenCreateFuncid(funcId)) { + // set returned tokend to tokenbase txid: + reftokenid = tx.GetHash(); + } + else if (IsTokenTransferFuncid(funcId)) { + // set returned tokenid to tokenid in opreturn: + reftokenid = tokenIdOpret; + } + else { + errorStr = "funcid not supported"; + return -1; + } + + if (reftokenid.IsNull()) { + errorStr = "null tokenid"; + return -1; + } + // skip token marker (token global address) + if (IsTokenMarkerVout(tx.vout[v])) { + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensV2::CheckTokensvout()" << " skipping marker vout for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); + return 0; + } - if (tx.vout[v].scriptPubKey.SpkHasEvalcodeCCV2(EVAL_TOKENSV2)) // it's token output, check it - { - /* let's do not verify opdrop in V2 - it is a just hint to users and does not really affect vaidation: + /* let's do not verify opdrop data in V2 + it is a just hint to users and does not really affect vaidation: // get output pubkeys and verify vout if (vParams.size() == 0) { errorStr = "no opdrop data"; @@ -626,11 +627,13 @@ CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcon if (!IsEqualScriptPubKeys(testVout.scriptPubKey, tx.vout[v].scriptPubKey)) { errorStr = "pubkeys in opdrop don't match vout"; return -1; - } - */ - + } */ return tx.vout[v].nValue; } + else + { + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensV2::CheckTokensvout()" << " skipping vout with non-token evalcode for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); + } } return(0); // normal or non-token2 vout } From a9352d990984045ffa5f5ecfb99304baaaae60f8 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 13 Jun 2021 15:39:15 +0300 Subject: [PATCH 003/348] RunCCEval logging fixed (no vintx printing as it doesn not make sense) --- src/cc/eval.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 3abb6f61da3..cbcdd992e18 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -34,7 +34,7 @@ Eval* EVAL_TEST = 0; struct CCcontract_info CCinfos[0x100]; extern pthread_mutex_t KOMODO_CC_mutex; -bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn,std::shared_ptr evalcodeChecker) +bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, std::shared_ptr evalcodeChecker) { EvalRef eval; pthread_mutex_lock(&KOMODO_CC_mutex); @@ -46,13 +46,14 @@ bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn,std::sha if (eval->state.IsValid()) return true; + // report cc error: std::string lvl = eval->state.IsInvalid() ? "Invalid" : "Error!"; - fprintf(stderr, "CC Eval %s %s: %s spending tx %s\n", - EvalToStr(cond->code[0]).data(), - lvl.data(), - eval->state.GetRejectReason().data(), - tx.vin[nIn].prevout.hash.GetHex().data()); - if (eval->state.IsError()) fprintf(stderr, "Culprit: %s\n", EncodeHexTx(tx).data()); + LOGSTREAMFN("cc", CCLOG_ERROR, stream << "CC Eval evalcode: " << EvalToStr(cond->code[0]) << " " << lvl << ", reason: " << eval->state.GetRejectReason() << std::endl); + if (eval->state.IsError()) { + LOGSTREAMFN("cc", CCLOG_ERROR, stream << "CC Eval Culprit tx: " << EncodeHexTx(tx) << std::endl); + } + + /* this hangs komodod bcs of lock! CTransaction tmp; if (mempool.lookup(tx.GetHash(), tmp)) { @@ -60,8 +61,9 @@ bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn,std::sha // Miner will mine 1 invalid block, but doesnt stop them mining until a restart. // This would almost never happen in normal use. std::list dummy; - mempool.remove(tx,dummy,true); + //mempool.remove(tx,dummy,true); } + */ return false; } From 946fc0785bf6e53ea4577e1940ea24d3580ffa83 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 13 Jun 2021 15:39:53 +0300 Subject: [PATCH 004/348] token debug logging improved --- src/cc/CCtokens_impl.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 21fe00f66c0..1dfbe79e3d8 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -119,7 +119,7 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c strcmp(destaddr, cp->unspendableaddr2) != 0*/) // or the logic is to allow to spend all available tokens (what about unspendableaddr3)? return; - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "checked tx vout destaddress=" << destaddr << " amount=" << tx.vout[index].nValue << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << "AddTokenCCInputs() checking tx vout destaddress=" << destaddr << " amount=" << tx.vout[index].nValue << std::endl); if (IsTokensvout(true, true, cp, NULL, tx, index, tokenid) > 0 && !myIsutxo_spentinmempool(ignoretxid, ignorevin, txhash, index)) { @@ -127,12 +127,16 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c mtx.vin.push_back(CTxIn(txhash, index, CScript())); totalinputs += satoshis; - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "adding input nValue=" << satoshis << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << "AddTokenCCInputs() adding input nValue=" << satoshis << std::endl); n++; if ((total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) return; } + else + { + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << "AddTokenCCInputs() IsTokensvout returned non-positive txid=" << txhash.GetHex() << " index=" << index << std::endl); + } } }; // auto add_token_vin @@ -145,7 +149,7 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c AddCCunspentsCCIndexMempool(unspentOutputs, tokenaddr, tokenid); // threshold = total / (maxinputs != 0 ? maxinputs : CC_MAXVINS); // let's not use threshold - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " found unspentOutputs=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "unspent ccindex found unspentOutputs=" << unspentOutputs.size() << std::endl); for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) add_token_vin(it->first.txhash, it->first.index, it->second.satoshis); } @@ -158,7 +162,7 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c else SetCCunspents(unspentOutputs, (char*)tokenaddr, CC_INPUTS_TRUE); - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " found unspentOutputs=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "unspent index found unspentOutputs=" << unspentOutputs.size() << std::endl); for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) add_token_vin(it->first.txhash, it->first.index, it->second.satoshis); } From b5bf46872ea6cb7655936c7341a5f8b5c2876526 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 13 Jun 2021 15:40:59 +0300 Subject: [PATCH 005/348] LOGSTREAMFN function printing improved --- src/cc/CCinclude.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 035543ecb1b..6caa48389a7 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -1193,7 +1193,7 @@ void CCLogPrintStream(const char *category, int level, const char *functionName, stream << (category ? category : "") << " "; if (functionName != NULL) - stream << functionName << " "; + stream << functionName << "() "; if (level < 0) stream << "ERROR:" << " "; print_to_stream(stream); @@ -1217,6 +1217,9 @@ void CCLogPrintStream(const char *category, int level, const char *functionName, /// @see LOGSTREAM #define LOGSTREAMFN(category, level, logoperator) CCLogPrintStream( category, level, __func__, [&](std::ostringstream &stream) {logoperator;} ) +/// class CCERROR to replace old single threaded CCerror global var +/// CCERROR is instanciated as thread_local and allows safely set error in cc rpc calls +/// Note: we cannot use std::string as the 'message' member as it would fail in thread_local mode class CCERROR { private: void init() { From 92ff8fabcfc15823abe40be950f997e2aa3216c7 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 13 Jun 2021 15:41:12 +0300 Subject: [PATCH 006/348] comment added --- src/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.h b/src/main.h index 7d67119f8ab..3f53646b32e 100644 --- a/src/main.h +++ b/src/main.h @@ -808,7 +808,7 @@ class CScriptCheck CScript scriptPubKey; CAmount amount; const CTransaction *ptxTo; - unsigned int n; + unsigned int n; // vin/vout index, since ccv2 unused for cc validation (it always validates the whole cc tx and does not re-enter validation for each vin) unsigned int nFlags; bool cacheStore; uint32_t consensusBranchId; From 6028e8a5e2e63fd3ae068b47aa8e3637cc87a690 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 13 Jun 2021 15:41:46 +0300 Subject: [PATCH 007/348] tui asset test updated for test chain usernames --- src/tui/tui_assets_orders.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index d5024e571e8..19a71a60337 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -47,9 +47,9 @@ def run_tokens_create(rpc): # set your own two node params # DIMXY20 - rpc1 = rpclib.rpc_connect("user2135429985", "passe26e9bce922bb0005fff3c41c20e7ea033399104aab3f148c515a2fa72fa4a9272", 14723) - rpc2 = rpclib.rpc_connect("user3701990598", "pass6df4dc57b2ee49b9e591ac6c8cb6aa89f0a06056ce67c6c45bbb14c0d63170e8a0", 15723) - rpc3 = rpclib.rpc_connect("user472219135", "passf6651258f69a92af554a7976ba44707db8eeb2372e6bb89e5557b8d7ee906eecbc", 16723) + rpc1 = rpclib.rpc_connect("user3088995989", "pass53c05895f37aa1eda9b0de63944275668e1956abb8c38f186132262fe53ae9be7c", 14723) + rpc2 = rpclib.rpc_connect("user2898668153", "passe99167496d2bbe43876e60430d52eb37b547fa1085b741a15776454eb126d9a603", 15723) + rpc3 = rpclib.rpc_connect("user972794450", "passe7eb16f5c015a53463cc5f27a004854cb76f4ec5c9aece177f01d8b3d13119e445", 16723) for v in ["", "v2"] : From a4021fa44800976f61fb01bc3e52268e70919428 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 21 Jun 2021 15:49:52 +0500 Subject: [PATCH 008/348] make a dedicated addrman.Init() call to prevent lock init concurrency (lock invalid param assertion on static construction) --- src/addrman.h | 5 +++++ src/init.cpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/addrman.h b/src/addrman.h index 28e07a82b13..7816f06b0fc 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -523,6 +523,11 @@ friend class CAddrManTest; } CAddrMan() + { + // Clear(); // causes boost: mutex lock failed in pthread_mutex_lock: Invalid argument exception because of static init concurrency (static dd_mutex has not been constructed yet) + } + + void Init() { Clear(); } diff --git a/src/init.cpp b/src/init.cpp index 052192c42a2..8898bb77971 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -951,6 +951,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (setProcDEPPol != NULL) setProcDEPPol(PROCESS_DEP_ENABLE); #endif + addrman.Init(); // call clear addr table + if (!SetupNetworking()) return InitError("Error: Initializing networking failed"); From 1840c69fc88f0084768c4ba83900a76c8aeda3fa Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 21 Jun 2021 15:50:21 +0500 Subject: [PATCH 009/348] removed unused komodo_defs include --- src/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.cpp b/src/util.cpp index fa62ba1ff85..65ecfe6ec7f 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -30,7 +30,7 @@ #include "sync.h" #include "utilstrencodings.h" #include "utiltime.h" -#include "komodo_defs.h" +//#include "komodo_defs.h" // plz dont add this where it is not used, we have build errors for komodo-cli #include #include From 2d66e2e880e2efea5f12ab6ebb901c7338a67dc4 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 21 Jun 2021 15:53:20 +0500 Subject: [PATCH 010/348] added tokens validation rules: disabled > 1 markers in tokenv2create, disabled markers in tokentransfer (v1 and v2), marker value is checked token validation code refactored (removed a separate create tx checking function, its checks moved into TokenExactAmounts) --- src/cc/CCtokens.cpp | 261 ++++++++++++++++++++++------------------- src/cc/CCtokens.h | 21 +--- src/cc/CCtokens_impl.h | 139 +++++++++++++++------- src/cc/import.cpp | 2 +- 4 files changed, 246 insertions(+), 177 deletions(-) diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 8a5cc6fb45b..e784742e769 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -28,7 +28,7 @@ thread_local uint32_t tokenValIndentSize = 0; // for debug logging // helper funcs: -bool IsEqualScriptPubKeys(const CScript &spk1, const CScript &spk2) +bool IsEqualDestinations(const CScript &spk1, const CScript &spk2) { char addr1[KOMODO_ADDRESS_BUFSIZE]; char addr2[KOMODO_ADDRESS_BUFSIZE]; @@ -50,16 +50,6 @@ static void FilterOutTokensUnspendablePk(const std::vector &sourcePubke } -static bool HasMyCCVin(struct CCcontract_info *cp, const CTransaction &tx) -{ - for (auto const &vin : tx.vin) { - if (cp->ismyvin(vin.scriptSig)) { - return true; - } - } - return false; -} - static std::vector GetEvalCodesCCV2(const CScript& spk) { std::vector ccdata = spk.GetCCV2SPK(); @@ -84,7 +74,7 @@ static std::vector GetEvalCodesCCV2(const CScript& spk) // internal function to check if token vout is valid // returns amount or -1 // return also tokenid -CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, std::string &errorStr) +CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr) { // this is just for log messages indentation fur debugging recursive calls: std::string indentStr = std::string().append(tokenValIndentSize, '.'); @@ -123,13 +113,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used // instead of recursively checking tx just check that the tx has token cc vin, that is it was validated by tokens cc module bool hasMyccvin = false; - for (auto const &vin : tx.vin) { - if (cp->ismyvin(vin.scriptSig)) { - hasMyccvin = true; - break; - } - } - + std::for_each (tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin){ cp->ismyvin(vin.scriptSig) ? hasMyccvin = true : hasMyccvin = hasMyccvin; }); CScript opret; bool isLastVoutOpret; @@ -148,7 +132,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used std::vector voutPubkeysInOpret; // token opret most important checks (tokenid == reftokenid, tokenid is non-zero, tx is 'tokenbase'): - uint8_t funcId = DecodeTokenOpRetV1(opret, tokenIdOpret, voutPubkeysInOpret, oprets); + funcId = DecodeTokenOpRetV1(opret, tokenIdOpret, voutPubkeysInOpret, oprets); if (funcId == 0) { // bad opreturn // errorStr = "can't decode opreturn data"; @@ -178,7 +162,6 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used return -1; } - if (!isLastVoutOpret) // check OP_DROP vouts: { // get up to two eval codes from cc data: @@ -216,15 +199,15 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used if (voutPubkeysInOpret.size() == 1) { if (evalCode1 == 0 && evalCode2 == 0) { - if (IsEqualScriptPubKeys(tx.vout[v].scriptPubKey, MakeTokensCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeysInOpret[0]).scriptPubKey)) + if (IsEqualDestinations(tx.vout[v].scriptPubKey, MakeTokensCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeysInOpret[0]).scriptPubKey)) return tx.vout[v].nValue; } else if (evalCode1 != 0 && evalCode2 == 0) { - if (IsEqualScriptPubKeys(tx.vout[v].scriptPubKey, MakeTokensCC1vout(evalCode1, tx.vout[v].nValue, voutPubkeysInOpret[0]).scriptPubKey)) + if (IsEqualDestinations(tx.vout[v].scriptPubKey, MakeTokensCC1vout(evalCode1, tx.vout[v].nValue, voutPubkeysInOpret[0]).scriptPubKey)) return tx.vout[v].nValue; } else if (evalCode1 != 0 && evalCode2 != 0) { - if (IsEqualScriptPubKeys(tx.vout[v].scriptPubKey, MakeTokensCC1vout(evalCode1, evalCode2, tx.vout[v].nValue, voutPubkeysInOpret[0]).scriptPubKey)) + if (IsEqualDestinations(tx.vout[v].scriptPubKey, MakeTokensCC1vout(evalCode1, evalCode2, tx.vout[v].nValue, voutPubkeysInOpret[0]).scriptPubKey)) return tx.vout[v].nValue; } else { @@ -235,15 +218,15 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used else if (voutPubkeysInOpret.size() == 2) { if (evalCode1 == 0 && evalCode2 == 0) { - if (IsEqualScriptPubKeys(tx.vout[v].scriptPubKey, MakeTokensCC1of2vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeysInOpret[0], voutPubkeysInOpret[1]).scriptPubKey)) + if (IsEqualDestinations(tx.vout[v].scriptPubKey, MakeTokensCC1of2vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeysInOpret[0], voutPubkeysInOpret[1]).scriptPubKey)) return tx.vout[v].nValue; } else if (evalCode1 != 0 && evalCode2 == 0) { - if (IsEqualScriptPubKeys(tx.vout[v].scriptPubKey, MakeTokensCC1of2vout(evalCode1, tx.vout[v].nValue, voutPubkeysInOpret[0], voutPubkeysInOpret[1]).scriptPubKey)) + if (IsEqualDestinations(tx.vout[v].scriptPubKey, MakeTokensCC1of2vout(evalCode1, tx.vout[v].nValue, voutPubkeysInOpret[0], voutPubkeysInOpret[1]).scriptPubKey)) return tx.vout[v].nValue; } else if (evalCode1 != 0 && evalCode2 != 0) { - if (IsEqualScriptPubKeys(tx.vout[v].scriptPubKey, MakeTokensCC1of2vout(evalCode1, evalCode2, tx.vout[v].nValue, voutPubkeysInOpret[0], voutPubkeysInOpret[1]).scriptPubKey)) + if (IsEqualDestinations(tx.vout[v].scriptPubKey, MakeTokensCC1of2vout(evalCode1, evalCode2, tx.vout[v].nValue, voutPubkeysInOpret[0], voutPubkeysInOpret[1]).scriptPubKey)) return tx.vout[v].nValue; } else { @@ -262,7 +245,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used // funcid == 'c' if (tx.IsCoinImport()) { // imported coin is checked in EvalImportCoin - if (!IsTokenMarkerVout(tx.vout[v])) // exclude marker + if (IsTokenMarkerVout(tx.vout[v]) > 0LL) // exclude marker return tx.vout[v].nValue; else return 0; @@ -286,7 +269,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used for (const auto &vout : tx.vout) if (vout.scriptPubKey.IsPayToCryptoCondition()) { CTxOut testvout = vopretNFT.size() == 0 ? MakeCC1vout(EVAL_TOKENS, vout.nValue, origPubkey) : MakeTokensCC1vout(vopretNFT[0], vout.nValue, origPubkey); - if (IsEqualScriptPubKeys(vout.scriptPubKey, testvout.scriptPubKey)) + if (IsEqualDestinations(vout.scriptPubKey, testvout.scriptPubKey)) ccOutputs += vout.nValue; } @@ -296,7 +279,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used // make test vout for origpubkey (either for fungible or NFT): CTxOut testvout = vopretNFT.size() == 0 ? MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, origPubkey) : MakeTokensCC1vout(vopretNFT[0], tx.vout[v].nValue, origPubkey); - if (IsEqualScriptPubKeys(tx.vout[v].scriptPubKey, testvout.scriptPubKey)) // check vout sent to orig pubkey + if (IsEqualDestinations(tx.vout[v].scriptPubKey, testvout.scriptPubKey)) // check vout sent to orig pubkey return tx.vout[v].nValue; else return 0; @@ -472,6 +455,11 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used vuint8_t vopretNFT; GetOpReturnCCBlob(oprets, vopretNFT); + if (origPubkey == GetUnspendable(cp, NULL)) { + errorStr = "cannot create tokens with token shared pubkey"; + return -1; + } + // TODO: add voutPubkeys for 'c' tx /* this would not work for imported tokens: @@ -490,31 +478,31 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used for (const auto &vout : tx.vout) if (vout.scriptPubKey.IsPayToCryptoCondition()) { CTxOut testvout = vopretNFT.size() == 0 ? MakeCC1vout(EVAL_TOKENS, vout.nValue, origPubkey) : MakeTokensCC1vout(vopretNFT[0], vout.nValue, origPubkey); - if (IsEqualScriptPubKeys(vout.scriptPubKey, testvout.scriptPubKey)) + if (IsEqualDestinations(vout.scriptPubKey, testvout.scriptPubKey)) ccOutputs += vout.nValue; } - CAmount normalInputs = TotalPubkeyNormalInputs(tx, origPubkey); // check if normal inputs are really signed by originator pubkey (someone not cheating with originator pubkey) - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() normalInputs=" << normalInputs << " ccOutputs=" << ccOutputs << " for tokenbase=" << reftokenid.GetHex() << std::endl); + CAmount origInputs = TotalPubkeyNormalInputs(tx, origPubkey); // check if normal inputs are really signed by originator pubkey (someone not cheating with originator pubkey) + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() origInputs=" << origInputs << " ccOutputs=" << ccOutputs << " for tokenbase=" << reftokenid.GetHex() << std::endl); - if (normalInputs >= ccOutputs) { - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() assured normalInputs >= ccOutputs" << " for tokenbase=" << reftokenid.GetHex() << std::endl); + if (origInputs >= ccOutputs) { + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() assured origInputs >= ccOutputs" << " for tokenbase=" << reftokenid.GetHex() << std::endl); // make test vout for origpubkey (either for fungible or NFT): CTxOut testvout = vopretNFT.size() == 0 ? MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, origPubkey) : MakeTokensCC1vout(vopretNFT[0], tx.vout[v].nValue, origPubkey); - if (IsEqualScriptPubKeys(tx.vout[v].scriptPubKey, testvout.scriptPubKey)) // check vout sent to orig pubkey + if (IsEqualDestinations(tx.vout[v].scriptPubKey, testvout.scriptPubKey)) // check vout sent to orig pubkey return tx.vout[v].nValue; else return 0; // vout is good, but do not take marker into account } else { - LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "IsTokensvout() skipping vout not fulfilled normalInputs >= ccOutput" << " for tokenbase=" << reftokenid.GetHex() << " normalInputs=" << normalInputs << " ccOutputs=" << ccOutputs << std::endl); + LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "IsTokensvout() skipping vout not fulfilled normalInputs >= ccOutput" << " for tokenbase=" << reftokenid.GetHex() << " origInputs=" << origInputs << " ccOutputs=" << ccOutputs << std::endl); } } else { // imported tokens are checked in the eval::ImportCoin() validation code - if (!IsTokenMarkerVout(tx.vout[v])) // exclude marker + if (IsTokenMarkerVout(tx.vout[v]) > 0LL) // exclude marker return tx.vout[v].nValue; else return 0; // vout is good, but do not take marker into account @@ -531,7 +519,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used // internal function to check if token 2 vout is valid // returns amount or -1 // return also tokenid -CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, std::string &errorStr) +CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr) { // this is just for log messages indentation fur debugging recursive calls: std::string indentStr = std::string().append(tokenValIndentSize, '.'); @@ -546,66 +534,88 @@ CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcon return -1; } - std::vector vParams; CScript dummy; - if (tx.vout[v].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams)) - { - if (tx.vout[v].scriptPubKey.SpkHasEvalcodeCCV2(EVAL_TOKENSV2)) // it's token output, check it - { - CScript opret; - bool isLastVoutOpret; - if (GetCCDropAsOpret(tx.vout[v].scriptPubKey, opret)) - { - isLastVoutOpret = false; - } - else - { - isLastVoutOpret = true; - opret = tx.vout.back().scriptPubKey; - } + if (tx.vout[v].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) && + tx.vout[v].scriptPubKey.SpkHasEvalcodeCCV2(EVAL_TOKENSV2)) // it's token output, check it + { + CScript opret; + bool isLastVoutOpret; + if (GetCCDropAsOpret(tx.vout[v].scriptPubKey, opret)) + { + isLastVoutOpret = false; + } + else + { + isLastVoutOpret = true; + opret = tx.vout.back().scriptPubKey; + } - uint256 tokenIdOpret; - std::vector oprets; + uint256 tokenIdOpret; + std::vector oprets; + std::vector vpksdummy; + + // token opret most important checks (tokenid == reftokenid, tokenid is non-zero, tx is 'tokenbase'): + funcId = TokensV2::DecodeTokenOpRet(opret, tokenIdOpret, vpksdummy, oprets); + if (funcId == 0) { + // bad opreturn + errorStr = "can't decode opreturn data"; + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensV2::CheckTokensvout()" << " skipping vout with non token opret for txid=" << tx.GetHash().GetHex() << " v=" << v << " isLastVoutOpret=" << isLastVoutOpret << std::endl); + return -1; // not token vout, skip + } + + // basic checks: + if (IsTokenCreateFuncid(funcId)) { std::vector vpksdummy; + std::vector oprets; + vuint8_t vorigpk; + std::string name, description; - // token opret most important checks (tokenid == reftokenid, tokenid is non-zero, tx is 'tokenbase'): - uint8_t funcId = TokensV2::DecodeTokenOpRet(opret, tokenIdOpret, vpksdummy, oprets); - if (funcId == 0) { - // bad opreturn - errorStr = "can't decode opreturn data"; - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensV2::CheckTokensvout()" << " skipping vout with non token opret for txid=" << tx.GetHash().GetHex() << " v=" << v << " isLastVoutOpret=" << isLastVoutOpret << std::endl); - return -1; // not token vout, skip - } - - // basic checks: - if (IsTokenCreateFuncid(funcId)) { - // set returned tokend to tokenbase txid: - reftokenid = tx.GetHash(); - } - else if (IsTokenTransferFuncid(funcId)) { - // set returned tokenid to tokenid in opreturn: - reftokenid = tokenIdOpret; - } - else { - errorStr = "funcid not supported"; + // set returned tokend to tokenbase txid: + reftokenid = tx.GetHash(); + + TokensV2::DecodeTokenCreateOpRet(opret, vorigpk, name, description, oprets); + + // check this is really creator + CPubKey origpk = pubkey2pk(vorigpk); + if (TotalPubkeyNormalInputs(tx, origpk) == 0) { + errorStr = "no vins signed with creator pubkey"; return -1; } - - if (reftokenid.IsNull()) { - errorStr = "null tokenid"; + if (origpk == GetUnspendable(cp, NULL)) { + errorStr = "cannot create tokens with token shared pubkey"; return -1; } + } + else if (IsTokenTransferFuncid(funcId)) { + // set returned tokenid to tokenid in opreturn: + reftokenid = tokenIdOpret; + } + else { + errorStr = "funcid not supported"; + return -1; + } + + if (reftokenid.IsNull()) { + errorStr = "null tokenid"; + return -1; + } - // skip token marker (token global address) - if (IsTokenMarkerVout(tx.vout[v])) { - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensV2::CheckTokensvout()" << " skipping marker vout for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); - return 0; - } + // skip token marker (token global address) + CAmount markerAmount = IsTokenMarkerVout(tx.vout[v]); + if (markerAmount > 0) { + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensV2::CheckTokensvout()" << " skipping marker vout for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); + return 0; + } + else if (markerAmount < 0) { + errorStr = "invalid marker value"; + return -1; + } - /* let's do not verify opdrop data in V2 - it is a just hint to users and does not really affect vaidation: - // get output pubkeys and verify vout + /* let's do not verify opdrop data in V2 + it is a just hint to users and does not really affect vaidation: + // get output pubkeys and verify vout + { if (vParams.size() == 0) { errorStr = "no opdrop data"; return -1; @@ -624,16 +634,12 @@ CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcon std::vector evalcodes = GetEvalCodesCCV2(tx.vout[v].scriptPubKey); testVout = MakeTokensCCMofNvoutMixed(evalcodes.size() >= 1 ? evalcodes[0] : 0, evalcodes.size() >= 2 ? evalcodes[1] : 0, tx.vout[v].nValue, opdrop.m, opdrop.vKeys); - if (!IsEqualScriptPubKeys(testVout.scriptPubKey, tx.vout[v].scriptPubKey)) { + if (!IsEqualDestinations(testVout.scriptPubKey, tx.vout[v].scriptPubKey)) { errorStr = "pubkeys in opdrop don't match vout"; return -1; - } */ - return tx.vout[v].nValue; - } - else - { - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensV2::CheckTokensvout()" << " skipping vout with non-token evalcode for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); - } + } + } */ + return tx.vout[v].nValue; } return(0); // normal or non-token2 vout } @@ -695,6 +701,7 @@ static bool report_validation_error(const std::string &func, Eval* eval, const C // checking creation txns is available with cryptocondition v2 mixed mode // therefore do not forget to check that the creation tx does not have cc inputs! +/* static bool CheckTokensV2CreateTx(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx) { std::vector vpksdummy; @@ -708,27 +715,35 @@ static bool CheckTokensV2CreateTx(struct CCcontract_info *cp, Eval* eval, const int32_t transferNum = 0; for(int32_t i = 0; i < tx.vout.size(); i ++) { - if (tx.vout[i].scriptPubKey.IsPayToCryptoCondition()) + if (tx.vout[i].scriptPubKey.IsPayToCryptoCondition() && tx.vout[i].scriptPubKey.SpkHasEvalcodeCCV2(EVAL_TOKENSV2)) { - CScript opdrop; - if (GetCCDropAsOpret(tx.vout[i].scriptPubKey, opdrop)) + CScript opret; + bool isLastVoutOpret; + if (GetCCDropAsOpret(tx.vout[v].scriptPubKey, opret)) { - uint8_t funcid = TokensV2::DecodeTokenOpRet(opdrop, tokenid, vpksdummy, oprets); - if (IsTokenCreateFuncid(funcid)) { - createNum ++; - if (createNum > 1) - return report_validation_error(__func__, eval, tx, "can't have more than 1 create vout"); - - TokensV2::DecodeTokenCreateOpRet(opdrop, vorigpk, name, description, oprets); - - // check this is really creator - CPubKey origpk = pubkey2pk(vorigpk); - if (TotalPubkeyNormalInputs(tx, origpk) == 0) - return report_validation_error(__func__, eval, tx, "no vins with creator pubkey"); - } - else if(IsTokenTransferFuncid(funcid)) - transferNum ++; + isLastVoutOpret = false; } + else + { + isLastVoutOpret = true; + opret = tx.vout.back().scriptPubKey; + } + + uint8_t funcid = TokensV2::DecodeTokenOpRet(opret, tokenid, vpksdummy, oprets); + if (IsTokenCreateFuncid(funcid)) { + createNum ++; + if (createNum > 1) + return report_validation_error(__func__, eval, tx, "can't have more than 1 create vout"); + + TokensV2::DecodeTokenCreateOpRet(opret, vorigpk, name, description, oprets); + + // check this is really creator + CPubKey origpk = pubkey2pk(vorigpk); + if (TotalPubkeyNormalInputs(tx, origpk) == 0) + return report_validation_error(__func__, eval, tx, "no vins with creator pubkey"); + } + else if(IsTokenTransferFuncid(funcid)) + transferNum ++; } } @@ -752,12 +767,15 @@ static bool CheckTokensV2CreateTx(struct CCcontract_info *cp, Eval* eval, const // check that creation tx does not have my cc vins if (createNum > 0) { - if (HasMyCCVin(cp, tx)) + bool hasMyccvin = false; + std::for_each (tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin){ cp->ismyvin(vin.scriptSig) ? hasMyccvin = true : hasMyccvin = hasMyccvin; }); + if (hasMyccvin) return report_validation_error(__func__, eval, tx, "creation tx can't have token vins"); return true; } return false; } +*/ // token 2 cc validation entry point bool Tokensv2Validate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) @@ -771,15 +789,18 @@ bool Tokensv2Validate(struct CCcontract_info *cp, Eval* eval, const CTransaction std::string errorStr; - if (CheckTokensV2CreateTx(cp, eval, tx)) //found create tx and it is valid - return true; - if (eval->state.IsInvalid()) // create tx is invalid - return false; + // these checks now are in TokensExactAmounts + //if (CheckTokensV2CreateTx(cp, eval, tx)) //found create tx and it is valid + // return true; + //if (eval->state.IsInvalid()) // create tx is invalid + // return false; - // check 't' vouts (could have multiple tokenids) + // check token vouts (token txns could have multiple tokenids for multiple token transfer) if (!TokensExactAmounts(true, cp, eval, tx, errorStr)) return report_validation_error(__func__, eval, tx, errorStr); + // disable many markers: + return true; } diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index 701f838c4e3..0a5b5a3c950 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -23,24 +23,16 @@ #include #include "CCinclude.h" +const CAmount TOKENS_MARKER_VALUE = 10000; + // implementation of basic token functions -/// Returns non-fungible data of token if this is a NFT -/// @param tokenid id of token -/// @param vopretNonfungible non-fungible token data. The first byte is the evalcode of the contract that validates the NFT-data -//void GetNonfungibleData(uint256 tokenid, vscript_t &vopretNonfungible); // see template impl typedef std::tuple TokenDataTuple; // pubkey, name, desc // CCcustom bool TokensValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); bool Tokensv2Validate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); -//bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, std::string &errorStr); - -// wrappers for tokens cc v1 or v2 -////std::string CreateTokenLocal(CAmount txfee, CAmount tokensupply, std::string name, std::string description, vscript_t nonfungibleData); -//bool IsTokenMarkerVout(CTxOut vout); - /// Adds token inputs to transaction object. If tokenid is a non-fungible token then the function will set additionalTokensEvalcode2 variable in the cp object to the eval code from NFT data to spend NFT outputs properly /// @param cp CCcontract_info structure /// @param mtx mutable transaction object @@ -287,7 +279,7 @@ UniValue TokenV2List(); inline bool IsTokenCreateFuncid(uint8_t funcid) { return funcid == 'c'; } inline bool IsTokenTransferFuncid(uint8_t funcid) { return funcid == 't'; } -bool IsEqualScriptPubKeys(const CScript &spk1, const CScript &spk2); +bool IsEqualDestinations(const CScript &spk1, const CScript &spk2); bool TokensIsVer1Active(const Eval *eval); @@ -299,7 +291,6 @@ class TokensV1 { static uint8_t EvalCode() { return EVAL_TOKENS; } static bool IsMixed() { return false; } - static CScript EncodeTokenCreateOpRet(const std::vector &origpubkey, const std::string &name, const std::string &description, const std::vector &oprets) { return ::EncodeTokenCreateOpRetV1(origpubkey, name, description, oprets); @@ -318,7 +309,7 @@ class TokensV1 { return ::DecodeTokenOpRetV1(scriptPubKey, tokenid, voutPubkeys, oprets); } - static CAmount CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, std::string &errorStr); + static CAmount CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr); // conds: static CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk) @@ -401,7 +392,7 @@ class TokensV2 { return ::DecodeTokenOpRetV2(scriptPubKey, tokenid, oprets); } - static CAmount CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, std::string &errorStr); + static CAmount CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr); // conds: static CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk) @@ -458,7 +449,7 @@ template uint8_t ValidateTokenOpret(uint256 txid, const CScript &scrip /// @private template bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector &vinPubkeys); /// @private -template bool IsTokenMarkerVout(CTxOut vout); +template CAmount IsTokenMarkerVout(CTxOut vout); /// @private uint8_t DecodeTokenOpretVersion(const CScript &scriptPubKey); diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 1dfbe79e3d8..f2e6e40a85f 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -500,9 +500,9 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup if (txfee == 0) txfee = 10000; - int32_t txfeeCount = 2; + int32_t markerCount = 1; if (additionalMarkerEvalCode > 0) - txfeeCount++; + markerCount++; bool isRemote = remotepk.IsValid(); CPubKey mypk = isRemote ? remotepk : pubkey2pk(Mypubkey()); @@ -514,7 +514,7 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup CAmount totalInputs; // always add inputs only from the mypk passed in the param to prove the token creator has the token originator pubkey // This what the AddNormalinputsRemote does (and it is not necessary that this is done only for nspv calls): - if ((totalInputs = AddNormalinputsRemote(mtx, mypk, tokensupply + txfeeCount * txfee, 0x10000, useMempool)) > 0) + if ((totalInputs = AddNormalinputsRemote(mtx, mypk, tokensupply + txfee + markerCount * TOKENS_MARKER_VALUE, 0x10000, useMempool)) > 0) { CAmount mypkInputs = TotalPubkeyNormalInputs(mtx, mypk); if (mypkInputs < tokensupply) { // check that the token amount is really issued with mypk (because in the wallet there may be some other privkeys) @@ -527,7 +527,7 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup destEvalCode = nonfungibleData[0]; // NOTE: we should prevent spending fake-tokens from this marker in IsTokenvout(): - mtx.vout.push_back(V::MakeCC1vout(V::EvalCode(), txfee, GetUnspendable(cp, NULL))); // new marker to token cc addr, burnable and validated, vout pos now changed to 0 (from 1) + mtx.vout.push_back(V::MakeCC1vout(V::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); // new marker to token cc addr, burnable and validated, vout pos now changed to 0 (from 1) mtx.vout.push_back(V::MakeTokensCC1vout(destEvalCode, tokensupply, mypk)); if (additionalMarkerEvalCode > 0) @@ -535,7 +535,7 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup // add additional marker for NFT cc evalcode: struct CCcontract_info *cpNFT, CNFT; cpNFT = CCinit(&CNFT, additionalMarkerEvalCode); - mtx.vout.push_back(V::MakeCC1vout(additionalMarkerEvalCode, txfee, GetUnspendable(cpNFT, NULL))); + mtx.vout.push_back(V::MakeCC1vout(additionalMarkerEvalCode, TOKENS_MARKER_VALUE, GetUnspendable(cpNFT, NULL))); } sigData = V::FinalizeCCTx(isRemote, FINALIZECCTX_NO_CHANGE_WHEN_ZERO, cp, mtx, mypk, txfee, V::EncodeTokenCreateOpRet(vscript_t(mypk.begin(), mypk.end()), name, description, { nonfungibleData })); @@ -875,16 +875,20 @@ static CAmount HasBurnedTokensvouts(const CTransaction& tx, uint256 reftokenid) return burnedAmount; } +// checks if this is tokens marker (sent to the token shared address) +// and the marker value is fixed +// returns -1 if this is a bad marker or marker's nValue +// return 0 if this is not a token marker template -bool IsTokenMarkerVout(CTxOut vout) { +CAmount IsTokenMarkerVout(CTxOut vout) { struct CCcontract_info *cpTokens, CCtokens_info; cpTokens = CCinit(&CCtokens_info, V::EvalCode()); - return IsEqualScriptPubKeys(vout.scriptPubKey, V::MakeCC1vout(V::EvalCode(), vout.nValue, GetUnspendable(cpTokens, NULL)).scriptPubKey); + if (IsEqualDestinations(vout.scriptPubKey, V::MakeCC1vout(V::EvalCode(), vout.nValue, GetUnspendable(cpTokens, NULL)).scriptPubKey)) + return vout.nValue == TOKENS_MARKER_VALUE ? vout.nValue : -1; + else + return 0; } - - - // Checks if the vout is a really Tokens CC vout. // For this the function takes eval codes and pubkeys from the token opret and tries to construct possible token vouts // if one of them matches to the passed vout then the passed vout is a correct token vout @@ -895,9 +899,11 @@ bool IsTokenMarkerVout(CTxOut vout) { template CAmount IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid) { + uint8_t funcId = 0; uint256 tokenIdInOpret; std::string errorStr; - CAmount retAmount = V::CheckTokensvout(goDeeper, checkPubkeys, cp, eval, tx, v, tokenIdInOpret, errorStr); + CAmount retAmount = V::CheckTokensvout(goDeeper, checkPubkeys, cp, eval, tx, v, tokenIdInOpret, funcId, errorStr); + std::cerr << __func__ << " tokenIdInOpret=" << tokenIdInOpret.GetHex() << " funcId=" << (int)funcId << std::endl; if (!errorStr.empty()) LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "error=" << errorStr << std::endl); if (retAmount < 0) @@ -962,12 +968,6 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c CTransaction vinTx; uint256 hashBlock; CAmount tokenoshis; - - //struct CCcontract_info *cpTokens, tokensC; - //cpTokens = CCinit(&tokensC, EVAL_TOKENS); - - int32_t numvins = tx.vin.size(); - int32_t numvouts = tx.vout.size(); std::map mapinputs, mapoutputs; @@ -977,7 +977,7 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c //LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() entered for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); // pick token vouts in vin transactions and calculate input total - for (int32_t i = 0; iismyvin)(tx.vin[i].scriptSig) /*|| IsVinAllowed(tx.vin[i].scriptSig) != 0*/) { @@ -985,7 +985,7 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c // we are not inside the validation code -- dimxy if ((eval && eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock) == 0) || (!eval && !myGetTransaction(tx.vin[i].prevout.hash, vinTx, hashBlock))) { - LOGSTREAM(cctokens_log, CCLOG_ERROR, stream << indentStr << "TokensExactAmounts() cannot read vintx for i." << i << " numvins." << numvins << std::endl); + LOGSTREAM(cctokens_log, CCLOG_ERROR, stream << indentStr << "TokensExactAmounts() cannot read vintx for vin i=" << i << std::endl); return (!eval) ? false : eval->Invalid("could not load vin tx " + std::to_string(i)); } else @@ -993,18 +993,20 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() checking vintx.vout for tx.vin[" << i << "] nValue=" << vinTx.vout[tx.vin[i].prevout.n].nValue << std::endl); uint256 reftokenid; + uint8_t funcId = 0; // validate vouts of vintx tokenValIndentSize++; - tokenoshis = V::CheckTokensvout(goDeeper, true, cp, eval, vinTx, tx.vin[i].prevout.n, reftokenid, errorStr); + tokenoshis = V::CheckTokensvout(goDeeper, true, cp, eval, vinTx, tx.vin[i].prevout.n, reftokenid, funcId, errorStr); tokenValIndentSize--; if (tokenoshis < 0) return false; // skip marker spending // later it will be checked if marker spending is allowed - if (IsTokenMarkerVout(vinTx.vout[tx.vin[i].prevout.n])) { + if (IsTokenMarkerVout(vinTx.vout[tx.vin[i].prevout.n]) > 0LL) { LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() skipping marker vintx.vout for tx.vin[" << i << "] nValue=" << vinTx.vout[tx.vin[i].prevout.n].nValue << std::endl); continue; + // do not check for marker count for on-chain transacitions, no point in checking this (for token v1) as it is an antispam feature } if (tokenoshis != 0) @@ -1017,24 +1019,44 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c } // pick token vouts in the current transaction and calculate output total - for (int32_t i = 0; i < numvouts; i ++) + int markerVouts = 0; + int createVouts = 0; + int transferVouts = 0; + for (int32_t i = 0; i < tx.vout.size(); i ++) { uint256 reftokenid; + uint8_t funcId = 0; LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() recursively checking tx.vout[" << i << "] nValue=" << tx.vout[i].nValue << std::endl); // Note: we pass in here IsTokensvout(false,...) because we don't need to call TokenExactAmounts() recursively from IsTokensvout here // indeed, if we pass 'true' we'll be checking this tx vout again tokenValIndentSize++; - tokenoshis = V::CheckTokensvout(false, true, cp, eval, tx, i, reftokenid, errorStr); + tokenoshis = V::CheckTokensvout(false, true, cp, eval, tx, i, reftokenid, funcId, errorStr); tokenValIndentSize--; if (tokenoshis < 0) return false; - if (IsTokenMarkerVout(tx.vout[i])) { + CAmount markerAmount = IsTokenMarkerVout(tx.vout[i]); + if (markerAmount > 0) { + ++ markerVouts; + if (IsTokenCreateFuncid(funcId) && markerVouts > 1) { + errorStr = "tokencreate cannot have more than one marker"; + return false; + } + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() skipping marker tx.vout[" << i << "] nValue=" << tx.vout[i].nValue << std::endl); - continue; + continue; // skip marker + } + else if (markerAmount < 0) { + errorStr = "invalid marker value"; + return false; } + if (IsTokenCreateFuncid(funcId)) + ++ createVouts; + if (IsTokenTransferFuncid(funcId)) + ++ transferVouts; + if (tokenoshis != 0) { LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() adding tx.vout[" << i << "] tokenoshis=" << tokenoshis << std::endl); @@ -1042,26 +1064,61 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c } } - //std::cerr << indentStr << "TokensExactAmounts() inputs=" << inputs << " outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << std::endl; + // can't mix tokencreate and tokentransfer + if (createVouts > 0 && transferVouts > 0) { + errorStr = "can't have both create and transfer vouts"; + return false; + } + + // tokencreate checks (this would work only for tokens v2 as tokens v1 tokencreate does not pass cc validation when it is added to the chain) + if (createVouts > 0) { + // check that creation tx does not have my cc vins + bool hasMyccvin = false; + std::for_each (tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin){ cp->ismyvin(vin.scriptSig) ? hasMyccvin = true : hasMyccvin = hasMyccvin; }); + if (hasMyccvin) { + errorStr = "creation tx can't have token vins"; + return false; + } + if (createVouts > 1) { + errorStr = "creation tx can't have several token vouts"; + return false; + } + // marker antispam check: + if (markerVouts > 1) { + errorStr = "tokencreate cannot have more than one marker"; + return false; + } + return true; // tokencreate checks finished + } - if (mapinputs.size() > 0 && mapinputs.size() == mapoutputs.size()) - { - for(auto const &m : mapinputs) { - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() inputs[" << m.first.GetHex() << "]=" << m.second << " outputs=" << mapoutputs[m.first] << std::endl); - if (m.second != mapoutputs[m.first]) { - errorStr = "cc inputs not equal outputs for tokenid=" + m.first.GetHex(); - return false; - } + // tokentransfer checks + if (transferVouts > 0) { + // markers are not allowed for tokentransfer (for antispam reasons) + if (markerVouts > 0) { + errorStr = "tokentransfer cannot have markers"; + return false; + } - // check marker spending: - if (!CheckMarkerSpending(cp, eval, tx, m.first)) { - errorStr = "marker spending is not allowed for tokenid=" + m.first.GetHex(); - return false; + // check token value balance: + if (mapinputs.size() > 0 && mapinputs.size() == mapoutputs.size()) + { + for(auto const &m : mapinputs) { + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() inputs[" << m.first.GetHex() << "]=" << m.second << " outputs=" << mapoutputs[m.first] << std::endl); + if (m.second != mapoutputs[m.first]) { + errorStr = "cc inputs not equal outputs for tokenid=" + m.first.GetHex(); + return false; + } + + // check marker spending: + if (!CheckMarkerSpending(cp, eval, tx, m.first)) { + errorStr = "marker spending is not allowed for tokenid=" + m.first.GetHex(); + return false; + } + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() mapinput.second=" << m.second << " mapoutputs[m.first]=" << mapoutputs[m.first] << std::endl); } - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() mapinput.second=" << m.second << " mapoutputs[m.first]=" << mapoutputs[m.first] << std::endl); + return true; } - return true; - } + } LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "TokensExactAmounts() no cc inputs or cc outputs for a tokenid, mapinputs.size()=" << mapinputs.size() << " mapoutputs.size()=" << mapoutputs.size() << std::endl); errorStr = "no cc vins or cc vouts for tokenid"; return false; diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 206d9e7fd23..7eb20f01665 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -571,7 +571,7 @@ bool CheckMigration(Eval *eval, const CTransaction &importTx, const CTransaction CAmount ccImportOutputs = 0; for (auto v : importTx.vout) if (v.scriptPubKey.IsPayToCryptoCondition() && - !IsTokenMarkerVout(v)) // should not be marker here + IsTokenMarkerVout(v) > 0LL) // should not be marker here ccImportOutputs += v.nValue; if (ccBurnOutputs != ccImportOutputs) From f8da82acaae9aeb77a700f6d2fd00902ae365afb Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 21 Jun 2021 15:54:27 +0500 Subject: [PATCH 011/348] test tui_asset_orders.py added check for MofN only for token v2 --- src/tui/tui_assets_orders.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 19a71a60337..5f8a26951c9 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -52,8 +52,8 @@ def run_tokens_create(rpc): rpc3 = rpclib.rpc_connect("user972794450", "passe7eb16f5c015a53463cc5f27a004854cb76f4ec5c9aece177f01d8b3d13119e445", 16723) - for v in ["", "v2"] : - # for v in ["v2"] : + # for v in ["", "v2"] : + for v in [""] : print("creating fungible token 1...") result = call_rpc(rpc1, "token"+v+"create", "T1", str(0.000001)) # 100 assert(check_tx(result)) @@ -108,13 +108,14 @@ def run_tokens_create(rpc): print("starting assets tests for nftf7id1 version=" + v + "...") run_assets_orders(rpc1, rpc2, v, nftf7id1, 1, 1, True) - print("starting MofN tests for tokenid1...") - run_MofN_transfers(rpc1, rpc2, rpc3, tokenid1, 10) - print("starting MofN tests for nft00id1...") - run_MofN_transfers(rpc1, rpc2, rpc3, nft00id1, 1) - print("starting MofN tests for nftf7id1...") - run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) - + if v == "v2" : + print("running MofN tests for tokens v2:") + print("starting MofN tests for tokenid1...") + run_MofN_transfers(rpc1, rpc2, rpc3, tokenid1, 10) + print("starting MofN tests for nft00id1...") + run_MofN_transfers(rpc1, rpc2, rpc3, nft00id1, 1) + print("starting MofN tests for nftf7id1...") + run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) print("assets tests finished okay") time.sleep(3) @@ -314,7 +315,7 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): print("sending partially1 signed tx returned:", result) assert not result, 'sending partially signed 2of2 tx should return error' except RpcException as e : - print ('got normal exception', e.message) + print ('got a normal exception (note "FULFILLMENT NOT ENCODED" msg on console is normal)', e.message) pass # should be error tx2of2back = call_rpc_retry(rpc2, "addccv2signature", '', partialtx['hex'], partialtx['PartiallySigned']) @@ -359,7 +360,7 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): print("sending partially1 signed tx returned:", result) assert not result, 'sending partially signed 2of3 tx should return error' except RpcException as e : - print ('got normal exception', e.message) + print ('got a normal exception (note "FULFILLMENT NOT ENCODED" msg on console is normal)', e.message) pass # should be error @@ -406,7 +407,7 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): print("sending partially1 signed tx returned:", result) assert not result, 'sending partially signed 3of3 tx should return error' except RpcException as e : - print ('got normal exception', e.message) + print ('got a normal exception (note "FULFILLMENT NOT ENCODED" msg on console is normal)', e.message) pass # should be error # add sig 2 @@ -419,7 +420,8 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): result = rpc2.sendrawtransaction(partialtx2['hex']) print("sending partially2 signed tx returned:", result) assert not result, 'sending partially signed 3of3 tx should return error' - except (RpcException) : + except RpcException as e : + print ('got a normal exception (note "FULFILLMENT NOT ENCODED" msg on console is normal)', e.message) pass # should be error # add sig 3 From e607c6b400188a21303bfd8ae292c27e4e07e6ff Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 21 Jun 2021 15:56:13 +0500 Subject: [PATCH 012/348] fix tui_asset_orders.py enabled both v1 and v2 tests --- src/tui/tui_assets_orders.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 5f8a26951c9..5c99248dc8d 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -52,8 +52,8 @@ def run_tokens_create(rpc): rpc3 = rpclib.rpc_connect("user972794450", "passe7eb16f5c015a53463cc5f27a004854cb76f4ec5c9aece177f01d8b3d13119e445", 16723) - # for v in ["", "v2"] : - for v in [""] : + for v in ["", "v2"] : + # for v in ["v2"] : print("creating fungible token 1...") result = call_rpc(rpc1, "token"+v+"create", "T1", str(0.000001)) # 100 assert(check_tx(result)) From 5cda0d7cd11cf9d74705fbddf8afe17b58f60f86 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 21 Jun 2021 20:40:39 +0500 Subject: [PATCH 013/348] disable nspv methods except tokensv2 --- src/komodo_nSPV_fullnode.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index e2e8cb49b90..568bfff90ac 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -24,16 +24,16 @@ static std::map nspv_remote_commands = { -{"channelsopen", true},{"channelspayment", true},{"channelsclose", true},{"channelsrefund", true}, -{"channelslist", true},{"channelsinfo", true},{"oraclescreate", true},{"oraclesfund", true},{"oraclesregister", true},{"oraclessubscribe", true}, -{"oraclesdata", true},{"oraclesinfo", false},{"oracleslist", false},{"gatewaysbind", true},{"gatewaysdeposit", true},{"gatewayswithdraw", true}, -{"gatewayswithdrawsign", true},{"gatewaysmarkdone", true},{"gatewayspendingsignwithdraws", true},{"gatewayssignedwithdraws", true}, -{"gatewaysinfo", false},{"gatewayslist", false},{"faucetfund", true},{"faucetget", true},{"pegscreate", true},{"pegsfund", true},{"pegsget", true},{"pegsclose", true}, -{"pegsclose", true},{"pegsredeem", true},{"pegsexchange", true},{"pegsliquidate", true},{"pegsaccounthistory", true},{"pegsaccountinfo", true},{"pegsworstaccounts", true}, -{"pegsinfo", true}, +{"channelsopen", false},{"channelspayment", false},{"channelsclose", false},{"channelsrefund", false}, +{"channelslist", false},{"channelsinfo", false},{"oraclescreate", false},{"oraclesfund", false},{"oraclesregister", false},{"oraclessubscribe", false}, +{"oraclesdata", false},{"oraclesinfo", false},{"oracleslist", false},{"gatewaysbind", false},{"gatewaysdeposit", false},{"gatewayswithdraw", false}, +{"gatewayswithdrawsign", false},{"gatewaysmarkdone", false},{"gatewayspendingsignwithdraws", false},{"gatewayssignedwithdraws", false}, +{"gatewaysinfo", false},{"gatewayslist", false},{"faucetfund", false},{"faucetget", false},{"pegscreate", false},{"pegsfund", false},{"pegsget", false},{"pegsclose", false}, +{"pegsclose", false},{"pegsredeem", false},{"pegsexchange", false},{"pegsliquidate", false},{"pegsaccounthistory", false},{"pegsaccountinfo", false},{"pegsworstaccounts", false}, +{"pegsinfo", false}, // tokens: - { "tokenask", true }, { "tokenbid", true }, { "tokenfillask", true }, { "tokenfillbid", true }, { "tokencancelask", true }, { "tokencancelbid", true }, - { "tokenorders", true }, { "mytokenorders", true }, { "tokentransfer", true },{ "tokencreate", true }, + { "tokenask", false }, { "tokenbid", false }, { "tokenfillask", false }, { "tokenfillbid", false }, { "tokencancelask", false }, { "tokencancelbid", false }, + { "tokenorders", false }, { "mytokenorders", false }, { "tokentransfer", false },{ "tokencreate", false }, { "tokenv2ask", true }, { "tokenv2bid", true }, { "tokenv2fillask", true }, { "tokenv2fillbid", true }, { "tokenv2cancelask", true }, { "tokenv2cancelbid", true }, { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", true },{ "tokenv2create", true } }; From 3f10f8d9a75862782b6a3af438f4fb8480b05877 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 23 Jun 2021 12:54:46 +0500 Subject: [PATCH 014/348] mytokenorders now uses marker on origpk; fixed CCchange init in CreateSell fixed vin_assetoshis init for cancelbid ('o') in AssetsValidate mypk marker is not created if bid/ask empty fixed dust checkes in AssetsValidate --- src/cc/CCassets.h | 27 ---- src/cc/CCassetsCore_impl.h | 6 +- src/cc/CCassetstx_impl.h | 307 +++++++++++++++++-------------------- src/cc/CCtokens.h | 2 +- src/cc/assets.cpp | 211 +++++++++++++------------ 5 files changed, 261 insertions(+), 292 deletions(-) diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index 92a00829755..0df386ab625 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -42,40 +42,13 @@ uint8_t DecodeAssetTokenOpRetV1(const CScript &scriptPubKey, uint8_t &assetsEval vscript_t EncodeAssetOpRetV2(uint8_t assetFuncId, uint256 assetid2, int64_t unit_price, std::vector origpubkey); uint8_t DecodeAssetTokenOpRetV2(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &unit_price, std::vector &origpubkey); -//uint8_t SetAssetOrigpubkey(std::vector &origpubkey_out, CAmount &unit_price, const CTransaction &tx); -//int64_t IsAssetvout(struct CCcontract_info *cp, int64_t &remaining_units_out, std::vector &origpubkey_out, const CTransaction& tx, int32_t v, uint256 refassetid); bool ValidateBidRemainder(CAmount unit_price, int64_t remaining_nValue, int64_t orig_nValue, int64_t received_nValue, int64_t paid_units); bool ValidateAskRemainder(CAmount unit_price, int64_t remaining_assetoshis, int64_t orig_assetoshis, int64_t received_assetoshis, int64_t paid_nValue); bool ValidateSwapRemainder(int64_t remaining_units, int64_t remaining_nValue, int64_t orig_nValue, int64_t received_nValue, int64_t paidprice, int64_t totalprice); bool SetBidFillamounts(CAmount unit_price, int64_t &received_nValue, int64_t orig_nValue, int64_t &paid_units, int64_t orig_units, CAmount paid_unit_price); bool SetAskFillamounts(CAmount unit_price, int64_t fill_assetoshis, int64_t orig_assetoshis, int64_t paid_nValue); bool SetSwapFillamounts(CAmount unit_price, int64_t &paid, int64_t orig_nValue, int64_t &received, int64_t totalprice); // not implemented -//int64_t AssetValidateBuyvin(struct CCcontract_info *cp, Eval* eval, int64_t &unit_price, std::vector &origpubkey_out, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, uint256 refassetid); -//int64_t AssetValidateSellvin(struct CCcontract_info *cp, Eval* eval, int64_t &unit_price, std::vector &origpubkey_out, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, uint256 assetid); -//bool AssetsCalcAmounts(struct CCcontract_info *cpAssets, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid); -//bool AssetsGetCCInputs(struct CCcontract_info *cpAssets, CAmount &tokensInputs, int64_t &assetsInputs, Eval* eval, const CTransaction &tx, uint256 assetid); CAmount AssetsGetCCInputs(struct CCcontract_info *cp, const char *addr, const CTransaction &tx); -//uint256 AssetsGetPrevOrdertxid(const CTransaction &tx); -//CAmount AssetsGetUnitPrice(uint256 ordertxid); - -// CCassetstx -//int64_t GetAssetBalance(CPubKey pk,uint256 tokenid); // --> GetTokenBalance() -//int64_t AddAssetInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 assetid, int64_t total, int32_t maxinputs); - -//UniValue AssetOrders(uint256 tokenid, CPubKey pubkey, uint8_t additionalEvalCode); -//UniValue AssetInfo(uint256 tokenid); -//UniValue AssetList(); -//std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description); -//std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total); -//std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total,int32_t evalcode); - -//UniValue CreateBuyOffer(const CPubKey &mypk, int64_t txfee, int64_t bidamount, uint256 assetid, int64_t numtokens); -//UniValue CancelBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 bidtxid); -//UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 bidtxid, int64_t fill_units, CAmount paid_unit_price); -//UniValue CreateSell(const CPubKey &mypk, int64_t txfee, int64_t numtokens, uint256 assetid, int64_t askamount); -//std::string CreateSwap(int64_t txfee, int64_t askamount, uint256 assetid, uint256 assetid2, int64_t pricetotal); -//UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 asktxid); -//UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 assetid2, uint256 asktxid, int64_t fillamount, CAmount paid_unit_price); const char ccassets_log[] = "ccassets"; diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index 9f1295fb509..5de861209b7 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -100,12 +100,12 @@ int64_t IsAssetvout(struct CCcontract_info *cp, int64_t &remaining_units_out, st // extract sell/buy owner's pubkey from the opret template -uint8_t SetAssetOrigpubkey(std::vector &origpubkey_out, CAmount &unit_price, const CTransaction &tx) +uint8_t GetOrderParams(std::vector &origpubkey_out, CAmount &unit_price, uint256 &assetid, const CTransaction &tx) { - uint256 assetid, assetid2; + uint256 assetid2; uint8_t evalCode, funcid; - if (tx.vout.size() > 0 && (funcid = A::DecodeAssetTokenOpRet(tx.vout[tx.vout.size() - 1].scriptPubKey, evalCode, assetid, assetid2, unit_price, origpubkey_out)) != 0) + if (tx.vout.size() > 0 && (funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCode, assetid, assetid2, unit_price, origpubkey_out)) != 0) return funcid; else return 0; diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index fb9adc2d551..03cb01c3204 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -57,7 +57,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeNFT) std::vector origpubkey; CTransaction ordertx; uint8_t funcid, evalCode; - char numstr[32], funcidstr[16], origaddr[KOMODO_ADDRESS_BUFSIZE], origtokenaddr[KOMODO_ADDRESS_BUFSIZE]; + char numstr[32], origaddr[KOMODO_ADDRESS_BUFSIZE], origtokenaddr[KOMODO_ADDRESS_BUFSIZE]; txid = it->first.txhash; LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << "addOrders() checking txid=" << txid.GetHex() << std::endl); @@ -79,24 +79,19 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeNFT) UniValue item(UniValue::VOBJ); - funcidstr[0] = funcid; - funcidstr[1] = 0; + std::string funcidstr(1, (char)funcid); item.push_back(Pair("funcid", funcidstr)); item.push_back(Pair("txid", txid.GetHex())); item.push_back(Pair("vout", (int64_t)it->first.index)); if (funcid == 'b' || funcid == 'B') { - sprintf(numstr, "%.8f", (double)ordertx.vout[it->first.index].nValue / COIN); - item.push_back(Pair("amount", numstr)); - sprintf(numstr, "%.8f", (double)ordertx.vout[0].nValue / COIN); - item.push_back(Pair("bidamount", numstr)); + item.push_back(Pair("amount", ValueFromAmount(ordertx.vout[it->first.index].nValue))); + item.push_back(Pair("bidamount", ValueFromAmount(ordertx.vout[0].nValue))); } else { - sprintf(numstr, "%lld", (long long)ordertx.vout[it->first.index].nValue); - item.push_back(Pair("amount", numstr)); - sprintf(numstr, "%lld", (long long)ordertx.vout[0].nValue); - item.push_back(Pair("askamount", numstr)); + item.push_back(Pair("amount", ordertx.vout[it->first.index].nValue)); + item.push_back(Pair("askamount", ordertx.vout[0].nValue)); } if (origpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { @@ -113,15 +108,12 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeNFT) { if (funcid == 's' || funcid == 'S' || funcid == 'e' || funcid == 'E') { - sprintf(numstr, "%.8f", (double)unit_price * ordertx.vout[ASSETS_GLOBALADDR_VOUT].nValue / COIN); - item.push_back(Pair("totalrequired", numstr)); - //sprintf(numstr, "%.8f", (double)remaining_units / (COIN * ordertx.vout[0].nValue)); + item.push_back(Pair("totalrequired", ValueFromAmount(unit_price * ordertx.vout[ASSETS_GLOBALADDR_VOUT].nValue))); item.push_back(Pair("price", ValueFromAmount(unit_price))); } else { - item.push_back(Pair("totalrequired", unit_price ? (int64_t)ordertx.vout[ASSETS_GLOBALADDR_VOUT].nValue / unit_price : 0)); - //sprintf(numstr, "%.8f", (double)ordertx.vout[0].nValue / (remaining_units * COIN)); + item.push_back(Pair("totalrequired", unit_price ? ordertx.vout[ASSETS_GLOBALADDR_VOUT].nValue / unit_price : 0)); item.push_back(Pair("price", ValueFromAmount(unit_price))); } } @@ -132,47 +124,63 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeNFT) } }; - std::vector > unspentOutputsTokens, unspentOutputsNFTs, unspentOutputsCoins; - - char assetsUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; - GetCCaddress(cpAssets, assetsUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); - SetCCunspents(unspentOutputsCoins, assetsUnspendableAddr, true); + - char assetsTokensUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; - TokenDataTuple tokenData; - vuint8_t vopretNFT; - if (refassetid != zeroid) { - GetTokenData(refassetid, tokenData, vopretNFT); - if (vopretNFT.size() > 0) - cpAssets->evalcodeNFT = vopretNFT.begin()[0]; + if (!pk.IsValid()) + { + std::vector > unspentOutputsTokens, unspentOutputsNFTs, unspentOutputsCoins; + char assetsUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; + GetCCaddress(cpAssets, assetsUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); + SetCCunspents(unspentOutputsCoins, assetsUnspendableAddr, true); + + char assetsTokensUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; + TokenDataTuple tokenData; + vuint8_t vopretNFT; + if (refassetid != zeroid) { + GetTokenData(refassetid, tokenData, vopretNFT); + if (vopretNFT.size() > 0) + cpAssets->evalcodeNFT = vopretNFT[0]; + } + GetTokensCCaddress(cpAssets, assetsTokensUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); + SetCCunspents(unspentOutputsTokens, assetsTokensUnspendableAddr, true); + + // tokenbids: + for (std::vector >::const_iterator itCoins = unspentOutputsCoins.begin(); + itCoins != unspentOutputsCoins.end(); + itCoins++) + addOrders(cpAssets, itCoins); + + // tokenasks: + for (std::vector >::const_iterator itTokens = unspentOutputsTokens.begin(); + itTokens != unspentOutputsTokens.end(); + itTokens++) + addOrders(cpAssets, itTokens); + + if (evalcodeNFT != 0) { //this would be mytokenorders + char assetsNFTUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; + + // try also dual eval tokenasks (and we do not need bids (why? bids are on assets global addr anyway.)): + cpAssets->evalcodeNFT = evalcodeNFT; + GetTokensCCaddress(cpAssets, assetsNFTUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); + SetCCunspents(unspentOutputsNFTs, assetsNFTUnspendableAddr,true); + + for (std::vector >::const_iterator itNFTs = unspentOutputsNFTs.begin(); + itNFTs != unspentOutputsNFTs.end(); + itNFTs++) + addOrders(cpAssets, itNFTs); + } } - GetTokensCCaddress(cpAssets, assetsTokensUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); - SetCCunspents(unspentOutputsTokens, assetsTokensUnspendableAddr, true); - - // tokenbids: - for (std::vector >::const_iterator itCoins = unspentOutputsCoins.begin(); - itCoins != unspentOutputsCoins.end(); - itCoins++) - addOrders(cpAssets, itCoins); - - // tokenasks: - for (std::vector >::const_iterator itTokens = unspentOutputsTokens.begin(); - itTokens != unspentOutputsTokens.end(); - itTokens++) - addOrders(cpAssets, itTokens); - - if (evalcodeNFT != 0) { //this would be mytokenorders - char assetsNFTUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; - - // try also dual eval tokenasks (and we do not need bids (why? bids are on assets global addr anyway.)): - cpAssets->evalcodeNFT = evalcodeNFT; - GetTokensCCaddress(cpAssets, assetsNFTUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); - SetCCunspents(unspentOutputsNFTs, assetsNFTUnspendableAddr,true); - - for (std::vector >::const_iterator itNFTs = unspentOutputsNFTs.begin(); - itNFTs != unspentOutputsNFTs.end(); - itNFTs++) - addOrders(cpAssets, itNFTs); + else + { + // use marker on my pk: + std::vector > unspentsMyAddr; + char assetsMyAddr[KOMODO_ADDRESS_BUFSIZE]; + GetCCaddress(cpAssets, assetsMyAddr, pk, A::IsMixed()); + SetCCunspents(unspentsMyAddr, assetsMyAddr, true); + for (std::vector >::const_iterator itOrders = unspentsMyAddr.begin(); + itOrders != unspentsMyAddr.end(); + itOrders++) + addOrders(cpAssets, itOrders); } return(result); } @@ -190,20 +198,17 @@ UniValue CreateBuyOffer(const CPubKey &mypk, int64_t txfee, int64_t bidamount, u int64_t inputs; std::vector oprets; - if (bidamount <= 0 || numtokens <= 0) - { + if (bidamount <= 0 || numtokens <= 0) { CCerror = "invalid bidamount or numtokens"; return(""); } // check if valid token - if (myGetTransaction(assetid, vintx, hashBlock) == 0) - { + if (myGetTransaction(assetid, vintx, hashBlock) == 0) { CCerror = "could not find assetid\n"; return(""); } - if (vintx.vout.size() == 0 || T::DecodeTokenCreateOpRet(vintx.vout.back().scriptPubKey, origpubkey, name, description, oprets) == 0) - { + if (vintx.vout.size() == 0 || T::DecodeTokenCreateOpRet(vintx.vout.back().scriptPubKey, origpubkey, name, description, oprets) == 0) { CCerror = "assetid isn't token creation txid\n"; return(""); } @@ -221,10 +226,13 @@ UniValue CreateBuyOffer(const CPubKey &mypk, int64_t txfee, int64_t bidamount, u } CAmount unit_price = bidamount / numtokens; - + if (unit_price <= 0) { + CCerror = "invalid bid params"; + return (""); + } CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, unspendableAssetsPubkey)); - mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk)); + mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk)); // marker for my orders UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), 0, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, {}, // TODO: actually this tx is not 'tokens', maybe it is better not to have token opret here but only asset opret. @@ -243,8 +251,7 @@ template UniValue CreateSell(const CPubKey &mypk, int64_t txfee, int64_t numtokens, uint256 assetid, int64_t askamount) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - uint64_t mask; - int64_t inputs, CCchange; + uint64_t mask = 0LL; struct CCcontract_info *cpAssets, assetsC; struct CCcontract_info *cpTokens, tokensC; @@ -260,28 +267,32 @@ UniValue CreateSell(const CPubKey &mypk, int64_t txfee, int64_t numtokens, uint2 if (AddNormalinputsRemote(mtx, mypk, txfee+ASSETS_MARKER_AMOUNT, 0x10000) > 0) // use AddNormalinputsRemote to sign with mypk { - mask = ~((1LL << mtx.vin.size()) - 1); + CAmount inputs; // add single-eval tokens (or non-fungible tokens): cpTokens = CCinit(&tokensC, T::EvalCode()); // NOTE: adding inputs only from EVAL_TOKENS cc - if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, numtokens, 60, false)) > 0) + if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, numtokens, 0x1000, false)) > 0LL) { if (inputs < numtokens) { - CCerror = strprintf("insufficient tokens for ask"); + CCerror = "insufficient tokens for ask"; return (""); } CAmount unit_price = askamount / numtokens; + if (unit_price <= 0) { + CCerror = "invalid ask params"; + return (""); + } uint8_t evalcodeNFT = cpTokens->evalcodeNFT ? cpTokens->evalcodeNFT : 0; CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), evalcodeNFT, numtokens, unspendableAssetsPubkey)); mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk)); //marker (seems, it is not for my tokenorders, not used yet) - if (inputs > numtokens) - CCchange = (inputs - numtokens); - if (CCchange != 0) + CAmount CCchange = inputs - numtokens; + if (CCchange != 0LL) { // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : T::EvalCode(), CCchange, mypk)); + } // cond to spend NFT from mypk CCwrapper wrCond(T::MakeTokensCCcond1(evalcodeNFT, mypk)); @@ -379,8 +390,8 @@ template UniValue CancelBuyOffer(const CPubKey &mypk, int64_t txfee,uint256 assetid,uint256 bidtxid) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx; uint64_t mask; - uint256 hashBlock; int64_t bidamount; + CTransaction vintx; + uint256 hashBlock; struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, A::EvalCode()); @@ -389,21 +400,19 @@ UniValue CancelBuyOffer(const CPubKey &mypk, int64_t txfee,uint256 assetid,uint2 txfee = 10000; // add normal inputs only from my mypk (not from any pk in the wallet) to validate the ownership of the canceller - if (AddNormalinputsRemote(mtx, mypk, txfee+ASSETS_MARKER_AMOUNT, 0x10000) > 0) + if (AddNormalinputsRemote(mtx, mypk, txfee /*+ ASSETS_MARKER_AMOUNT*/, 0x10000) > 0) { uint256 spendingtxid; int32_t spendingvin, h; - mask = ~((1LL << mtx.vin.size()) - 1); + uint64_t mask = 0LL; LOCK(cs_main); - if ((CCgetspenttxid(spendingtxid, spendingvin, h, bidtxid, ASSETS_GLOBALADDR_VOUT) != 0 || !IsTxidInActiveChain(spendingtxid)) && myGetTransaction(bidtxid, vintx, hashBlock) && vintx.vout.size() > ASSETS_GLOBALADDR_VOUT) + if ((CCgetspenttxid(spendingtxid, spendingvin, h, bidtxid, ASSETS_GLOBALADDR_VOUT) != 0 || !IsTxidInActiveChain(spendingtxid)) && + myGetTransaction(bidtxid, vintx, hashBlock) && vintx.vout.size() > ASSETS_GLOBALADDR_VOUT) { - uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector dummyOrigpubkey; - - //std::vector vopretNonfungible; - //GetNonfungibleData(assetid, vopretNonfungible); + uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; CAmount dummyPrice; std::vector dummyOrigpubkey; - bidamount = vintx.vout[ASSETS_GLOBALADDR_VOUT].nValue; + CAmount bidamount = vintx.vout[ASSETS_GLOBALADDR_VOUT].nValue; if (bidamount == 0) { CCerror = "bid is empty"; return ""; @@ -424,11 +433,11 @@ UniValue CancelBuyOffer(const CPubKey &mypk, int64_t txfee,uint256 assetid,uint2 mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); else { // send dust back to global addr - CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); - mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, unspendableAssetsPubkey)); + mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, GetUnspendable(cpAssets, NULL))); + std::cerr << __func__ << " dust detected bidamount=" << bidamount << std::endl; } - mtx.vout.push_back(CTxOut(ASSETS_MARKER_AMOUNT, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + // mtx.vout.push_back(CTxOut(ASSETS_MARKER_AMOUNT, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // we dont need a marker for cancelled orders UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), mask, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, {}, @@ -460,7 +469,7 @@ UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 txfee = 10000; // add normal inputs only from my mypk (not from any pk in the wallet) to validate the ownership - if (AddNormalinputsRemote(mtx, mypk, txfee+ASSETS_MARKER_AMOUNT, 0x10000) > 0) + if (AddNormalinputsRemote(mtx, mypk, txfee /* + ASSETS_MARKER_AMOUNT*/, 0x10000) > 0) { uint256 spendingtxid; int32_t spendingvin, h; @@ -498,19 +507,13 @@ UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 cpAssets->evalcodeNFT = vopretNonfungible.begin()[0]; mtx.vout.push_back(T::MakeTokensCC1vout(cpAssets->evalcodeNFT ? cpAssets->evalcodeNFT : T::EvalCode(), askamount, mypk)); // one-eval token vout - mtx.vout.push_back(CTxOut(ASSETS_MARKER_AMOUNT, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + // mtx.vout.push_back(CTxOut(ASSETS_MARKER_AMOUNT, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // we dont need marker for cancelled orders - // this is only for unspendable addresses: - //CCaddr2set(cpTokens, EVAL_ASSETS, mypk, myPrivkey, myCCaddr); //do we need this? Seems FinalizeCCTx can attach to any evalcode cc addr by calling Getscriptaddress - - uint8_t unspendableAssetsPrivkey[32]; - //char unspendableAssetsAddr[KOMODO_ADDRESS_BUFSIZE]; // init assets 'unspendable' privkey and pubkey + uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - //GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk, A::IsMixed()); // add additional eval-tokens unspendable assets privkey: - //CCaddr2set(cpAssets, T::EvalCode(), unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), cpAssets->evalcodeNFT, unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); @@ -538,8 +541,8 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 uint256 hashBlock; std::vector origpubkey; const int32_t bidvout = ASSETS_GLOBALADDR_VOUT; - uint64_t mask; - int64_t orig_units, unit_price, bid_amount, paid_amount, remaining_units, inputs, tokensChange = 0; + uint64_t mask = 0LL; + CAmount orig_units, unit_price, bid_amount, paid_amount, remaining_units, inputs; struct CCcontract_info *cpTokens, tokensC; struct CCcontract_info *cpAssets, assetsC; @@ -570,22 +573,27 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 uint256 spendingtxid; int32_t spendingvin, h; - mask = ~((1LL << mtx.vin.size()) - 1); LOCK(cs_main); if ((CCgetspenttxid(spendingtxid, spendingvin, h, bidtxid, bidvout) != 0 || !IsTxidInActiveChain(spendingtxid)) && myGetTransaction(bidtxid, vintx, hashBlock) != 0 && vintx.vout.size() > bidvout) { + uint256 assetidOpret; + bid_amount = vintx.vout[bidvout].nValue; - uint8_t funcid = SetAssetOrigpubkey(origpubkey, unit_price, vintx); // get orig pk, orig units + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, vintx); // get orig pk, orig units if (funcid != 'b' && funcid != 'B') { CCerror = "not an bid order"; return ""; } + if (assetid != assetidOpret) { + CCerror = "invalid tokenid"; + return ""; + } orig_units = bid_amount / unit_price; if (paid_unit_price == 0) paid_unit_price = unit_price; mtx.vin.push_back(CTxIn(bidtxid, bidvout, CScript())); // Coins on Assets unspendable - if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, fill_units, 60, false)) > 0) + if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, fill_units, 0x1000, false)) > 0) { if (inputs < fill_units) { CCerror = strprintf("insufficient tokens to fill buy offer"); @@ -597,36 +605,28 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 return (""); } CAmount royaltyValue = royaltyFract > 0 ? paid_amount / NFTROYALTY_DIVISOR * royaltyFract : 0; - - if (inputs > fill_units) - tokensChange = (inputs - fill_units); + CAmount tokensChange = inputs - fill_units; uint8_t unspendableAssetsPrivkey[32]; cpAssets = CCinit(&assetsC, A::EvalCode()); CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - - if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) + if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { // bidder has coins for more tokens or only dust is sent back to global address mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bid_amount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder or the dust is sent back to cc global addr - else + if (bid_amount - paid_amount <= ASSETS_NORMAL_DUST) + std::cerr << __func__ << " dust detected (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; + } + else mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to mypk normal if (royaltyFract > 0) // note it makes vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : T::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator - mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey + if (orig_units - fill_units > 0) // order is not finished yet + mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey - if (tokensChange != 0) + if (tokensChange != 0LL) mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : T::EvalCode(), tokensChange, mypk)); // change in single-eval tokens - - //fprintf(stderr, "%s remaining_units %lld -> origpubkey\n", __func__, (long long)remaining_units); - - //char unspendableAssetsAddr[KOMODO_ADDRESS_BUFSIZE]; - //cpAssets = CCinit(&assetsC, A::EvalCode()); - //GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk, A::IsMixed()); - - // add additional unspendable addr from Assets: - //CCaddr2set(cpTokens, A::EvalCode(), unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); CCwrapper wrCond1(MakeCCcond1(A::EvalCode(), unspendableAssetsPk)); // spend coins CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); @@ -663,10 +663,9 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a CTransaction vintx; uint256 hashBlock; std::vector origpubkey; - //double dprice; uint64_t mask = 0; const int32_t askvout = ASSETS_GLOBALADDR_VOUT; - int64_t unit_price, orig_assetoshis, paid_nValue, inputs, CCchange = 0LL; + CAmount unit_price, orig_assetoshis, paid_nValue; struct CCcontract_info *cpAssets, assetsC; if (fillunits < 0) @@ -703,14 +702,17 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a LOCK(cs_main); if ((CCgetspenttxid(spendingtxid, spendingvin, h, asktxid, askvout) != 0 || !IsTxidInActiveChain(spendingtxid)) && myGetTransaction(asktxid, vintx, hashBlock) && vintx.vout.size() > askvout) { + uint256 assetidOpret; orig_assetoshis = vintx.vout[askvout].nValue; - uint8_t funcid = SetAssetOrigpubkey(origpubkey, unit_price, vintx); // get orig pk, orig value + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, vintx); // get orig pk, orig value if (funcid != 's' && funcid != 'S') { CCerror = "not an ask order"; return ""; } - - //dprice = (double)orig_nValue / orig_assetoshis; + if (assetid != assetidOpret) { + CCerror = "invalid tokenid"; + return ""; + } if (paid_unit_price <= 0LL) paid_unit_price = unit_price; if (paid_unit_price <= 0LL) { @@ -722,14 +724,13 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / NFTROYALTY_DIVISOR * royaltyFract : 0; if (assetid2 != zeroid) { - inputs = 0; // = AddAssetInputs(cpAssets, mtx, mypk, assetid2, paid_nValue, 60); // not implemented yet - } - else - { - // Use only one AddNormalinputs() in each rpc call to allow payment if user has only single utxo with normal funds - inputs = AddNormalinputs(mtx, mypk, txfee + ASSETS_MARKER_AMOUNT + paid_nValue, 0x10000, IsRemoteRPCCall()); - mask = ~((1LL << mtx.vin.size()) - 1); + // inputs = AddAssetInputs(cpAssets, mtx, mypk, assetid2, paid_nValue, 60); // not implemented yet + CCerror = "swaps not implemented"; + return ""; } + + // Use only one AddNormalinputs() in each rpc call to allow payment if user has only single utxo with normal funds + CAmount inputs = AddNormalinputs(mtx, mypk, txfee + ASSETS_MARKER_AMOUNT + paid_nValue, 0x10000, IsRemoteRPCCall()); if (inputs > 0) { if (inputs < paid_nValue) { @@ -740,55 +741,31 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a // cc vin should be after normal vin mtx.vin.push_back(CTxIn(asktxid, askvout, CScript())); - if (assetid2 != zeroid) - ; // SetSwapFillamounts(orig_unit_price, fillunits, orig_assetoshis, paid_nValue, orig_nValue); //not implemented correctly yet - else { - if (!SetAskFillamounts(unit_price, fillunits, orig_assetoshis, paid_nValue)) { - CCerror = "incorrect units or price"; - return ""; - } + if (!SetAskFillamounts(unit_price, fillunits, orig_assetoshis, paid_nValue)) { + CCerror = "incorrect units or price"; + return ""; } - + if (paid_nValue == 0) { CCerror = "ask totally filled"; return ""; } - if (assetid2 != zeroid && inputs > paid_nValue) - CCchange = (inputs - paid_nValue); - // vout.0 tokens remainder to unspendable cc addr: mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), evalcodeNFT, orig_assetoshis - fillunits, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr + //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : T::EvalCode(), fillunits, mypk)); - - if (assetid2 != zeroid) { - std::cerr << __func__ << " WARNING: asset swap not implemented yet!" << std::endl; - // TODO: change MakeCC1vout appropriately when implementing: - //mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, paid_nValue, origpubkey)); //vout.2 tokens... (swap is not implemented yet) - } - else { - mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr - if (royaltyFract > 0) // note it makes the vout even if roaltyValue is 0 - mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner - } - mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) - - // not implemented - if (CCchange != 0) { - std::cerr << __func__ << " WARNING: asset swap not implemented yet! (CCchange)" << std::endl; - // TODO: change MakeCC1vout appropriately when implementing: - //mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk)); //vout.3 coins in Assets cc addr (swap not implemented) - } + mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr + if (royaltyFract > 0) // note it makes the vout even if roaltyValue is 0 + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner + + if (orig_assetoshis - fillunits > 0) // we dont need the marker if order is filled + mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) - uint8_t unspendableAssetsPrivkey[32]; - // char unspendableAssetsAddr[KOMODO_ADDRESS_BUFSIZE]; // init assets 'unspendable' privkey and pubkey + uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - //GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk, A::IsMixed()); - - // add additional eval-tokens unspendable assets privkey: - //CCaddr2set(cpAssets, T::EvalCode(), unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), evalcodeNFT, unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); @@ -797,12 +774,12 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), mask, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { mypk }, - { A::EncodeAssetOpRet(assetid2 != zeroid ? 'E' : 'S', assetid2, unit_price, origpubkey) } )); + { A::EncodeAssetOpRet('S', assetid2, unit_price, origpubkey) } )); if (!ResultHasTx(sigData)) return MakeResultError("Could not finalize tx"); return sigData; } else { - CCerror = strprintf("filltx not enough normal utxos"); + CCerror = "filltx not enough normal utxos"; return ""; } } diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index 0a5b5a3c950..56865a787cf 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -445,7 +445,7 @@ class TokensV2 { }; /// @private -template uint8_t ValidateTokenOpret(uint256 txid, const CScript &scriptPubKey, uint256 tokenid); +//template uint8_t ValidateTokenOpret(uint256 txid, const CScript &scriptPubKey, uint256 tokenid); /// @private template bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector &vinPubkeys); /// @private diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 30c9840ec06..d6537b8d2bb 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -19,6 +19,10 @@ #include "CCassetsCore_impl.h" #include "CCNFTData.h" +const int32_t CCVOUT = 1; +const int32_t NORMALVOUT = 0; + + /* TODO: update: @@ -169,7 +173,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const uint8_t funcid, evalCodeInOpret; char destaddr[KOMODO_ADDRESS_BUFSIZE], origNormalAddr[KOMODO_ADDRESS_BUFSIZE], ownerNormalAddr[KOMODO_ADDRESS_BUFSIZE]; char origTokensCCaddr[KOMODO_ADDRESS_BUFSIZE], origCCaddrDummy[KOMODO_ADDRESS_BUFSIZE]; - char tokensDualEvalUnspendableCCaddr[KOMODO_ADDRESS_BUFSIZE], origAssetsCCaddr[KOMODO_ADDRESS_BUFSIZE]; + char tokensDualEvalUnspendableCCaddr[KOMODO_ADDRESS_BUFSIZE], origAssetsCCaddr[KOMODO_ADDRESS_BUFSIZE], globalAssetsCCaddr[KOMODO_ADDRESS_BUFSIZE]; CAmount vin_tokens = 0; CAmount vin_assetoshis = 0; @@ -180,7 +184,6 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (tx.vout.size() == 0) return eval->Invalid("AssetValidate: no vouts"); - if((funcid = A::DecodeAssetTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCodeInOpret, assetid, assetid2, unit_price, vorigpubkey)) == 0 ) return eval->Invalid("AssetValidate: invalid opreturn payload"); @@ -211,6 +214,9 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // originator cc address, this is for marker validation: GetCCaddress(cpAssets, origAssetsCCaddr, vorigpubkey, A::IsMixed()); + // global cc address: + GetCCaddress(cpAssets, globalAssetsCCaddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); + if( IsCCInput(tx.vin[0].scriptSig) != false ) // vin0 should be normal vin return eval->Invalid("illegal asset cc vin0"); else if( numvouts < 2 ) @@ -246,12 +252,14 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //preventCCvouts = 2; if (numvouts < 3) return eval->Invalid("too few vouts"); - else if( A::ConstrainVout(tx.vout[0], 1, cpAssets->unspendableCCaddr, 0LL, A::EvalCode()) == false ) + else if( A::ConstrainVout(tx.vout[0], CCVOUT, cpAssets->unspendableCCaddr, 0LL, A::EvalCode()) == false ) return eval->Invalid("invalid funding for bid"); - else if( A::ConstrainVout(tx.vout[1], 1, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr + else if( A::ConstrainVout(tx.vout[1], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr return eval->Invalid("invalid vout1 marker for original pubkey"); else if( TotalPubkeyNormalInputs(tx, pubkey2pk(vorigpubkey)) == 0 ) // check tx is signed by originator pubkey - return eval->Invalid("not the originator pubkey signed"); + return eval->Invalid("not the originator pubkey signed for bid"); + else if (unit_price <= 0) + return eval->Invalid("invalid unit price"); // check should not be assets cc vins: for (auto const &vin : tx.vin) { @@ -272,22 +280,23 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //vout.n-1: opreturn [EVAL_ASSETS] ['o'] ccvins = 2; // order and marker ccvouts = 0; - if (vin_assetoshis = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origCCaddrDummy, origNormalAddr, tx, assetid) == 0) - return(false); + vin_assetoshis = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origCCaddrDummy, origNormalAddr, tx, assetid); + if (vin_assetoshis == 0) + return false; // eval already set if (tx.vout[0].nValue > ASSETS_NORMAL_DUST) { - if( A::ConstrainVout(tx.vout[0], 0, origNormalAddr, vin_assetoshis, 0) == false ) + if (!A::ConstrainVout(tx.vout[0], NORMALVOUT, origNormalAddr, vin_assetoshis, 0)) return eval->Invalid("invalid refund for cancelbid"); } else { - bool isCCVout = A::ConstrainVout(tx.vout[0], 1, cpAssets->unspendableCCaddr, vin_assetoshis, 0); - if( A::ConstrainVout(tx.vout[0], 0, origNormalAddr, vin_assetoshis, 0) == false && + bool isCCVout = A::ConstrainVout(tx.vout[0], CCVOUT, cpAssets->unspendableCCaddr, vin_assetoshis, 0); + if (!A::ConstrainVout(tx.vout[0], NORMALVOUT, origNormalAddr, vin_assetoshis, 0) && !isCCVout ) // dust allowed to go back - return eval->Invalid("invalid refund for cancelbid"); + return eval->Invalid("invalid dust refund for cancelbid"); if( isCCVout ) ccvouts ++; } - if( TotalPubkeyNormalInputs(tx, pubkey2pk(vin_origpubkey)) == 0 ) // check tx is signed by originator pubkey - return eval->Invalid("not the originator pubkey signed"); + if (TotalPubkeyNormalInputs(tx, pubkey2pk(vin_origpubkey)) == 0) // check tx is signed by originator pubkey + return eval->Invalid("not the originator pubkey signed for cancelbid"); //preventCCvins = 2; //preventCCvouts = 0; @@ -298,83 +307,94 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //vin.0: normal input //vin.1: cc assets unspendable (vout.0 from buyoffer) buyTx.vout[0] //vin.2+: valid CC output satisfies buyoffer (*tx.vin[2])->nValue - //vout.0: remaining amount of bid to cc assets global address + //vout.0: remaining amount of bid to cc assets global address (if sufficient to buy a token or dust) //vout.1: vin.1 value to signer of vin.2 - //vout.2: vin.2 assetoshis to original pubkey (-royalty) + //vout.2: vin.2 satoshi to original pubkey (except royalty if any) //vout.3: royalty to token owner (optional) - //vout.4: CC output for assetoshis change (if any) + //vout.4: CC output for satoshi change (if any) //vout.5: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['B'] [assetid] [remaining asset required] [origpubkey] - //preventCCvouts = 4; ccvins = 1; - ccvouts = 3; - - if( (vin_assetoshis = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 ) - return false; - else if( numvouts < 4 ) + ccvouts = 0; // at least tokens output + vin_assetoshis = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid); + if (vin_assetoshis == 0) + return false; // eval already set + else if( numvouts < 3 ) return eval->Invalid("not enough vouts for fillbid"); else if( vin_origpubkey != vorigpubkey ) // originator pk does not change in the new opret return eval->Invalid("mismatched opreturn originator pubkeys for fillbid"); else if (unit_price != vin_unit_price) return eval->Invalid("mismatched unit price for fillbid"); + else if (unit_price <= 0) + return eval->Invalid("invalid unit price"); else { int32_t r = royaltyFract > 0 ? 1 : 0; + CAmount assetoshis = tx.vout[0].nValue + tx.vout[1].nValue + (royaltyFract > 0 ? tx.vout[2].nValue : 0); if( vin_assetoshis != assetoshis ) // coins -> global cc address (remainder) + normal self address - return eval->Invalid("input cc value doesnt match vout0+1" + std::string(royaltyFract > 0 ? "+2" : "") + " for fillbid"); - + return eval->Invalid("input cc value does not equal to vout0+1" + std::string(royaltyFract > 0 ? "+2" : "") + " for fillbid"); + + // coins remainder + if (tx.vout[0].nValue / unit_price > 0 || tx.vout[0].nValue <= ASSETS_NORMAL_DUST) { + if (!A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, 0LL, A::EvalCode())) + return eval->Invalid("invalid vout0 should to global address for fillbid"); + ccvouts ++; + } + if (tx.vout[0].nValue / unit_price > 0 || tx.vout[0].nValue <= ASSETS_NORMAL_DUST) // there are remaining tokens to buy + { + if (!A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, 0LL, A::EvalCode())) // if remainder sufficient to buy tokens -> coins to asset global cc addr + return eval->Invalid("mismatched vout0 global assets CC addr for fillbid"); + } + else + { // if remaining_units == 0 (empty bid) then the remainder should go to the originator normal address (if not dust) + if (!A::ConstrainVout(tx.vout[0], NORMALVOUT, origNormalAddr, 0LL, 0)) // remainder less than token price should return to originator normal addr + return eval->Invalid("vout0 should be originator normal address with remainder for fillbid"); + } + vin_tokens = AssetsGetCCInputs(cpTokens, NULL, tx); - if( tx.vout[4+r].scriptPubKey.IsPayToCryptoCondition() != false ) // if tokens remainder exists + int32_t myNormalVout = 1; + int32_t myTokenVout = 2+r; + int32_t tokenRemainderVout; + if (tx.vout[0].nValue / unit_price > 0) + tokenRemainderVout = 4+r; // marker present before this vout + else + tokenRemainderVout = 3+r; // no marker + + if (tx.vout.size() > tokenRemainderVout && tx.vout[tokenRemainderVout].scriptPubKey.IsPayToCryptoCondition()) // if tokens remainder exists { - if( A::ConstrainVout(tx.vout[2+r], 1, origTokensCCaddr, 0LL, T::EvalCode()) == false ) // tokens to originator cc addr (tokens+nonfungible evalcode) - return eval->Invalid("vout" + std::to_string(2+r) + " tokens value should go to originator pubkey for fillbid"); - else if( vin_tokens != tx.vout[2+r].nValue + tx.vout[4+r].nValue ) // tokens from cc global address -> token global addr (remainder) + originator cc address - return eval->Invalid("tokens inputs doesnt match tokens vout" + std::to_string(2+r) + "+" + "vout"+std::to_string(4+r) + " for fillbid"); - //preventCCvouts ++; - ccvouts++; + if (!A::ConstrainVout(tx.vout[myTokenVout], CCVOUT, origTokensCCaddr, 0LL, T::EvalCode())) // tokens to originator cc addr (tokens+nonfungible evalcode) + return eval->Invalid("vout" + std::to_string(myTokenVout) + " tokens value should go to originator pubkey for fillbid"); + else if (vin_tokens != tx.vout[myTokenVout].nValue + tx.vout[tokenRemainderVout].nValue) // tokens from cc global address -> token global addr (remainder) + originator cc address + return eval->Invalid("tokens inputs doesnt match tokens vout" + std::to_string(myTokenVout) + "+" + "vout"+std::to_string(tokenRemainderVout) + " for fillbid"); + ccvouts += 2; + } + else { + if (tx.vout.size() <= myTokenVout || !A::ConstrainVout(tx.vout[myTokenVout], CCVOUT, origTokensCCaddr, vin_tokens, T::EvalCode())) // all tokens to originator cc addr, no cc change present + return eval->Invalid("vout" + std::to_string(myTokenVout) + " should have tokens to originator cc addr for fillbid"); + ccvouts ++; } - else if( A::ConstrainVout(tx.vout[2+r], 1, origTokensCCaddr, vin_tokens, T::EvalCode()) == false ) // all tokens to originator cc addr, no cc change present - return eval->Invalid("vout" + std::to_string(2+r) + " should have tokens to originator cc addr for fillbid"); - if( A::ConstrainVout(tx.vout[1], 0, NULL, 0LL, 0) == false ) // amount paid for tokens goes to normal addr (we can't check 'self' address) - return eval->Invalid("vout1 should be normal for fillbid"); - else if( A::ConstrainVout(tx.vout[3+r], 1, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr - return eval->Invalid("invalid vout" + std::to_string(3+r) + " marker for originator pubkey for fillbid"); + if (!A::ConstrainVout(tx.vout[myNormalVout], NORMALVOUT, NULL, 0LL, 0)) // amount paid for tokens goes to normal addr (we can't check 'self' address) + return eval->Invalid("vout " + std::to_string(myNormalVout) + " should be normal for fillbid"); + + if (tx.vout[0].nValue / unit_price > 0) { // bid coins remainder sufficient for more tokens - marker should exist + int32_t markerVout = 3 + r; + if (tx.vout.size() <= markerVout || !A::ConstrainVout(tx.vout[markerVout], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode())) // marker to originator asset cc addr + return eval->Invalid("invalid vout" + std::to_string(markerVout) + " marker for originator pubkey for fillbid"); + ccvouts ++; + } CAmount received_value = royaltyFract > 0 ? tx.vout[1].nValue + tx.vout[2].nValue : tx.vout[1].nValue; // vout1 paid value to seller, vout2 royalty to owner CAmount paid_units = tx.vout[2+r].nValue; - if( ValidateBidRemainder(unit_price, tx.vout[0].nValue, vin_assetoshis, received_value, paid_units) == false ) // check real price and coins spending from global addr + if (!ValidateBidRemainder(unit_price, tx.vout[0].nValue, vin_assetoshis, received_value, paid_units)) // check real price and coins spending from global addr return eval->Invalid("vout" + std::to_string(2+r) + " mismatched remainder for fillbid"); - if (unit_price <= 0) - return eval->Invalid("invalid unit price"); if (royaltyFract > 0) { if ((tx.vout[1].nValue + tx.vout[2].nValue) / NFTROYALTY_DIVISOR * royaltyFract != tx.vout[2].nValue) // validate royalty value return eval->Invalid("vout2 invalid royalty amount for fillask"); - if( A::ConstrainVout(tx.vout[2], 0, ownerNormalAddr, 0LL, 0) == false ) // validate owner royalty dest + if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest return eval->Invalid("vout2 invalid royalty detination for fillask"); } - if( tx.vout[0].nValue / unit_price != 0 ) // remaining tokens to buy - { - if( A::ConstrainVout(tx.vout[0], 1, cpAssets->unspendableCCaddr, 0LL, A::EvalCode()) == false ) // if remainder sufficient to buy tokens -> coins to asset global cc addr - return eval->Invalid("mismatched vout0 global assets CC addr for fillbid"); - } - else - { // remaining_units == 0 - if( tx.vout[0].nValue > ASSETS_NORMAL_DUST ) { - if( A::ConstrainVout(tx.vout[0], 0, origNormalAddr, 0LL, 0) == false ) // remainder less than token price should return to originator normal addr - return eval->Invalid("vout0 should be originator normal address with remainder for fillbid"); - ccvouts--; - } - else { - bool isCCVout = A::ConstrainVout(tx.vout[0], 1, cpAssets->unspendableCCaddr, 0, 0); - if( A::ConstrainVout(tx.vout[0], 0, origNormalAddr, 0LL, 0) == false && - !isCCVout ) // dust allowed to go back to cc global addr - return eval->Invalid("vout0 should be originator normal address with remainder or dust should go back to global addr for fillbid"); - if( !isCCVout ) - ccvouts--; - } - } } //fprintf(stderr,"fillbuy validated\n"); break; @@ -398,21 +418,21 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const char origTokenAddr[KOMODO_ADDRESS_BUFSIZE]; CPubKey origpk = pubkey2pk(vorigpubkey); - //preventCCvouts = 2; ccvouts = 2; if (numvouts < 3) return eval->Invalid("too few vouts"); - else if (A::ConstrainVout(tx.vout[0], 1, tokensDualEvalUnspendableCCaddr, 0LL, T::EvalCode()) == false) // tokens sent to global addr + else if (A::ConstrainVout(tx.vout[0], CCVOUT, tokensDualEvalUnspendableCCaddr, 0LL, T::EvalCode()) == false) // tokens sent to global addr return eval->Invalid("invalid vout0 global two eval address for sell"); - else if( A::ConstrainVout(tx.vout[1], 1, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr + else if( A::ConstrainVout(tx.vout[1], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr return eval->Invalid("invalid vout1 marker for originator pubkey"); else if (TotalPubkeyNormalInputs(tx, origpk) == 0) // check tx is signed by originator pubkey - return eval->Invalid("not the originator pubkey signed"); + return eval->Invalid("not the originator pubkey signed for ask"); + else if (unit_price <= 0) + return eval->Invalid("invalid unit price"); - //GetTokensCCaddress(cpTokens, origTokenAddr, origpk, A::IsMixed()); if (tx.vout[2].scriptPubKey.IsPayToCryptoCondition()) if (!tx.vout[2].scriptPubKey.IsPayToCCV2() || tx.vout[2].scriptPubKey.SpkHasEvalcodeCCV2(T::EvalCode())) // have token change - ccvouts ++; // preventCCvouts ++; + ccvouts ++; // check should not be assets cc vins: for (auto const &vin : tx.vin) { @@ -430,15 +450,13 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //vout.1: vin.2 back to users pubkey //vout.2: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid] - - if( (vin_tokens = AssetValidateSellvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 ) + vin_tokens = AssetValidateSellvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid); + if (vin_tokens == 0) return false; // eval already set - else if (A::ConstrainVout(tx.vout[0], 1, origTokensCCaddr, vin_tokens, T::EvalCode()) == false) // tokens returning to originator cc addr + else if (A::ConstrainVout(tx.vout[0], CCVOUT, origTokensCCaddr, vin_tokens, T::EvalCode()) == false) // tokens returning to originator cc addr return eval->Invalid("invalid vout0 for cancelask"); else if (TotalPubkeyNormalInputs(tx, pubkey2pk(vin_origpubkey)) == 0) // check tx is signed by originator pubkey - return eval->Invalid("not the originator pubkey signed"); - //preventCCvins = 3; - //preventCCvouts = 1; + return eval->Invalid("not the originator pubkey signed for cancelask"); ccvins = 2; // order and marker ccvouts = 1; break; @@ -453,11 +471,11 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //vout.3: normal output for change (if any) //'S'.vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey] ccvins = 1; - ccvouts = 3; - - if( (vin_tokens = AssetValidateSellvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 ) - return false; // eval is set - else if( numvouts < 4 ) + ccvouts = 2; + vin_tokens = AssetValidateSellvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid); + if (vin_tokens == 0) + return false; // eval is already set + else if( numvouts < 3 ) return eval->Invalid("not enough vouts for fillask"); else if( vin_origpubkey != vorigpubkey ) return eval->Invalid("mismatched origpubkeys for fillask"); @@ -465,29 +483,30 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("mismatched unit price for fillask"); else { - int32_t markerVout = royaltyFract > 0 ? 4 : 3; - if( vin_tokens != tx.vout[0].nValue + tx.vout[1].nValue ) + if (vin_tokens != tx.vout[0].nValue + tx.vout[1].nValue) return eval->Invalid("locked value doesnt match vout0+1 fillask"); CAmount paid_value = royaltyFract > 0 ? tx.vout[2].nValue+tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner - if( ValidateAskRemainder(unit_price, tx.vout[0].nValue, vin_tokens, tx.vout[1].nValue, paid_value) == false ) + if (!ValidateAskRemainder(unit_price, tx.vout[0].nValue, vin_tokens, tx.vout[1].nValue, paid_value)) return eval->Invalid("mismatched vout0 remainder for fillask"); - else if( A::ConstrainVout(tx.vout[1], 1, NULL, 0LL, T::EvalCode()) == false ) // do not check tokens buyer's 'self' cc addr + else if (!A::ConstrainVout(tx.vout[1], CCVOUT, NULL, 0LL, T::EvalCode())) // do not check tokens buyer's 'self' cc addr return eval->Invalid("vout1 should be cc for fillask"); - else if( A::ConstrainVout(tx.vout[2], 0, origNormalAddr, 0LL, 0) == false ) // coins to originator normal addr + else if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, origNormalAddr, 0LL, 0)) // coins to originator normal addr return eval->Invalid("vout2 should be cc for fillask"); if (royaltyFract > 0) { if ((tx.vout[2].nValue + tx.vout[3].nValue) / NFTROYALTY_DIVISOR * royaltyFract != tx.vout[3].nValue) // validate royalty value return eval->Invalid("vout3 invalid royalty amount for fillask"); - if( A::ConstrainVout(tx.vout[3], 0, ownerNormalAddr, 0LL, 0) == false ) // validate owner royalty dest + if (!A::ConstrainVout(tx.vout[3], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest return eval->Invalid("vout3 invalid royalty detination for fillask"); } - if( A::ConstrainVout(tx.vout[markerVout], 1, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr - return eval->Invalid("invalid marker vout for original pubkey"); - else // if( remaining_units != 0 ) // remaining expected amount in coins, should be anyway - { - if( A::ConstrainVout(tx.vout[0], 1, tokensDualEvalUnspendableCCaddr, 0LL, A::EvalCode()) == false ) // tokens remainder on global addr - return eval->Invalid("mismatched vout0 two eval global CC addr for fillask"); + if (!A::ConstrainVout(tx.vout[0], CCVOUT, tokensDualEvalUnspendableCCaddr, 0LL, A::EvalCode())) // tokens remainder on global addr + return eval->Invalid("invalid vout0 should pay to tokens/assets global address for fillask"); + if (tx.vout[0].nValue > 0) { + int32_t markerVout = royaltyFract > 0 ? 4 : 3; + // marker should exist if remainder not empty + if( tx.vout.size() <= markerVout || A::ConstrainVout(tx.vout[markerVout], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr + return eval->Invalid("invalid marker vout for original pubkey"); + ccvouts ++; } } @@ -527,7 +546,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const else if( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != false ) ////////// not implemented yet //////////// { - if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, 0) == false ) + if( ConstrainVout(tx.vout[2], CCVOUT, origTokensCCaddr, 0) == false ) return eval->Invalid("vout2 doesnt go to origpubkey fillex"); else if( tokens != tx.vout[2].nValue + tx.vout[3].nValue ) { @@ -536,19 +555,19 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const } } ////////// not implemented yet //////////// - else if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, tokens) == false ) + else if( ConstrainVout(tx.vout[2], CCVOUT, origTokensCCaddr, tokens) == false ) return eval->Invalid("vout2 doesnt match inputs fillex"); - else if( ConstrainVout(tx.vout[1], 0, 0, 0) == false ) + else if( ConstrainVout(tx.vout[1], NORMALVOUT, 0, 0) == false ) return eval->Invalid("vout1 is CC for fillex"); fprintf(stderr,"assets vout0 %lld, tokens %lld, vout2 %lld -> orig, vout1 %lld, total %lld\n", (long long)tx.vout[0].nValue, (long long)tokens,(long long)tx.vout[2].nValue,(long long)tx.vout[1].nValue,(long long)orig_units); if( ValidateSwapRemainder(remaining_units, tx.vout[0].nValue, tokens, tx.vout[1].nValue, tx.vout[2].nValue, orig_units) == false ) // return eval->Invalid("mismatched remainder for fillex"); - else if( ConstrainVout(tx.vout[1], 1, 0, 0) == false ) + else if( ConstrainVout(tx.vout[1], CCVOUT, 0, 0) == false ) ////////// not implemented yet //////////// return eval->Invalid("normal vout1 for fillex"); else if( remaining_units != 0 ) { - if( ConstrainVout(tx.vout[0], 1, (char *)cpAssets->unspendableCCaddr, 0) == false ) // TODO: unsure about this, but this is not impl yet anyway + if( ConstrainVout(tx.vout[0], CCVOUT, (char *)cpAssets->unspendableCCaddr, 0) == false ) // TODO: unsure about this, but this is not impl yet anyway return eval->Invalid("mismatched vout0 AssetsCCaddr for fillex"); } */ From e4cc8353f5b331894045b0fbecd57f930b06c452 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 23 Jun 2021 12:56:07 +0500 Subject: [PATCH 015/348] test for asset with dust added --- src/tui/tui_assets_orders.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 5c99248dc8d..c13efa12b9b 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -117,7 +117,7 @@ def run_tokens_create(rpc): print("starting MofN tests for nftf7id1...") run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) - print("assets tests finished okay") + print("token/assets tests finished okay") time.sleep(3) exit @@ -522,6 +522,15 @@ def run_assets_orders(rpc1, rpc2, v, tokenid, total, units, isnft): print("creating token"+v+"cancelbid tx #3...") cancelid = call_token_rpc_send_tx(rpc1, "token"+v+"cancelbid", 'bid is empty', tokenid, fillbidid3) + # create tokenbid to test dust + print("creating token"+v+"bid tx #4...") + bidid4 = call_token_rpc_send_tx(rpc1, "token"+v+"bid", '', str(1), tokenid, str(0.0000_01)) + + # fill bid to self with dust + print("creating token"+v+"fillbid tx #4 (to create dust)...") + fillbidid4 = call_token_rpc_send_tx(rpc1, "token"+v+"fillbid", '', tokenid, bidid4, str(1), str(0.0000_005)) + + # check balance after retries = 24 delay = 10 From 047717110b4248d37785eb8a912b2432e618286a Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 23 Jun 2021 14:49:16 +0500 Subject: [PATCH 016/348] added spent order processing for mytokenorders to get the actual order --- src/cc/CCassetstx_impl.h | 117 ++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 50 deletions(-) diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index 03cb01c3204..d6db9466d14 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -43,6 +43,7 @@ template UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeNFT) { UniValue result(UniValue::VARR); + const char *funcname = __func__; struct CCcontract_info *cpAssets, assetsC; struct CCcontract_info *cpTokens, tokensC; @@ -57,69 +58,85 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeNFT) std::vector origpubkey; CTransaction ordertx; uint8_t funcid, evalCode; - char numstr[32], origaddr[KOMODO_ADDRESS_BUFSIZE], origtokenaddr[KOMODO_ADDRESS_BUFSIZE]; + char origaddr[KOMODO_ADDRESS_BUFSIZE], origtokenaddr[KOMODO_ADDRESS_BUFSIZE]; txid = it->first.txhash; - LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << "addOrders() checking txid=" << txid.GetHex() << std::endl); - if ( myGetTransaction(txid, ordertx, hashBlock) != 0) - { - if (ordertx.vout.size() > ASSETS_GLOBALADDR_VOUT && (funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, assetid2, unit_price, origpubkey)) != 0) - { - LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << "addOrders() checking ordertx.vout.size()=" << ordertx.vout.size() << " funcid=" << (char)(funcid ? funcid : ' ') << " assetid=" << assetid.GetHex() << std::endl); + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " checking txid=" << txid.GetHex() << std::endl); + if (!myGetTransaction(txid, ordertx, hashBlock)) { + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname <<" could not load order txid=" << txid.GetHex() << std::endl); + return; + } - if (!pk.IsValid() && (refassetid == zeroid || assetid == refassetid) || // tokenorders - pk.IsValid() && pk == pubkey2pk(origpubkey)) // mytokenorders - { + if (ordertx.vout.size() > 1 && (funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, assetid2, unit_price, origpubkey)) != 0) + { + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " checking ordertx.vout.size()=" << ordertx.vout.size() << " funcid=" << (char)(funcid ? funcid : ' ') << " assetid=" << assetid.GetHex() << std::endl); - LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << "addOrders() it->first.index=" << it->first.index << " ordertx.vout[it->first.index].nValue=" << ordertx.vout[it->first.index].nValue << std::endl); - if (ordertx.vout[it->first.index].nValue == 0) { - LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << "addOrders() order with value=0 skipped" << std::endl); + if (!pk.IsValid() && (refassetid == zeroid || assetid == refassetid) || // tokenorders + pk.IsValid() && pk == pubkey2pk(origpubkey)) // mytokenorders + { + uint256 spenttxid; + uint256 init_txid = txid; + int32_t spentvin; + int32_t height; + while(CCgetspenttxid(spenttxid, spentvin, height, init_txid, ASSETS_GLOBALADDR_VOUT) == 0 && IsTxidInActiveChain(spenttxid)) { + init_txid = spenttxid; + } + if (init_txid != txid) { + txid = init_txid; + if (!myGetTransaction(txid, ordertx, hashBlock)) { + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " could not load order txid=" << txid.GetHex() << std::endl); + return; + } + if ((funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, assetid2, unit_price, origpubkey)) == 0) { + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " could not decode order txid=" << txid.GetHex() << std::endl); return; } + } - UniValue item(UniValue::VOBJ); + if (ordertx.vout.size() < 2) { + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " txid skipped " << txid.GetHex() << std::endl); + return; + } - std::string funcidstr(1, (char)funcid); - item.push_back(Pair("funcid", funcidstr)); - item.push_back(Pair("txid", txid.GetHex())); - item.push_back(Pair("vout", (int64_t)it->first.index)); - if (funcid == 'b' || funcid == 'B') - { - item.push_back(Pair("amount", ValueFromAmount(ordertx.vout[it->first.index].nValue))); - item.push_back(Pair("bidamount", ValueFromAmount(ordertx.vout[0].nValue))); - } - else - { - item.push_back(Pair("amount", ordertx.vout[it->first.index].nValue)); - item.push_back(Pair("askamount", ordertx.vout[0].nValue)); - } - if (origpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) + UniValue item(UniValue::VOBJ); + + std::string funcidstr(1, (char)funcid); + item.push_back(Pair("funcid", funcidstr)); + item.push_back(Pair("txid", txid.GetHex())); + if (funcid == 'b' || funcid == 'B') + { + item.push_back(Pair("bidamount", ValueFromAmount(ordertx.vout[0].nValue))); + } + else if (funcid == 's' || funcid == 'S') + { + item.push_back(Pair("askamount", ordertx.vout[0].nValue)); + } + if (origpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) + { + GetCCaddress(cp, origaddr, pubkey2pk(origpubkey), A::IsMixed()); + item.push_back(Pair("origaddress", origaddr)); + GetTokensCCaddress(cpTokens, origtokenaddr, pubkey2pk(origpubkey), A::IsMixed()); + item.push_back(Pair("origtokenaddress", origtokenaddr)); + } + if (assetid != zeroid) + item.push_back(Pair("tokenid", assetid.GetHex())); + if (assetid2 != zeroid) + item.push_back(Pair("otherid", assetid2.GetHex())); + if (unit_price > 0) + { + if (funcid == 's' || funcid == 'S' /*|| funcid == 'e' || funcid == 'E' not supported */) { - GetCCaddress(cp, origaddr, pubkey2pk(origpubkey), A::IsMixed()); - item.push_back(Pair("origaddress", origaddr)); - GetTokensCCaddress(cpTokens, origtokenaddr, pubkey2pk(origpubkey), A::IsMixed()); - item.push_back(Pair("origtokenaddress", origtokenaddr)); + item.push_back(Pair("totalrequired", ValueFromAmount(unit_price * ordertx.vout[0].nValue))); + item.push_back(Pair("price", ValueFromAmount(unit_price))); } - if (assetid != zeroid) - item.push_back(Pair("tokenid", assetid.GetHex())); - if (assetid2 != zeroid) - item.push_back(Pair("otherid", assetid2.GetHex())); - if (unit_price > 0) + else if (funcid == 'b' || funcid == 'B') { - if (funcid == 's' || funcid == 'S' || funcid == 'e' || funcid == 'E') - { - item.push_back(Pair("totalrequired", ValueFromAmount(unit_price * ordertx.vout[ASSETS_GLOBALADDR_VOUT].nValue))); - item.push_back(Pair("price", ValueFromAmount(unit_price))); - } - else - { - item.push_back(Pair("totalrequired", unit_price ? ordertx.vout[ASSETS_GLOBALADDR_VOUT].nValue / unit_price : 0)); - item.push_back(Pair("price", ValueFromAmount(unit_price))); - } + item.push_back(Pair("totalrequired", unit_price ? ordertx.vout[0].nValue / unit_price : 0)); + item.push_back(Pair("price", ValueFromAmount(unit_price))); } - result.push_back(item); - LOGSTREAM(ccassets_log, CCLOG_DEBUG1, stream << "addOrders() added order funcId=" << (char)(funcid ? funcid : ' ') << " it->first.index=" << it->first.index << " ordertx.vout[it->first.index].nValue=" << ordertx.vout[it->first.index].nValue << " tokenid=" << assetid.GetHex() << std::endl); } + result.push_back(item); + LOGSTREAM(ccassets_log, CCLOG_DEBUG1, stream << funcname << " added order funcId=" << (char)(funcid ? funcid : ' ') << " it->first.index=" << it->first.index << " ordertx.vout[it->first.index].nValue=" << ordertx.vout[it->first.index].nValue << " tokenid=" << assetid.GetHex() << std::endl); } } }; From 53b5e334de09f41abe73e4fe3426fb5e89f36943 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 26 Jun 2021 15:16:27 +0500 Subject: [PATCH 017/348] added test-komodo-cc app makefile and added some tests for assets/tokens cc assets/tokens modified to use GetTxUnconfirmed (to enable tests) --- src/Makefile.am | 1 + src/Makefile.kcctest.include | 13 + src/cc/CCNFTData.cpp | 2 +- src/cc/CCassets.h | 2 +- src/cc/CCassetsCore_impl.h | 14 +- src/cc/CCassetsUtils.cpp | 4 +- src/cc/CCassetstx_impl.h | 8 +- src/cc/CCinclude.h | 6 +- src/cc/CCtokens.cpp | 85 ++-- src/cc/CCtokens.h | 10 +- src/cc/CCtokens_impl.h | 186 +++++---- src/cc/CCtokenutils.cpp | 17 - src/cc/CCutils.cpp | 55 +-- src/cc/assets.cpp | 19 +- src/cc/eval.cpp | 5 + src/cc/eval.h | 3 + src/cc/gamescc.cpp | 2 +- src/cc/heir.cpp | 12 +- src/cc/old/CCassetsCore_v0.cpp | 2 +- src/cc/old/CCtokens_v0.cpp | 4 +- src/cc/prices.cpp | 2 +- src/cc/rogue_rpc.cpp | 2 +- src/rpc/tokensrpc.cpp | 2 +- src/test-komodo-cc/test-assets.cpp | 640 +++++++++++++++++++++++++++++ src/test-komodo-cc/test-main.cpp | 21 + 25 files changed, 897 insertions(+), 220 deletions(-) create mode 100644 src/Makefile.kcctest.include create mode 100644 src/test-komodo-cc/test-assets.cpp create mode 100644 src/test-komodo-cc/test-main.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 8741dc856db..2e2e077166b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -799,6 +799,7 @@ endif if ENABLE_TESTS include Makefile.ktest.include +include Makefile.kcctest.include #include Makefile.test.include #include Makefile.gtest.include endif diff --git a/src/Makefile.kcctest.include b/src/Makefile.kcctest.include new file mode 100644 index 00000000000..7446b395d34 --- /dev/null +++ b/src/Makefile.kcctest.include @@ -0,0 +1,13 @@ +TESTS += komodo-test-cc +bin_PROGRAMS += komodo-test-cc + +# tool for generating our public parameters +komodo_test_cc_SOURCES = \ + test-komodo-cc/test-main.cpp \ + test-komodo-cc/test-assets.cpp + +komodo_test_cc_CPPFLAGS = $(komodod_CPPFLAGS) + +komodo_test_cc_LDADD = -lgtest $(komodod_LDADD) + +komodo_test_cc_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static diff --git a/src/cc/CCNFTData.cpp b/src/cc/CCNFTData.cpp index af683cfd637..e5123513ba7 100644 --- a/src/cc/CCNFTData.cpp +++ b/src/cc/CCNFTData.cpp @@ -234,7 +234,7 @@ bool NFTDataValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction { CScript ccdata; vuint8_t vopdrop; - if (GetCCDropAsOpret(tx.vout[i].scriptPubKey, ccdata) && + if (!(ccdata = GetCCDropAsOpret(tx.vout[i].scriptPubKey)).empty() && GetOpReturnData(ccdata, vopdrop) && vopdrop.size() > 2 && vopdrop[0] == EVAL_TOKENS) diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index 0df386ab625..038eba4bb8b 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -48,7 +48,7 @@ bool ValidateSwapRemainder(int64_t remaining_units, int64_t remaining_nValue, in bool SetBidFillamounts(CAmount unit_price, int64_t &received_nValue, int64_t orig_nValue, int64_t &paid_units, int64_t orig_units, CAmount paid_unit_price); bool SetAskFillamounts(CAmount unit_price, int64_t fill_assetoshis, int64_t orig_assetoshis, int64_t paid_nValue); bool SetSwapFillamounts(CAmount unit_price, int64_t &paid, int64_t orig_nValue, int64_t &received, int64_t totalprice); // not implemented -CAmount AssetsGetCCInputs(struct CCcontract_info *cp, const char *addr, const CTransaction &tx); +CAmount AssetsGetCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx); const char ccassets_log[] = "ccassets"; diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index 5de861209b7..49004c8cdea 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -148,12 +148,12 @@ bool GetAssetorigaddrs(struct CCcontract_info *cp, char *origCCaddr, char *origN } template -int64_t AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, int32_t vini, CTransaction &vinTx) +CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, int32_t vini, CTransaction &vinTx) { uint256 hashBlock; uint256 assetid, assetid2; uint256 vinAssetId, vinAssetId2; - int64_t tmpprice, vinPrice; + CAmount tmpprice, vinPrice; std::vector tmporigpubkey; std::vector vinOrigpubkey; uint8_t evalCode; @@ -224,7 +224,7 @@ int64_t AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *o } // check no more other vins spending from global addr: - if (AssetsGetCCInputs(cpAssets, unspendableAddr, tx) != vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue) + if (AssetsGetCCInputs(eval, cpAssets, unspendableAddr, tx) != vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue) return eval->Invalid("invalid assets cc vins found"); if (vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue == 0) @@ -234,9 +234,9 @@ int64_t AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *o } template -int64_t AssetValidateBuyvin(struct CCcontract_info *cpAssets, Eval* eval, int64_t &unit_price, std::vector &origpubkey_out, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, uint256 refassetid) +CAmount AssetValidateBuyvin(struct CCcontract_info *cpAssets, Eval* eval, CAmount &unit_price, std::vector &origpubkey_out, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, uint256 refassetid) { - CTransaction vinTx; int64_t nValue; uint256 assetid, assetid2; uint8_t funcid, evalCode; + CTransaction vinTx; CAmount nValue; uint256 assetid, assetid2; uint8_t funcid, evalCode; origCCaddr_out[0] = origaddr_out[0] = 0; @@ -271,9 +271,9 @@ int64_t AssetValidateBuyvin(struct CCcontract_info *cpAssets, Eval* eval, int64_ } template -int64_t AssetValidateSellvin(struct CCcontract_info *cpAssets, Eval* eval, int64_t &unit_price, std::vector &origpubkey_out, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, uint256 assetid) +CAmount AssetValidateSellvin(struct CCcontract_info *cpAssets, Eval* eval, CAmount &unit_price, std::vector &origpubkey_out, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, uint256 assetid) { - CTransaction vinTx; int64_t nValue, assetoshis; + CTransaction vinTx; CAmount nValue, assetoshis; //fprintf(stderr,"AssetValidateSellvin()\n"); // get first ccvin: diff --git a/src/cc/CCassetsUtils.cpp b/src/cc/CCassetsUtils.cpp index baa67e44e21..1a370a34e3f 100644 --- a/src/cc/CCassetsUtils.cpp +++ b/src/cc/CCassetsUtils.cpp @@ -459,7 +459,7 @@ bool ValidateSwapRemainder(int64_t remaining_price, int64_t remaining_nValue, in } // get tx's vin inputs for cp->evalcode and addr. If addr is null then all inputs are added -CAmount AssetsGetCCInputs(struct CCcontract_info *cp, const char *addr, const CTransaction &tx) +CAmount AssetsGetCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx) { CTransaction vinTx; uint256 hashBlock; @@ -472,7 +472,7 @@ CAmount AssetsGetCCInputs(struct CCcontract_info *cp, const char *addr, const CT { if (cp->ismyvin(tx.vin[i].scriptSig)) { - if (myGetTransaction(tx.vin[i].prevout.hash, vinTx, hashBlock)) + if (eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock)) { char scriptaddr[KOMODO_ADDRESS_BUFSIZE]; if (addr == NULL || Getscriptaddress(scriptaddr, vinTx.vout[tx.vin[i].prevout.n].scriptPubKey) && strcmp(scriptaddr, addr) == 0) { diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index d6db9466d14..7bc4c262ca7 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -154,7 +154,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeNFT) TokenDataTuple tokenData; vuint8_t vopretNFT; if (refassetid != zeroid) { - GetTokenData(refassetid, tokenData, vopretNFT); + GetTokenData(NULL, refassetid, tokenData, vopretNFT); if (vopretNFT.size() > 0) cpAssets->evalcodeNFT = vopretNFT[0]; } @@ -519,7 +519,7 @@ UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 TokenDataTuple tokenData; vuint8_t vopretNonfungible; - GetTokenData(assetid, tokenData, vopretNonfungible); + GetTokenData(NULL, assetid, tokenData, vopretNonfungible); if (vopretNonfungible.size() > 0) cpAssets->evalcodeNFT = vopretNonfungible.begin()[0]; @@ -573,7 +573,7 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 vuint8_t vopretNonfungible; uint8_t evalcodeNFT = 0; uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - GetTokenData(assetid, tokenData, vopretNonfungible); + GetTokenData(NULL, assetid, tokenData, vopretNonfungible); if (vopretNonfungible.size() > 0) { evalcodeNFT = vopretNonfungible.begin()[0]; GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); @@ -700,7 +700,7 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a vuint8_t vopretNonfungible; uint8_t evalcodeNFT = 0; uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - GetTokenData(assetid, tokenData, vopretNonfungible); + GetTokenData(NULL, assetid, tokenData, vopretNonfungible); if (vopretNonfungible.size() > 0) { evalcodeNFT = vopretNonfungible.begin()[0]; GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 6caa48389a7..31888f50777 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -1027,7 +1027,7 @@ int32_t oracleprice_add(std::vector &publishers,CPubKey UniValue OracleFormat(uint8_t *data,int32_t datalen,char *format,int32_t formatlen); /// @private -bool GetCCDropAsOpret(const CScript &scriptPubKey, CScript &opret); +CScript GetCCDropAsOpret(const CScript &scriptPubKey); /*! \cond INTERNAL */ // curve25519 and sha256 @@ -1040,8 +1040,8 @@ bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); /*! \endcond */ /*! \cond INTERNAL */ -int64_t TotalPubkeyNormalInputs(const CTransaction &tx, const CPubKey &pubkey); -int64_t TotalPubkeyCCInputs(const CTransaction &tx, const CPubKey &pubkey); +CAmount TotalPubkeyNormalInputs(Eval *eval, const CTransaction &tx, const CPubKey &pubkey); +CAmount TotalPubkeyCCInputs(Eval *eval, const CTransaction &tx, const CPubKey &pubkey); inline std::string STR_TOLOWER(const std::string &str) { std::string out; for (std::string::const_iterator i = str.begin(); i != str.end(); i++) out += std::tolower(*i); return out; } /*! \endcond */ diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index e784742e769..581cd0d0de8 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -74,17 +74,18 @@ static std::vector GetEvalCodesCCV2(const CScript& spk) // internal function to check if token vout is valid // returns amount or -1 // return also tokenid -CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr) +CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, CScript &opret, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr) { // this is just for log messages indentation fur debugging recursive calls: std::string indentStr = std::string().append(tokenValIndentSize, '.'); + const char *funcname = __func__; - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "CheckTokensvout()" << " entered for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " entered for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); int32_t n = tx.vout.size(); // just check boundaries: if (n == 0 || v < 0 || v >= n) { - LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "CheckTokensvout()" << " incorrect params: (n == 0 or v < 0 or v >= n)" << " v=" << v << " n=" << n << " returning error" << std::endl); + LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << funcname << "()" << " incorrect params: (n == 0 or v < 0 or v >= n)" << " v=" << v << " n=" << n << " returning error" << std::endl); errorStr = "out of bounds"; return(-1); } @@ -115,9 +116,8 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used bool hasMyccvin = false; std::for_each (tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin){ cp->ismyvin(vin.scriptSig) ? hasMyccvin = true : hasMyccvin = hasMyccvin; }); - CScript opret; bool isLastVoutOpret; - if (GetCCDropAsOpret(tx.vout[v].scriptPubKey, opret)) + if (!(opret = GetCCDropAsOpret(tx.vout[v].scriptPubKey)).empty()) { isLastVoutOpret = false; } @@ -175,7 +175,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used // get optional nft eval code: TokenDataTuple tokenData; vscript_t vopretNonfungible; - GetTokenData(reftokenid, tokenData, vopretNonfungible); + GetTokenData(eval, reftokenid, tokenData, vopretNonfungible); if (vopretNonfungible.size() > 0) { // shift evalcodes so the first is NFT evalcode @@ -183,7 +183,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used evalCode1 = vopretNonfungible[0]; } - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() for txid=" << tx.GetHash().GetHex() << " checking evalCode1=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " voutPubkeysInOpret.size()=" << voutPubkeysInOpret.size() << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " for txid=" << tx.GetHash().GetHex() << " checking evalCode1=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " voutPubkeysInOpret.size()=" << voutPubkeysInOpret.size() << std::endl); if (IsTokenTransferFuncid(funcId)) { @@ -256,7 +256,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used std::vector oprets; if (DecodeTokenCreateOpRetV1(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, oprets) == 0) { - LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "IsTokensvout() could not decode create opret" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); + LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << funcname << "()" << " could not decode create opret" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); return 0; } @@ -273,9 +273,9 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used ccOutputs += vout.nValue; } - CAmount normalInputs = TotalPubkeyNormalInputs(tx, origPubkey); // calc normal inputs really signed by originator pubkey (someone not cheating with originator pubkey) + CAmount normalInputs = TotalPubkeyNormalInputs(eval, tx, origPubkey); // calc normal inputs really signed by originator pubkey (someone not cheating with originator pubkey) if (normalInputs >= ccOutputs) { - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() assured normalInputs >= ccOutputs" << " for tokenbase=" << reftokenid.GetHex() << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " assured normalInputs >= ccOutputs" << " for tokenbase=" << reftokenid.GetHex() << std::endl); // make test vout for origpubkey (either for fungible or NFT): CTxOut testvout = vopretNFT.size() == 0 ? MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, origPubkey) : MakeTokensCC1vout(vopretNFT[0], tx.vout[v].nValue, origPubkey); @@ -285,7 +285,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used return 0; } else { - LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "IsTokensvout() skipping vout not fulfilled normalInputs >= ccOutput" << " for tokenbase=" << reftokenid.GetHex() << " normalInputs=" << normalInputs << " ccOutputs=" << ccOutputs << std::endl); + LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << funcname << "()" << " skipping vout not fulfilled normalInputs >= ccOutput" << " for tokenbase=" << reftokenid.GetHex() << " normalInputs=" << normalInputs << " ccOutputs=" << ccOutputs << std::endl); errorStr = "tokenbase tx issued by not pubkey in opret"; return -1; } @@ -304,7 +304,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used return -1; } - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() ValidateTokenOpret returned not-null funcId=" << (char)(funcId ? funcId : ' ') << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " function ValidateTokenOpret returned not-null funcId=" << (char)(funcId ? funcId : ' ') << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); TokenDataTuple tokenData; vscript_t vopretExtra, vopretNonfungible; @@ -321,17 +321,17 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used uint8_t version; DecodeTokenOpRetV1(tx.vout.back().scriptPubKey, tokenIdOpret, voutPubkeysInOpret, oprets); - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << "IsTokensvout() oprets.size()=" << oprets.size() << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << funcname << "()" << " oprets.size()=" << oprets.size() << std::endl); // get assets/channels/gateways token data in vopretExtra: //FilterOutNonCCOprets(oprets, vopretExtra); // NOTE: only 1 additional evalcode in token opret is currently supported: if (oprets.size() > 0) vopretExtra = oprets[0]; - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << "IsTokensvout() vopretExtra=" << HexStr(vopretExtra) << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << funcname << "()" << " vopretExtra=" << HexStr(vopretExtra) << std::endl); // get non-fungible data - GetTokenData(reftokenid, tokenData, vopretNonfungible); + GetTokenData(eval, reftokenid, tokenData, vopretNonfungible); std::vector voutPubkeys; FilterOutTokensUnspendablePk(voutPubkeysInOpret, voutPubkeys); // cannot send tokens to token unspendable cc addr (only marker is allowed there) @@ -431,7 +431,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used // try all test vouts: for (const auto &t : testVouts) { if (t.first == tx.vout[v]) { // test vout matches - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "IsTokensvout() valid amount=" << tx.vout[v].nValue << " msg=" << t.second << " evalCode=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " txid=" << tx.GetHash().GetHex() << " tokenid=" << reftokenid.GetHex() << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << funcname << "()" << " valid amount=" << tx.vout[v].nValue << " msg=" << t.second << " evalCode=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " txid=" << tx.GetHash().GetHex() << " tokenid=" << reftokenid.GetHex() << std::endl); return tx.vout[v].nValue; } } @@ -447,7 +447,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used uint8_t version; if (DecodeTokenCreateOpRetV1(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, oprets) == 0) { - LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "IsTokensvout() could not decode create opret" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); + LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << funcname << "()" << " could not decode create opret" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); return 0; } @@ -482,11 +482,11 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used ccOutputs += vout.nValue; } - CAmount origInputs = TotalPubkeyNormalInputs(tx, origPubkey); // check if normal inputs are really signed by originator pubkey (someone not cheating with originator pubkey) - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() origInputs=" << origInputs << " ccOutputs=" << ccOutputs << " for tokenbase=" << reftokenid.GetHex() << std::endl); + CAmount origInputs = TotalPubkeyNormalInputs(eval, tx, origPubkey); // check if normal inputs are really signed by originator pubkey (someone not cheating with originator pubkey) + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " origInputs=" << origInputs << " ccOutputs=" << ccOutputs << " for tokenbase=" << reftokenid.GetHex() << std::endl); if (origInputs >= ccOutputs) { - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() assured origInputs >= ccOutputs" << " for tokenbase=" << reftokenid.GetHex() << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " assured origInputs >= ccOutputs" << " for tokenbase=" << reftokenid.GetHex() << std::endl); // make test vout for origpubkey (either for fungible or NFT): CTxOut testvout = vopretNFT.size() == 0 ? MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, origPubkey) : MakeTokensCC1vout(vopretNFT[0], tx.vout[v].nValue, origPubkey); @@ -497,7 +497,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used return 0; // vout is good, but do not take marker into account } else { - LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "IsTokensvout() skipping vout not fulfilled normalInputs >= ccOutput" << " for tokenbase=" << reftokenid.GetHex() << " origInputs=" << origInputs << " ccOutputs=" << ccOutputs << std::endl); + LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << funcname << "()" << " skipping vout not fulfilled normalInputs >= ccOutput" << " for tokenbase=" << reftokenid.GetHex() << " origInputs=" << origInputs << " ccOutputs=" << ccOutputs << std::endl); } } else { @@ -508,7 +508,7 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used return 0; // vout is good, but do not take marker into account } } - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "IsTokensvout() no valid vouts evalCode=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << funcname << "()" << " no valid vouts evalCode=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); } } return(0); // normal vout @@ -519,17 +519,15 @@ CAmount TokensV1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used // internal function to check if token 2 vout is valid // returns amount or -1 // return also tokenid -CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr) +CAmount TokensV2::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, CScript &opret, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr) { - // this is just for log messages indentation fur debugging recursive calls: - std::string indentStr = std::string().append(tokenValIndentSize, '.'); - - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensV2::CheckTokensvout()" << " entered for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); + // this is just for log messages indentation fur debugging recursive calls: + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG2, stream << " entered for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); int32_t n = tx.vout.size(); // just check boundaries: if (n == 0 || v < 0 || v >= n) { - LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "TokensV2::CheckTokensvout()" << " incorrect params: (n == 0 or v < 0 or v >= n)" << " v=" << v << " n=" << n << " returning error" << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " incorrect params: (n == 0 or v < 0 or v >= n)" << " v=" << v << " n=" << n << " returning error" << std::endl); errorStr = "out of bounds"; return -1; } @@ -539,9 +537,8 @@ CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcon if (tx.vout[v].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) && tx.vout[v].scriptPubKey.SpkHasEvalcodeCCV2(EVAL_TOKENSV2)) // it's token output, check it { - CScript opret; bool isLastVoutOpret; - if (GetCCDropAsOpret(tx.vout[v].scriptPubKey, opret)) + if (!(opret = GetCCDropAsOpret(tx.vout[v].scriptPubKey)).empty()) { isLastVoutOpret = false; } @@ -560,32 +557,14 @@ CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcon if (funcId == 0) { // bad opreturn errorStr = "can't decode opreturn data"; - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensV2::CheckTokensvout()" << " skipping vout with non token opret for txid=" << tx.GetHash().GetHex() << " v=" << v << " isLastVoutOpret=" << isLastVoutOpret << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " skipping vout with non token opret for txid=" << tx.GetHash().GetHex() << " v=" << v << " isLastVoutOpret=" << isLastVoutOpret << std::endl); return -1; // not token vout, skip } // basic checks: if (IsTokenCreateFuncid(funcId)) { - std::vector vpksdummy; - std::vector oprets; - vuint8_t vorigpk; - std::string name, description; - // set returned tokend to tokenbase txid: reftokenid = tx.GetHash(); - - TokensV2::DecodeTokenCreateOpRet(opret, vorigpk, name, description, oprets); - - // check this is really creator - CPubKey origpk = pubkey2pk(vorigpk); - if (TotalPubkeyNormalInputs(tx, origpk) == 0) { - errorStr = "no vins signed with creator pubkey"; - return -1; - } - if (origpk == GetUnspendable(cp, NULL)) { - errorStr = "cannot create tokens with token shared pubkey"; - return -1; - } } else if (IsTokenTransferFuncid(funcId)) { // set returned tokenid to tokenid in opreturn: @@ -604,7 +583,7 @@ CAmount TokensV2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcon // skip token marker (token global address) CAmount markerAmount = IsTokenMarkerVout(tx.vout[v]); if (markerAmount > 0) { - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensV2::CheckTokensvout()" << " skipping marker vout for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " skipping marker vout for txid=" << tx.GetHash().GetHex() << " v=" << v << std::endl); return 0; } else if (markerAmount < 0) { @@ -719,7 +698,7 @@ static bool CheckTokensV2CreateTx(struct CCcontract_info *cp, Eval* eval, const { CScript opret; bool isLastVoutOpret; - if (GetCCDropAsOpret(tx.vout[v].scriptPubKey, opret)) + if (!(opret = GetCCDropAsOpret(tx.vout[v].scriptPubKey)).empty()) { isLastVoutOpret = false; } @@ -739,7 +718,7 @@ static bool CheckTokensV2CreateTx(struct CCcontract_info *cp, Eval* eval, const // check this is really creator CPubKey origpk = pubkey2pk(vorigpk); - if (TotalPubkeyNormalInputs(tx, origpk) == 0) + if (TotalPubkeyNormalInputs(eval, tx, origpk) == 0) return report_validation_error(__func__, eval, tx, "no vins with creator pubkey"); } else if(IsTokenTransferFuncid(funcid)) @@ -759,7 +738,7 @@ static bool CheckTokensV2CreateTx(struct CCcontract_info *cp, Eval* eval, const // check this is really creator CPubKey origpk = pubkey2pk(vorigpk); - if (TotalPubkeyNormalInputs(tx, origpk) == 0) + if (TotalPubkeyNormalInputs(eval, tx, origpk) == 0) return report_validation_error(__func__, eval, tx, "no vins with creator pubkey"); createNum ++; } diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index 56865a787cf..0a3ca1ec4dc 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -66,17 +66,13 @@ bool Tokensv2Validate(struct CCcontract_info *cp,Eval* eval,const CTransaction & /// Checks if a transaction vout is true token vout, for this check pubkeys and eval code in token opreturn are used to recreate vout and compare it with the checked vout. /// Verifies that the transaction total token inputs value equals to total token outputs (that is, token balance is not changed in this transaction) -/// @param goDeeper also recursively checks the previous token transactions (or the creation transaction) and ensures token balance is not changed for them too -/// @param checkPubkeys always true /// @param cp CCcontract_info structure initialized for EVAL_TOKENS eval code /// @param eval could be NULL, if not NULL then the eval parameter is used to report validation error /// @param tx transaction object to check /// @param v vout number (starting from 0) /// @param reftokenid id of the token. The vout is checked if it has this tokenid /// @returns true if vout is true token with the reftokenid id -//CAmount IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid); - -template CAmount IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid); +template CAmount IsTokensvout(struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid); /// Creates a token cryptocondition that allows to spend it by one key @@ -309,7 +305,7 @@ class TokensV1 { return ::DecodeTokenOpRetV1(scriptPubKey, tokenid, voutPubkeys, oprets); } - static CAmount CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr); + static CAmount CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, CScript &opret, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr); // conds: static CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk) @@ -392,7 +388,7 @@ class TokensV2 { return ::DecodeTokenOpRetV2(scriptPubKey, tokenid, oprets); } - static CAmount CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr); + static CAmount CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, CScript &opret, uint256 &reftokenid, uint8_t &funcId, std::string &errorStr); // conds: static CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk) diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index f2e6e40a85f..8b29d89c8dd 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -26,7 +26,7 @@ // get non-fungible data from 'tokenbase' tx (the data might be empty) template -bool GetTokenData(uint256 tokenid, TokenDataTuple &tokenData, vscript_t &vopretNonfungible) +bool GetTokenData(Eval *eval, uint256 tokenid, TokenDataTuple &tokenData, vscript_t &vopretNonfungible) { CTransaction tokenbasetx; uint256 hashBlock; @@ -34,7 +34,7 @@ bool GetTokenData(uint256 tokenid, TokenDataTuple &tokenData, vscript_t &vopretN tokenData = std::make_tuple(vuint8_t(), std::string(), std::string()); vopretNonfungible.clear(); - if (!myGetTransaction(tokenid, tokenbasetx, hashBlock)) { + if (!GetTxUnconfirmedOpt(eval, tokenid, tokenbasetx, hashBlock)) { LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << "could not load token creation tx=" << tokenid.GetHex() << std::endl); return false; } @@ -57,7 +57,7 @@ bool GetTokenData(uint256 tokenid, TokenDataTuple &tokenData, vscript_t &vopretN } template -uint8_t GetTokenOpReturnVersion(uint256 tokenid) +uint8_t GetTokenOpReturnVersion(Eval *eval, uint256 tokenid) { CTransaction tokencreatetx; uint256 hashBlock; @@ -65,7 +65,7 @@ uint8_t GetTokenOpReturnVersion(uint256 tokenid) std::string name, desc; std::vector oprets; - if (myGetTransaction(tokenid, tokencreatetx, hashBlock) && + if (GetTxUnconfirmedOpt(eval, tokenid, tokencreatetx, hashBlock) && tokencreatetx.vout.size() > 0 && V::DecodeTokenCreateOpRet(tokencreatetx.vout.back().scriptPubKey, vorigpk, name, desc, oprets) != 0) return DecodeTokenOpretVersion(tokencreatetx.vout.back().scriptPubKey); @@ -81,16 +81,17 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c CAmount totalinputs = 0; int32_t n = 0; const bool CC_INPUTS_TRUE = true; + const char *funcname = __func__; if (cp->evalcode != V::EvalCode()) - LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << "warning: EVAL_TOKENS *cp is needed but used evalcode=" << (int)cp->evalcode << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << funcname << "()" << " warning: EVAL_TOKENS *cp is needed but used evalcode=" << (int)cp->evalcode << std::endl); if (cp->evalcodeNFT == 0) // if not set yet (in TransferToken or this func overload) { // check if this is a NFT TokenDataTuple tokenData; vscript_t vopretNonfungible; - GetTokenData(tokenid, tokenData, vopretNonfungible); + GetTokenData(NULL, tokenid, tokenData, vopretNonfungible); if (vopretNonfungible.size() > 0) cp->evalcodeNFT = vopretNonfungible.begin()[0]; // set evalcode of NFT, for signing } @@ -119,15 +120,15 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c strcmp(destaddr, cp->unspendableaddr2) != 0*/) // or the logic is to allow to spend all available tokens (what about unspendableaddr3)? return; - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << "AddTokenCCInputs() checking tx vout destaddress=" << destaddr << " amount=" << tx.vout[index].nValue << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << "()" << " checking tx vout destaddress=" << destaddr << " amount=" << tx.vout[index].nValue << std::endl); - if (IsTokensvout(true, true, cp, NULL, tx, index, tokenid) > 0 && !myIsutxo_spentinmempool(ignoretxid, ignorevin, txhash, index)) + if (IsTokensvout(cp, NULL, tx, index, tokenid) > 0 && !myIsutxo_spentinmempool(ignoretxid, ignorevin, txhash, index)) { if (total != 0 && maxinputs != 0) // if it is not just to calc amount... mtx.vin.push_back(CTxIn(txhash, index, CScript())); totalinputs += satoshis; - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << "AddTokenCCInputs() adding input nValue=" << satoshis << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << "()" << " adding input nValue=" << satoshis << std::endl); n++; if ((total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) @@ -135,12 +136,12 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c } else { - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << "AddTokenCCInputs() IsTokensvout returned non-positive txid=" << txhash.GetHex() << " index=" << index << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << "()" << " function IsTokensvout returned non-positive for txid=" << txhash.GetHex() << " index=" << index << std::endl); } } }; // auto add_token_vin - if (fUnspentCCIndex && GetTokenOpReturnVersion(tokenid) > 0) + if (fUnspentCCIndex && GetTokenOpReturnVersion(NULL, tokenid) > 0) { std::vector > unspentOutputs; @@ -149,7 +150,7 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c AddCCunspentsCCIndexMempool(unspentOutputs, tokenaddr, tokenid); // threshold = total / (maxinputs != 0 ? maxinputs : CC_MAXVINS); // let's not use threshold - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "unspent ccindex found unspentOutputs=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << funcname << "()" << " unspent ccindex found unspentOutputs=" << unspentOutputs.size() << std::endl); for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) add_token_vin(it->first.txhash, it->first.index, it->second.satoshis); } @@ -162,7 +163,7 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c else SetCCunspents(unspentOutputs, (char*)tokenaddr, CC_INPUTS_TRUE); - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "unspent index found unspentOutputs=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << funcname << "()" << " unspent index found unspentOutputs=" << unspentOutputs.size() << std::endl); for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) add_token_vin(it->first.txhash, it->first.index, it->second.satoshis); } @@ -179,7 +180,7 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c // check if this is a NFT TokenDataTuple tokenData; vscript_t vopretNonfungible; - GetTokenData(tokenid, tokenData, vopretNonfungible); + GetTokenData(NULL, tokenid, tokenData, vopretNonfungible); if (vopretNonfungible.size() > 0) cp->evalcodeNFT = vopretNonfungible.begin()[0]; // set evalcode of NFT @@ -461,7 +462,7 @@ std::string TokenTransfer(CAmount txfee, uint256 tokenid, uint8_t M, const std:: TokenDataTuple tokenData; vscript_t vopretNonfungible; - GetTokenData(tokenid, tokenData, vopretNonfungible); + GetTokenData(NULL, tokenid, tokenData, vopretNonfungible); if (vopretNonfungible.size() > 0) cp->evalcodeNFT = vopretNonfungible.begin()[0]; // set evalcode of NFT GetTokensCCaddress(cp, tokenaddr, mypk, V::IsMixed()); @@ -516,7 +517,7 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup // This what the AddNormalinputsRemote does (and it is not necessary that this is done only for nspv calls): if ((totalInputs = AddNormalinputsRemote(mtx, mypk, tokensupply + txfee + markerCount * TOKENS_MARKER_VALUE, 0x10000, useMempool)) > 0) { - CAmount mypkInputs = TotalPubkeyNormalInputs(mtx, mypk); + CAmount mypkInputs = TotalPubkeyNormalInputs(NULL, mtx, mypk); if (mypkInputs < tokensupply) { // check that the token amount is really issued with mypk (because in the wallet there may be some other privkeys) CCerror = "some inputs signed not with mypubkey (-pubkey=pk)"; return NullUniValue; @@ -635,7 +636,7 @@ UniValue TokenInfo(uint256 tokenid) CAmount supply = 0, output; for (int v = 0; v < tokenbaseTx.vout.size(); v++) - if ((output = IsTokensvout(false, true, cpTokens, NULL, tokenbaseTx, v, tokenid)) > 0) + if ((output = IsTokensvout(cpTokens, NULL, tokenbaseTx, v, tokenid)) > 0) supply += output; result.push_back(Pair("supply", supply)); result.push_back(Pair("description", description)); @@ -793,7 +794,7 @@ static uint8_t ValidateTokenOpret(uint256 txid, const CScript &scriptPubKey, uin // checks if any token vouts are sent to 'dead' pubkey template -static CAmount HasBurnedTokensvouts(const CTransaction& tx, uint256 reftokenid) +static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 reftokenid) { uint8_t dummyEvalCode; uint256 tokenIdOpret; @@ -828,7 +829,7 @@ static CAmount HasBurnedTokensvouts(const CTransaction& tx, uint256 reftokenid) LOGSTREAMFN(cctokens_log, CCLOG_DEBUG2, stream << "vopretExtra=" << HexStr(vopretExtra) << std::endl); - GetTokenData(reftokenid, tokenData, vopretNonfungible); + GetTokenData(eval, reftokenid, tokenData, vopretNonfungible); if (vopretNonfungible.size() > 0) evalCode = vopretNonfungible.begin()[0]; if (vopretExtra.size() > 0) @@ -897,13 +898,15 @@ CAmount IsTokenMarkerVout(CTxOut vout) { // it should be either sum(cc vins) == sum(cc vouts) or the transaction is the 'tokenbase' ('c' or 'C') tx // checkPubkeys is true: validates if the vout is token vout1 or token vout1of2. Should always be true! template -CAmount IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid) +CAmount IsTokensvout(struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid) { uint8_t funcId = 0; uint256 tokenIdInOpret; + CScript opret; std::string errorStr; - CAmount retAmount = V::CheckTokensvout(goDeeper, checkPubkeys, cp, eval, tx, v, tokenIdInOpret, funcId, errorStr); - std::cerr << __func__ << " tokenIdInOpret=" << tokenIdInOpret.GetHex() << " funcId=" << (int)funcId << std::endl; + + CAmount retAmount = V::CheckTokensvout(cp, eval, tx, v, opret, tokenIdInOpret, funcId, errorStr); + // std::cerr << __func__ << " tokenIdInOpret=" << tokenIdInOpret.GetHex() << " funcId=" << (int)funcId << std::endl; if (!errorStr.empty()) LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "error=" << errorStr << std::endl); if (retAmount < 0) @@ -930,22 +933,22 @@ static bool CheckMarkerSpending(struct CCcontract_info *cp, Eval *eval, const CT if (vin.prevout.hash == tokenid) // check if this is my marker { // calc burned amount - CAmount burnedAmount = HasBurnedTokensvouts(tx, tokenid); + CAmount burnedAmount = HasBurnedTokensvouts(eval, tx, tokenid); if (burnedAmount > 0) { TokenDataTuple tokenData; vscript_t vopretNonfungible; - GetTokenData(tokenid, tokenData, vopretNonfungible); + GetTokenData(eval, tokenid, tokenData, vopretNonfungible); if (!vopretNonfungible.empty()) { CTransaction tokenbaseTx; uint256 hashBlock; - if (myGetTransaction(tokenid, tokenbaseTx, hashBlock)) + if (GetTxUnconfirmedOpt(eval, tokenid, tokenbaseTx, hashBlock)) { // get total supply CAmount supply = 0L, output; for (int v = 0; v < tokenbaseTx.vout.size() - 1; v++) - if ((output = IsTokensvout(false, true, cp, NULL, tokenbaseTx, v, tokenid)) > 0) + if ((output = IsTokensvout(cp, eval, tokenbaseTx, v, tokenid)) > 0) supply += output; if (supply == 1 && supply == burnedAmount) // burning marker is allowed only for burned NFTs (that is with supply == 1) @@ -968,35 +971,34 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c CTransaction vinTx; uint256 hashBlock; CAmount tokenoshis; + const char *funcname = __func__; std::map mapinputs, mapoutputs; // this is just for log messages indentation for debugging recursive calls: std::string indentStr = std::string().append(tokenValIndentSize, '.'); - //LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() entered for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); - - // pick token vouts in vin transactions and calculate input total - for (int32_t i = 0; i < tx.vin.size(); i++) - { // check for additional contracts which may send tokens to the Tokens contract - if ((*cp->ismyvin)(tx.vin[i].scriptSig) /*|| IsVinAllowed(tx.vin[i].scriptSig) != 0*/) + // pick token vouts in vin transactions and calculate total inputs + for (int32_t i = 0; i < tx.vin.size(); i ++) + { + if ((*cp->ismyvin)(tx.vin[i].scriptSig)) { - //std::cerr << indentStr << __func__ << " eval is true=" << (eval != NULL) << " ismyvin=ok for_i=" << i << std::endl; - // we are not inside the validation code -- dimxy - if ((eval && eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock) == 0) || (!eval && !myGetTransaction(tx.vin[i].prevout.hash, vinTx, hashBlock))) + if (!GetTxUnconfirmedOpt(eval, tx.vin[i].prevout.hash, vinTx, hashBlock)) { - LOGSTREAM(cctokens_log, CCLOG_ERROR, stream << indentStr << "TokensExactAmounts() cannot read vintx for vin i=" << i << std::endl); + LOGSTREAM(cctokens_log, CCLOG_ERROR, stream << indentStr << funcname << "()" << " cannot read vintx for vin i=" << i << std::endl); return (!eval) ? false : eval->Invalid("could not load vin tx " + std::to_string(i)); } else { - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() checking vintx.vout for tx.vin[" << i << "] nValue=" << vinTx.vout[tx.vin[i].prevout.n].nValue << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " checking vintx.vout for cc tx.vin[" << i << "] nValue=" << vinTx.vout[tx.vin[i].prevout.n].nValue << std::endl); uint256 reftokenid; uint8_t funcId = 0; + CScript opret; // validate vouts of vintx tokenValIndentSize++; - tokenoshis = V::CheckTokensvout(goDeeper, true, cp, eval, vinTx, tx.vin[i].prevout.n, reftokenid, funcId, errorStr); + tokenoshis = V::CheckTokensvout(cp, eval, vinTx, tx.vin[i].prevout.n, opret, reftokenid, funcId, errorStr); + // std::cerr << __func__ << " reftokenid=" << reftokenid.GetHex() << " vin=" << i << " funcId=" << (int)funcId << " " << funcId << std::endl; tokenValIndentSize--; if (tokenoshis < 0) return false; @@ -1004,14 +1006,14 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c // skip marker spending // later it will be checked if marker spending is allowed if (IsTokenMarkerVout(vinTx.vout[tx.vin[i].prevout.n]) > 0LL) { - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() skipping marker vintx.vout for tx.vin[" << i << "] nValue=" << vinTx.vout[tx.vin[i].prevout.n].nValue << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " skipping marker vintx.vout for tx.vin[" << i << "] nValue=" << vinTx.vout[tx.vin[i].prevout.n].nValue << std::endl); continue; // do not check for marker count for on-chain transacitions, no point in checking this (for token v1) as it is an antispam feature } if (tokenoshis != 0) { - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() adding vintx.vout for tx.vin[" << i << "] tokenoshis=" << tokenoshis << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << indentStr << funcname << "()" << " adding vintx.vout for tx.vin[" << i << "] tokenoshis=" << tokenoshis << std::endl); mapinputs[reftokenid] += tokenoshis; } } @@ -1022,46 +1024,50 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c int markerVouts = 0; int createVouts = 0; int transferVouts = 0; + CScript opret; for (int32_t i = 0; i < tx.vout.size(); i ++) { - uint256 reftokenid; - uint8_t funcId = 0; - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() recursively checking tx.vout[" << i << "] nValue=" << tx.vout[i].nValue << std::endl); - - // Note: we pass in here IsTokensvout(false,...) because we don't need to call TokenExactAmounts() recursively from IsTokensvout here - // indeed, if we pass 'true' we'll be checking this tx vout again - tokenValIndentSize++; - tokenoshis = V::CheckTokensvout(false, true, cp, eval, tx, i, reftokenid, funcId, errorStr); - tokenValIndentSize--; - if (tokenoshis < 0) - return false; + if (tx.vout[i].scriptPubKey.IsPayToCryptoCondition()) + { + uint256 reftokenid; + uint8_t funcId = 0; + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " checking cc tx.vout[" << i << "] nValue=" << tx.vout[i].nValue << std::endl); + + // indeed, if we pass 'true' we'll be checking this tx vout again + tokenValIndentSize++; + tokenoshis = V::CheckTokensvout(cp, eval, tx, i, opret, reftokenid, funcId, errorStr); + // std::cerr << __func__ << " reftokenid=" << reftokenid.GetHex() << " vout=" << i << " funcId=" << (int)funcId << " " << funcId << std::endl; + tokenValIndentSize--; + if (tokenoshis < 0) + return false; - CAmount markerAmount = IsTokenMarkerVout(tx.vout[i]); - if (markerAmount > 0) { - ++ markerVouts; - if (IsTokenCreateFuncid(funcId) && markerVouts > 1) { - errorStr = "tokencreate cannot have more than one marker"; + CAmount markerAmount = IsTokenMarkerVout(tx.vout[i]); + if (markerAmount > 0) { + ++ markerVouts; + if (IsTokenCreateFuncid(funcId) && markerVouts > 1) { + errorStr = "tokencreate cannot have more than one marker"; + return false; + } + + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " skipping marker tx.vout[" << i << "] nValue=" << tx.vout[i].nValue << std::endl); + continue; // skip marker + } + else if (markerAmount < 0) { + errorStr = "invalid marker value"; return false; } - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() skipping marker tx.vout[" << i << "] nValue=" << tx.vout[i].nValue << std::endl); - continue; // skip marker - } - else if (markerAmount < 0) { - errorStr = "invalid marker value"; - return false; - } - - if (IsTokenCreateFuncid(funcId)) - ++ createVouts; - if (IsTokenTransferFuncid(funcId)) - ++ transferVouts; + if (IsTokenCreateFuncid(funcId)) + ++ createVouts; + if (IsTokenTransferFuncid(funcId)) + ++ transferVouts; - if (tokenoshis != 0) - { - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() adding tx.vout[" << i << "] tokenoshis=" << tokenoshis << std::endl); - mapoutputs[reftokenid] += tokenoshis; - } + if (tokenoshis != 0) + { + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << funcname << "()" << " adding tx.vout[" << i << "] tokenoshis=" << tokenoshis << std::endl); + mapoutputs[reftokenid] += tokenoshis; + } + } } // can't mix tokencreate and tokentransfer @@ -1071,7 +1077,8 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c } // tokencreate checks (this would work only for tokens v2 as tokens v1 tokencreate does not pass cc validation when it is added to the chain) - if (createVouts > 0) { + if (createVouts > 0) + { // check that creation tx does not have my cc vins bool hasMyccvin = false; std::for_each (tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin){ cp->ismyvin(vin.scriptSig) ? hasMyccvin = true : hasMyccvin = hasMyccvin; }); @@ -1088,11 +1095,32 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c errorStr = "tokencreate cannot have more than one marker"; return false; } + + std::vector vpksdummy; + std::vector oprets; + vuint8_t vorigpk; + std::string name, description; + + TokensV2::DecodeTokenCreateOpRet(opret, vorigpk, name, description, oprets); + + // check this is really creator + CPubKey origpk = pubkey2pk(vorigpk); + if (TotalPubkeyNormalInputs(eval, tx, origpk) == 0) { + errorStr = "no vins signed with creator pubkey"; + return false; + } + + // can't create tokens with global key + if (origpk == GetUnspendable(cp, NULL)) { + errorStr = "cannot create tokens with token shared pubkey"; + return false; + } return true; // tokencreate checks finished } // tokentransfer checks - if (transferVouts > 0) { + if (transferVouts > 0) + { // markers are not allowed for tokentransfer (for antispam reasons) if (markerVouts > 0) { errorStr = "tokentransfer cannot have markers"; @@ -1103,7 +1131,7 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c if (mapinputs.size() > 0 && mapinputs.size() == mapoutputs.size()) { for(auto const &m : mapinputs) { - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() inputs[" << m.first.GetHex() << "]=" << m.second << " outputs=" << mapoutputs[m.first] << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << funcname << "()" << " inputs[" << m.first.GetHex() << "]=" << m.second << " outputs=" << mapoutputs[m.first] << std::endl); if (m.second != mapoutputs[m.first]) { errorStr = "cc inputs not equal outputs for tokenid=" + m.first.GetHex(); return false; @@ -1114,13 +1142,13 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c errorStr = "marker spending is not allowed for tokenid=" + m.first.GetHex(); return false; } - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() mapinput.second=" << m.second << " mapoutputs[m.first]=" << mapoutputs[m.first] << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << funcname << "()" << " mapinput.second=" << m.second << " mapoutputs[m.first]=" << mapoutputs[m.first] << std::endl); } return true; } } - LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << "TokensExactAmounts() no cc inputs or cc outputs for a tokenid, mapinputs.size()=" << mapinputs.size() << " mapoutputs.size()=" << mapoutputs.size() << std::endl); - errorStr = "no cc vins or cc vouts for tokenid"; + LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << funcname << "()" << " no cc inputs or cc outputs, mapinputs.size()=" << mapinputs.size() << " mapoutputs.size()=" << mapoutputs.size() << std::endl); + errorStr = "no tokens cc vins or cc vouts"; return false; } diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index ee124966bb1..977b86ddd30 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -613,20 +613,3 @@ uint8_t DecodeTokenOpretVersion(const CScript &scriptPubKey) } return version; } - -template -uint8_t GetTokenOpReturnVersion(uint256 tokenid) -{ - CTransaction tokencreatetx; - uint256 hashBlock; - vuint8_t vorigpk; - std::string name, desc; - std::vector oprets; - - if (myGetTransaction(tokenid, tokencreatetx, hashBlock) && - tokencreatetx.vout.size() > 0 && - V::DecodeTokenCreateOpRet(tokencreatetx.vout.back().scriptPubKey, vorigpk, name, desc, oprets) != 0) - return DecodeTokenOpretVersion(tokencreatetx.vout.back().scriptPubKey); - else - return 0; -} \ No newline at end of file diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 6dd066f318f..038a8b7c0c2 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -282,7 +282,7 @@ bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn, { uint256 blockHash; - if (myGetTransaction(tx.vin[nIn].prevout.hash, txOut, blockHash) && txOut.vout.size() > tx.vin[nIn].prevout.n) + if (eval->GetTxUnconfirmed(tx.vin[nIn].prevout.hash, txOut, blockHash) && txOut.vout.size() > tx.vin[nIn].prevout.n) { CBlockIndex index; if (eval->GetBlock(blockHash, index)) @@ -961,13 +961,14 @@ CPubKey check_signing_pubkey(CScript scriptSig) // returns total of normal inputs signed with this pubkey -int64_t TotalPubkeyNormalInputs(const CTransaction &tx, const CPubKey &pubkey) +CAmount TotalPubkeyNormalInputs(Eval *eval, const CTransaction &tx, const CPubKey &pubkey) { - int64_t total = 0; - for (auto vin : tx.vin) { + CAmount total = 0; + + for (const auto &vin : tx.vin) { CTransaction vintx; uint256 hashBlock; - if (!IsCCInput(vin.scriptSig) && myGetTransaction(vin.prevout.hash, vintx, hashBlock)) { + if (!IsCCInput(vin.scriptSig) && GetTxUnconfirmedOpt(eval, vin.prevout.hash, vintx, hashBlock)) { typedef std::vector valtype; std::vector vSolutions; txnouttype whichType; @@ -990,17 +991,17 @@ int64_t TotalPubkeyNormalInputs(const CTransaction &tx, const CPubKey &pubkey) } // returns total of CC inputs signed with this pubkey -int64_t TotalPubkeyCCInputs(const CTransaction &tx, const CPubKey &pubkey) +CAmount TotalPubkeyCCInputs(Eval *eval, const CTransaction &tx, const CPubKey &pubkey) { - int64_t total = 0; - for (auto vin : tx.vin) { + CAmount total = 0; + for (const auto &vin : tx.vin) { if (IsCCInput(vin.scriptSig)) { CPubKey vinPubkey = check_signing_pubkey(vin.scriptSig); if (vinPubkey.IsValid()) { if (vinPubkey == pubkey) { CTransaction vintx; uint256 hashBlock; - if (myGetTransaction(vin.prevout.hash, vintx, hashBlock)) { + if (GetTxUnconfirmedOpt(eval, vin.prevout.hash, vintx, hashBlock)) { total += vintx.vout[vin.prevout.n].nValue; } } @@ -1480,10 +1481,11 @@ UniValue OracleFormat(uint8_t *data,int32_t datalen,char *format,int32_t formatl // get OP_DROP data: -bool GetCCDropAsOpret(const CScript &scriptPubKey, CScript &opret) +CScript GetCCDropAsOpret(const CScript &scriptPubKey) { std::vector> vParams; CScript dummy; + CScript opret; if (scriptPubKey.IsPayToCryptoCondition(&dummy, vParams)) { @@ -1494,7 +1496,7 @@ bool GetCCDropAsOpret(const CScript &scriptPubKey, CScript &opret) LOGSTREAMFN("ccutils", CCLOG_DEBUG1, stream << " evalcode=" << (int)parsed.evalCode << " vKeys.size()=" << (int)parsed.vKeys.size() << " vData.size()=" << (int)parsed.vData.size() << std::endl); if (parsed.vData.size() > 0) { opret << OP_RETURN << parsed.vData[0]; // return vData[0] as cc opret - return true; + return opret; } } @@ -1526,7 +1528,7 @@ bool GetCCDropAsOpret(const CScript &scriptPubKey, CScript &opret) } */ } - return false; + return CScript(); } // get OP_DROP data for mixed cc vouts @@ -1627,7 +1629,7 @@ UniValue CCaddress(struct CCcontract_info *cp, const char *name, const std::vect bool CCDecodeTxVout(const CTransaction &tx, int32_t n, uint8_t &evalcode, uint8_t &funcid, uint8_t &version, uint256 &creationId) { CScript opdrop; - vscript_t ccdata; + vscript_t vccdata; if (tx.vout.size() > 0) { @@ -1635,18 +1637,23 @@ bool CCDecodeTxVout(const CTransaction &tx, int32_t n, uint8_t &evalcode, uint8_ // first try if OP_DROP data exists bool usedOpreturn; - if (GetCCDropAsOpret(tx.vout[n].scriptPubKey, opdrop)) - GetOpReturnData(opdrop, ccdata), usedOpreturn = false; - else - GetOpReturnData(tx.vout.back().scriptPubKey, ccdata), usedOpreturn = true; // use OP_RETURN in the last vout if no OP_DROP data + CScript opdrop; + if (!(opdrop = GetCCDropAsOpret(tx.vout[n].scriptPubKey)).empty()) { + GetOpReturnData(opdrop, vccdata); + usedOpreturn = false; + } + else { + GetOpReturnData(tx.vout.back().scriptPubKey, vccdata); + usedOpreturn = true; // use OP_RETURN in the last vout if no OP_DROP data + } // use following algotithm to determine creationId // get the evalcode from ccdata // if no cc vins found with this evalcode this is the creation tx and creationId = tx.GetHash() // else the creationId is after the version field: 'evalcode funcid version creationId' - if (ccdata.size() >= 3) { + if (vccdata.size() >= 3) { struct CCcontract_info *cp, C; - cp = CCinit(&C, ccdata[0]); + cp = CCinit(&C, vccdata[0]); int32_t i = 0; for (; i < tx.vin.size(); i ++) if (cp->ismyvin(tx.vin[i].scriptSig)) @@ -1654,17 +1661,17 @@ bool CCDecodeTxVout(const CTransaction &tx, int32_t n, uint8_t &evalcode, uint8_ if (i == tx.vin.size()) { creationId = tx.GetHash(); // tx is the creation tx - evalcode = ccdata[0]; - funcid = ccdata[1]; - version = ccdata[2]; + evalcode = vccdata[0]; + funcid = vccdata[1]; + version = vccdata[2]; LOGSTREAMFN("ccutils", CCLOG_DEBUG1, stream << " evalcode=" << (int)evalcode << " funcid=" << (char)funcid << "(" << (int)funcid << "), version=" << (int)version << std::endl); } else { uint256 encodedCrid; - if (ccdata.size() >= 3 + sizeof(uint256)) { // get creationId from the ccdata + if (vccdata.size() >= 3 + sizeof(uint256)) { // get creationId from the ccdata bool isEof = true; - if (!E_UNMARSHAL(ccdata, ss >> evalcode; ss >> funcid; ss >> version; ss >> encodedCrid; isEof = ss.eof()) && isEof) { // E_UNMARSHAL might parse okay but return false if not EoF yet. So EoF==true means bad parse + if (!E_UNMARSHAL(vccdata, ss >> evalcode; ss >> funcid; ss >> version; ss >> encodedCrid; isEof = ss.eof()) && isEof) { // E_UNMARSHAL might parse okay but return false if not EoF yet. So EoF==true means bad parse LOGSTREAMFN("ccutils", CCLOG_DEBUG1, stream << "failed to decode ccdata, isEof=" << isEof << " usedOpreturn=" << usedOpreturn << " tx=" << HexStr(E_MARSHAL(ss << tx)) << std::endl); return false; } diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index d6537b8d2bb..8b2cb4ebd97 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -165,7 +165,6 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const CTxDestination address; CTransaction vinTx, createTx; uint256 hashBlock, assetid, assetid2; - //int32_t preventCCvins, preventCCvouts; int32_t ccvins = -1, ccvouts = -1; int64_t unit_price, vin_unit_price; vuint8_t vorigpubkey, vin_origpubkey, vopretNonfungible; @@ -180,8 +179,9 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const int32_t numvins = tx.vin.size(); int32_t numvouts = tx.vout.size(); - //preventCCvins = preventCCvouts = -1; - + + if (tx.vin.size() == 0) + return eval->Invalid("AssetValidate: no vins"); if (tx.vout.size() == 0) return eval->Invalid("AssetValidate: no vouts"); if((funcid = A::DecodeAssetTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCodeInOpret, assetid, assetid2, unit_price, vorigpubkey)) == 0 ) @@ -196,7 +196,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const cpTokens = CCinit(&tokensC, T::EvalCode()); // non-fungible tokens support: - GetTokenData(assetid, tokenData, vopretNonfungible); + GetTokenData(eval, assetid, tokenData, vopretNonfungible); uint64_t royaltyFract = 0; // royalty is N in N/1000 fraction if (vopretNonfungible.size() > 0) { cpAssets->evalcodeNFT = vopretNonfungible.begin()[0]; @@ -256,7 +256,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("invalid funding for bid"); else if( A::ConstrainVout(tx.vout[1], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr return eval->Invalid("invalid vout1 marker for original pubkey"); - else if( TotalPubkeyNormalInputs(tx, pubkey2pk(vorigpubkey)) == 0 ) // check tx is signed by originator pubkey + else if( TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vorigpubkey)) == 0 ) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for bid"); else if (unit_price <= 0) return eval->Invalid("invalid unit price"); @@ -295,7 +295,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if( isCCVout ) ccvouts ++; } - if (TotalPubkeyNormalInputs(tx, pubkey2pk(vin_origpubkey)) == 0) // check tx is signed by originator pubkey + if (TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vin_origpubkey)) == 0) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for cancelbid"); //preventCCvins = 2; @@ -352,7 +352,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("vout0 should be originator normal address with remainder for fillbid"); } - vin_tokens = AssetsGetCCInputs(cpTokens, NULL, tx); + vin_tokens = AssetsGetCCInputs(eval, cpTokens, NULL, tx); int32_t myNormalVout = 1; int32_t myTokenVout = 2+r; int32_t tokenRemainderVout; @@ -417,7 +417,6 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // for EVAL_ASSETSV2 check the creation tx char origTokenAddr[KOMODO_ADDRESS_BUFSIZE]; CPubKey origpk = pubkey2pk(vorigpubkey); - ccvouts = 2; if (numvouts < 3) return eval->Invalid("too few vouts"); @@ -425,7 +424,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("invalid vout0 global two eval address for sell"); else if( A::ConstrainVout(tx.vout[1], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr return eval->Invalid("invalid vout1 marker for originator pubkey"); - else if (TotalPubkeyNormalInputs(tx, origpk) == 0) // check tx is signed by originator pubkey + else if (TotalPubkeyNormalInputs(eval, tx, origpk) == 0) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for ask"); else if (unit_price <= 0) return eval->Invalid("invalid unit price"); @@ -455,7 +454,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return false; // eval already set else if (A::ConstrainVout(tx.vout[0], CCVOUT, origTokensCCaddr, vin_tokens, T::EvalCode()) == false) // tokens returning to originator cc addr return eval->Invalid("invalid vout0 for cancelask"); - else if (TotalPubkeyNormalInputs(tx, pubkey2pk(vin_origpubkey)) == 0) // check tx is signed by originator pubkey + else if (TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vin_origpubkey)) == 0) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for cancelask"); ccvins = 2; // order and marker ccvouts = 1; diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index cbcdd992e18..dbf05ae232a 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -261,3 +261,8 @@ uint256 GetMerkleRoot(const std::vector& vLeaves) std::vector vMerkleTree; return BuildMerkleTree(&fMutated, vLeaves, vMerkleTree); } + +bool GetTxUnconfirmedOpt(Eval *eval, const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) +{ + return eval ? eval->GetTxUnconfirmed(hash, txOut, hashBlock) : myGetTransaction(hash, txOut, hashBlock); +} \ No newline at end of file diff --git a/src/cc/eval.h b/src/cc/eval.h index c36a2e77d6a..342eb442718 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -295,5 +295,8 @@ uint256 GetMerkleRoot(const std::vector& vLeaves); struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode); bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector paramsNull, const CTransaction &tx, unsigned int nIn, std::shared_ptr evalcodeChecker); +// switches between get tx inside validation or ouside +bool GetTxUnconfirmedOpt(Eval *eval, const uint256 &hash, CTransaction &txOut, uint256 &hashBlock); + #endif /* CC_EVAL_H */ diff --git a/src/cc/gamescc.cpp b/src/cc/gamescc.cpp index facedd99659..b9dd3fa4792 100644 --- a/src/cc/gamescc.cpp +++ b/src/cc/gamescc.cpp @@ -303,7 +303,7 @@ uint8_t games_finishopretdecode(uint256 &gametxid, uint256 &tokenid, int32_t &re else if ( script[1] != 'H' && script[1] != 'Q' && (f= DecodeTokenOpRetV1(scriptPubKey, tokenid, voutPubkeys, opretsDummy)) != 0 ) { //fprintf(stderr,"decode opret %c tokenid.%s\n",script[1],tokenid.GetHex().c_str()); - GetTokenData(reftokenid, tokenData, vopretNonfungible); //load nonfungible data from the 'tokenbase' tx + GetTokenData(NULL, reftokenid, tokenData, vopretNonfungible); //load nonfungible data from the 'tokenbase' tx vopret = vopretNonfungible; } if ( vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> gametxid; ss >> symbol; ss >> pname; ss >> regslot; ss >> pk; ss >> playerdata) != 0 && e == EVAL_GAMES && (f == 'H' || f == 'Q') ) diff --git a/src/cc/heir.cpp b/src/cc/heir.cpp index 33cd7f9d719..406f9f424c3 100644 --- a/src/cc/heir.cpp +++ b/src/cc/heir.cpp @@ -451,7 +451,8 @@ uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &toke bool isNonOwner = false; // we ignore 'donations' tx (with non-owner inputs) for calculating if heir is allowed to spend: - if (TotalPubkeyNormalInputs(regtx, ownerPubkey) > 0 || TotalPubkeyCCInputs(regtx, ownerPubkey) > 0) + // TODO: pass Eval instead of NULL + if (TotalPubkeyNormalInputs(NULL, regtx, ownerPubkey) > 0 || TotalPubkeyCCInputs(NULL, regtx, ownerPubkey) > 0) { // CheckVinPubkey(regtx.vin, ownerPubkey, isOwner, isNonOwner); // if (isOwner && !isNonOwner) { @@ -520,7 +521,7 @@ template int64_t Add1of2AddressInputs(struct CCcontract_info* cp, if ((txid == fundingtxid || fundingTxidInOpret == fundingtxid) && funcId != 0 && isMyFuncId(funcId) && - (typeid(Helper) != typeid(TokenHelper) || IsTokensvout(true, true, cp, nullptr, heirtx, voutIndex, tokenid) > 0) && // token validation logic + (typeid(Helper) != typeid(TokenHelper) || IsTokensvout(cp, nullptr, heirtx, voutIndex, tokenid) > 0) && // token validation logic //(voutValue = IsHeirFundingVout(cp, heirtx, voutIndex, ownerPubkey, heirPubkey)) > 0 && // heir contract vout validation logic - not used since we moved to 2-eval vouts !myIsutxo_spentinmempool(ignoretxid,ignorevin,txid, voutIndex)) { @@ -569,7 +570,7 @@ template int64_t LifetimeHeirContractFunds(struct CCcontract_info if (funcId != 0 && (txid == fundingtxid || fundingTxidInOpret == fundingtxid) && isMyFuncId(funcId) && !isSpendingTx(funcId) && - (typeid(Helper) != typeid(TokenHelper) || IsTokensvout(true, true, cp, nullptr, heirtx, ivout, tokenid) > 0) && + (typeid(Helper) != typeid(TokenHelper) || IsTokensvout(cp, nullptr, heirtx, ivout, tokenid) > 0) && !myIsutxo_spentinmempool(ignoretxid,ignorevin,txid, ivout)) // exclude tx in mempool { total += it->second; // dont do this: tx.vout[ivout].nValue; // in vin[0] always is the pay to 1of2 addr (funding or change) @@ -647,7 +648,7 @@ template UniValue _HeirFund(int64_t txfee, int64_t amount, std // for initial funding do not allow to sign by non-owner key: // if (hasNotMypubkey) { - if (TotalPubkeyNormalInputs(mtx, myPubkey) < amount && TotalPubkeyCCInputs(mtx, myPubkey) < amount) + if (TotalPubkeyNormalInputs(NULL, mtx, myPubkey) < amount && TotalPubkeyCCInputs(NULL, mtx, myPubkey) < amount) { result.push_back(Pair("result", "error")); result.push_back(Pair("error", "using non-owner inputs not allowed")); @@ -773,7 +774,8 @@ template UniValue _HeirAdd(uint256 fundingtxid, int64_t txfee, in // warn the user he's making a donation if this is all non-owner keys: // if (hasNotMypubkey) { - if (TotalPubkeyNormalInputs(mtx, myPubkey) < amount && TotalPubkeyCCInputs(mtx, myPubkey) < amount) { + // TODO: change to Eval instead of NULL + if (TotalPubkeyNormalInputs(NULL, mtx, myPubkey) < amount && TotalPubkeyCCInputs(NULL, mtx, myPubkey) < amount) { result.push_back(Pair("result", "warning")); result.push_back(Pair("warning", "you are about to make a donation to heir fund")); } diff --git a/src/cc/old/CCassetsCore_v0.cpp b/src/cc/old/CCassetsCore_v0.cpp index 4e482ce0af0..d8d27f34d96 100644 --- a/src/cc/old/CCassetsCore_v0.cpp +++ b/src/cc/old/CCassetsCore_v0.cpp @@ -625,7 +625,7 @@ bool AssetCalcAmounts(struct CCcontract_info *cpAssets, int64_t &inputs, int64_t std::vector vinPubkeysEmpty; // TODO: maybe we do not need call to IsTokensVout here, cause we've already selected token vins - assetoshis = IsTokensvout(false, false, cpTokens, NULL, vinTx, tx.vin[i].prevout.n, assetid); + assetoshis = IsTokensvout(false, false, cpTokens, eval, vinTx, tx.vin[i].prevout.n, assetid); if (assetoshis != 0) { //std::cerr << "AssetCalcAmounts() vin i=" << i << " assetoshis=" << assetoshis << std::endl; diff --git a/src/cc/old/CCtokens_v0.cpp b/src/cc/old/CCtokens_v0.cpp index 831be452c1d..40eca3d715d 100644 --- a/src/cc/old/CCtokens_v0.cpp +++ b/src/cc/old/CCtokens_v0.cpp @@ -472,7 +472,7 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true && !IsTokenMarkerVout(vout)) // should not be marker here ccOutputs += vout.nValue; - int64_t normalInputs = TotalPubkeyNormalInputs(tx, origPubkey); // check if normal inputs are really signed by originator pubkey (someone not cheating with originator pubkey) + int64_t normalInputs = TotalPubkeyNormalInputs(eval, tx, origPubkey); // check if normal inputs are really signed by originator pubkey (someone not cheating with originator pubkey) LOGSTREAM("cctokens", CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() normalInputs=" << normalInputs << " ccOutputs=" << ccOutputs << " for tokenbase=" << reftokenid.GetHex() << std::endl); if (normalInputs >= ccOutputs) { @@ -827,7 +827,7 @@ std::string CreateToken(int64_t txfee, int64_t tokensupply, std::string name, st if (AddNormalinputs2(mtx, tokensupply + 2 * txfee, 64) > 0) // add normal inputs only from mypk { - int64_t mypkInputs = TotalPubkeyNormalInputs(mtx, mypk); + int64_t mypkInputs = TotalPubkeyNormalInputs(NULL, mtx, mypk); if (mypkInputs < tokensupply) { // check that tokens amount are really issued with mypk (because in the wallet there maybe other privkeys) CCerror = "some inputs signed not with -pubkey=pk"; return std::string(""); diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 0fcc2e512c3..61c7d785573 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -274,7 +274,7 @@ static bool ValidateBetTx(struct CCcontract_info *cp, Eval *eval, const CTransac for (auto vout : bettx.vout) if (vout.scriptPubKey.IsPayToCryptoCondition()) ccOutputs += vout.nValue; - CAmount normalInputs = TotalPubkeyNormalInputs(bettx, pk); + CAmount normalInputs = TotalPubkeyNormalInputs(eval, bettx, pk); if (normalInputs < ccOutputs) { return eval->Invalid("bettx normal inputs not signed with pubkey in opret"); } diff --git a/src/cc/rogue_rpc.cpp b/src/cc/rogue_rpc.cpp index 9d101857e0b..fbd5ba8add8 100644 --- a/src/cc/rogue_rpc.cpp +++ b/src/cc/rogue_rpc.cpp @@ -186,7 +186,7 @@ uint8_t rogue_highlanderopretdecode(uint256 &gametxid, uint256 &tokenid, int32_t else if ( script[1] != 'H' && script[1] != 'Q' && (f= DecodeTokenOpRetV1(scriptPubKey, tokenid, voutPubkeys, opretsDummy)) != 0 ) { //fprintf(stderr,"decode opret %c tokenid.%s\n",script[1],tokenid.GetHex().c_str()); - GetTokenData(tokenid, tokenData, vopretNonfungible); //load nonfungible data from the 'tokenbase' tx + GetTokenData(NULL, tokenid, tokenData, vopretNonfungible); //load nonfungible data from the 'tokenbase' tx vopret = vopretNonfungible; } if ( vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> gametxid; ss >> symbol; ss >> pname; ss >> regslot; ss >> pk; ss >> playerdata) != 0 && e == EVAL_ROGUE && (f == 'H' || f == 'Q') ) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 7dcdaed307d..ac372803169 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -489,7 +489,7 @@ UniValue tokentransfermany(const std::string& name, const UniValue& params, bool { TokenDataTuple tokenData; vuint8_t vnftData; - GetTokenData(tokenid, tokenData, vnftData); + GetTokenData(NULL, tokenid, tokenData, vnftData); CCwrapper probeCond; if (vnftData.size() > 0) probeCond.reset( V::MakeTokensCCcond1(vnftData[0], mypk) ); diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp new file mode 100644 index 00000000000..c2e72a55b2b --- /dev/null +++ b/src/test-komodo-cc/test-assets.cpp @@ -0,0 +1,640 @@ + +#include +#include + +#include "cc/CCinclude.h" + +#include "cc/CCtokens.h" +#include "cc/CCtokens_impl.h" + +#include "cc/CCassets.h" +#include "cc/CCassetstx_impl.h" + +#include "cc/CCNFTData.h" + + +#include "cc/eval.h" +#include "importcoin.h" +#include "base58.h" +#include "core_io.h" +#include "key.h" +#include "main.h" +#include "primitives/transaction.h" +#include "script/cc.h" +#include "script/interpreter.h" +#include "script/serverchecker.h" +#include "txmempool.h" + +extern Eval* EVAL_TEST; + +namespace CCAssetsTests { + +static uint8_t testNum = 0; + +uint256 getRandomHash() +{ + CSHA256 sha; + uint256 res; + uint32_t rnd = rand(); + sha.Write((uint8_t*)&rnd, sizeof(rnd)); + sha.Finalize((uint8_t*)&res); + return res; +} + + +class EvalMock : public Eval +{ +public: + int currentHeight; + std::map txs; + std::map blocks; + std::map> spends; + + bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const + { + auto r = txs.find(hash); + if (r != txs.end()) { + txOut = r->second; + if (blocks.count(hash) > 0) + hashBlock = hash; + return true; + } + return false; + } +}; + +static EvalMock eval; + +static CTransaction txnormal1, txnormal2, txnormal3, txnormal4, txnormalg, txask, txbid, txtokencreate1, txtokencreate2, txtokencreate3; +static uint256 tokenid1, tokenid2, tokenid3; + +// RJXkCF7mn2DRpUZ77XBNTKCe55M2rJbTcu +static CPubKey pk1 = CPubKey(ParseHex("035d3b0f2e98cf0fba19f80880ec7c08d770c6cf04aa5639bc57130d5ac54874db")); +static uint8_t privkey1[] = { 0x0d, 0xf0, 0x44, 0xc4, 0xbe, 0xd3, 0x3b, 0x74, 0xaf, 0x69, 0x6b, 0x05, 0x1d, 0xbf, 0x70, 0x14, 0x2f, 0xc3, 0xa7, 0x8d, 0xa3, 0x47, 0x38, 0xc0, 0x33, 0x6f, 0x50, 0x15, 0xe3, 0xd2, 0x85, 0xee }; +// RR2nTYFBPTJafxQ6en2dhUgaJcMDk4RWef +static CPubKey pk2 = CPubKey(ParseHex("034777b18effce6f7a849b72de8e6810bf7a7e050274b3782e1b5a13d0263a44dc")); +static uint8_t privkey2[] = { 0x9e, 0x69, 0x33, 0x27, 0x1c, 0x1c, 0x60, 0x5e, 0x57, 0xaf, 0xb6, 0xb7, 0xfd, 0xeb, 0xac, 0xa3, 0x11, 0x41, 0xd1, 0x3a, 0xe2, 0x36, 0x47, 0xfc, 0xe4, 0xe0, 0x79, 0x44, 0xae, 0xee, 0x43, 0xde }; +// RTbiYv9u1mrp7TmJspxduJCe3oarCqv9K4 +static CPubKey pk3 = CPubKey(ParseHex("025f97b6c42409e8e69eb2fdab281219aafe15169deec801ee621c63cc1ba0bb8c")); +static uint8_t privkey3[] = { 0x0d, 0xf8, 0xcd, 0xd4, 0x42, 0xbd, 0x77, 0xd2, 0xdd, 0x44, 0x89, 0x4b, 0x21, 0x78, 0xbf, 0x8d, 0x8a, 0xc3, 0x30, 0x0c, 0x5a, 0x70, 0x3d, 0xbe, 0xc9, 0x21, 0x75, 0x33, 0x23, 0x77, 0xd3, 0xde }; + +//char Tokensv2CChexstr[] = { "032fd27f72591b02f13a7f9701246eb0296b2be7cfdad32c520e594844ec3d4801" }; +//uint8_t Tokensv2CCpriv[] = { 0xb5, 0xba, 0x92, 0x7f, 0x53, 0x45, 0x4f, 0xf8, 0xa4, 0xad, 0x0d, 0x38, 0x30, 0x4f, 0xd0, 0x97, 0xd1, 0xb7, 0x94, 0x1b, 0x1f, 0x52, 0xbd, 0xae, 0xa2, 0xe7, 0x49, 0x06, 0x2e, 0xd2, 0x2d, 0xa5 }; + +static uint8_t privkeyGlobal[] = { }; + +bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vini, int64_t utxovalue, const CScript scriptPubKey) +{ + CTransaction txNewConst(mtx); + SignatureData sigdata; + auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + if (ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, vini, utxovalue, SIGHASH_ALL), scriptPubKey, sigdata, consensusBranchId) != 0) { + UpdateTransaction(mtx, vini, sigdata); + return (true); + } else + std::cerr << __func__ << "signing error for vini=" << vini << " amount=" << utxovalue << std::endl; + return (false); +} + +class TestAssetsCC : public ::testing::Test { +public: + //uint32_t GetAssetchainsCC() const { return testCcid; } + //std::string GetAssetchainsSymbol() const { return testSymbol; } + +protected: + static void SetUpTestCase() { + // setup eval for tests + CreateTransactions(&eval); + } + virtual void SetUp() { + // enable print + fDebug = true; + fPrintToConsole = true; + mapMultiArgs["-debug"] = { "cctokens", "ccassets" }; + } + + static void CreateTransactions(EvalMock *eval) + { + std::cerr << __func__ << " enterred" << std::endl; + txnormal1 = MakeNormalTx(pk1, 1000); + txnormal2 = MakeNormalTx(pk1, 1000); + txnormal3 = MakeNormalTx(pk2, 1000); + txnormal4 = MakeNormalTx(pk2, 1000); + txnormalg = MakeNormalTxG(); + + eval->txs[txnormal1.GetHash()] = txnormal1; + eval->txs[txnormal2.GetHash()] = txnormal2; + eval->txs[txnormal3.GetHash()] = txnormal3; + eval->txs[txnormal4.GetHash()] = txnormal4; + eval->txs[txnormalg.GetHash()] = txnormalg; + + txtokencreate1 = MakeTokenV2CreateTx(pk1); + eval->txs[txtokencreate1.GetHash()] = txtokencreate1; + tokenid1 = txtokencreate1.GetHash(); + + txtokencreate2 = MakeTokenV2CreateTx(pk2); + eval->txs[txtokencreate2.GetHash()] = txtokencreate2; + tokenid2 = txtokencreate2.GetHash(); + + txtokencreate3 = MakeTokenV2CreateTx(pk2); + eval->txs[txtokencreate3.GetHash()] = txtokencreate3; + tokenid3 = txtokencreate3.GetHash(); + + txask = MakeTokenV2AskTx(pk1); + eval->txs[txask.GetHash()] = txask; + + txbid = MakeTokenV2BidTx(pk2); + eval->txs[txbid.GetHash()] = txbid; + } + + static CTransaction MakeNormalTx(CPubKey pk, CAmount val) + { + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + mtx.vin.push_back(CTxIn(getRandomHash(), 0)); + mtx.vout.push_back(CTxOut(val, GetScriptForDestination(pk))); + return CTransaction(mtx); + } + + static CTransaction MakeNormalTxG() + { + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + uint8_t privkeyg[32]; + CPubKey pkg = GetUnspendable(cpTokens, privkeyg); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + mtx.vin.push_back(CTxIn(getRandomHash(), 0)); + mtx.vout.push_back(CTxOut(100000, GetScriptForDestination(pkg))); + return CTransaction(mtx); + } + + static CTransaction MakeTokenV2CreateTx(CPubKey pk) + { + struct CCcontract_info *cp, C; + cp = CCinit(&C, TokensV2::EvalCode()); + std::string name = "Test"; + std::string description = "desc"; + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + mtx.vin.push_back(CTxIn(getRandomHash(), 0)); + mtx.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk)); + mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk.begin(), pk.end()), name, description, { }))); + return CTransaction(mtx); + } + + + static CTransaction MakeTokenV2AskTx(CPubKey pk) + { + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpAssets, C; + + CAmount askamount = 1000; + CAmount numtokens = 2; + CAmount txfee = 10000; + + cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! + + CAmount unit_price = askamount / numtokens; + + mtx.vin.push_back(CTxIn(txnormal1.GetHash(), 0)); + + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), askamount, unspendableAssetsPubkey)); // tokens to global + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk)); // marker for my orders + + mtx.vout.push_back(CTxOut(0, + TokensV2::EncodeTokenOpRet(tokenid1, {}, + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pk.begin(), pk.end())) }))); + return CTransaction(mtx); + } + + static CTransaction MakeTokenV2BidTx(CPubKey pk) + { + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpAssets, C; + + CAmount bidamount = 1000; + CAmount numtokens = 2; + CAmount txfee = 10000; + + cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! + + CAmount unit_price = bidamount / numtokens; + + mtx.vin.push_back(CTxIn(txnormal3.GetHash(), 0)); + + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); + + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, unspendableAssetsPubkey)); + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk)); // marker for my orders + + mtx.vout.push_back(CTxOut(0, + TokensV2::EncodeTokenOpRet(tokenid2, {}, + { AssetsV2::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(pk.begin(), pk.end())) }))); + return CTransaction(mtx); + } + + bool TestRunCCEval(const CMutableTransaction &mtx) + { + CTransaction tx(mtx); + PrecomputedTransactionData txdata(tx); + ServerTransactionSignatureChecker checker(&tx, 0, 0, false, NULL, txdata); + CValidationState verifystate; + VerifyEval verifyEval = [] (CC *cond, void *checker) { + //fprintf(stderr,"checker.%p\n",(TransactionSignatureChecker*)checker); + return ((TransactionSignatureChecker*)checker)->CheckEvalCondition(cond); + }; + + // set some vars used in validation: + KOMODO_CONNECTING = 1; + ASSETCHAINS_CC = 2; + KOMODO_CCACTIVATE = 1; + eval.state = CValidationState(); // clear validation state + EVAL_TEST = &eval; + + for(const auto &vin : tx.vin) { + if (IsCCInput(vin.scriptSig)) { + CC *cond = GetCryptoCondition(vin.scriptSig); + if (cond == NULL) { + std::cerr << __func__ << " GetCryptoCondition could not decode vin.scriptSig" << std::endl; + return false; + } + + int r = cc_verifyEval(cond, verifyEval, &checker); + if (r == 0) { + std::cerr << __func__ << " cc_verify error D" << std::endl; + return false; + } + std::cerr << __func__ << " cc_verify okay for vin.hash=" << vin.prevout.hash.GetHex() << std::endl; + break; + } + } + for(const auto &vout : tx.vout) { + if (vout.scriptPubKey.IsPayToCCV2()) { + + ScriptError error; + + bool bCheck = checker.CheckCryptoCondition(vout.scriptPubKey.GetCCV2SPK(), &error); + if (!bCheck) { + std::cerr << __func__ << " CheckCryptoCondition error=" << ScriptErrorString(error) << std::endl; + return false; + } + std::cerr << __func__ << " cc_verify okay for vout.nValue=" << vout.nValue << std::endl; + } + } + return true; + } +}; + +TEST_F(TestAssetsCC, tokenv2ask) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpAssets, C; + struct CCcontract_info *cpTokens, tokensC; + + CAmount askamount = 1000; + CAmount numtokens = 2; + CAmount txfee = 10000; + + //CPubKey mypk(ParseHex("035d3b0f2e98cf0fba19f80880ec7c08d770c6cf04aa5639bc57130d5ac54874db")); + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + uint8_t evalcodeNFT = cpTokens->evalcodeNFT ? cpTokens->evalcodeNFT : 0; + CAmount unit_price = askamount / numtokens; + + mtx.vin.push_back(CTxIn(txnormal2.GetHash(), 0)); + mtx.vin.push_back(CTxIn(txtokencreate1.GetHash(), 1)); + + CAmount inputs = txtokencreate1.vout[1].nValue; + + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeNFT, numtokens, unspendableAssetsPubkey)); + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk1)); + CAmount CCchange = inputs - numtokens; + if (CCchange != 0LL) { + // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), CCchange, pk1)); + } + + mtx.vout.push_back(CTxOut(0, + TokensV2::EncodeTokenOpRet(tokenid1, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pk1.begin(), pk1.end())) }))); + + // sign vins: + // sign normal vin: + CBasicKeyStore tempKeystore; + CKey key; + key.Set(privkey1, privkey1+sizeof(privkey1), true); + tempKeystore.AddKey(key); + int32_t ivin = 0; + ASSERT_TRUE( TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey) ); + + ++ivin; + // sign cc vin: + PrecomputedTransactionData txdata(mtx); + CCwrapper cond(TokensV2::MakeTokensCCcond1(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), pk1)); + uint256 sighash = SignatureHash(CCPubKey(cond.get()), mtx, ivin, SIGHASH_ALL, 0, 0, &txdata); + ASSERT_TRUE( cc_signTreeSecp256k1Msg32(cond.get(), privkey1, sighash.begin()) > 0 ); + mtx.vin[ivin].scriptSig = CCSig(cond.get()); + + EXPECT_TRUE(TestRunCCEval(mtx)); +} + +TEST_F(TestAssetsCC, tokenv2bid) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpAssets, C; + + CAmount bidamount = 1000; + CAmount numtokens = 2; + CAmount txfee = 10000; + + cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! + + CAmount unit_price = bidamount / numtokens; + + mtx.vin.push_back(CTxIn(txnormal2.GetHash(), 0)); + + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, unspendableAssetsPubkey)); + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk1)); // marker for my orders + + mtx.vout.push_back(CTxOut(0, + TokensV2::EncodeTokenOpRet(tokenid1, {}, + { AssetsV2::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(pk1.begin(), pk1.end())) }))); + + // sign vins: + // normal vin: + CBasicKeyStore tempKeystore; + CKey key; + key.Set(privkey1, privkey1+sizeof(privkey1), true); + tempKeystore.AddKey(key); + int32_t ivin = 0; + ASSERT_TRUE( TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey) ); + + EXPECT_TRUE(TestRunCCEval(mtx)); +} + + +TEST_F(TestAssetsCC, tokenv2fillask) +{ + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpAssets, C; + struct CCcontract_info *cpTokens, tokensC; + + CAmount unit_price = 0;; + CAmount fillunits = 2; + CAmount txfee = 10000; + const int32_t askvout = ASSETS_GLOBALADDR_VOUT; + uint256 assetidOpret; + CAmount paid_unit_price = -1; // not set + CAmount orig_assetoshis = txask.vout[askvout].nValue; + + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + TokenDataTuple tokenData; + vuint8_t vopretNonfungible; + uint8_t evalcodeNFT = 0; + uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + ASSERT_TRUE( GetTokenData(&eval, tokenid1, tokenData, vopretNonfungible) ); + if (vopretNonfungible.size() > 0) { + evalcodeNFT = vopretNonfungible.begin()[0]; + GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); + if (royaltyFract > NFTROYALTY_DIVISOR-1) + royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit + } + vuint8_t ownerpubkey = std::get<0>(tokenData); + + vuint8_t origpubkey; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txask); // get orig pk, orig value + + if (paid_unit_price <= 0LL) + paid_unit_price = unit_price; + + CAmount paid_nValue = paid_unit_price * fillunits; + + CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / NFTROYALTY_DIVISOR * royaltyFract : 0; + + mtx.vin.push_back(CTxIn(txnormal2.GetHash(), 0)); + mtx.vin.push_back(CTxIn(txask.GetHash(), askvout, CScript())); // spend order tx + + + // vout.0 tokens remainder to unspendable cc addr: + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeNFT, orig_assetoshis - fillunits, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr + + //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), fillunits, pk2)); + mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr + if (royaltyFract > 0) // note it makes the vout even if roaltyValue is 0 + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner + + if (orig_assetoshis - fillunits > 0) // we dont need the marker if order is filled + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) + + + mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { pk2 }, + { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))); + + // sign normal vin: + CBasicKeyStore tempKeystore; + CKey key; + key.Set(privkey1, privkey1+sizeof(privkey1), true); + tempKeystore.AddKey(key); + int32_t ivin = 0; + ASSERT_TRUE( TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey) ); + + ++ivin; + // sign cc vin: + PrecomputedTransactionData txdata(mtx); + uint8_t privkeyAssets[32]; + CCwrapper cond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), GetUnspendable(cpAssets, privkeyAssets))); + uint256 sighash = SignatureHash(CCPubKey(cond.get()), mtx, ivin, SIGHASH_ALL, 0, 0, &txdata); + ASSERT_TRUE( cc_signTreeSecp256k1Msg32(cond.get(), privkeyAssets, sighash.begin()) > 0 ); + mtx.vin[ivin].scriptSig = CCSig(cond.get()); + + EXPECT_TRUE(TestRunCCEval(mtx)); +} + + +TEST_F(TestAssetsCC, tokenv2fillbid) +{ + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpAssets, C; + struct CCcontract_info *cpTokens, tokensC; + + const int32_t bidvout = ASSETS_GLOBALADDR_VOUT; + CAmount paid_amount; + CAmount bid_amount; + CAmount orig_units; + CAmount unit_price = 0; + CAmount fill_units = 2; + CAmount txfee = 10000; + uint256 assetidOpret; + CAmount paid_unit_price = 0; // not set + + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + TokenDataTuple tokenData; + vuint8_t vopretNonfungible; + uint8_t evalcodeNFT = 0; + uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + ASSERT_TRUE( GetTokenData(&eval, tokenid1, tokenData, vopretNonfungible) ); + if (vopretNonfungible.size() > 0) { + evalcodeNFT = vopretNonfungible.begin()[0]; + GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); + if (royaltyFract > NFTROYALTY_DIVISOR-1) + royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit + } + vuint8_t ownerpubkey = std::get<0>(tokenData); + + vuint8_t origpubkey; + bid_amount = txbid.vout[bidvout].nValue; + ASSERT_TRUE(GetOrderParams(origpubkey, unit_price, assetidOpret, txbid) != 0); // get orig pk, orig value + ASSERT_TRUE(unit_price != 0); + + orig_units = bid_amount / unit_price; + + if (paid_unit_price <= 0LL) + paid_unit_price = unit_price; + + + mtx.vin.push_back(CTxIn(txnormal2.GetHash(), 0)); + mtx.vin.push_back(CTxIn(txtokencreate2.GetHash(), 1, CScript())); // spend token tx + mtx.vin.push_back(CTxIn(txbid.GetHash(), bidvout, CScript())); // spend order tx + + CAmount inputs = txnormal2.vout[0].nValue; + CAmount tokenInputs = txtokencreate2.vout[1].nValue; + + + ASSERT_TRUE(SetBidFillamounts(unit_price, paid_amount, bid_amount, fill_units, orig_units, paid_unit_price)); + + CAmount royaltyValue = royaltyFract > 0 ? paid_amount / NFTROYALTY_DIVISOR * royaltyFract : 0; + CAmount tokensChange = tokenInputs - fill_units; + + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + + if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { // bidder has coins for more tokens or only dust is sent back to global address + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bid_amount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder or the dust is sent back to cc global addr + if (bid_amount - paid_amount <= ASSETS_NORMAL_DUST) + std::cerr << __func__ << " dust detected (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; + } + else + mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator + mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(pk2)) << OP_CHECKSIG)); // vout1 coins to mypk normal + if (royaltyFract > 0) // note it makes vout even if roaltyValue is 0 + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator + if (orig_units - fill_units > 0) // order is not finished yet + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey + + if (tokensChange != 0LL) + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), tokensChange, pk2)); // change in single-eval tokens + + mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pubkey2pk(origpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); + + // sign normal vin: + CBasicKeyStore tempKeystore; + CKey key; + key.Set(privkey1, privkey1+sizeof(privkey1), true); + tempKeystore.AddKey(key); + int32_t ivin = 0; + ASSERT_TRUE( TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey) ); + + ++ivin; + // sign cc token vin: + PrecomputedTransactionData txdata(mtx); + CCwrapper cond1(TokensV2::MakeTokensCCcond1(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), pk2)); + uint256 sighash1 = SignatureHash(CCPubKey(cond1.get()), mtx, ivin, SIGHASH_ALL, 0, 0, &txdata); + ASSERT_TRUE( cc_signTreeSecp256k1Msg32(cond1.get(), privkey2, sighash1.begin()) > 0 ); + mtx.vin[ivin].scriptSig = CCSig(cond1.get()); + + ++ivin; + // sign cc assets vin: + uint8_t privkeyAssets[32]; + CCwrapper cond2(MakeCCcond1(AssetsV2::EvalCode(), GetUnspendable(cpAssets, privkeyAssets))); + uint256 sighash2 = SignatureHash(CCPubKey(cond2.get()), mtx, ivin, SIGHASH_ALL, 0, 0, &txdata); + ASSERT_TRUE( cc_signTreeSecp256k1Msg32(cond2.get(), privkeyAssets, sighash2.begin()) > 0 ); + mtx.vin[ivin].scriptSig = CCSig(cond2.get()); + + EXPECT_TRUE(TestRunCCEval(mtx)); + + // check bad tokenid bid + CMutableTransaction mtx2(mtx); + ivin = 1; + mtx2.vin[ivin] = CTxIn(txtokencreate3.GetHash(), 1, CScript()); // spend bad tokenid3 + mtx2.vout.pop_back(); + mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(origpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); + // sign cc token vin: + PrecomputedTransactionData txdata2(mtx2); + CCwrapper cond3(TokensV2::MakeTokensCCcond1(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), pk2)); + uint256 sighash3 = SignatureHash(CCPubKey(cond3.get()), mtx2, ivin, SIGHASH_ALL, 0, 0, &txdata2); + ASSERT_TRUE( cc_signTreeSecp256k1Msg32(cond3.get(), privkey2, sighash3.begin()) > 0 ); + mtx2.vin[ivin].scriptSig = CCSig(cond3.get()); + + EXPECT_FALSE(TestRunCCEval(mtx2)); + + +} + +TEST_F(TestAssetsCC, tokenv2create) +{ + struct CCcontract_info *cp, C; + cp = CCinit(&C, TokensV2::EvalCode()); + std::string name = "T1"; + std::string description = "desc"; + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + mtx.vin.push_back(CTxIn(txnormal1.GetHash(), 0)); + mtx.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); + mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + + CMutableTransaction mtx3(mtx); + + // sign vins: + // normal vin: + CBasicKeyStore tempKeystore; + CKey key; + key.Set(privkey1, privkey1+sizeof(privkey1), true); + tempKeystore.AddKey(key); + int32_t ivin = 0; + ASSERT_TRUE(TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey)); + EXPECT_TRUE(TestRunCCEval(mtx)); + + // token sent to another pk + CMutableTransaction mtx1(mtx); + mtx1.vout[1] = TokensV2::MakeTokensCC1vout(0, 10, pk2); + EXPECT_TRUE(TestRunCCEval(mtx1)); // allow sent created tokens to any pk! + + // invalid pk in opreturn: + CMutableTransaction mtx2(mtx); + mtx2.vout[2] = CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { })); // should send to self (?) + EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail + + // create with global pk: + mtx3.vin[0] = CTxIn(txnormalg.GetHash(), 0); + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + uint8_t privkeyg[32]; + CPubKey pkg = GetUnspendable(cpTokens, privkeyg); + CKey keyg; + keyg.Set(privkeyg, privkeyg+sizeof(privkeyg), true); + CBasicKeyStore tempKeystoreg; + tempKeystoreg.AddKey(keyg); + // change opreturn + mtx3.vout[2] = CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pkg.begin(), pkg.end()), name, description, { })); // should send to self (?) + ivin = 0; + ASSERT_TRUE(TestSignTx(tempKeystoreg, mtx3, ivin, txnormalg.vout[0].nValue, txnormalg.vout[0].scriptPubKey)); + EXPECT_FALSE(TestRunCCEval(mtx3)); // must fail + +} + +} /* namespace CCAssetsTests */ diff --git a/src/test-komodo-cc/test-main.cpp b/src/test-komodo-cc/test-main.cpp new file mode 100644 index 00000000000..cfbdf9b5783 --- /dev/null +++ b/src/test-komodo-cc/test-main.cpp @@ -0,0 +1,21 @@ +#include "key.h" +#include "base58.h" +#include "chainparams.h" +#include "gtest/gtest.h" +#include "crypto/common.h" + + +int main(int argc, char **argv) { + assert(init_and_check_sodium() != -1); + ECC_Start(); + ECCVerifyHandle handle; // Inits secp256k1 verify context + SelectParams(CBaseChainParams::REGTEST); + + CBitcoinSecret vchSecret; + // this returns false due to network prefix mismatch but works anyway + //vchSecret.SetString(notarySecret); + //notaryKey = vchSecret.GetKey(); + + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From 7e5f6985aeb751296d01a8cf0598cbcca510ed72 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 26 Jun 2021 23:18:27 +0500 Subject: [PATCH 018/348] added TestFinalizeTx and TestAddNormalInputs --- src/test-komodo-cc/test-assets.cpp | 605 ++++++++++++++++++++++------- 1 file changed, 464 insertions(+), 141 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index c2e72a55b2b..9a1495427c5 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -48,7 +48,7 @@ class EvalMock : public Eval int currentHeight; std::map txs; std::map blocks; - std::map> spends; + //sstd::map> spends; bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const { @@ -65,8 +65,8 @@ class EvalMock : public Eval static EvalMock eval; -static CTransaction txnormal1, txnormal2, txnormal3, txnormal4, txnormalg, txask, txbid, txtokencreate1, txtokencreate2, txtokencreate3; -static uint256 tokenid1, tokenid2, tokenid3; +static CTransaction txnormal1, txnormal2, txnormal3, txnormal4, txnormalg, txask, txbid, txtokencreate1, txtokencreate2, txtokencreate3, txtokencreateUnused; +static uint256 tokenid1, tokenid2, tokenid3, tokenidUnused; // RJXkCF7mn2DRpUZ77XBNTKCe55M2rJbTcu static CPubKey pk1 = CPubKey(ParseHex("035d3b0f2e98cf0fba19f80880ec7c08d770c6cf04aa5639bc57130d5ac54874db")); @@ -78,10 +78,37 @@ static uint8_t privkey2[] = { 0x9e, 0x69, 0x33, 0x27, 0x1c, 0x1c, 0x60, 0x5e, 0x static CPubKey pk3 = CPubKey(ParseHex("025f97b6c42409e8e69eb2fdab281219aafe15169deec801ee621c63cc1ba0bb8c")); static uint8_t privkey3[] = { 0x0d, 0xf8, 0xcd, 0xd4, 0x42, 0xbd, 0x77, 0xd2, 0xdd, 0x44, 0x89, 0x4b, 0x21, 0x78, 0xbf, 0x8d, 0x8a, 0xc3, 0x30, 0x0c, 0x5a, 0x70, 0x3d, 0xbe, 0xc9, 0x21, 0x75, 0x33, 0x23, 0x77, 0xd3, 0xde }; +std::map testKeys = { + { pk1, privkey1 }, + { pk2, privkey2 }, + { pk3, privkey3 }, +}; + //char Tokensv2CChexstr[] = { "032fd27f72591b02f13a7f9701246eb0296b2be7cfdad32c520e594844ec3d4801" }; //uint8_t Tokensv2CCpriv[] = { 0xb5, 0xba, 0x92, 0x7f, 0x53, 0x45, 0x4f, 0xf8, 0xa4, 0xad, 0x0d, 0x38, 0x30, 0x4f, 0xd0, 0x97, 0xd1, 0xb7, 0x94, 0x1b, 0x1f, 0x52, 0xbd, 0xae, 0xa2, 0xe7, 0x49, 0x06, 0x2e, 0xd2, 0x2d, 0xa5 }; -static uint8_t privkeyGlobal[] = { }; +static CPubKey pkunused = CPubKey(ParseHex("034b082c5819b5bf8798a387630ad236a8e800dbce4c4e24a46f36dfddab3cbff5")); + +CAmount TestAddNormalInputs(CMutableTransaction &mtx, CPubKey mypk, CAmount amount) +{ + CAmount totalInputs = 0LL; + char mypkaddr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(mypkaddr, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG); + for (auto const &t : eval.txs) { + for (int32_t v = 0; v < t.second.vout.size(); v ++) { + char utxoaddr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(utxoaddr, t.second.vout[v].scriptPubKey); + //std::cerr << __func__ << " utxoaddr=" << utxoaddr << " mypkaddr=" << mypkaddr << " tx=" << t.second.GetHash().GetHex() << " v=" << v << std::endl; + if (strcmp(utxoaddr, mypkaddr) == 0) { + mtx.vin.push_back(CTxIn(t.second.GetHash(), v)); + totalInputs += t.second.vout[v].nValue; + if (totalInputs >= amount) + return totalInputs; + } + } + } + return 0LL; +} bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vini, int64_t utxovalue, const CScript scriptPubKey) { @@ -90,12 +117,162 @@ bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vin auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); if (ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, vini, utxovalue, SIGHASH_ALL), scriptPubKey, sigdata, consensusBranchId) != 0) { UpdateTransaction(mtx, vini, sigdata); - return (true); - } else - std::cerr << __func__ << "signing error for vini=" << vini << " amount=" << utxovalue << std::endl; - return (false); + return true; + } else { + std::cerr << __func__ << " signing error for vini=" << vini << " amount=" << utxovalue << std::endl; + return false; + } } +bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_t *myprivkey, CAmount txfee, CScript opret) +{ + auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + CAmount totaloutputs = 0LL; + for (int i = 0; i < mtx.vout.size(); i ++) + totaloutputs += mtx.vout[i].nValue; + + if (!cp || !cp->evalcode) { + std::cerr << __func__ << " invalid cp param" << std::endl; + return false; + } + + CAmount totalinputs = 0LL; + for (int i = 0; i < mtx.vin.size(); i ++) + { + CTransaction vintx; + uint256 hashBlock; + if (i == 0 && mtx.vin[i].prevout.n == 10e8) + continue; // skip pegs vin + + if (GetTxUnconfirmedOpt(&eval, mtx.vin[i].prevout.hash, vintx, hashBlock)) { + totalinputs += vintx.vout[mtx.vin[i].prevout.n].nValue; + } else { + fprintf(stderr, "%s couldnt find vintx %s\n", __func__, mtx.vin[i].prevout.hash.ToString().c_str()); + return false; + } + } + + if (!myprivkey) { + std::cerr << __func__ << "myprivkey not set" << std::endl; + return false; + } + + CKey mykey; + mykey.SetKey32(myprivkey); + CPubKey mypk = mykey.GetPubKey(); + if (totalinputs >= totaloutputs + txfee) { + CAmount change = totalinputs - (totaloutputs + txfee); + if (change > 0) + mtx.vout.push_back(CTxOut(change, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + } + + if (opret.size() > 0) + mtx.vout.push_back(CTxOut(0, opret)); + + CPubKey globalpk; + char myccaddr[KOMODO_ADDRESS_BUFSIZE], + globaladdr[KOMODO_ADDRESS_BUFSIZE], + mytokenaddr[KOMODO_ADDRESS_BUFSIZE] = { '\0' }; + globalpk = GetUnspendable(cp, NULL); + _GetCCaddress(myccaddr, cp->evalcode, mypk, true); + _GetCCaddress(globaladdr, cp->evalcode, globalpk, true); + GetTokensCCaddress(cp, mytokenaddr, mypk, true); // get token or nft probe + + PrecomputedTransactionData txdata(mtx); + for (int i = 0; i < mtx.vin.size(); i++) + { + CTransaction vintx; + uint256 hashBlock; + bool mgret; + + if (i == 0 && mtx.vin[i].prevout.n == 10e8) // skip PEGS vin + continue; + if ((mgret = GetTxUnconfirmedOpt(&eval, mtx.vin[i].prevout.hash, vintx, hashBlock)) != false) { + CCwrapper cond; + uint8_t *privkey = NULL; + + if (!vintx.vout[mtx.vin[i].prevout.n].scriptPubKey.IsPayToCryptoCondition()) + { + /*char coinaddr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(coinaddr, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG); + if (strcmp(destaddr, coinaddr) != 0) { + fprintf(stderr, "%s signing error for normal vini.%d myprivkey does not match\n", __func__, i); + return false; + }*/ + + CBasicKeyStore tempKeystore; + CKey key; + key.Set(myprivkey, myprivkey+32, true); + tempKeystore.AddKey(key); + if (!TestSignTx(tempKeystore, mtx, i, vintx.vout[mtx.vin[i].prevout.n].nValue, vintx.vout[mtx.vin[i].prevout.n].scriptPubKey)) { + fprintf(stderr, "%s signing error for normal vini.%d\n", __func__, i); + return false; + } + + } else { + char destaddr[KOMODO_ADDRESS_BUFSIZE]; + if (!Getscriptaddress(destaddr, vintx.vout[mtx.vin[i].prevout.n].scriptPubKey)) { + std::cerr << __func__ << " could not Getscriptaddress for scriptPubKey=" << vintx.vout[mtx.vin[i].prevout.n].scriptPubKey.ToString() << std::endl; + return false; + } + + if (strcmp(destaddr, globaladdr) == 0) { + std::cerr << __func__ << " found globaladdress=" << globaladdr << " destaddr=" << destaddr << " strlen=" << strlen(globaladdr) << " evalcode=" << (int)cp->evalcode << std::endl; + + privkey = cp->CCpriv; + cond.reset(MakeCCcond1(cp->evalcode, globalpk)); + } else if (strcmp(destaddr, myccaddr) == 0) { + privkey = myprivkey; + cond.reset(MakeCCcond1(cp->evalcode, mypk)); + std::cerr << __func__ << " found myccaddr=" << myccaddr << std::endl; + + } else if (strcmp(destaddr, mytokenaddr) == 0) { + privkey = myprivkey; + cond.reset(MakeTokensv2CCcond1(cp->evalcode, cp->evalcodeNFT, mypk)); + std::cerr << __func__ << " found mytokenaddr=" << mytokenaddr << " evalcode=" << (int)cp->evalcode << " evalcodeNFT=" << (int)cp->evalcodeNFT << std::endl; + } else { + const uint8_t nullpriv[32] = {'\0'}; + // use vector of dest addresses and conds to probe vintxconds + for (auto& t : cp->CCvintxprobes) { + char coinaddr[KOMODO_ADDRESS_BUFSIZE]; + if (t.CCwrapped.get() != NULL) { + CCwrapper anonCond = t.CCwrapped; + CCtoAnon(anonCond.get()); + Getscriptaddress(coinaddr, CCPubKey(anonCond.get(), true)); + if (strcmp(destaddr, coinaddr) == 0) { + std::cerr << __func__ << " found vintxprobe=" << coinaddr << " privkey=" << (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) << std::endl; + if (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) + privkey = t.CCpriv; + else + privkey = myprivkey; + cond = t.CCwrapped; + break; + } + } + } + } + if (cond.get() == NULL) { + fprintf(stderr, "%s vini.%d has CC signing error: could not find matching cond, address.(%s) %s\n", __func__, i, destaddr, EncodeHexTx(mtx).c_str()); + return false; + } + + uint256 sighash = SignatureHash(CCPubKey(cond.get()), mtx, i, SIGHASH_ALL, vintx.vout[mtx.vin[i].prevout.n].nValue, consensusBranchId, &txdata); + if (cc_signTreeSecp256k1Msg32(cond.get(), privkey, sighash.begin()) == 0) { + fprintf(stderr, "%s vini.%d has CC signing error: cc_signTreeSecp256k1Msg32 returned error, address.(%s) %s\n", __func__, i, destaddr, EncodeHexTx(mtx).c_str()); + return false; + } + mtx.vin[i].scriptSig = CCSig(cond.get()); + } + } else { + fprintf(stderr, "%s could not find tx %s myGetTransaction returned %d\n", __func__, mtx.vin[i].prevout.hash.ToString().c_str(), mgret); + return false; + } + } + return true; +} + + + class TestAssetsCC : public ::testing::Test { public: //uint32_t GetAssetchainsCC() const { return testCcid; } @@ -104,7 +281,9 @@ class TestAssetsCC : public ::testing::Test { protected: static void SetUpTestCase() { // setup eval for tests - CreateTransactions(&eval); + ASSETCHAINS_CC = 2; + + CreateTransactions(); } virtual void SetUp() { // enable print @@ -113,38 +292,32 @@ class TestAssetsCC : public ::testing::Test { mapMultiArgs["-debug"] = { "cctokens", "ccassets" }; } - static void CreateTransactions(EvalMock *eval) + static void CreateTransactions() { std::cerr << __func__ << " enterred" << std::endl; - txnormal1 = MakeNormalTx(pk1, 1000); - txnormal2 = MakeNormalTx(pk1, 1000); - txnormal3 = MakeNormalTx(pk2, 1000); - txnormal4 = MakeNormalTx(pk2, 1000); - txnormalg = MakeNormalTxG(); - - eval->txs[txnormal1.GetHash()] = txnormal1; - eval->txs[txnormal2.GetHash()] = txnormal2; - eval->txs[txnormal3.GetHash()] = txnormal3; - eval->txs[txnormal4.GetHash()] = txnormal4; - eval->txs[txnormalg.GetHash()] = txnormalg; + txnormal1 = MakeNormalTx(pk1, 20000); + txnormal2 = MakeNormalTx(pk1, 20000); + txnormal3 = MakeNormalTx(pk2, 20000); + txnormal4 = MakeNormalTx(pk2, 20000); + + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + txnormalg = MakeNormalTx(GetUnspendable(cpTokens, NULL), 20000); txtokencreate1 = MakeTokenV2CreateTx(pk1); - eval->txs[txtokencreate1.GetHash()] = txtokencreate1; tokenid1 = txtokencreate1.GetHash(); txtokencreate2 = MakeTokenV2CreateTx(pk2); - eval->txs[txtokencreate2.GetHash()] = txtokencreate2; tokenid2 = txtokencreate2.GetHash(); txtokencreate3 = MakeTokenV2CreateTx(pk2); - eval->txs[txtokencreate3.GetHash()] = txtokencreate3; tokenid3 = txtokencreate3.GetHash(); - txask = MakeTokenV2AskTx(pk1); - eval->txs[txask.GetHash()] = txask; + txtokencreateUnused = MakeTokenV2CreateTx(pk1); + tokenidUnused = txtokencreateUnused.GetHash(); + txask = MakeTokenV2AskTx(pk1); txbid = MakeTokenV2BidTx(pk2); - eval->txs[txbid.GetHash()] = txbid; } static CTransaction MakeNormalTx(CPubKey pk, CAmount val) @@ -152,10 +325,11 @@ class TestAssetsCC : public ::testing::Test { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); mtx.vin.push_back(CTxIn(getRandomHash(), 0)); mtx.vout.push_back(CTxOut(val, GetScriptForDestination(pk))); + eval.txs[mtx.GetHash()] = mtx; return CTransaction(mtx); } - static CTransaction MakeNormalTxG() + /*static CTransaction MakeNormalTxG() { struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); @@ -165,7 +339,7 @@ class TestAssetsCC : public ::testing::Test { mtx.vin.push_back(CTxIn(getRandomHash(), 0)); mtx.vout.push_back(CTxOut(100000, GetScriptForDestination(pkg))); return CTransaction(mtx); - } + }*/ static CTransaction MakeTokenV2CreateTx(CPubKey pk) { @@ -179,6 +353,7 @@ class TestAssetsCC : public ::testing::Test { mtx.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk)); mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk.begin(), pk.end()), name, description, { }))); + eval.txs[mtx.GetHash()] = mtx; return CTransaction(mtx); } @@ -205,6 +380,7 @@ class TestAssetsCC : public ::testing::Test { mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, {}, { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pk.begin(), pk.end())) }))); + eval.txs[mtx.GetHash()] = mtx; return CTransaction(mtx); } @@ -231,6 +407,7 @@ class TestAssetsCC : public ::testing::Test { mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, {}, { AssetsV2::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(pk.begin(), pk.end())) }))); + eval.txs[mtx.GetHash()] = mtx; return CTransaction(mtx); } @@ -247,7 +424,6 @@ class TestAssetsCC : public ::testing::Test { // set some vars used in validation: KOMODO_CONNECTING = 1; - ASSETCHAINS_CC = 2; KOMODO_CCACTIVATE = 1; eval.state = CValidationState(); // clear validation state EVAL_TEST = &eval; @@ -296,14 +472,13 @@ TEST_F(TestAssetsCC, tokenv2ask) CAmount numtokens = 2; CAmount txfee = 10000; - //CPubKey mypk(ParseHex("035d3b0f2e98cf0fba19f80880ec7c08d770c6cf04aa5639bc57130d5ac54874db")); cpAssets = CCinit(&C, AssetsV2::EvalCode()); cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); uint8_t evalcodeNFT = cpTokens->evalcodeNFT ? cpTokens->evalcodeNFT : 0; CAmount unit_price = askamount / numtokens; - mtx.vin.push_back(CTxIn(txnormal2.GetHash(), 0)); + ASSERT_TRUE( TestAddNormalInputs(mtx, pk1, txfee) > 0LL); mtx.vin.push_back(CTxIn(txtokencreate1.GetHash(), 1)); CAmount inputs = txtokencreate1.vout[1].nValue; @@ -317,26 +492,14 @@ TEST_F(TestAssetsCC, tokenv2ask) mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), CCchange, pk1)); } - mtx.vout.push_back(CTxOut(0, - TokensV2::EncodeTokenOpRet(tokenid1, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pk1.begin(), pk1.end())) }))); + // cond to spend NFT from mypk + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(evalcodeNFT, pk1)); + CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey // sign vins: - // sign normal vin: - CBasicKeyStore tempKeystore; - CKey key; - key.Set(privkey1, privkey1+sizeof(privkey1), true); - tempKeystore.AddKey(key); - int32_t ivin = 0; - ASSERT_TRUE( TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey) ); - - ++ivin; - // sign cc vin: - PrecomputedTransactionData txdata(mtx); - CCwrapper cond(TokensV2::MakeTokensCCcond1(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), pk1)); - uint256 sighash = SignatureHash(CCPubKey(cond.get()), mtx, ivin, SIGHASH_ALL, 0, 0, &txdata); - ASSERT_TRUE( cc_signTreeSecp256k1Msg32(cond.get(), privkey1, sighash.begin()) > 0 ); - mtx.vin[ivin].scriptSig = CCSig(cond.get()); + ASSERT_TRUE(TestFinalizeTx(mtx, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenOpRet(tokenid1, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pk1.begin(), pk1.end())) }))); EXPECT_TRUE(TestRunCCEval(mtx)); } @@ -354,24 +517,16 @@ TEST_F(TestAssetsCC, tokenv2bid) CAmount unit_price = bidamount / numtokens; - mtx.vin.push_back(CTxIn(txnormal2.GetHash(), 0)); + ASSERT_TRUE( TestAddNormalInputs(mtx, pk1, txfee) > 0LL); CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, unspendableAssetsPubkey)); mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk1)); // marker for my orders - mtx.vout.push_back(CTxOut(0, - TokensV2::EncodeTokenOpRet(tokenid1, {}, - { AssetsV2::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(pk1.begin(), pk1.end())) }))); - // sign vins: - // normal vin: - CBasicKeyStore tempKeystore; - CKey key; - key.Set(privkey1, privkey1+sizeof(privkey1), true); - tempKeystore.AddKey(key); - int32_t ivin = 0; - ASSERT_TRUE( TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey) ); + ASSERT_TRUE(TestFinalizeTx(mtx, cpAssets, testKeys[pk1], txfee, + TokensV2::EncodeTokenOpRet(tokenid1, {}, + { AssetsV2::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(pk1.begin(), pk1.end())) }))); EXPECT_TRUE(TestRunCCEval(mtx)); } @@ -415,13 +570,11 @@ TEST_F(TestAssetsCC, tokenv2fillask) paid_unit_price = unit_price; CAmount paid_nValue = paid_unit_price * fillunits; - CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / NFTROYALTY_DIVISOR * royaltyFract : 0; - mtx.vin.push_back(CTxIn(txnormal2.GetHash(), 0)); + ASSERT_TRUE( TestAddNormalInputs(mtx, pk2, txfee) > 0LL); mtx.vin.push_back(CTxIn(txask.GetHash(), askvout, CScript())); // spend order tx - // vout.0 tokens remainder to unspendable cc addr: mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeNFT, orig_assetoshis - fillunits, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr @@ -434,26 +587,15 @@ TEST_F(TestAssetsCC, tokenv2fillask) if (orig_assetoshis - fillunits > 0) // we dont need the marker if order is filled mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { pk2 }, - { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))); - - // sign normal vin: - CBasicKeyStore tempKeystore; - CKey key; - key.Set(privkey1, privkey1+sizeof(privkey1), true); - tempKeystore.AddKey(key); - int32_t ivin = 0; - ASSERT_TRUE( TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey) ); + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeNFT, unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); - ++ivin; - // sign cc vin: - PrecomputedTransactionData txdata(mtx); - uint8_t privkeyAssets[32]; - CCwrapper cond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), GetUnspendable(cpAssets, privkeyAssets))); - uint256 sighash = SignatureHash(CCPubKey(cond.get()), mtx, ivin, SIGHASH_ALL, 0, 0, &txdata); - ASSERT_TRUE( cc_signTreeSecp256k1Msg32(cond.get(), privkeyAssets, sighash.begin()) > 0 ); - mtx.vin[ivin].scriptSig = CCSig(cond.get()); + ASSERT_TRUE(TestFinalizeTx(mtx, cpAssets, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(tokenid1, { pk2 }, + { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))); EXPECT_TRUE(TestRunCCEval(mtx)); } @@ -461,7 +603,6 @@ TEST_F(TestAssetsCC, tokenv2fillask) TEST_F(TestAssetsCC, tokenv2fillbid) { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); struct CCcontract_info *cpAssets, C; struct CCcontract_info *cpTokens, tokensC; @@ -502,15 +643,13 @@ TEST_F(TestAssetsCC, tokenv2fillbid) if (paid_unit_price <= 0LL) paid_unit_price = unit_price; - - mtx.vin.push_back(CTxIn(txnormal2.GetHash(), 0)); + ASSERT_TRUE( TestAddNormalInputs(mtx, pk2, txfee) > 0LL); mtx.vin.push_back(CTxIn(txtokencreate2.GetHash(), 1, CScript())); // spend token tx mtx.vin.push_back(CTxIn(txbid.GetHash(), bidvout, CScript())); // spend order tx - CAmount inputs = txnormal2.vout[0].nValue; + //CAmount inputs = txnormal2.vout[0].nValue; CAmount tokenInputs = txtokencreate2.vout[1].nValue; - ASSERT_TRUE(SetBidFillamounts(unit_price, paid_amount, bid_amount, fill_units, orig_units, paid_unit_price)); CAmount royaltyValue = royaltyFract > 0 ? paid_amount / NFTROYALTY_DIVISOR * royaltyFract : 0; @@ -535,104 +674,288 @@ TEST_F(TestAssetsCC, tokenv2fillbid) if (tokensChange != 0LL) mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), tokensChange, pk2)); // change in single-eval tokens - - mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); - // sign normal vin: - CBasicKeyStore tempKeystore; - CKey key; - key.Set(privkey1, privkey1+sizeof(privkey1), true); - tempKeystore.AddKey(key); - int32_t ivin = 0; - ASSERT_TRUE( TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey) ); + CMutableTransaction mtx2(mtx); // copy - ++ivin; - // sign cc token vin: - PrecomputedTransactionData txdata(mtx); - CCwrapper cond1(TokensV2::MakeTokensCCcond1(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), pk2)); - uint256 sighash1 = SignatureHash(CCPubKey(cond1.get()), mtx, ivin, SIGHASH_ALL, 0, 0, &txdata); - ASSERT_TRUE( cc_signTreeSecp256k1Msg32(cond1.get(), privkey2, sighash1.begin()) > 0 ); - mtx.vin[ivin].scriptSig = CCSig(cond1.get()); - - ++ivin; - // sign cc assets vin: - uint8_t privkeyAssets[32]; - CCwrapper cond2(MakeCCcond1(AssetsV2::EvalCode(), GetUnspendable(cpAssets, privkeyAssets))); - uint256 sighash2 = SignatureHash(CCPubKey(cond2.get()), mtx, ivin, SIGHASH_ALL, 0, 0, &txdata); - ASSERT_TRUE( cc_signTreeSecp256k1Msg32(cond2.get(), privkeyAssets, sighash2.begin()) > 0 ); - mtx.vin[ivin].scriptSig = CCSig(cond2.get()); + CCwrapper wrCond1(MakeCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); // spend coins + CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); + + CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(evalcodeNFT, pk2)); // spend my tokens to fill buy + CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey + ASSERT_TRUE(TestFinalizeTx(mtx, cpTokens, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(tokenid2, { pubkey2pk(origpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); EXPECT_TRUE(TestRunCCEval(mtx)); - // check bad tokenid bid - CMutableTransaction mtx2(mtx); - ivin = 1; - mtx2.vin[ivin] = CTxIn(txtokencreate3.GetHash(), 1, CScript()); // spend bad tokenid3 - mtx2.vout.pop_back(); - mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); - // sign cc token vin: - PrecomputedTransactionData txdata2(mtx2); - CCwrapper cond3(TokensV2::MakeTokensCCcond1(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), pk2)); - uint256 sighash3 = SignatureHash(CCPubKey(cond3.get()), mtx2, ivin, SIGHASH_ALL, 0, 0, &txdata2); - ASSERT_TRUE( cc_signTreeSecp256k1Msg32(cond3.get(), privkey2, sighash3.begin()) > 0 ); - mtx2.vin[ivin].scriptSig = CCSig(cond3.get()); + // spend bad tokenid + mtx2.vin[1] = CTxIn(txtokencreate3.GetHash(), 1, CScript()); // spend bad tokenid3 + ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(origpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); EXPECT_FALSE(TestRunCCEval(mtx2)); } +TEST_F(TestAssetsCC, tokenv2cancelask) +{ + struct CCcontract_info *cpAssets, C; + struct CCcontract_info *cpTokens, tokensC; + + CAmount txfee = 10000; + + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + for (CTransaction vintx : std::vector{ txask }) // TODO add more txasks + { + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + uint256 asktxid = vintx.GetHash(); + CAmount askamount = vintx.vout[ASSETS_GLOBALADDR_VOUT].nValue; + + TokenDataTuple tokenData; + vuint8_t vopretNonfungible; + ASSERT_TRUE( GetTokenData(&eval, tokenid1, tokenData, vopretNonfungible) ); + uint8_t evalcodeNFT = 0; + if (vopretNonfungible.size() > 0) + evalcodeNFT = vopretNonfungible[0]; + vuint8_t ownerpubkey = std::get<0>(tokenData); + + ASSERT_TRUE( TestAddNormalInputs(mtx, ownerpubkey, txfee) > 0LL); + mtx.vin.push_back(CTxIn(asktxid, ASSETS_GLOBALADDR_VOUT, CScript())); + + uint8_t dummyEvalCode; + uint256 dummyAssetid, dummyAssetid2; + int64_t dummyPrice; + std::vector dummyOrigpubkey; + uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey); + if (funcid == 's' && vintx.vout.size() > 1) + mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // spend marker if funcid='s' + else if (funcid == 'S' && vintx.vout.size() > 3) + mtx.vin.push_back(CTxIn(asktxid, 3, CScript())); // spend marker if funcid='S' + else { + std::cerr << __func__ << "invalid ask tx" << std::endl; + ASSERT_FALSE(true); + } + + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(cpAssets->evalcodeNFT ? cpAssets->evalcodeNFT : TokensV2::EvalCode(), askamount, ownerpubkey)); // one-eval token vout + + // init assets 'unspendable' privkey and pubkey + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), cpAssets->evalcodeNFT, unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); + + ASSERT_TRUE(TestFinalizeTx(mtx, cpAssets, testKeys[ownerpubkey], txfee, + TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + + EXPECT_TRUE(TestRunCCEval(mtx)); + + // invalid pk in assets opreturn + CMutableTransaction mtx2(mtx); + mtx2.vout.pop_back(); + mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(pk2.begin(), pk2.end())) } ))); + // EXPECT_FALSE(TestRunCCEval(mtx2)); // is not checked + + // invalid pk in token opret + CMutableTransaction mtx3(mtx); + mtx3.vout.pop_back(); + mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { pkunused }, + { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + // EXPECT_FALSE(TestRunCCEval(mtx3)); // is not checked + + // invalid pk where to funds sent + CMutableTransaction mtx4(mtx); + mtx4.vout[0] = TokensV2::MakeTokensCC1vout(cpAssets->evalcodeNFT ? cpAssets->evalcodeNFT : TokensV2::EvalCode(), askamount, pk2); + EXPECT_FALSE(TestRunCCEval(mtx4)); // is not checked + + // invalid tokenid in token opret + CMutableTransaction mtx5(mtx); + mtx5.vout.pop_back(); + mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + EXPECT_FALSE(TestRunCCEval(mtx5)); // is not checked + + // opposite funcid in token opret + CMutableTransaction mtx6(mtx); + mtx6.vout.pop_back(); + mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + EXPECT_FALSE(TestRunCCEval(mtx6)); // is not checked + } +} + +TEST_F(TestAssetsCC, tokenv2cancelbid) +{ + struct CCcontract_info *cpAssets, C; + struct CCcontract_info *cpTokens, tokensC; + CAmount txfee = 10000; + + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + for (CTransaction vintx : std::vector{ txbid }) // TODO add more txasks + { + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + uint256 bidtxid = vintx.GetHash(); + CAmount bidamount = vintx.vout[ASSETS_GLOBALADDR_VOUT].nValue; + + TokenDataTuple tokenData; + vuint8_t vopretNonfungible; + ASSERT_TRUE( GetTokenData(&eval, tokenid2, tokenData, vopretNonfungible) ); + uint8_t evalcodeNFT = 0; + if (vopretNonfungible.size() > 0) + evalcodeNFT = vopretNonfungible[0]; + vuint8_t ownerpubkey = std::get<0>(tokenData); + + ASSERT_TRUE( TestAddNormalInputs(mtx, ownerpubkey, txfee) > 0LL); + mtx.vin.push_back(CTxIn(bidtxid, ASSETS_GLOBALADDR_VOUT, CScript())); + + uint8_t dummyEvalCode; + uint256 dummyAssetid, dummyAssetid2; + int64_t dummyPrice; + std::vector dummyOrigpubkey; + uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey); + if (funcid == 'b' && vintx.vout.size() > 1) + mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' + else if (funcid == 'B' && vintx.vout.size() > 3) + mtx.vin.push_back(CTxIn(bidtxid, 3, CScript())); // spend marker if funcid='B' + else { + std::cerr << __func__ << "invalid bid tx" << std::endl; + ASSERT_FALSE(true); + } + + if (bidamount > ASSETS_NORMAL_DUST) + mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); + else { + // send dust back to global addr + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, GetUnspendable(cpAssets, NULL))); + std::cerr << __func__ << " dust detected bidamount=" << bidamount << std::endl; + } + + // init assets 'unspendable' privkey and pubkey + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + + // sign, add change, add opreturn + ASSERT_TRUE(TestFinalizeTx(mtx, cpAssets, testKeys[ownerpubkey], txfee, + TokensV2::EncodeTokenOpRet(tokenid2, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + + EXPECT_TRUE(TestRunCCEval(mtx)); + + // invalid pk in assets opreturn + CMutableTransaction mtx2(mtx); + mtx2.vout.pop_back(); + mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(pk1.begin(), pk1.end())) } ))); + // EXPECT_FALSE(TestRunCCEval(mtx2)); // is not checked + + // invalid pk in token opret + CMutableTransaction mtx3(mtx); + mtx3.vout.pop_back(); + mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pkunused }, + { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + // EXPECT_FALSE(TestRunCCEval(mtx3)); // is not checked + + // invalid pk where to funds sent + CMutableTransaction mtx4(mtx); + mtx4.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(pkunused)) << OP_CHECKSIG); + EXPECT_FALSE(TestRunCCEval(mtx4)); // is not checked + + // invalid tokenid in token opret + CMutableTransaction mtx5(mtx); + mtx5.vout.pop_back(); + mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + EXPECT_FALSE(TestRunCCEval(mtx5)); + + // opposite funcid in token opret + CMutableTransaction mtx6(mtx); + mtx6.vout.pop_back(); + mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pk2 }, + { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + EXPECT_FALSE(TestRunCCEval(mtx6)); + } +} + + +/* ---------------------------------------------------------------------------------------------------------------------------------- */ +// tokens tests: + TEST_F(TestAssetsCC, tokenv2create) { struct CCcontract_info *cp, C; cp = CCinit(&C, TokensV2::EvalCode()); std::string name = "T1"; std::string description = "desc"; + CAmount txfee = 10000; CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - mtx.vin.push_back(CTxIn(txnormal1.GetHash(), 0)); + ASSERT_TRUE( TestAddNormalInputs(mtx, pk1, txfee) > 0LL); mtx.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); - mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); - CMutableTransaction mtx3(mtx); + // copies: + CMutableTransaction mtx1(mtx); + CMutableTransaction mtx2(mtx); + //CMutableTransaction mtx3(mtx); // sign vins: // normal vin: - CBasicKeyStore tempKeystore; + /*CBasicKeyStore tempKeystore; CKey key; key.Set(privkey1, privkey1+sizeof(privkey1), true); tempKeystore.AddKey(key); int32_t ivin = 0; - ASSERT_TRUE(TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey)); + ASSERT_TRUE(TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey));*/ + + // sign, add change, add opreturn + ASSERT_TRUE(TestFinalizeTx(mtx, cp, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + EXPECT_TRUE(TestRunCCEval(mtx)); // token sent to another pk - CMutableTransaction mtx1(mtx); mtx1.vout[1] = TokensV2::MakeTokensCC1vout(0, 10, pk2); - EXPECT_TRUE(TestRunCCEval(mtx1)); // allow sent created tokens to any pk! + ASSERT_TRUE(TestFinalizeTx(mtx1, cp, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + EXPECT_TRUE(TestRunCCEval(mtx1)); // allow sent created tokens to any pk!! // invalid pk in opreturn: - CMutableTransaction mtx2(mtx); - mtx2.vout[2] = CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { })); // should send to self (?) + //mtx2.vout[2] = CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { })); // should send to self (?) + ASSERT_TRUE(TestFinalizeTx(mtx2, cp, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { }))); EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail - // create with global pk: - mtx3.vin[0] = CTxIn(txnormalg.GetHash(), 0); - struct CCcontract_info *cpTokens, tokensC; + // create token with global pk: + CMutableTransaction mtx3 = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); uint8_t privkeyg[32]; CPubKey pkg = GetUnspendable(cpTokens, privkeyg); - CKey keyg; + + mtx3.vin.push_back(CTxIn(txnormalg.GetHash(), 0)); + mtx3.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); + mtx3.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); + /* CKey keyg; keyg.Set(privkeyg, privkeyg+sizeof(privkeyg), true); CBasicKeyStore tempKeystoreg; tempKeystoreg.AddKey(keyg); // change opreturn mtx3.vout[2] = CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pkg.begin(), pkg.end()), name, description, { })); // should send to self (?) - ivin = 0; - ASSERT_TRUE(TestSignTx(tempKeystoreg, mtx3, ivin, txnormalg.vout[0].nValue, txnormalg.vout[0].scriptPubKey)); + ivin = 0; + ASSERT_TRUE(TestSignTx(tempKeystoreg, mtx3, ivin, txnormalg.vout[0].nValue, txnormalg.vout[0].scriptPubKey)); */ + + ASSERT_TRUE(TestFinalizeTx(mtx3, cp, privkeyg, txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pkg.begin(), pkg.end()), name, description, { }))); EXPECT_FALSE(TestRunCCEval(mtx3)); // must fail } From 76e394870419e5a52df569bab28cb4e3df7b0fd3 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 26 Jun 2021 23:21:24 +0500 Subject: [PATCH 019/348] extra test code removed --- src/test-komodo-cc/test-assets.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 9a1495427c5..8b22bb846c7 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -929,7 +929,6 @@ TEST_F(TestAssetsCC, tokenv2create) EXPECT_TRUE(TestRunCCEval(mtx1)); // allow sent created tokens to any pk!! // invalid pk in opreturn: - //mtx2.vout[2] = CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { })); // should send to self (?) ASSERT_TRUE(TestFinalizeTx(mtx2, cp, testKeys[pk1], txfee, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { }))); EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail @@ -945,14 +944,6 @@ TEST_F(TestAssetsCC, tokenv2create) mtx3.vin.push_back(CTxIn(txnormalg.GetHash(), 0)); mtx3.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); mtx3.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); - /* CKey keyg; - keyg.Set(privkeyg, privkeyg+sizeof(privkeyg), true); - CBasicKeyStore tempKeystoreg; - tempKeystoreg.AddKey(keyg); - // change opreturn - mtx3.vout[2] = CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pkg.begin(), pkg.end()), name, description, { })); // should send to self (?) - ivin = 0; - ASSERT_TRUE(TestSignTx(tempKeystoreg, mtx3, ivin, txnormalg.vout[0].nValue, txnormalg.vout[0].scriptPubKey)); */ ASSERT_TRUE(TestFinalizeTx(mtx3, cp, privkeyg, txfee, TokensV2::EncodeTokenCreateOpRet(vscript_t(pkg.begin(), pkg.end()), name, description, { }))); From 32b5c940bc9cbd863a39761c39120b27e7ff2b88 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 28 Jun 2021 20:03:04 +0500 Subject: [PATCH 020/348] assets validation: added some boundary checks, dust on normals always checked, code small refactoring --- src/cc/CCassetsCore_impl.h | 68 +++++++++++++++++--------------------- src/cc/assets.cpp | 49 ++++++++++----------------- 2 files changed, 48 insertions(+), 69 deletions(-) diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index 49004c8cdea..f4c1137c5cd 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -167,19 +167,19 @@ CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *o if (tx.vout.size() > 0) funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCode, assetid, assetid2, tmpprice, tmporigpubkey); else - return eval->Invalid("no vouts in tx"); + return eval->Invalid("no vouts in tx"), 0LL; - if( tx.vin.size() < 2 ) - return eval->Invalid("not enough for CC vins"); - else if(tx.vin[vini].prevout.n != ASSETS_GLOBALADDR_VOUT) // check gobal addr vout number == 0 - return eval->Invalid("vin1 needs to be buyvin.vout[0]"); + if (tx.vin.size() < 2) + return eval->Invalid("not enough vins"), 0LL; + else if(tx.vin[vini].prevout.n != ASSETS_GLOBALADDR_VOUT) // check global addr vout number == 0 + return eval->Invalid("asset cc vin must refer bid vintx.vout[0]"), 0LL; else if(eval->GetTxUnconfirmed(tx.vin[vini].prevout.hash, vinTx, hashBlock) == false) { LOGSTREAMFN(ccassets_log, CCLOG_ERROR, stream << "cannot load vintx for vin=" << vini << " vintx id=" << tx.vin[vini].prevout.hash.GetHex() << std::endl); - return eval->Invalid("could not load previous tx or it has too few vouts"); + return eval->Invalid("could not load previous tx or it has too few vouts"), 0LL; } else if (vinTx.vout.size() < 1 || (vinFuncId = A::DecodeAssetTokenOpRet(vinTx.vout.back().scriptPubKey, vinEvalCode, vinAssetId, vinAssetId2, vinPrice, vinOrigpubkey)) == 0) { - return eval->Invalid("could not find assets opreturn in previous tx"); + return eval->Invalid("could not find assets opreturn in previous tx"), 0LL; } // if fillSell or cancelSell --> should spend tokens from dual-eval token-assets global addr: else if((funcid == 'S' || funcid == 'x') && @@ -189,7 +189,7 @@ CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *o strcmp(destaddr, unspendableAddr) != 0)) { CCLogPrintF(ccassets_log, CCLOG_ERROR, "%s cc addr %s is not dual token-evalcode=0x%02x asset unspendable addr %s\n", __func__, destaddr, (int)cpAssets->evalcode, unspendableAddr); - return eval->Invalid("invalid vin assets CCaddr"); + return eval->Invalid("invalid vin assets CCaddr"), 0LL; } // if fillBuy or cancelBuy --> should spend coins from asset cc global addr else if ((funcid == 'B' || funcid == 'o') && @@ -199,38 +199,32 @@ CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *o strcmp(destaddr, unspendableAddr) != 0)) { CCLogPrintF(ccassets_log, CCLOG_ERROR, "%s cc addr %s is not evalcode=0x%02x asset unspendable addr %s\n", __func__, destaddr, (int)cpAssets->evalcode, unspendableAddr); - return eval->Invalid("invalid vin assets CCaddr"); + return eval->Invalid("invalid vin assets CCaddr"), 0LL; } // end of check source unspendable cc address //else if ( vinTx.vout[0].nValue < 10000 ) // return eval->Invalid("invalid dust for buyvin"); // get user dest cc and normal addresses: else if(GetAssetorigaddrs(cpAssets, origCCaddr_out, origaddr_out, vinTx) == false) - return eval->Invalid("couldnt get origaddr for vin tx"); + return eval->Invalid("couldnt get origaddr for vin tx"), 0LL; //fprintf(stderr,"AssetValidateCCvin() got %.8f to origaddr.(%s)\n", (double)vinTx.vout[tx.vin[vini].prevout.n].nValue/COIN,origaddr); // check that vinTx B or S has assets cc vins: if (vinFuncId == 'B' || vinFuncId == 'S') { - bool found = false; - for (auto const &vin : vinTx.vin) - if (cpAssets->ismyvin(vin.scriptSig)) { - found = true; - break; - } - if (!found) - return eval->Invalid("no assets cc vins in previous fillbuy or fillsell tx"); + if (std::find_if(vinTx.vin.begin(), vinTx.vin.end(), [&](const CTxIn &vin) { return cpAssets->ismyvin(vin.scriptSig); }) == vinTx.vin.end()) + return eval->Invalid("no assets cc vins in previous fillbuy or fillsell tx"), 0LL; } // check no more other vins spending from global addr: if (AssetsGetCCInputs(eval, cpAssets, unspendableAddr, tx) != vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue) - return eval->Invalid("invalid assets cc vins found"); + return eval->Invalid("invalid assets cc vins found"), 0LL; if (vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue == 0) - return eval->Invalid("null value in previous tx CC vout0"); + return eval->Invalid("null value in previous tx CC vout0"), 0LL; - return(vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue); + return vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue; } template @@ -245,29 +239,27 @@ CAmount AssetValidateBuyvin(struct CCcontract_info *cpAssets, Eval* eval, CAmoun for (ivincc = 0; ivincc < tx.vin.size(); ivincc ++) if (cpAssets->ismyvin(tx.vin[ivincc].scriptSig)) break; + if (ivincc == tx.vin.size()) + return eval->Invalid("cc vin not found in tx"), 0LL; // validate locked coins on Assets vin[1] if ((nValue = AssetValidateCCvin(cpAssets, eval, origCCaddr_out, origaddr_out, tx, /*ASSETS_GLOBALADDR_VIN*/ivincc, vinTx)) == 0) - return(0); + return 0LL; // eval is set already in AssetValidateCCvin else if (vinTx.vout.size() < 2) - return eval->Invalid("invalid previous tx, too few vouts"); + return eval->Invalid("invalid previous tx, too few vouts"), 0LL; else if (vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == false) - return eval->Invalid("invalid not cc vout0 for buyvin"); + return eval->Invalid("invalid not cc vout0 for buyvin"), 0LL; else if ((funcid = A::DecodeAssetTokenOpRet(vinTx.vout[vinTx.vout.size() - 1].scriptPubKey, evalCode, assetid, assetid2, unit_price, origpubkey_out)) == 'b' && vinTx.vout[1].scriptPubKey.IsPayToCryptoCondition() == false) // marker is only in 'b'? - return eval->Invalid("invalid not cc vout1 for buyvin"); + return eval->Invalid("invalid not cc vout1 for buyvin"), 0LL; else { - //fprintf(stderr,"have %.8f checking assetid origaddr.(%s)\n",(double)nValue/COIN,origaddr); - if (vinTx.vout.size() > 0 && funcid != 'b' && funcid != 'B') - return eval->Invalid("invalid opreturn for buyvin"); + if (funcid != 'b' && funcid != 'B') + return eval->Invalid("invalid opreturn funcid for buyvin"), 0LL; else if (refassetid != assetid) - return eval->Invalid("invalid assetid for buyvin"); - //int32_t i; for (i=31; i>=0; i--) - // fprintf(stderr,"%02x",((uint8_t *)&assetid)[i]); - //fprintf(stderr," AssetValidateBuyvin assetid for %s\n",origaddr); + return eval->Invalid("invalid assetid for buyvin"), 0LL; } - return(nValue); + return nValue; } template @@ -275,20 +267,20 @@ CAmount AssetValidateSellvin(struct CCcontract_info *cpAssets, Eval* eval, CAmou { CTransaction vinTx; CAmount nValue, assetoshis; - //fprintf(stderr,"AssetValidateSellvin()\n"); // get first ccvin: int32_t ivincc; for (ivincc = 0; ivincc < tx.vin.size(); ivincc ++) if (cpAssets->ismyvin(tx.vin[ivincc].scriptSig)) break; - + if (ivincc == tx.vin.size()) + return eval->Invalid("cc vin not found"), 0LL; if ((nValue = AssetValidateCCvin(cpAssets, eval, origCCaddr_out, origaddr_out, tx, /*ASSETS_GLOBALADDR_VIN*/ivincc, vinTx)) == 0) - return(0); + return 0LL; // eval is set already in AssetValidateCCvin if ((assetoshis = IsAssetvout(cpAssets, unit_price, origpubkey_out, vinTx, ASSETS_GLOBALADDR_VOUT, assetid)) == 0) - return eval->Invalid("invalid missing CC vout0 for sellvin"); + return eval->Invalid("invalid missing CC vout0 for sellvin"), 0LL; else - return(assetoshis); + return assetoshis; } diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 8b2cb4ebd97..efd77a569e2 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -252,7 +252,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //preventCCvouts = 2; if (numvouts < 3) return eval->Invalid("too few vouts"); - else if( A::ConstrainVout(tx.vout[0], CCVOUT, cpAssets->unspendableCCaddr, 0LL, A::EvalCode()) == false ) + else if( A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, 0LL, A::EvalCode()) == false ) return eval->Invalid("invalid funding for bid"); else if( A::ConstrainVout(tx.vout[1], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr return eval->Invalid("invalid vout1 marker for original pubkey"); @@ -260,8 +260,10 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("not the originator pubkey signed for bid"); else if (unit_price <= 0) return eval->Invalid("invalid unit price"); + else if (tx.vout[0].nValue < unit_price) + return eval->Invalid("invalid bid amount too low"); - // check should not be assets cc vins: + // check it should not be assets cc vins for tokenv2bid at all: for (auto const &vin : tx.vin) { if (cpAssets->ismyvin(vin.scriptSig)) return eval->Invalid("could not have cc assets vin for creation tx"); @@ -288,19 +290,13 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (!A::ConstrainVout(tx.vout[0], NORMALVOUT, origNormalAddr, vin_assetoshis, 0)) return eval->Invalid("invalid refund for cancelbid"); } else { - bool isCCVout = A::ConstrainVout(tx.vout[0], CCVOUT, cpAssets->unspendableCCaddr, vin_assetoshis, 0); - if (!A::ConstrainVout(tx.vout[0], NORMALVOUT, origNormalAddr, vin_assetoshis, 0) && - !isCCVout ) // dust allowed to go back + // dust must go to global cc address + if (!A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, vin_assetoshis, 0)) return eval->Invalid("invalid dust refund for cancelbid"); - if( isCCVout ) - ccvouts ++; + ccvouts ++; } if (TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vin_origpubkey)) == 0) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for cancelbid"); - - //preventCCvins = 2; - //preventCCvouts = 0; - //fprintf(stderr,"cancelbuy validated to origaddr.(%s)\n",origNormalAddr); break; case 'B': // fillbid: @@ -331,23 +327,19 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const { int32_t r = royaltyFract > 0 ? 1 : 0; - CAmount assetoshis = tx.vout[0].nValue + tx.vout[1].nValue + (royaltyFract > 0 ? tx.vout[2].nValue : 0); + CAmount assetoshis = tx.vout[0].nValue + tx.vout[1].nValue + (r ? tx.vout[2].nValue : 0); if( vin_assetoshis != assetoshis ) // coins -> global cc address (remainder) + normal self address - return eval->Invalid("input cc value does not equal to vout0+1" + std::string(royaltyFract > 0 ? "+2" : "") + " for fillbid"); + return eval->Invalid("input cc value does not equal to vout0+1" + std::string(r ? "+2" : "") + " for fillbid"); // coins remainder - if (tx.vout[0].nValue / unit_price > 0 || tx.vout[0].nValue <= ASSETS_NORMAL_DUST) { - if (!A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, 0LL, A::EvalCode())) - return eval->Invalid("invalid vout0 should to global address for fillbid"); - ccvouts ++; - } - if (tx.vout[0].nValue / unit_price > 0 || tx.vout[0].nValue <= ASSETS_NORMAL_DUST) // there are remaining tokens to buy + if (tx.vout[0].nValue / unit_price > 0 || tx.vout[0].nValue <= ASSETS_NORMAL_DUST) // there are remaining tokens to buy or dust must return to global cc address { if (!A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, 0LL, A::EvalCode())) // if remainder sufficient to buy tokens -> coins to asset global cc addr return eval->Invalid("mismatched vout0 global assets CC addr for fillbid"); + ccvouts ++; } else - { // if remaining_units == 0 (empty bid) then the remainder should go to the originator normal address (if not dust) + { // if remaining_units == 0 (empty bid) then the remainder should go to the originator normal address, if it is not dust if (!A::ConstrainVout(tx.vout[0], NORMALVOUT, origNormalAddr, 0LL, 0)) // remainder less than token price should return to originator normal addr return eval->Invalid("vout0 should be originator normal address with remainder for fillbid"); } @@ -396,10 +388,11 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("vout2 invalid royalty detination for fillask"); } } - //fprintf(stderr,"fillbuy validated\n"); break; + //case 'e': // sell swap offer // break; // disable swaps + case 's': // ask offer //vin.0: normal input //vin.1+: valid CC output for sale @@ -433,7 +426,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (!tx.vout[2].scriptPubKey.IsPayToCCV2() || tx.vout[2].scriptPubKey.SpkHasEvalcodeCCV2(T::EvalCode())) // have token change ccvouts ++; - // check should not be assets cc vins: + // check should not be assets cc vins for tokenv2ask at all: for (auto const &vin : tx.vin) { if (cpAssets->ismyvin(vin.scriptSig)) return eval->Invalid("could not have cc assets vin for creation tx"); @@ -456,8 +449,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("invalid vout0 for cancelask"); else if (TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vin_origpubkey)) == 0) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for cancelask"); - ccvins = 2; // order and marker - ccvouts = 1; + ccvins = 2; // order and marker vins + ccvouts = 1; // token back to the originator break; case 'S': // fill ask @@ -508,9 +501,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const ccvouts ++; } } - - //fprintf(stderr,"fill validated\n"); break; + case 'E': // fillexchange ////////// not implemented yet //////////// return eval->Invalid("unexpected assets fillexchange funcid"); @@ -572,18 +564,13 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const */ } ////////// not implemented yet //////////// - //fprintf(stderr,"fill validated\n"); break; default: fprintf(stderr,"illegal assets funcid.(%c)\n",funcid); return eval->Invalid("unexpected assets funcid"); - //break; } - //bool bPrevent = PreventCC(eval, tx, preventCCvins, numvins, preventCCvouts, numvouts); // prevent presence of unknown cc vin or cc vouts in the tx - //std::cerr << "AssetsValidate() PreventCC returned=" << bPrevent << std::endl; - //return (bPrevent); // replaced PreventCC with min/max cc vin/vout calc to allow vin position flexibility: if (!CountCCVinVouts(cpAssets, tx, ccvins, ccvouts)) return eval->Invalid("invalid cc vin or vout count"); From ef2d1632b0b503325c8ee2bc24420a99bacba7ee Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 28 Jun 2021 20:03:43 +0500 Subject: [PATCH 021/348] test code refactored (mock tx and test tx made with same funcs) --- src/test-komodo-cc/test-assets.cpp | 1054 +++++++++++++++++----------- 1 file changed, 631 insertions(+), 423 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 8b22bb846c7..f6cf924461e 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -44,16 +44,24 @@ uint256 getRandomHash() class EvalMock : public Eval { -public: +private: int currentHeight; std::map txs; std::map blocks; //sstd::map> spends; - +public: + void AddTx(const CTransaction &tx) { + if (!tx.IsNull()) { + txs[tx.GetHash()] = tx; + } + } + const std::map & getTxs() { return txs; } bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const { + //std::cerr <<__func__ << " hash=" << hash.GetHex() << std::endl; auto r = txs.find(hash); if (r != txs.end()) { + std::cerr <<__func__ << " hash=" << hash.GetHex() << " found" << std::endl; txOut = r->second; if (blocks.count(hash) > 0) hashBlock = hash; @@ -65,7 +73,7 @@ class EvalMock : public Eval static EvalMock eval; -static CTransaction txnormal1, txnormal2, txnormal3, txnormal4, txnormalg, txask, txbid, txtokencreate1, txtokencreate2, txtokencreate3, txtokencreateUnused; +static CTransaction txnormal1, txnormal2, txnormal3, txnormal4, txnormalg, txask1, txbid1, txbid2, txtokencreate1, txtokencreate2, txtokencreate3, txtokencreateUnused; static uint256 tokenid1, tokenid2, tokenid3, tokenidUnused; // RJXkCF7mn2DRpUZ77XBNTKCe55M2rJbTcu @@ -94,7 +102,7 @@ CAmount TestAddNormalInputs(CMutableTransaction &mtx, CPubKey mypk, CAmount amou CAmount totalInputs = 0LL; char mypkaddr[KOMODO_ADDRESS_BUFSIZE]; Getscriptaddress(mypkaddr, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG); - for (auto const &t : eval.txs) { + for (auto const &t : eval.getTxs()) { for (int32_t v = 0; v < t.second.vout.size(); v ++) { char utxoaddr[KOMODO_ADDRESS_BUFSIZE]; Getscriptaddress(utxoaddr, t.second.vout[v].scriptPubKey); @@ -109,8 +117,33 @@ CAmount TestAddNormalInputs(CMutableTransaction &mtx, CPubKey mypk, CAmount amou } return 0LL; } +CAmount TestAddTokenInputs(CMutableTransaction &mtx, CPubKey mypk, uint256 tokenid, CAmount amount) +{ + CAmount totalInputs = 0LL; + struct CCcontract_info *cp, C; + cp = CCinit(&C, TokensV2::EvalCode()); + char mypkaddr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(mypkaddr, TokensV2::MakeCC1vout(EVAL_TOKENSV2, 0, mypk).scriptPubKey); + for (auto const &t : eval.getTxs()) { + for (int32_t v = 0; v < t.second.vout.size(); v ++) { + char utxoaddr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(utxoaddr, t.second.vout[v].scriptPubKey); + CTransaction tx; + //std::cerr << __func__ << " utxoaddr=" << utxoaddr << " mypkaddr=" << mypkaddr << " tx=" << t.second.GetHash().GetHex() << " v=" << v << std::endl; + if (strcmp(utxoaddr, mypkaddr) == 0 && + IsTokensvout(cp, &eval, t.second, v, tokenid )) { + mtx.vin.push_back(CTxIn(t.second.GetHash(), v)); + totalInputs += t.second.vout[v].nValue; + if (totalInputs >= amount) + return totalInputs; + } + } + } + return 0LL; +} -bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vini, int64_t utxovalue, const CScript scriptPubKey) + +bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vini, CAmount utxovalue, const CScript scriptPubKey) { CTransaction txNewConst(mtx); SignatureData sigdata; @@ -124,6 +157,10 @@ bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vin } } +// sign normal and cc inputs like FinalizeCCV2Tx does +// signatures are not checked really in these tests +// however normal and cc vins should have valid script or condition as this is checked in the assets cc validation code +// in functions like cp->ismyvin() or TotalPubkeyNormalAmount() bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_t *myprivkey, CAmount txfee, CScript opret) { auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); @@ -283,7 +320,7 @@ class TestAssetsCC : public ::testing::Test { // setup eval for tests ASSETCHAINS_CC = 2; - CreateTransactions(); + CreateMockTransactions(); } virtual void SetUp() { // enable print @@ -292,32 +329,104 @@ class TestAssetsCC : public ::testing::Test { mapMultiArgs["-debug"] = { "cctokens", "ccassets" }; } - static void CreateTransactions() + // run over CC V2 validation + bool TestRunCCEval(const CMutableTransaction &mtx) + { + CTransaction tx(mtx); + PrecomputedTransactionData txdata(tx); + ServerTransactionSignatureChecker checker(&tx, 0, 0, false, NULL, txdata); + CValidationState verifystate; + VerifyEval verifyEval = [] (CC *cond, void *checker) { + //fprintf(stderr,"checker.%p\n",(TransactionSignatureChecker*)checker); + return ((TransactionSignatureChecker*)checker)->CheckEvalCondition(cond); + }; + + // set some vars used in validation: + KOMODO_CONNECTING = 1; + KOMODO_CCACTIVATE = 1; + eval.state = CValidationState(); // clear validation state + EVAL_TEST = &eval; + + for(const auto &vin : tx.vin) { + if (IsCCInput(vin.scriptSig)) { + CC *cond = GetCryptoCondition(vin.scriptSig); + if (cond == NULL) { + std::cerr << __func__ << " GetCryptoCondition could not decode vin.scriptSig" << std::endl; + return false; + } + + int r = cc_verifyEval(cond, verifyEval, &checker); + if (r == 0) { + std::cerr << __func__ << " cc_verify error D" << std::endl; + return false; + } + std::cerr << __func__ << " cc_verify okay for vin.hash=" << vin.prevout.hash.GetHex() << std::endl; + break; + } + } + for(const auto &vout : tx.vout) { + if (vout.scriptPubKey.IsPayToCCV2()) { + + ScriptError error; + + bool bCheck = checker.CheckCryptoCondition(vout.scriptPubKey.GetCCV2SPK(), &error); + if (!bCheck) { + std::cerr << __func__ << " CheckCryptoCondition error=" << ScriptErrorString(error) << std::endl; + return false; + } + std::cerr << __func__ << " cc_verify okay for vout.nValue=" << vout.nValue << std::endl; + } + } + return true; + } + + static void CreateMockTransactions() { - std::cerr << __func__ << " enterred" << std::endl; txnormal1 = MakeNormalTx(pk1, 20000); + eval.AddTx(txnormal1); + txnormal2 = MakeNormalTx(pk1, 20000); + eval.AddTx(txnormal2); + txnormal3 = MakeNormalTx(pk2, 20000); + eval.AddTx(txnormal3); + txnormal4 = MakeNormalTx(pk2, 20000); + eval.AddTx(txnormal4); struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! + txnormalg = MakeNormalTx(GetUnspendable(cpTokens, NULL), 20000); + eval.AddTx(txnormalg); - txtokencreate1 = MakeTokenV2CreateTx(pk1); + txtokencreate1 = MakeTokenV2CreateTx(pk1, 10); + eval.AddTx(txtokencreate1); tokenid1 = txtokencreate1.GetHash(); - txtokencreate2 = MakeTokenV2CreateTx(pk2); + txtokencreate2 = MakeTokenV2CreateTx(pk2, 10); + eval.AddTx(txtokencreate2); tokenid2 = txtokencreate2.GetHash(); - txtokencreate3 = MakeTokenV2CreateTx(pk2); + txtokencreate3 = MakeTokenV2CreateTx(pk2, 10); + eval.AddTx(txtokencreate3); tokenid3 = txtokencreate3.GetHash(); - txtokencreateUnused = MakeTokenV2CreateTx(pk1); + txtokencreateUnused = MakeTokenV2CreateTx(pk1, 10); + eval.AddTx(txtokencreateUnused); tokenidUnused = txtokencreateUnused.GetHash(); - txask = MakeTokenV2AskTx(pk1); - txbid = MakeTokenV2BidTx(pk2); + txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 1000, 1000/2); + eval.AddTx(txask1); + + txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 1000, 1000/2); + eval.AddTx(txbid1); + + + //txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2); // test dust + } static CTransaction MakeNormalTx(CPubKey pk, CAmount val) @@ -325,378 +434,538 @@ class TestAssetsCC : public ::testing::Test { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); mtx.vin.push_back(CTxIn(getRandomHash(), 0)); mtx.vout.push_back(CTxOut(val, GetScriptForDestination(pk))); - eval.txs[mtx.GetHash()] = mtx; + //eval.txs[mtx.GetHash()] = mtx; return CTransaction(mtx); } - /*static CTransaction MakeNormalTxG() - { - struct CCcontract_info *cpTokens, tokensC; - cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - uint8_t privkeyg[32]; - CPubKey pkg = GetUnspendable(cpTokens, privkeyg); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - mtx.vin.push_back(CTxIn(getRandomHash(), 0)); - mtx.vout.push_back(CTxOut(100000, GetScriptForDestination(pkg))); - return CTransaction(mtx); - }*/ - - static CTransaction MakeTokenV2CreateTx(CPubKey pk) + static CMutableTransaction MakeTokenV2CreateTx(CPubKey pk, CAmount amount) { struct CCcontract_info *cp, C; cp = CCinit(&C, TokensV2::EvalCode()); - std::string name = "Test"; + std::string name = "Test" + std::to_string(rand()); std::string description = "desc"; + CAmount txfee = 10000; CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - mtx.vin.push_back(CTxIn(getRandomHash(), 0)); + if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { + std::cerr << __func__ << " could not add normal inputs" << std::endl; + return CTransaction(); + } mtx.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk)); - mtx.vout.push_back(CTxOut(0, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk.begin(), pk.end()), name, description, { }))); - eval.txs[mtx.GetHash()] = mtx; - return CTransaction(mtx); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, amount, pk)); + + if (!TestFinalizeTx(mtx, cp, testKeys[pk], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk.begin(), pk.end()), name, description, { }))) { + std::cerr << __func__ << " could finalize tx" << std::endl; + return CTransaction(); + } + //eval.txs[mtx.GetHash()] = mtx; + return mtx; } - static CTransaction MakeTokenV2AskTx(CPubKey pk) + static CMutableTransaction MakeTokenV2AskTx(struct CCcontract_info *cpTokens, CPubKey pk, uint256 tokenid, CAmount askamount, CAmount unit_price) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); struct CCcontract_info *cpAssets, C; + //struct CCcontract_info *cpTokens, tokensC; - CAmount askamount = 1000; - CAmount numtokens = 2; + uint8_t evalcodeNFT = 0; + //CAmount askamount = 1000; + //CAmount numtokens = 2; CAmount txfee = 10000; - cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + //cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - CAmount unit_price = askamount / numtokens; + //CAmount unit_price = askamount / numtokens; + CAmount numtokens = askamount / unit_price; - mtx.vin.push_back(CTxIn(txnormal1.GetHash(), 0)); + if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { + std::cerr << __func__ << " cant add normal inputs" << std::endl; + return CTransaction(); + } - CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), askamount, unspendableAssetsPubkey)); // tokens to global - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk)); // marker for my orders + CAmount inputs = TestAddTokenInputs(mtx, pk, tokenid, numtokens); + if (inputs == 0) { + std::cerr << __func__ << " cant add token inputs" << std::endl; + return CTransaction(); + } - mtx.vout.push_back(CTxOut(0, - TokensV2::EncodeTokenOpRet(tokenid1, {}, - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pk.begin(), pk.end())) }))); - eval.txs[mtx.GetHash()] = mtx; - return CTransaction(mtx); + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeNFT, numtokens, unspendableAssetsPubkey)); + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk)); + CAmount CCchange = inputs - numtokens; + if (CCchange != 0LL) { + // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), CCchange, pk)); + } + + // cond to spend NFT from mypk + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(evalcodeNFT, pk)); + CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey + + // sign vins: + if(!TestFinalizeTx(mtx, cpTokens, testKeys[pk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pk.begin(), pk.end())) }))) { + std::cerr << __func__ << " cant finalise tx" << std::endl; + return CTransaction(); + } + return mtx; } - static CTransaction MakeTokenV2BidTx(CPubKey pk) + static CMutableTransaction MakeTokenV2BidTx(struct CCcontract_info *cpAssets, CPubKey pk, uint256 tokenid, CAmount bidamount, CAmount unit_price) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cpAssets, C; + //struct CCcontract_info *cpAssets, C; - CAmount bidamount = 1000; - CAmount numtokens = 2; + //CAmount bidamount = 1000; + //CAmount numtokens = 2; CAmount txfee = 10000; - cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! + //cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! - CAmount unit_price = bidamount / numtokens; - - mtx.vin.push_back(CTxIn(txnormal3.GetHash(), 0)); + //CAmount unit_price = bidamount / numtokens; + if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { + std::cerr << __func__ << " cant add normal inputs" << std::endl; + return CTransaction(); + } CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, unspendableAssetsPubkey)); mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk)); // marker for my orders - mtx.vout.push_back(CTxOut(0, - TokensV2::EncodeTokenOpRet(tokenid2, {}, - { AssetsV2::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(pk.begin(), pk.end())) }))); - eval.txs[mtx.GetHash()] = mtx; - return CTransaction(mtx); + // sign vins: + if (!TestFinalizeTx(mtx, cpAssets, testKeys[pk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, {}, + { AssetsV2::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(pk.begin(), pk.end())) }))) { + std::cerr << __func__ << " cant finalise tx" << std::endl; + return CTransaction(); + } + return mtx; } - bool TestRunCCEval(const CMutableTransaction &mtx) + static CMutableTransaction MakeTokenV2FillAskTx(struct CCcontract_info *cpAssets, CPubKey pk, uint256 tokenid, uint256 asktxid, CAmount fill_units, CAmount paid_unit_price) { - CTransaction tx(mtx); - PrecomputedTransactionData txdata(tx); - ServerTransactionSignatureChecker checker(&tx, 0, 0, false, NULL, txdata); - CValidationState verifystate; - VerifyEval verifyEval = [] (CC *cond, void *checker) { - //fprintf(stderr,"checker.%p\n",(TransactionSignatureChecker*)checker); - return ((TransactionSignatureChecker*)checker)->CheckEvalCondition(cond); - }; + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpTokens, tokensC; - // set some vars used in validation: - KOMODO_CONNECTING = 1; - KOMODO_CCACTIVATE = 1; - eval.state = CValidationState(); // clear validation state - EVAL_TEST = &eval; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - for(const auto &vin : tx.vin) { - if (IsCCInput(vin.scriptSig)) { - CC *cond = GetCryptoCondition(vin.scriptSig); - if (cond == NULL) { - std::cerr << __func__ << " GetCryptoCondition could not decode vin.scriptSig" << std::endl; - return false; - } + CTransaction asktx; + uint256 hashBlock; + if (!GetTxUnconfirmedOpt(&eval, asktxid, asktx, hashBlock)) { + std::cerr << __func__ << " could not load asktx" << std::endl; + return CTransaction(); + } - int r = cc_verifyEval(cond, verifyEval, &checker); - if (r == 0) { - std::cerr << __func__ << " cc_verify error D" << std::endl; - return false; - } - std::cerr << __func__ << " cc_verify okay for vin.hash=" << vin.prevout.hash.GetHex() << std::endl; - break; - } + CAmount unit_price = 0; + // CAmount fillunits = ask; + CAmount txfee = 10000; + const int32_t askvout = ASSETS_GLOBALADDR_VOUT; + uint256 assetidOpret; + //CAmount paid_unit_price = -1; // not set + CAmount orig_assetoshis = asktx.vout[askvout].nValue; + + TokenDataTuple tokenData; + vuint8_t vopretNonfungible; + uint8_t evalcodeNFT = 0; + uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + if (!GetTokenData(&eval, tokenid, tokenData, vopretNonfungible)) { + std::cerr << __func__ << " cant get tokendata" << std::endl; + return CTransaction(); } - for(const auto &vout : tx.vout) { - if (vout.scriptPubKey.IsPayToCCV2()) { + if (vopretNonfungible.size() > 0) { + evalcodeNFT = vopretNonfungible.begin()[0]; + GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); + if (royaltyFract > NFTROYALTY_DIVISOR-1) + royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit + } + vuint8_t ownerpubkey = std::get<0>(tokenData); - ScriptError error; + vuint8_t origpubkey; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, asktx); // get orig pk, orig value - bool bCheck = checker.CheckCryptoCondition(vout.scriptPubKey.GetCCV2SPK(), &error); - if (!bCheck) { - std::cerr << __func__ << " CheckCryptoCondition error=" << ScriptErrorString(error) << std::endl; - return false; - } - std::cerr << __func__ << " cc_verify okay for vout.nValue=" << vout.nValue << std::endl; - } + if (paid_unit_price <= 0LL) + paid_unit_price = unit_price; + + CAmount paid_nValue = paid_unit_price * fill_units; + CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / NFTROYALTY_DIVISOR * royaltyFract : 0; + + if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { + std::cerr << __func__ << " cant add normal inputs" << std::endl; + return CTransaction(); } - return true; + mtx.vin.push_back(CTxIn(asktx.GetHash(), askvout, CScript())); // spend order tx + + // vout.0 tokens remainder to unspendable cc addr: + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeNFT, orig_assetoshis - fill_units, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr + + //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), fill_units, pk)); + mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr + if (royaltyFract > 0) // note it makes the vout even if roaltyValue is 0 + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner + + if (orig_assetoshis - fill_units > 0) // we dont need the marker if order is filled + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) + + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeNFT, unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); + + if (!TestFinalizeTx(mtx, cpAssets, testKeys[pk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { pk }, + { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))) { + std::cerr << __func__ << " cant finalise tx" << std::endl; + return CTransaction(); + } + + return mtx; } -}; -TEST_F(TestAssetsCC, tokenv2ask) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cpAssets, C; - struct CCcontract_info *cpTokens, tokensC; - CAmount askamount = 1000; - CAmount numtokens = 2; - CAmount txfee = 10000; + static CMutableTransaction MakeTokenV2FillBidTx(struct CCcontract_info *cpTokens, CPubKey pk, uint256 tokenid, uint256 bidtxid, CAmount bid_amount, CAmount unit_price, UniValue &data) + { + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpAssets, C; + //struct CCcontract_info *cpTokens, tokensC; + + const int32_t bidvout = ASSETS_GLOBALADDR_VOUT; + CAmount paid_amount; + //CAmount bid_amount; + CAmount orig_units; + //CAmount unit_price = 0; + CAmount fill_units = 2; + CAmount txfee = 10000; + uint256 assetidOpret; + CAmount paid_unit_price = 0; // not set - cpAssets = CCinit(&C, AssetsV2::EvalCode()); - cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + //cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - uint8_t evalcodeNFT = cpTokens->evalcodeNFT ? cpTokens->evalcodeNFT : 0; - CAmount unit_price = askamount / numtokens; + CTransaction bidtx; + uint256 hashBlock; + std::cerr << __func__ << " call to GetTxUnconfirmedOpt " << bidtxid.GetHex() << std::endl; + if (!GetTxUnconfirmedOpt(&eval, bidtxid, bidtx, hashBlock)) { + std::cerr << __func__ << " could not load bidtx" << std::endl; + return CTransaction(); + } - ASSERT_TRUE( TestAddNormalInputs(mtx, pk1, txfee) > 0LL); - mtx.vin.push_back(CTxIn(txtokencreate1.GetHash(), 1)); + TokenDataTuple tokenData; + vuint8_t vopretNonfungible; + uint8_t evalcodeNFT = 0; + uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + if (!GetTokenData(&eval, tokenid, tokenData, vopretNonfungible)) { + std::cerr << __func__ << " cant get token data" << std::endl; + return CTransaction(); + } + if (vopretNonfungible.size() > 0) { + evalcodeNFT = vopretNonfungible.begin()[0]; + GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); + if (royaltyFract > NFTROYALTY_DIVISOR-1) + royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit + } + vuint8_t ownerpubkey = std::get<0>(tokenData); - CAmount inputs = txtokencreate1.vout[1].nValue; + vuint8_t origpubkey; + std::cerr << __func__ << " bidtx=" << bidtx.GetHash().GetHex() << " " << HexStr(E_MARSHAL(ss << bidtx)) << " vouts=" << bidtx.vout.size() << std::endl; - CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeNFT, numtokens, unspendableAssetsPubkey)); - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk1)); - CAmount CCchange = inputs - numtokens; - if (CCchange != 0LL) { - // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), CCchange, pk1)); - } + bid_amount = bidtx.vout[bidvout].nValue; + if (GetOrderParams(origpubkey, unit_price, assetidOpret, bidtx) == 0) { // get orig pk, orig value + std::cerr << __func__ << " cant get order data" << std::endl; + return CTransaction(); + } + if (unit_price == 0) { + std::cerr << __func__ << " zero unit_price" << std::endl; + return CTransaction(); + } - // cond to spend NFT from mypk - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(evalcodeNFT, pk1)); - CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey + orig_units = bid_amount / unit_price; - // sign vins: - ASSERT_TRUE(TestFinalizeTx(mtx, cpTokens, testKeys[pk1], txfee, - TokensV2::EncodeTokenOpRet(tokenid1, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pk1.begin(), pk1.end())) }))); + if (paid_unit_price <= 0LL) + paid_unit_price = unit_price; - EXPECT_TRUE(TestRunCCEval(mtx)); -} + if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { + std::cerr << __func__ << " cant add normal inputs" << std::endl; + return CTransaction(); + } + mtx.vin.push_back(CTxIn(txtokencreate2.GetHash(), 1, CScript())); // spend token tx + mtx.vin.push_back(CTxIn(bidtx.GetHash(), bidvout, CScript())); // spend order tx -TEST_F(TestAssetsCC, tokenv2bid) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cpAssets, C; + CAmount tokenInputs = txtokencreate2.vout[1].nValue; - CAmount bidamount = 1000; - CAmount numtokens = 2; - CAmount txfee = 10000; + if (!SetBidFillamounts(unit_price, paid_amount, bid_amount, fill_units, orig_units, paid_unit_price)) { + std::cerr << __func__ << " SetBidFillamounts return false" << std::endl; + return CTransaction(); + } - cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! + CAmount royaltyValue = royaltyFract > 0 ? paid_amount / NFTROYALTY_DIVISOR * royaltyFract : 0; + CAmount tokensChange = tokenInputs - fill_units; - CAmount unit_price = bidamount / numtokens; + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - ASSERT_TRUE( TestAddNormalInputs(mtx, pk1, txfee) > 0LL); + if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { // bidder has coins for more tokens or only dust is sent back to global address + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bid_amount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder or the dust is sent back to cc global addr + if (bid_amount - paid_amount <= ASSETS_NORMAL_DUST) + std::cerr << __func__ << " dust detected (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; + } + else + mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator + mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG)); // vout1 coins to mypk normal + if (royaltyFract > 0) // note it makes vout even if roaltyValue is 0 + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator + if (orig_units - fill_units > 0) // order is not finished yet + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey + + if (tokensChange != 0LL) + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), tokensChange, pk)); // change in single-eval tokens + + CMutableTransaction mtx2(mtx); // copy + + CCwrapper wrCond1(MakeCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); // spend coins + CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); + + CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(evalcodeNFT, pk)); // spend my tokens to fill buy + CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey + + if (!TestFinalizeTx(mtx, cpTokens, testKeys[pk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { pubkey2pk(origpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))) { + std::cerr << __func__ << " could not finalize tx" << std::endl; + return CTransaction(); + } + data.pushKV("origpubkey", HexStr(origpubkey)); + data.pushKV("unit_price", unit_price); - CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, unspendableAssetsPubkey)); - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk1)); // marker for my orders + return mtx; + } - // sign vins: - ASSERT_TRUE(TestFinalizeTx(mtx, cpAssets, testKeys[pk1], txfee, - TokensV2::EncodeTokenOpRet(tokenid1, {}, - { AssetsV2::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(pk1.begin(), pk1.end())) }))); - EXPECT_TRUE(TestRunCCEval(mtx)); -} + static CMutableTransaction MakeTokenV2CancelAskTx(struct CCcontract_info *cpAssets, uint256 tokenid, uint256 asktxid, UniValue &data) + { + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CTransaction asktx; + uint256 hashBlock; + if (!GetTxUnconfirmedOpt(&eval, asktxid, asktx, hashBlock)) { + std::cerr << __func__ << " could not load asktx" << std::endl; + return CTransaction(); + } + CAmount txfee = 10000; + CAmount askamount = asktx.vout[ASSETS_GLOBALADDR_VOUT].nValue; -TEST_F(TestAssetsCC, tokenv2fillask) -{ + TokenDataTuple tokenData; + vuint8_t vopretNonfungible; + if (!GetTokenData(&eval, tokenid, tokenData, vopretNonfungible)) { + std::cerr << __func__ << " could not load token data" << std::endl; + return CTransaction(); + } + uint8_t evalcodeNFT = 0; + if (vopretNonfungible.size() > 0) + evalcodeNFT = vopretNonfungible[0]; + vuint8_t ownerpubkey = std::get<0>(tokenData); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cpAssets, C; - struct CCcontract_info *cpTokens, tokensC; + if (TestAddNormalInputs(mtx, ownerpubkey, txfee) == 0LL) { + std::cerr << __func__ << " could not add normal inputs" << std::endl; + return CTransaction(); + } + mtx.vin.push_back(CTxIn(asktxid, ASSETS_GLOBALADDR_VOUT, CScript())); + + uint8_t dummyEvalCode; + uint256 dummyAssetid, dummyAssetid2; + int64_t dummyPrice; + std::vector dummyOrigpubkey; + uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(asktx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey); + if (funcid == 's' && asktx.vout.size() > 1) + mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // spend marker if funcid='s' + else if (funcid == 'S' && asktx.vout.size() > 3) + mtx.vin.push_back(CTxIn(asktxid, 3, CScript())); // spend marker if funcid='S' + else { + std::cerr << __func__ << "invalid ask tx" << std::endl; + return CTransaction(); + } - CAmount unit_price = 0;; - CAmount fillunits = 2; - CAmount txfee = 10000; - const int32_t askvout = ASSETS_GLOBALADDR_VOUT; - uint256 assetidOpret; - CAmount paid_unit_price = -1; // not set - CAmount orig_assetoshis = txask.vout[askvout].nValue; + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(cpAssets->evalcodeNFT ? cpAssets->evalcodeNFT : TokensV2::EvalCode(), askamount, ownerpubkey)); // one-eval token vout - cpAssets = CCinit(&C, AssetsV2::EvalCode()); - cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + // init assets 'unspendable' privkey and pubkey + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), cpAssets->evalcodeNFT, unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); + + if (!TestFinalizeTx(mtx, cpAssets, testKeys[ownerpubkey], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))) { + std::cerr << __func__ << " could not finalize tx" << std::endl; + return CTransaction(); + } + + data.pushKV("ownerpubkey", HexStr(ownerpubkey)); + data.pushKV("askamount", askamount); - TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - uint8_t evalcodeNFT = 0; - uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - ASSERT_TRUE( GetTokenData(&eval, tokenid1, tokenData, vopretNonfungible) ); - if (vopretNonfungible.size() > 0) { - evalcodeNFT = vopretNonfungible.begin()[0]; - GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); - if (royaltyFract > NFTROYALTY_DIVISOR-1) - royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit + return mtx; } - vuint8_t ownerpubkey = std::get<0>(tokenData); - vuint8_t origpubkey; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txask); // get orig pk, orig value + static CMutableTransaction MakeTokenV2CancelBidTx(struct CCcontract_info *cpAssets, uint256 tokenid, uint256 bidtxid, UniValue &data) + { + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - if (paid_unit_price <= 0LL) - paid_unit_price = unit_price; + CTransaction bidtx; + uint256 hashBlock; + if (!GetTxUnconfirmedOpt(&eval, bidtxid, bidtx, hashBlock)) { + std::cerr << __func__ << " could not load bidtx" << std::endl; + return CTransaction(); + } + CAmount txfee = 10000; + CAmount bidamount = bidtx.vout[ASSETS_GLOBALADDR_VOUT].nValue; - CAmount paid_nValue = paid_unit_price * fillunits; - CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / NFTROYALTY_DIVISOR * royaltyFract : 0; + TokenDataTuple tokenData; + vuint8_t vopretNonfungible; + if (!GetTokenData(&eval, tokenid, tokenData, vopretNonfungible)) { + std::cerr << __func__ << " could not load token data" << std::endl; + return CTransaction(); + } - ASSERT_TRUE( TestAddNormalInputs(mtx, pk2, txfee) > 0LL); - mtx.vin.push_back(CTxIn(txask.GetHash(), askvout, CScript())); // spend order tx - // vout.0 tokens remainder to unspendable cc addr: - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeNFT, orig_assetoshis - fillunits, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr + uint8_t evalcodeNFT = 0; + if (vopretNonfungible.size() > 0) + evalcodeNFT = vopretNonfungible[0]; + vuint8_t ownerpubkey = std::get<0>(tokenData); - //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), fillunits, pk2)); - mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr - if (royaltyFract > 0) // note it makes the vout even if roaltyValue is 0 - mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner + if (TestAddNormalInputs(mtx, ownerpubkey, txfee) == 0LL) { + std::cerr << __func__ << " could not add normal inputs" << std::endl; + return CTransaction(); + } + mtx.vin.push_back(CTxIn(bidtxid, ASSETS_GLOBALADDR_VOUT, CScript())); + + uint8_t dummyEvalCode; + uint256 dummyAssetid, dummyAssetid2; + int64_t dummyPrice; + std::vector dummyOrigpubkey; + uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(bidtx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey); + if (funcid == 'b' && bidtx.vout.size() > 1) + mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' + else if (funcid == 'B' && bidtx.vout.size() > 3) + mtx.vin.push_back(CTxIn(bidtxid, 3, CScript())); // spend marker if funcid='B' + else { + std::cerr << __func__ << "invalid bid tx" << std::endl; + return CTransaction(); } - if (orig_assetoshis - fillunits > 0) // we dont need the marker if order is filled - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) + if (bidamount > ASSETS_NORMAL_DUST) + mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); + else { + // send dust back to global addr + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, GetUnspendable(cpAssets, NULL))); + std::cerr << __func__ << " dust detected bidamount=" << bidamount << std::endl; + } - uint8_t unspendableAssetsPrivkey[32]; - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + // init assets 'unspendable' privkey and pubkey + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeNFT, unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); + // sign, add change, add opreturn + if (!TestFinalizeTx(mtx, cpAssets, testKeys[ownerpubkey], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))) { + std::cerr << __func__ << " could not finalise tx" << std::endl; + return CTransaction(); + } - ASSERT_TRUE(TestFinalizeTx(mtx, cpAssets, testKeys[pk2], txfee, - TokensV2::EncodeTokenOpRet(tokenid1, { pk2 }, - { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))); + data.pushKV("ownerpubkey", HexStr(ownerpubkey)); + data.pushKV("bidamount", bidamount); + return mtx; + } - EXPECT_TRUE(TestRunCCEval(mtx)); -} +}; -TEST_F(TestAssetsCC, tokenv2fillbid) + +// -------------------------------------------------- +// assets cc tests: + +TEST_F(TestAssetsCC, tokenv2ask) { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cpAssets, C; struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - const int32_t bidvout = ASSETS_GLOBALADDR_VOUT; - CAmount paid_amount; - CAmount bid_amount; - CAmount orig_units; - CAmount unit_price = 0; - CAmount fill_units = 2; + CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 1000, 1000/2); + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: valid tokenv2ask + EXPECT_TRUE(TestRunCCEval(mtx)); +} + +TEST_F(TestAssetsCC, tokenv2bid) +{ CAmount txfee = 10000; - uint256 assetidOpret; - CAmount paid_unit_price = 0; // not set + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - cpAssets = CCinit(&C, AssetsV2::EvalCode()); - cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + CMutableTransaction mtx = MakeTokenV2BidTx(cpAssets, pk2, tokenid1, 1000, 1000/2); + ASSERT_FALSE(CTransaction(mtx).IsNull()); - TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - uint8_t evalcodeNFT = 0; - uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - ASSERT_TRUE( GetTokenData(&eval, tokenid1, tokenData, vopretNonfungible) ); - if (vopretNonfungible.size() > 0) { - evalcodeNFT = vopretNonfungible.begin()[0]; - GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); - if (royaltyFract > NFTROYALTY_DIVISOR-1) - royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit - } - vuint8_t ownerpubkey = std::get<0>(tokenData); + // test: valid tokenv2bid + EXPECT_TRUE(TestRunCCEval(mtx)); - vuint8_t origpubkey; - bid_amount = txbid.vout[bidvout].nValue; - ASSERT_TRUE(GetOrderParams(origpubkey, unit_price, assetidOpret, txbid) != 0); // get orig pk, orig value - ASSERT_TRUE(unit_price != 0); + CMutableTransaction mtx1(mtx); - orig_units = bid_amount / unit_price; + // test: too low bid amount < unit_price + mtx1.vout[0] = TokensV2::MakeCC1vout(AssetsV2::EvalCode(), 9999, unspendableAssetsPubkey); + mtx1.vout.pop_back(); - if (paid_unit_price <= 0LL) - paid_unit_price = unit_price; + ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(tokenid1, {}, + { AssetsV2::EncodeAssetOpRet('b', zeroid, 10000, vuint8_t(pk2.begin(), pk2.end())) }))); + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail +} - ASSERT_TRUE( TestAddNormalInputs(mtx, pk2, txfee) > 0LL); - mtx.vin.push_back(CTxIn(txtokencreate2.GetHash(), 1, CScript())); // spend token tx - mtx.vin.push_back(CTxIn(txbid.GetHash(), bidvout, CScript())); // spend order tx - //CAmount inputs = txnormal2.vout[0].nValue; - CAmount tokenInputs = txtokencreate2.vout[1].nValue; +TEST_F(TestAssetsCC, tokenv2fillask) +{ - ASSERT_TRUE(SetBidFillamounts(unit_price, paid_amount, bid_amount, fill_units, orig_units, paid_unit_price)); + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, txask1.GetHash(), 2, 0); + ASSERT_FALSE(CTransaction(mtx).IsNull()); - CAmount royaltyValue = royaltyFract > 0 ? paid_amount / NFTROYALTY_DIVISOR * royaltyFract : 0; - CAmount tokensChange = tokenInputs - fill_units; + // test: valid tokenv2fillask + EXPECT_TRUE(TestRunCCEval(mtx)); +} - uint8_t unspendableAssetsPrivkey[32]; - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { // bidder has coins for more tokens or only dust is sent back to global address - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bid_amount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder or the dust is sent back to cc global addr - if (bid_amount - paid_amount <= ASSETS_NORMAL_DUST) - std::cerr << __func__ << " dust detected (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; - } - else - mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator - mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(pk2)) << OP_CHECKSIG)); // vout1 coins to mypk normal - if (royaltyFract > 0) // note it makes vout even if roaltyValue is 0 - mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator - if (orig_units - fill_units > 0) // order is not finished yet - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey - - if (tokensChange != 0LL) - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), tokensChange, pk2)); // change in single-eval tokens - - CMutableTransaction mtx2(mtx); // copy - - CCwrapper wrCond1(MakeCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); // spend coins - CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); - - CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(evalcodeNFT, pk2)); // spend my tokens to fill buy - CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey +TEST_F(TestAssetsCC, tokenv2fillbid) +{ + UniValue data(UniValue::VOBJ); + struct CCcontract_info *cpTokens, C; + cpTokens = CCinit(&C, TokensV2::EvalCode()); + + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, txbid1.GetHash(), 2, 0, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); - ASSERT_TRUE(TestFinalizeTx(mtx, cpTokens, testKeys[pk2], txfee, - TokensV2::EncodeTokenOpRet(tokenid2, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); + // test: valid tokenv2fillbid EXPECT_TRUE(TestRunCCEval(mtx)); + CMutableTransaction mtx1(mtx); + + CAmount txfee = 10000; + vuint8_t origpubkey = ParseHex(data["origpubkey"].getValStr()); + CAmount unit_price = data["unit_price"].get_int64(); - // spend bad tokenid - mtx2.vin[1] = CTxIn(txtokencreate3.GetHash(), 1, CScript()); // spend bad tokenid3 - ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk2], txfee, + // test: fill with another tokenid + mtx1.vin[1] = CTxIn(txtokencreate3.GetHash(), 1, CScript()); // spend other tokenid3 + mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(origpubkey) }, { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); - EXPECT_FALSE(TestRunCCEval(mtx2)); - - + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: can't fill with another tokenid3 } TEST_F(TestAssetsCC, tokenv2cancelask) @@ -709,85 +978,54 @@ TEST_F(TestAssetsCC, tokenv2cancelask) cpAssets = CCinit(&C, AssetsV2::EvalCode()); cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - for (CTransaction vintx : std::vector{ txask }) // TODO add more txasks + for (CTransaction vintx : std::vector{ txask1 }) // TODO add more txasks { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - + UniValue data(UniValue::VOBJ); uint256 asktxid = vintx.GetHash(); - CAmount askamount = vintx.vout[ASSETS_GLOBALADDR_VOUT].nValue; - - TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - ASSERT_TRUE( GetTokenData(&eval, tokenid1, tokenData, vopretNonfungible) ); - uint8_t evalcodeNFT = 0; - if (vopretNonfungible.size() > 0) - evalcodeNFT = vopretNonfungible[0]; - vuint8_t ownerpubkey = std::get<0>(tokenData); - - ASSERT_TRUE( TestAddNormalInputs(mtx, ownerpubkey, txfee) > 0LL); - mtx.vin.push_back(CTxIn(asktxid, ASSETS_GLOBALADDR_VOUT, CScript())); - - uint8_t dummyEvalCode; - uint256 dummyAssetid, dummyAssetid2; - int64_t dummyPrice; - std::vector dummyOrigpubkey; - uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey); - if (funcid == 's' && vintx.vout.size() > 1) - mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // spend marker if funcid='s' - else if (funcid == 'S' && vintx.vout.size() > 3) - mtx.vin.push_back(CTxIn(asktxid, 3, CScript())); // spend marker if funcid='S' - else { - std::cerr << __func__ << "invalid ask tx" << std::endl; - ASSERT_FALSE(true); - } - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(cpAssets->evalcodeNFT ? cpAssets->evalcodeNFT : TokensV2::EvalCode(), askamount, ownerpubkey)); // one-eval token vout - - // init assets 'unspendable' privkey and pubkey - uint8_t unspendableAssetsPrivkey[32]; - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), cpAssets->evalcodeNFT, unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + CMutableTransaction mtx = MakeTokenV2CancelAskTx(cpAssets, tokenid1, asktxid, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); - ASSERT_TRUE(TestFinalizeTx(mtx, cpAssets, testKeys[ownerpubkey], txfee, - TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + vuint8_t ownerpubkey = ParseHex(data["ownerpubkey"].getValStr()); + CAmount askamount = data["askamount"].get_int64(); + // test: valid tokenv2cancelask EXPECT_TRUE(TestRunCCEval(mtx)); - // invalid pk in assets opreturn + // test: invalid pk in assets opreturn CMutableTransaction mtx2(mtx); mtx2.vout.pop_back(); mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(pk2.begin(), pk2.end())) } ))); - // EXPECT_FALSE(TestRunCCEval(mtx2)); // is not checked + EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret not checked - // invalid pk in token opret + // test: another pk in token opret CMutableTransaction mtx3(mtx); mtx3.vout.pop_back(); mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { pkunused }, { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - // EXPECT_FALSE(TestRunCCEval(mtx3)); // is not checked + EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked - // invalid pk where to funds sent + // test: invalid pk where to funds sent CMutableTransaction mtx4(mtx); mtx4.vout[0] = TokensV2::MakeTokensCC1vout(cpAssets->evalcodeNFT ? cpAssets->evalcodeNFT : TokensV2::EvalCode(), askamount, pk2); - EXPECT_FALSE(TestRunCCEval(mtx4)); // is not checked + EXPECT_FALSE(TestRunCCEval(mtx4)); // must fail - // invalid tokenid in token opret + // test: invalid tokenid in token opret CMutableTransaction mtx5(mtx); mtx5.vout.pop_back(); mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { ownerpubkey }, { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - EXPECT_FALSE(TestRunCCEval(mtx5)); // is not checked + EXPECT_FALSE(TestRunCCEval(mtx5)); // must fail: cant send to another tokenid - // opposite funcid in token opret + // test: invalid funcid in token opret CMutableTransaction mtx6(mtx); mtx6.vout.pop_back(); mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - EXPECT_FALSE(TestRunCCEval(mtx6)); // is not checked + EXPECT_FALSE(TestRunCCEval(mtx6)); // must fail } } @@ -800,88 +1038,59 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) cpAssets = CCinit(&C, AssetsV2::EvalCode()); cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - for (CTransaction vintx : std::vector{ txbid }) // TODO add more txasks + for (CTransaction vintx : std::vector{ txbid1 }) // TODO add more txbid { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue data(UniValue::VOBJ); uint256 bidtxid = vintx.GetHash(); - CAmount bidamount = vintx.vout[ASSETS_GLOBALADDR_VOUT].nValue; - - TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - ASSERT_TRUE( GetTokenData(&eval, tokenid2, tokenData, vopretNonfungible) ); - uint8_t evalcodeNFT = 0; - if (vopretNonfungible.size() > 0) - evalcodeNFT = vopretNonfungible[0]; - vuint8_t ownerpubkey = std::get<0>(tokenData); - - ASSERT_TRUE( TestAddNormalInputs(mtx, ownerpubkey, txfee) > 0LL); - mtx.vin.push_back(CTxIn(bidtxid, ASSETS_GLOBALADDR_VOUT, CScript())); - - uint8_t dummyEvalCode; - uint256 dummyAssetid, dummyAssetid2; - int64_t dummyPrice; - std::vector dummyOrigpubkey; - uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey); - if (funcid == 'b' && vintx.vout.size() > 1) - mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' - else if (funcid == 'B' && vintx.vout.size() > 3) - mtx.vin.push_back(CTxIn(bidtxid, 3, CScript())); // spend marker if funcid='B' - else { - std::cerr << __func__ << "invalid bid tx" << std::endl; - ASSERT_FALSE(true); - } - if (bidamount > ASSETS_NORMAL_DUST) - mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); - else { - // send dust back to global addr - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, GetUnspendable(cpAssets, NULL))); - std::cerr << __func__ << " dust detected bidamount=" << bidamount << std::endl; - } + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + CMutableTransaction mtx = MakeTokenV2CancelBidTx(cpAssets, tokenid2, bidtxid, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); - // init assets 'unspendable' privkey and pubkey - uint8_t unspendableAssetsPrivkey[32]; - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - - // sign, add change, add opreturn - ASSERT_TRUE(TestFinalizeTx(mtx, cpAssets, testKeys[ownerpubkey], txfee, - TokensV2::EncodeTokenOpRet(tokenid2, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + vuint8_t ownerpubkey = ParseHex(data["ownerpubkey"].getValStr()); + CAmount bidamount = data["bidamount"].get_int64(); + // test: valid tokenv2cancelbid EXPECT_TRUE(TestRunCCEval(mtx)); - // invalid pk in assets opreturn + // test: invalid pk in assets opreturn CMutableTransaction mtx2(mtx); mtx2.vout.pop_back(); mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { ownerpubkey }, { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(pk1.begin(), pk1.end())) } ))); - // EXPECT_FALSE(TestRunCCEval(mtx2)); // is not checked + EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret is not checked - // invalid pk in token opret + // test: invalid pk in token opret CMutableTransaction mtx3(mtx); mtx3.vout.pop_back(); mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pkunused }, { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - // EXPECT_FALSE(TestRunCCEval(mtx3)); // is not checked + EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked - // invalid pk where to funds sent + // test: invalid pk where to funds sent CMutableTransaction mtx4(mtx); mtx4.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(pkunused)) << OP_CHECKSIG); - EXPECT_FALSE(TestRunCCEval(mtx4)); // is not checked + EXPECT_FALSE(TestRunCCEval(mtx4)); // must fail as can't send the remainder to another pk - // invalid tokenid in token opret + // test: invalid tokenid in token opret CMutableTransaction mtx5(mtx); mtx5.vout.pop_back(); mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { ownerpubkey }, { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); EXPECT_FALSE(TestRunCCEval(mtx5)); - // opposite funcid in token opret + // test: invalid funcid in token opret CMutableTransaction mtx6(mtx); mtx6.vout.pop_back(); mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pk2 }, { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); EXPECT_FALSE(TestRunCCEval(mtx6)); + + // test: send dust to normals + //CMutableTransaction mtx7(mtx); + //mtx7.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG); + //EXPECT_FALSE(TestRunCCEval(mtx7)); // must fail: dust should stay on cc global output } } @@ -891,63 +1100,62 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) TEST_F(TestAssetsCC, tokenv2create) { - struct CCcontract_info *cp, C; - cp = CCinit(&C, TokensV2::EvalCode()); - std::string name = "T1"; - std::string description = "desc"; - CAmount txfee = 10000; - - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - ASSERT_TRUE( TestAddNormalInputs(mtx, pk1, txfee) > 0LL); - mtx.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); - - // copies: - CMutableTransaction mtx1(mtx); - CMutableTransaction mtx2(mtx); - //CMutableTransaction mtx3(mtx); - - // sign vins: - // normal vin: - /*CBasicKeyStore tempKeystore; - CKey key; - key.Set(privkey1, privkey1+sizeof(privkey1), true); - tempKeystore.AddKey(key); - int32_t ivin = 0; - ASSERT_TRUE(TestSignTx(tempKeystore, mtx, ivin, txnormal2.vout[0].nValue, txnormal2.vout[0].scriptPubKey));*/ - - // sign, add change, add opreturn - ASSERT_TRUE(TestFinalizeTx(mtx, cp, testKeys[pk1], txfee, - TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + struct CCcontract_info *cpTokens, C; + cpTokens = CCinit(&C, TokensV2::EvalCode()); + CMutableTransaction mtx = MakeTokenV2CreateTx(pk1, 10); + ASSERT_FALSE(CTransaction(mtx).IsNull()); EXPECT_TRUE(TestRunCCEval(mtx)); - // token sent to another pk + CAmount txfee = 0; + std::string name = "T2"; + std::string description = "desc2"; + + // test: token sent to another pk + CMutableTransaction mtx1(mtx); mtx1.vout[1] = TokensV2::MakeTokensCC1vout(0, 10, pk2); - ASSERT_TRUE(TestFinalizeTx(mtx1, cp, testKeys[pk1], txfee, + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk1], txfee, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); - EXPECT_TRUE(TestRunCCEval(mtx1)); // allow sent created tokens to any pk!! + EXPECT_TRUE(TestRunCCEval(mtx1)); // allow sending created tokens to any pk!! - // invalid pk in opreturn: - ASSERT_TRUE(TestFinalizeTx(mtx2, cp, testKeys[pk1], txfee, + // test: invalid pk in opreturn: + CMutableTransaction mtx2(mtx); + mtx2.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk1], txfee, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { }))); EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail - // create token with global pk: - CMutableTransaction mtx3 = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + // test: no token vouts, sent to normal + CMutableTransaction mtx3(mtx); + mtx3.vout[1] = CTxOut(10, CScript() << ParseHex(HexStr(pk1)) << OP_CHECKSIG); + mtx3.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx3, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + EXPECT_FALSE(TestRunCCEval(mtx3)); // fail for no token cc vouts + + // test: no token vouts, sent to cc v1 + CMutableTransaction mtx4(mtx); + mtx4.vout[1] = TokensV1::MakeCC1vout(EVAL_ASSETS, 10, pk2); // sent to cc v1 vout + mtx4.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx4, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + EXPECT_FALSE(TestRunCCEval(mtx4)); // fail for no token cc vouts + + // test: invalid token created with global pk: + CMutableTransaction mtx5 = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cpTokens, tokensC; - cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); uint8_t privkeyg[32]; CPubKey pkg = GetUnspendable(cpTokens, privkeyg); - mtx3.vin.push_back(CTxIn(txnormalg.GetHash(), 0)); - mtx3.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); - mtx3.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); + mtx5.vin.push_back(CTxIn(txnormalg.GetHash(), 0)); + mtx5.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cpTokens, NULL))); + mtx5.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); - ASSERT_TRUE(TestFinalizeTx(mtx3, cp, privkeyg, txfee, + ASSERT_TRUE(TestFinalizeTx(mtx5, cpTokens, privkeyg, txfee, TokensV2::EncodeTokenCreateOpRet(vscript_t(pkg.begin(), pkg.end()), name, description, { }))); - EXPECT_FALSE(TestRunCCEval(mtx3)); // must fail + EXPECT_FALSE(TestRunCCEval(mtx5)); // must fail } From 3def8b449a9f785c0b0f727554a2367b8867762b Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 29 Jun 2021 09:38:44 +0500 Subject: [PATCH 022/348] dust disabled on non-cc tx --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 5f00330167f..ebdd821de8b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -924,7 +924,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight) else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) { reason = "bare-multisig"; return false; - } else if (!IsCryptoConditionsEnabled() && txout.IsDust(::minRelayTxFee)) { // allow dust for cc chains + } else if (whichType != TX_CRYPTOCONDITION /*!IsCryptoConditionsEnabled()*/ && txout.IsDust(::minRelayTxFee)) { // allow dust for cc chains reason = "dust"; return false; } From d54d792035b44cbfa6f534c72e28e871ca7fca56 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 29 Jun 2021 09:39:46 +0500 Subject: [PATCH 023/348] Added FinalizeCCTx param to disable dust change --- src/cc/CCassets.h | 1 - src/cc/CCassetstx_impl.h | 14 +++++------ src/cc/CCinclude.h | 17 ++++++++----- src/cc/CCtokens.h | 2 +- src/cc/CCtokens_impl.h | 7 +++--- src/cc/CCtx.cpp | 51 ++++++++++++++++++++++---------------- src/cc/old/CCtokens_v0.cpp | 2 +- 7 files changed, 53 insertions(+), 41 deletions(-) diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index 038eba4bb8b..c0e574d3a38 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -30,7 +30,6 @@ #define ASSETS_GLOBALADDR_VIN 1 #define ASSETS_GLOBALADDR_VOUT 0 #define ASSETS_MARKER_AMOUNT 10000 -#define ASSETS_NORMAL_DUST 500 // CCcustom bool AssetsValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index 7bc4c262ca7..d05f4824550 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -251,7 +251,7 @@ UniValue CreateBuyOffer(const CPubKey &mypk, int64_t txfee, int64_t bidamount, u mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, unspendableAssetsPubkey)); mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk)); // marker for my orders - UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), 0, cpAssets, mtx, mypk, txfee, + UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, {}, // TODO: actually this tx is not 'tokens', maybe it is better not to have token opret here but only asset opret. { A::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(mypk.begin(), mypk.end())) } )); // But still such token opret should not make problems because no token eval in these vouts if (!ResultHasTx(sigData)) @@ -315,7 +315,7 @@ UniValue CreateSell(const CPubKey &mypk, int64_t txfee, int64_t numtokens, uint2 CCwrapper wrCond(T::MakeTokensCCcond1(evalcodeNFT, mypk)); CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey - UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), mask, cpTokens, mtx, mypk, txfee, + UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpTokens, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { unspendableAssetsPubkey }, { A::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(mypk.begin(), mypk.end()) ) } )); if (!ResultHasTx(sigData)) @@ -389,7 +389,7 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a EncodeAssetOpRet('e', assetid2, pricetotal, Mypubkey())); } ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// - return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret)); + return(FinalizeCCTx(FINALIZECCTX_NO_CHANGE_WHEN_DUST,cp,mtx,mypk,txfee,opret)); } else { fprintf(stderr, "need some assets to place ask\n"); @@ -456,7 +456,7 @@ UniValue CancelBuyOffer(const CPubKey &mypk, int64_t txfee,uint256 assetid,uint2 // mtx.vout.push_back(CTxOut(ASSETS_MARKER_AMOUNT, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // we dont need a marker for cancelled orders - UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), mask, cpAssets, mtx, mypk, txfee, + UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, {}, { A::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(mypk.begin(), mypk.end())) })); if (!ResultHasTx(sigData)) @@ -534,7 +534,7 @@ UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), cpAssets->evalcodeNFT, unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); - UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), mask, cpAssets, mtx, mypk, txfee, + UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { mypk }, { A::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(mypk.begin(), mypk.end())) } )); if (!ResultHasTx(sigData)) @@ -651,7 +651,7 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 CCwrapper wrCond2(T::MakeTokensCCcond1(evalcodeNFT, mypk)); // spend my tokens to fill buy CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey - UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), mask, cpTokens, mtx, mypk, txfee, + UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpTokens, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { pubkey2pk(origpubkey) }, { A::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) })); if (!ResultHasTx(sigData)) @@ -789,7 +789,7 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a //cpAssets->evalcodeNFT = evalcodeNFT; // set nft eval for signing - UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), mask, cpAssets, mtx, mypk, txfee, + UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { mypk }, { A::EncodeAssetOpRet('S', assetid2, unit_price, origpubkey) } )); if (!ResultHasTx(sigData)) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 31888f50777..29079e6f1bb 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -87,6 +87,8 @@ Details. #define CCENABLE(x) ASSETCHAINS_CCDISABLES[((uint8_t)x)] = 0 #define bits256_nonz(a) (((a).ulongs[0] | (a).ulongs[1] | (a).ulongs[2] | (a).ulongs[3]) != 0) +#define ASSETS_NORMAL_DUST 500 + #define MAY2020_NNELECTION_HARDFORK 1592146800 //(Sunday, June 14th, 2020 03:00:00 PM UTC) #define JUNE2021_NNELECTION_HARDFORK 1623682800 // dPoW Season 5 Monday, June 14th, 2021 (03:00:00 PM UTC) @@ -866,11 +868,14 @@ CPubKey check_signing_pubkey(CScript scriptSig); bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey); extern std::vector NULL_pubkeys; //!< constant value for use in functions where such value might be passed @see FinalizeCCTx -#define FINALIZECCTX_NO_CHANGE 0x1 + +#define FINALIZECCTX_ALWAYS_CHANGE 0x0 +#define FINALIZECCTX_NO_CHANGE 0x1 #define FINALIZECCTX_NO_CHANGE_WHEN_ZERO 0x2 +#define FINALIZECCTX_NO_CHANGE_WHEN_DUST 0x4 /// overload old-style FinalizeCCTx for compatibility -/// @param skipmask parameter is not used +/// @param changeFlag whether or not add normal change. Default 0 is always add change even 0 /// @param cp contract info structure with cc eval code, module's global address and privkey. It also could have a vector of probe cryptoconditions created by CCAddVintxCond /// @param mtx prepared transaction to sign /// @param mypk my pubkey to sign @@ -878,7 +883,7 @@ extern std::vector NULL_pubkeys; //!< constant value for use in functio /// @param opret opreturn vout which function will add if it is not empty /// @param pubkeys array of pubkeys to make multiple probe 1of2 cc's with the call Make1of2cond(cp->evalcode, globalpk, pubkeys[i]) /// @returns signed transaction in hex encoding -std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector pubkeys = NULL_pubkeys); +std::string FinalizeCCTx(uint32_t changeFlag,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector pubkeys = NULL_pubkeys); /// FinalizeCCTx is a very useful function that will properly sign both CC and normal inputs, adds normal change and might add an opreturn output. /// This allows for Antara module transaction creation rpc functions to create an CMutableTransaction object, add the appropriate vins and vouts to it and use FinalizeCCTx to properly sign the transaction. @@ -890,7 +895,7 @@ std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTr /// For a set of 1of2 cc with pairs of module globalpk and some other pk, spending with global pk, pass a vector with pubkeys as 'pubkeys' parameter. /// For any other cc case use CCAddVintxCond function to add any possible probe cryptoconditions to the cp opbject. /// @param remote true if the caller is in remote nspv mode -/// @param skipmask parameter is not used +/// @param changeFlag whether or not add normal change. Default 0 is always add change even 0 /// @param cp contract info structure with cc eval code, module's global address and privkey. It also could have a vector of probe cryptoconditions created by CCAddVintxCond /// @param mtx prepared transaction to sign /// @param mypk my pubkey to sign @@ -898,11 +903,11 @@ std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTr /// @param opret opreturn vout which function will add if it is not empty /// @param pubkeys array of pubkeys to make multiple probe 1of2 cc's with the call Make1of2cond(cp->evalcode, globalpk, pubkeys[i]) /// @returns signed transaction in hex encoding -UniValue FinalizeCCTxExt(bool remote, uint64_t skipmask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector pubkeys = NULL_pubkeys); +UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector pubkeys = NULL_pubkeys); /// version FinalizeCCTx for CC v2, for params @see FinalizeCCTxExt /// @returns signed transaction in hex and optional PartiallySigned univalue object with vin indexes and partially signed conditions (if signature threshold not reached) -UniValue FinalizeCCV2Tx(bool remote, uint64_t mask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret); +UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret); /// Add signature to multisig scriptSig /// @param mtx mutable tx with multisig cc vins diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index 0a3ca1ec4dc..7e7744e8185 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -436,7 +436,7 @@ class TokensV2 { } static UniValue FinalizeCCTx(bool remote, uint64_t CCmask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret) { - return ::FinalizeCCV2Tx(remote, FINALIZECCTX_NO_CHANGE_WHEN_ZERO, cp, mtx, mypk, txfee, opret); + return ::FinalizeCCV2Tx(remote, CCmask, cp, mtx, mypk, txfee, opret); } }; diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 8b29d89c8dd..f91abad169f 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -306,7 +306,7 @@ UniValue TokenFinalizeTransferTx(CMutableTransaction &mtx, struct CCcontract_inf // TODO maybe add also opret blobs form vintx // as now this TokenTransfer() allows to transfer only tokens (including NFTs) that are unbound to other cc - UniValue sigData = V::FinalizeCCTx(isRemote, 0LL, cp, mtx, mypk, txfee, opret); + UniValue sigData = V::FinalizeCCTx(isRemote, FINALIZECCTX_NO_CHANGE_WHEN_DUST, cp, mtx, mypk, txfee, opret); LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "mtx=" << HexStr(E_MARSHAL(ss << mtx)) << std::endl); if (ResultHasTx(sigData)) { // LockUtxoInMemory::AddInMemoryTransaction(mtx); // to be able to spend mtx change @@ -428,7 +428,7 @@ UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokeni // TODO maybe add also opret blobs form vintx // as now this TokenTransfer() allows to transfer only tokens (including NFTs) that are unbound to other cc - UniValue sigData = V::FinalizeCCTx(isRemote, 0LL, cp, mtx, mypk, txfee, V::EncodeTokenOpRet(tokenid, destpubkeys, {} )); + UniValue sigData = V::FinalizeCCTx(isRemote, FINALIZECCTX_NO_CHANGE_WHEN_DUST, cp, mtx, mypk, txfee, V::EncodeTokenOpRet(tokenid, destpubkeys, {} )); if (!ResultHasTx(sigData)) CCerror = "could not finalize tx"; return sigData; @@ -539,7 +539,8 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup mtx.vout.push_back(V::MakeCC1vout(additionalMarkerEvalCode, TOKENS_MARKER_VALUE, GetUnspendable(cpNFT, NULL))); } - sigData = V::FinalizeCCTx(isRemote, FINALIZECCTX_NO_CHANGE_WHEN_ZERO, cp, mtx, mypk, txfee, V::EncodeTokenCreateOpRet(vscript_t(mypk.begin(), mypk.end()), name, description, { nonfungibleData })); + // prevent adding dust change in tokens + sigData = V::FinalizeCCTx(isRemote, FINALIZECCTX_NO_CHANGE_WHEN_DUST, cp, mtx, mypk, txfee, V::EncodeTokenCreateOpRet(vscript_t(mypk.begin(), mypk.end()), name, description, { nonfungibleData })); if (!ResultHasTx(sigData)) { CCerror = "couldnt finalize token tx"; return NullUniValue; diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index a420bbd773e..f2d3ad955f7 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -20,13 +20,6 @@ std::vector NULL_pubkeys; struct NSPV_CCmtxinfo NSPV_U; -#ifndef FINALIZECCTX_NO_CHANGE - #define FINALIZECCTX_NO_CHANGE 0x1 -#endif -#ifndef FINALIZECCTX_NO_CHANGE_WHEN_ZERO - #define FINALIZECCTX_NO_CHANGE_WHEN_ZERO 0x2 -#endif - /* see description to function definition in CCinclude.h */ bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey) { @@ -49,15 +42,15 @@ This allows the contract transaction functions to create the appropriate vins an 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) +std::string FinalizeCCTx(uint32_t changeFlag, 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); + UniValue sigData = FinalizeCCTxExt(false, changeFlag, cp, mtx, mypk, txfee, opret, pubkeys); return sigData[JSON_HEXTX].getValStr(); } // 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) +UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, 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; @@ -170,13 +163,21 @@ UniValue FinalizeCCTxExt(bool remote, uint64_t CCmask, struct CCcontract_info *c } } else fprintf(stderr,"FinalizeCCTx couldnt find %s mgret.%d\n",mtx.vin[i].prevout.hash.ToString().c_str(),mgret); } - nmask = (1LL << n) - 1; - if ( 0 && (mask & nmask) != (CCmask & nmask) ) - fprintf(stderr,"mask.%llx vs CCmask.%llx %llx %llx %llx\n",(long long)(mask & nmask),(long long)(CCmask & nmask),(long long)mask,(long long)CCmask,(long long)nmask); - if ( totalinputs >= totaloutputs+txfee ) - { - change = totalinputs - (totaloutputs+txfee); - mtx.vout.push_back(CTxOut(change,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + //nmask = (1LL << n) - 1; + //if ( 0 && (mask & nmask) != (CCmask & nmask) ) + // fprintf(stderr,"mask.%llx vs CCmask.%llx %llx %llx %llx\n",(long long)(mask & nmask),(long long)(CCmask & nmask),(long long)mask,(long long)CCmask,(long long)nmask); + + // + if (changeFlag != FINALIZECCTX_NO_CHANGE) { // no need change at all (already added by the caller itself) + CAmount change = totalinputs - (totaloutputs + txfee); + if (change >= 0) + { + if ((change != 0LL || changeFlag != FINALIZECCTX_NO_CHANGE_WHEN_ZERO) && // prevent adding zero change + (change > ASSETS_NORMAL_DUST || changeFlag != FINALIZECCTX_NO_CHANGE_WHEN_DUST)) // prevent adding dust change + { + mtx.vout.push_back(CTxOut(change, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + } + } } if ( opret.size() > 0 ) mtx.vout.push_back(CTxOut(0,opret)); @@ -424,7 +425,7 @@ UniValue FinalizeCCTxExt(bool remote, uint64_t CCmask, struct CCcontract_info *c } // extended version that supports signInfo object with conds to vins map for remote cc calls - for V2 mixed mode cc vins -UniValue FinalizeCCV2Tx(bool remote, uint64_t mask, struct CCcontract_info* cp, CMutableTransaction& mtx, CPubKey mypk, uint64_t txfee, CScript opret) +UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info* cp, CMutableTransaction& mtx, CPubKey mypk, uint64_t txfee, CScript opret) { auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); CTransaction vintx; @@ -474,10 +475,16 @@ UniValue FinalizeCCV2Tx(bool remote, uint64_t mask, struct CCcontract_info* cp, } else fprintf(stderr, "%s couldnt find %s mgret.%d\n", __func__, mtx.vin[i].prevout.hash.ToString().c_str(), mgret); } - if (!(mask & FINALIZECCTX_NO_CHANGE) && totalinputs >= totaloutputs + txfee) { - change = totalinputs - (totaloutputs + txfee); - if (!(mask & FINALIZECCTX_NO_CHANGE_WHEN_ZERO) || change > 0) - mtx.vout.push_back(CTxOut(change, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + if (changeFlag != FINALIZECCTX_NO_CHANGE) { // no need change at all (already added by the caller itself) + CAmount change = totalinputs - (totaloutputs + txfee); + if (change >= 0) + { + if ((change != 0LL || changeFlag != FINALIZECCTX_NO_CHANGE_WHEN_ZERO) && // prevent adding zero change + (change > ASSETS_NORMAL_DUST || changeFlag != FINALIZECCTX_NO_CHANGE_WHEN_DUST)) // prevent adding dust change + { + mtx.vout.push_back(CTxOut(change, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + } + } } if (opret.size() > 0) mtx.vout.push_back(CTxOut(0, opret)); diff --git a/src/cc/old/CCtokens_v0.cpp b/src/cc/old/CCtokens_v0.cpp index 40eca3d715d..0f057ad597c 100644 --- a/src/cc/old/CCtokens_v0.cpp +++ b/src/cc/old/CCtokens_v0.cpp @@ -900,7 +900,7 @@ std::string TokenTransfer(int64_t txfee, uint256 tokenid, vscript_t destpubkey, std::vector voutTokenPubkeys; voutTokenPubkeys.push_back(pubkey2pk(destpubkey)); // dest pubkey for validating vout - return FinalizeCCTx(mask, cp, mtx, mypk, txfee, EncodeTokenOpRet(tokenid, voutTokenPubkeys, std::make_pair((uint8_t)0, vopretEmpty))); + return FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeTokenOpRet(tokenid, voutTokenPubkeys, std::make_pair((uint8_t)0, vopretEmpty))); } else { CCerror = strprintf("no token inputs"); From 519045cd2ffc5c450442cba78c5ff1288bc0b8a6 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 29 Jun 2021 11:42:57 +0500 Subject: [PATCH 024/348] fixed default changeFlag in FinalizeCCTx to 0 --- src/cc/CCtokens.h | 8 ++++---- src/cc/auction.cpp | 4 ++-- src/cc/cclib.cpp | 2 +- src/cc/fsm.cpp | 2 +- src/cc/lotto.cpp | 2 +- src/cc/old/CCassetstx_v0.cpp | 8 ++++---- src/cc/rewards.cpp | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index 7e7744e8185..bd6dd36ef30 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -357,9 +357,9 @@ class TokensV1 { return CTxOut(); } - static UniValue FinalizeCCTx(bool remote, uint64_t CCmask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret) + static UniValue FinalizeCCTx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret) { - return ::FinalizeCCTxExt(remote, CCmask, cp, mtx, mypk, txfee, opret); + return ::FinalizeCCTxExt(remote, changeFlag, cp, mtx, mypk, txfee, opret); } }; @@ -434,9 +434,9 @@ class TokensV2 { { return ::MakeTokensCCMofNvoutMixed(evalcode1, evalcode2, nValue, M, pks, (pvvData != nullptr ? &(*pvvData)[0] : nullptr)); } - static UniValue FinalizeCCTx(bool remote, uint64_t CCmask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret) + static UniValue FinalizeCCTx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret) { - return ::FinalizeCCV2Tx(remote, CCmask, cp, mtx, mypk, txfee, opret); + return ::FinalizeCCV2Tx(remote, changeFlag, cp, mtx, mypk, txfee, opret); } }; diff --git a/src/cc/auction.cpp b/src/cc/auction.cpp index 88d5134af53..3aa49082867 100644 --- a/src/cc/auction.cpp +++ b/src/cc/auction.cpp @@ -164,7 +164,7 @@ std::string AuctionBid(uint64_t txfee,uint256 itemhash,int64_t amount) if ( CCchange != 0 ) mtx.vout.push_back(MakeCC1vout(EVAL_AUCTION,CCchange,Auctionpk)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); } else fprintf(stderr,"cant find Auction inputs\n"); return(""); } @@ -185,7 +185,7 @@ std::string AuctionDeliver(uint64_t txfee,uint256 itemhash,uint256 bidtxid) if ( CCchange != 0 ) mtx.vout.push_back(MakeCC1vout(EVAL_AUCTION,CCchange,Auctionpk)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); } else fprintf(stderr,"cant find Auction inputs\n"); return(""); } diff --git a/src/cc/cclib.cpp b/src/cc/cclib.cpp index 36495314887..f9a4ad6e7d3 100644 --- a/src/cc/cclib.cpp +++ b/src/cc/cclib.cpp @@ -608,7 +608,7 @@ std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *para for (i=0; i<1000000; i++,j++) { tmpmtx = mtx; - rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_FAUCET2 << (uint8_t)'G' << j)); + rawhex = FinalizeCCTx(0,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_FAUCET2 << (uint8_t)'G' << j)); if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 ) { len >>= 1; diff --git a/src/cc/fsm.cpp b/src/cc/fsm.cpp index 58b2120cfbe..85510643ff8 100644 --- a/src/cc/fsm.cpp +++ b/src/cc/fsm.cpp @@ -171,7 +171,7 @@ std::string FSMCreate(uint64_t txfee,std::string name,std::string states) if ( CCchange != 0 ) mtx.vout.push_back(MakeCC1vout(EVAL_FSM,CCchange,fsmpk)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); } else fprintf(stderr,"cant find fsm inputs\n"); return(""); } diff --git a/src/cc/lotto.cpp b/src/cc/lotto.cpp index d7a0b949ac9..5828f322ed0 100644 --- a/src/cc/lotto.cpp +++ b/src/cc/lotto.cpp @@ -316,7 +316,7 @@ std::string LottoTicket(uint64_t txfee,uint256 lottoid,int64_t numtickets) if ( CCchange != 0 ) mtx.vout.push_back(MakeCC1vout(EVAL_LOTTO,CCchange,lottopk)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); } else fprintf(stderr,"cant find Lotto inputs\n"); return(""); } diff --git a/src/cc/old/CCassetstx_v0.cpp b/src/cc/old/CCassetstx_v0.cpp index 617e232b347..63bd3da2a20 100644 --- a/src/cc/old/CCassetstx_v0.cpp +++ b/src/cc/old/CCassetstx_v0.cpp @@ -368,7 +368,7 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p std::vector voutTokenPubkeys; voutTokenPubkeys.push_back(unspendableAssetsPubkey); - return FinalizeCCTx(mask, cpTokens, mtx, mypk, txfee, + return FinalizeCCTx(0, cpTokens, mtx, mypk, txfee, EncodeTokenOpRet(assetid, voutTokenPubkeys, std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('s', zeroid, pricetotal, Mypubkey())))); } @@ -565,7 +565,7 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) // add additional eval-tokens unspendable assets privkey: CCaddr2set(cpAssets, EVAL_TOKENS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); - return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee, + return(FinalizeCCTx(0, cpAssets, mtx, mypk, txfee, EncodeTokenOpRet(assetid, voutTokenPubkeys, std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('x', zeroid, 0, Mypubkey()))))); } @@ -652,7 +652,7 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f std::vector voutTokenPubkeys; voutTokenPubkeys.push_back(pubkey2pk(origpubkey)); - return(FinalizeCCTx(mask, cpTokens, mtx, mypk, txfee, + return(FinalizeCCTx(0, cpTokens, mtx, mypk, txfee, EncodeTokenOpRet(assetid, voutTokenPubkeys, std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('B', zeroid, remaining_required, origpubkey))))); } @@ -785,7 +785,7 @@ std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 a cpAssets->evalcodeNFT = additionalTokensEvalcode2; - return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee, + return(FinalizeCCTx(0, cpAssets, mtx, mypk, txfee, EncodeTokenOpRet(assetid, voutTokenPubkeys, std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet(assetid2 != zeroid ? 'E' : 'S', assetid2, remaining_nValue, origpubkey))))); } else { diff --git a/src/cc/rewards.cpp b/src/cc/rewards.cpp index 1bc79ef6dde..7fc86d1f2d4 100644 --- a/src/cc/rewards.cpp +++ b/src/cc/rewards.cpp @@ -722,13 +722,13 @@ std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint2 fprintf(stderr,"inputs %.8f CCchange %.8f amount %.8f reward %.8f\n",(double)inputs/COIN,(double)CCchange/COIN,(double)amount/COIN,(double)reward/COIN); mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,rewardspk)); mtx.vout.push_back(CTxOut(amount+reward,scriptPubKey)); - return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid))); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid))); } else { firstmtx.vout.push_back(CTxOut(amount-txfee*2,scriptPubKey)); fprintf(stderr,"not enough rewards funds to payout %.8f, recover mode tx\n",(double)(reward+txfee)/COIN); - return(FinalizeCCTx(-1LL,cp,firstmtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid))); + return(FinalizeCCTx(0,cp,firstmtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid))); } } else From 91f97e54759600d21a268e445324043328c2face Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 1 Jul 2021 21:25:25 +0500 Subject: [PATCH 025/348] code formatting --- src/main.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main.h b/src/main.h index 3f53646b32e..bd03b1eb982 100644 --- a/src/main.h +++ b/src/main.h @@ -668,30 +668,29 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF class CCheckCCEvalCodes { //! The set of evalcodes that are already processed in CC validation. - std::map > evalcodes; + std::map> evalcodes; //! Mutex to protect evalcodes map boost::mutex mutex_eval; public: - void MarkEvalCode(uint256 txid,uint8_t ecode) + void MarkEvalCode(uint256 txid, uint8_t ecode) { boost::unique_lock lock(mutex_eval); auto search = evalcodes.find(txid); - if (search==evalcodes.end()) - { + if (search == evalcodes.end()) { std::set tmp; tmp.insert(ecode); - evalcodes[txid]=tmp; - } - else search->second.insert(ecode); + evalcodes[txid] = tmp; + } else + search->second.insert(ecode); } bool CheckEvalCode(uint256 txid, uint8_t ecode) { boost::unique_lock lock(mutex_eval); auto search = evalcodes.find(txid); - return search==evalcodes.end()?false:(search->second.find(ecode)!=search->second.end()); + return search == evalcodes.end() ? false : (search->second.find(ecode) != search->second.end()); } }; From e4e534e536d199725c5789a324d2cf529748c1ac Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 1 Jul 2021 21:35:42 +0500 Subject: [PATCH 026/348] added new rpc tokencreatetoken with token json param for eval f7; token extra data allowed for fungible tokens added flag disable dust change to FinalizeCCtx assets cc validation fixes (dust unit_price) tokens cc disable many opreturns to prevent spam some vars renamed more komodo-test-cc assets tests added --- src/Makefile.am | 2 +- src/cc/CCNFTData.cpp | 257 ------------ src/cc/CCNFTData.h | 31 -- src/cc/CCTokelData.cpp | 326 +++++++++++++++ src/cc/CCTokelData.h | 39 ++ src/cc/CCassetsCore_impl.h | 2 +- src/cc/CCassetstx_impl.h | 90 ++--- src/cc/CCcustom.cpp | 14 +- src/cc/CCinclude.h | 10 +- src/cc/CCtokens.cpp | 74 +++- src/cc/CCtokens.h | 5 +- src/cc/CCtokens_impl.h | 80 ++-- src/cc/CCtokenutils.cpp | 18 +- src/cc/CCtx.cpp | 8 +- src/cc/CCutils.cpp | 102 ++--- src/cc/assets.cpp | 33 +- src/cc/eval.h | 2 +- src/cc/gamescc.cpp | 22 +- src/cc/old/CCassetsCore_v0.cpp | 4 +- src/cc/old/CCassetstx_v0.cpp | 16 +- src/cc/old/CCtokens_v0.cpp | 4 +- src/cc/old/assets_v0.cpp | 2 +- src/rpc/tokensrpc.cpp | 152 +++++-- src/test-komodo-cc/test-assets.cpp | 622 ++++++++++++++++++++--------- 24 files changed, 1174 insertions(+), 741 deletions(-) delete mode 100644 src/cc/CCNFTData.cpp delete mode 100644 src/cc/CCNFTData.h create mode 100644 src/cc/CCTokelData.cpp create mode 100644 src/cc/CCTokelData.h diff --git a/src/Makefile.am b/src/Makefile.am index 2e2e077166b..6179524f7a0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -318,7 +318,7 @@ libbitcoin_server_a_SOURCES = \ cc/betprotocol.cpp \ cc/pricesfeed.cpp \ cc/priceslibs/cjsonpointer.cpp \ - cc/CCNFTData.cpp \ + cc/CCTokelData.cpp \ chain.cpp \ checkpoints.cpp \ fs.cpp \ diff --git a/src/cc/CCNFTData.cpp b/src/cc/CCNFTData.cpp deleted file mode 100644 index e5123513ba7..00000000000 --- a/src/cc/CCNFTData.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/****************************************************************************** -* 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. * -* * -******************************************************************************/ - -#include "CCtokens.h" -#include "CCNFTData.h" - -typedef std::pair nftPropDesc_t; -typedef std::map nftPropDesc_map; -static const nftPropDesc_map nftPropDesc = { - { NFTPROP_ID, { NFTTYP_UINT64, true }}, - { NFTPROP_URL, { NFTTYP_VUINT8, true }}, - { NFTPROP_ROYALTY, { NFTTYP_UINT64, false }}, - { NFTPROP_ARBITRARY, { NFTTYP_VUINT8, false }} -}; - -typedef struct { - nftPropType type; - struct - { - uint64_t uint64; - vuint8_t vuint8; - } v; -} nftPropValue; - -static bool ParseNftData(const vuint8_t &vdata, std::map &propMap, std::string &sError) -{ - if (vdata.size() > 2 && vdata[0] == EVAL_NFTDATA) - { - uint8_t evalCode, version; - bool invalidPropType = false; - bool hasDuplicates = false; - const char *funcname = __func__; - int mandatoryCount = 0; - - if (vdata[1] != NFTDATA_VERSION) - { - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "invalid nft data version" << std::endl); - sError = "invalide nft data version"; - return false; - } - propMap.clear(); - - if (E_UNMARSHAL(vdata, ss >> evalCode; ss >> version; // evalcode in the first byte - while(!ss.eof()) - { - uint8_t propId; - ss >> propId; - auto itDesc = nftPropDesc.find((nftPropId)propId); - nftPropValue value; - nftPropType type = itDesc != nftPropDesc.end() ? itDesc->second.first : NFTTYP_INVALID; - switch(type) { - case NFTTYP_UINT64: - value.type = type; - ss >> COMPACTSIZE(value.v.uint64); - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << " parsed prop id=" << (int)propId << " compactsize value=" << value.v.uint64 << std::endl); - break; - case NFTTYP_VUINT8: - value.type = type; - ss >> value.v.vuint8; - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << " parsed prop id=" << (int)propId << " varbuffer=" << HexStr(value.v.vuint8) << std::endl); - break; - default: - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << " property id not allowed (" << (int)propId << ")" << std::endl); - invalidPropType = true; - break; - } - if (invalidPropType) - break; - if (propMap.count((nftPropId)propId) != 0) - hasDuplicates = true; - else { - propMap.insert(std::make_pair((nftPropId)propId, value)); - if (itDesc->second.second) // if mandatory - mandatoryCount ++; - } - } - )) - { - if (invalidPropType) { - sError = "invalid property type"; - return false; - } - if (hasDuplicates) { - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << __func__ << " duplicates in nft data " << std::endl); - sError = "duplicate property type"; - return false; - } - if (mandatoryCount != std::count_if(nftPropDesc.begin(), nftPropDesc.end(), [](std::pair e){ return e.second.second; })) { - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << __func__ << " invalid mandatory property count=" << mandatoryCount << std::endl); - sError = "not all mandatory properties"; - return false; - } - return true; - } - else - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << __func__ << " could not unmarshal nft data" << std::endl); - } - sError = "could not unmarshal nft data"; - return false; -} - -bool GetNftDataAsUint64(const vuint8_t &vdata, nftPropId propId, uint64_t &val) -{ - std::map propMap; - std::string sError; - ParseNftData(vdata, propMap, sError); - if (propMap.count(propId) > 0 && propMap[propId].type == NFTTYP_UINT64) { - val = propMap[propId].v.uint64; - return true; - } - return false; -} - -bool GetNftDataAsVuint8(const vuint8_t &vdata, nftPropId propId, vuint8_t &val) -{ - std::map propMap; - std::string sError; - - ParseNftData(vdata, propMap, sError); - if (propMap.count(propId) > 0 && propMap[propId].type == NFTTYP_VUINT8) { - val = propMap[propId].v.vuint8; - return true; - } - return false; -} - -static bool ValidateNftData(const vuint8_t &vdata, std::string &sError) -{ - std::map propMap; - if( ParseNftData(vdata, propMap, sError) ) { - if (propMap[NFTPROP_ROYALTY].v.uint64 >= NFTROYALTY_DIVISOR ) { - sError = "invalid royalty value (must be in 0...999)"; - return false; - } - return true; - } - return false; -} - -bool ValidatePrevTxNFTOpretV1(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, const CScript &opret) -{ - uint256 tokenid; - std::vector vpks; - std::vector voprets; - if (DecodeTokenOpRetV1(opret, tokenid, vpks, voprets) == 0) - return eval->Error("could not decode nft data"); - - for(auto const &vin : tx.vin) - { - if (vin.prevout.hash == tokenid) // for token v1 check directly spent token create tx - { - CTransaction vintx; - uint256 hashBlock; - vuint8_t vorigpk; - std::string name, desc; - std::vector vcroprets; - std::string sError; - - if (!myGetTransaction(vin.prevout.hash, vintx, hashBlock)) - return eval->Error("could load vintx"); - if (DecodeTokenCreateOpRetV1(vintx.vout.back().scriptPubKey, vorigpk, name, desc, vcroprets) == 0) - return eval->Error("could not decode token create tx opreturn"); - if (vcroprets.size() == 0) - return eval->Error("no nft data in opreturn"); - if (!ValidateNftData(vcroprets[0], sError)) - return eval->Error("nft data invalid: " + sError); - } - } - return true; -} - -// check token v2 create tx -bool ValidateNFTOpretV2(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, const CScript &opret) -{ - vuint8_t vorigpk; - std::string name, desc; - std::vector vcroprets; - - if (IsTokenCreateFuncid(DecodeTokenCreateOpRetV2(opret, vorigpk, name, desc, vcroprets))) - { - std::string sError; - - if (vcroprets.size() == 0) - return eval->Error("no nft data in opreturn"); - if (!ValidateNftData(vcroprets[0], sError)) - return eval->Error("nft data invalid: " + sError); - } - return true; -} - -bool NFTDataValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) -{ - if (strcmp(ASSETCHAINS_SYMBOL, "TKLTEST") == 0 && chainActive.Height() <= 33711) - return true; - //if (strcmp(ASSETCHAINS_SYMBOL, "DIMXY20") == 0 && chainActive.Height() <= 1704) - // return true; - - if (tx.vout.size() < 1) - return eval->Error("no vouts"); - - vuint8_t vopret; - uint8_t evalTokens; - int goodTokenData = 0; - - // check if this is a token v2 create tx - if (GetOpReturnData(tx.vout.back().scriptPubKey, vopret) && - vopret.size() > 2 && - vopret[0] == EVAL_TOKENSV2) - { - if (IsTokenCreateFuncid(vopret[1])) - return ValidateNFTOpretV2(cp, eval, tx, tx.vout.back().scriptPubKey); - else - return true; // do not check further tokens txns - } - - // for token v1 we do not have create tx in validation - // let's find NFT vout and check if previous tx - for (int i = 0; i < tx.vout.size(); i ++) { - //uint256 tokenid; - //std::string errstr; - if (tx.vout[i].scriptPubKey.IsPayToCryptoCondition()) - { - CScript ccdata; - vuint8_t vopdrop; - if (!(ccdata = GetCCDropAsOpret(tx.vout[i].scriptPubKey)).empty() && - GetOpReturnData(ccdata, vopdrop) && - vopdrop.size() > 2 && - vopdrop[0] == EVAL_TOKENS) - { - if( !ValidatePrevTxNFTOpretV1(cp, eval, tx, ccdata) ) - return false; // eval is set - } - } - } - - // if last vout v1 opreturn exists - if (vopret.size() > 2 && - vopret[0] == EVAL_TOKENS) - { - if (!ValidatePrevTxNFTOpretV1(cp, eval, tx, tx.vout.back().scriptPubKey)) - return false; - } - return true; // no prev tx is token create tx -} - diff --git a/src/cc/CCNFTData.h b/src/cc/CCNFTData.h deleted file mode 100644 index a77fff4f07e..00000000000 --- a/src/cc/CCNFTData.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef CC_NFTDATA_H -#define CC_NFTDATA_H - -#include "CCinclude.h" - -const uint32_t NFTDATA_VERSION = 1; - -const uint64_t NFTROYALTY_DIVISOR = 1000; - -// nft Prop id: -enum nftPropId : uint8_t { - NFTPROP_NONE = 0x0, - NFTPROP_ID = 0x1, - NFTPROP_URL = 0x2, - NFTPROP_ROYALTY = 0x3, - NFTPROP_ARBITRARY = 0x4 -}; - -// nft property type -enum nftPropType : uint8_t { - NFTTYP_INVALID = 0x0, - NFTTYP_UINT64 = 0x1, - NFTTYP_VUINT8 = 0x2 -}; - -bool GetNftDataAsUint64(const vuint8_t &vdata, nftPropId propId, uint64_t &val); -bool GetNftDataAsVuint8(const vuint8_t &vdata, nftPropId propId, vuint8_t &val); - -bool NFTDataValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); - -#endif diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp new file mode 100644 index 00000000000..922b699adfe --- /dev/null +++ b/src/cc/CCTokelData.cpp @@ -0,0 +1,326 @@ +/****************************************************************************** +* Copyright 2014-2021 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. * +* * +******************************************************************************/ + +#include +#include "CCtokens.h" +#include "CCTokelData.h" + + +static UniValue tklReadString(CDataStream &ss) +{ + std::string sval; + ::Unserialize(ss, sval); + UniValue ret(sval); + return ret; +} + +static UniValue tklReadInt64(CDataStream &ss) +{ + int64_t i64val; + ::Unserialize(ss, i64val); + UniValue ret(i64val); + return ret; +} + +static UniValue tklReadVuint8(CDataStream &ss) +{ + vuint8_t vuint8val; + ::Unserialize(ss, vuint8val); + UniValue ret(HexStr(vuint8val)); + return ret; +} + +static void tklWriteString(CDataStream &ss, const UniValue &val) +{ + std::string sval = val.getValStr(); + ::Serialize(ss, sval); +} + +static void tklWriteInt64(CDataStream &ss, const UniValue &val) +{ + int64_t i64val = 0; + ParseInt64(val.getValStr(), &i64val); + ::Serialize(ss, i64val); +} + +static void tklWriteVuint8(CDataStream &ss, const UniValue &val) +{ + vuint8_t vuint8val = ParseHex(val.getValStr()); + ::Serialize(ss, vuint8val); +} + +typedef std::map tklPropDesc_map; +static const tklPropDesc_map tklPropDesc = { + { TKLPROP_ID, { TKLTYP_INT64, "id", &tklReadInt64, &tklWriteInt64 }}, + { TKLPROP_URL, { TKLTYP_VUINT8, "url", &tklReadString, &tklWriteString }}, + { TKLPROP_ROYALTY, { TKLTYP_INT64, "royalty", &tklReadInt64, &tklWriteInt64 }}, + { TKLPROP_ARBITRARY, { TKLTYP_VUINT8, "arbitrary", &tklReadVuint8, &tklWriteVuint8 }} +}; + +/*typedef struct { + tklPropType type; + struct + { + uint64_t uint64; + vuint8_t vuint8; + } v; +} tklPropValue; +*/ + +static tklPropId FindTokelDataIdByName(const std::string &name) +{ + auto found = std::find_if(tklPropDesc.begin(), tklPropDesc.end(), [&](const std::pair &e){ return std::get<1>(e.second) == name; }); + if (found != tklPropDesc.end()) + return found->first; + else + return (tklPropId)0; +} + +static tklPropDesc_t GetTokelDataDesc(tklPropId id) +{ + tklPropDesc_t empty = std::make_tuple( TKLTYP_INVALID, std::string(), nullptr, nullptr ); + auto found = tklPropDesc.find(id); + if (found != tklPropDesc.end()) + return found->second; + else + return empty; +} + +vuint8_t ParseTokelJson(const UniValue &jsonParams) +{ + uint8_t evalcode = 0; + /*size_t ikey; + if (jsonParams["evalcode"].isStr()) { + evalcode = strtol(jsonParams["evalcode"].getValStr().c_str(), NULL, 16); + if (evalcode < 0 || evalcode > 0xFF) + throw std::runtime_error("invalid evalcode in token data"); + }*/ + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << evalcode << (uint8_t)TKLDATA_VERSION; + for(int i = 0; i < jsonParams.getKeys().size(); i ++) + { + std::string key = jsonParams.getKeys()[i]; + tklPropId id; + //CAmount valAmount; + //vuint8_t valVuint8; + if ((id = FindTokelDataIdByName(key)) == (tklPropId)0) + throw std::runtime_error("invalid token data id=" + key); + tklPropDesc_t entry = GetTokelDataDesc(id); + ss << (uint8_t)id; + (*std::get<3>(entry))(ss, jsonParams[key]); + } + + return vuint8_t(ss.begin(), ss.end()); +} + +static bool ParseTokelData(const vuint8_t &vdata, std::map &propMapOut, std::string &sError) +{ + if (vdata.size() >= 2 && vdata[0] == EVAL_TOKELDATA) + { + uint8_t evalCode, version; + bool invalidPropType = false; + bool hasDuplicates = false; + const char *funcname = __func__; + //int mandatoryCount = 0; + std::map propMap; + + if (vdata[1] != TKLDATA_VERSION) + { + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "invalid tkl data version" << std::endl); + sError = "invalid tkl data version"; + return false; + } + + try { + CDataStream ss(vdata, SER_NETWORK, PROTOCOL_VERSION); + ::Unserialize(ss, evalCode); + ::Unserialize(ss, version); + bool ssErrof = false; + while(!ss.eof()) { + uint8_t id; + ::Unserialize(ss, id); + tklPropDesc_t entry = GetTokelDataDesc((tklPropId)id); + if (std::get<0>(entry) == TKLTYP_INVALID) { + sError = "invalid tokel data property type"; + return false; + } + if (propMap.count((tklPropId)id) != 0) { + sError = "duplicate tokel data property type"; + return false; + } + //if (itDesc->second.second) // if mandatory + // mandatoryCount ++; + UniValue val = (*std::get<2>(entry))(ss); // read ss + propMap.insert(std::make_pair((tklPropId)id, val)); + + } + } catch(...) { + sError = "could not parse tokel token data"; + return false; + } + } + sError = "invalid tokel data"; + return false; +} + +bool GetTokelDataAsInt64(const vuint8_t &vdata, tklPropId propId, int64_t &val) +{ + std::map propMap; + std::string sError; + ParseTokelData(vdata, propMap, sError); + if (propMap.count(propId) > 0 && propMap[propId].isNum()) { + ParseInt64(propMap[propId].getValStr(), &val); + return true; + } + return false; +} + +bool GetTokelDataAsVuint8(const vuint8_t &vdata, tklPropId propId, vuint8_t &val) +{ + std::map propMap; + std::string sError; + + ParseTokelData(vdata, propMap, sError); + if (propMap.count(propId) > 0) { + val = ParseHex(propMap[propId].getValStr()); + return true; + } + return false; +} + +static bool CheckTokelData(const vuint8_t &vdata, std::string &sError) +{ + std::map propMap; + if( ParseTokelData(vdata, propMap, sError) ) { + int64_t val; + if (!ParseInt64(propMap[TKLPROP_ROYALTY].getValStr(), &val)) { + sError = "could not parse tokel royalty"; + return false; + } + if (val < 0 || val >= TKLROYALTY_DIVISOR) { + sError = "invalid tokel royalty value (must be in 0...999)"; + return false; + } + return true; + } + return false; +} + +bool ValidatePrevTxTokelOpretV1(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, const CScript &opret) +{ + uint256 tokenid; + std::vector vpks; + std::vector voprets; + if (DecodeTokenOpRetV1(opret, tokenid, vpks, voprets) == 0) + return eval->Error("could not decode tkl data"); + + for(auto const &vin : tx.vin) + { + if (vin.prevout.hash == tokenid) // for token v1 check directly spent token create tx + { + CTransaction vintx; + uint256 hashBlock; + vuint8_t vorigpk; + std::string name, desc; + std::vector vcroprets; + std::string sError; + + if (!myGetTransaction(vin.prevout.hash, vintx, hashBlock)) + return eval->Error("could load vintx"); + if (DecodeTokenCreateOpRetV1(vintx.vout.back().scriptPubKey, vorigpk, name, desc, vcroprets) == 0) + return eval->Error("could not decode token create tx opreturn"); + if (vcroprets.size() == 0) + return eval->Error("no tkl data in opreturn"); + if (!CheckTokelData(vcroprets[0], sError)) + return eval->Error("tkl data invalid: " + sError); + } + } + return true; +} + +// check token v2 create tx +bool ValidateTokelOpretV2(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, const CScript &opret) +{ + vuint8_t vorigpk; + std::string name, desc; + std::vector vcroprets; + + if (IsTokenCreateFuncid(DecodeTokenCreateOpRetV2(opret, vorigpk, name, desc, vcroprets))) + { + std::string sError; + + if (vcroprets.size() == 0) + return eval->Error("no tkl data in opreturn"); + if (!CheckTokelData(vcroprets[0], sError)) + return eval->Error("tkl data invalid: " + sError); + } + return true; +} + +bool TokelDataValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) +{ + //if (strcmp(ASSETCHAINS_SYMBOL, "TKLTEST") == 0 && chainActive.Height() <= 33711) + // return true; + //if (strcmp(ASSETCHAINS_SYMBOL, "DIMXY20") == 0 && chainActive.Height() <= 1704) + // return true; + + if (tx.vout.size() < 1) + return eval->Error("no vouts"); + + vuint8_t vopret; + uint8_t evalTokens; + int goodTokenData = 0; + + // check if this is a token v2 create tx + if (GetOpReturnData(tx.vout.back().scriptPubKey, vopret) && + vopret.size() > 2 && + vopret[0] == EVAL_TOKENSV2) + { + if (IsTokenCreateFuncid(vopret[1])) + return ValidateTokelOpretV2(cp, eval, tx, tx.vout.back().scriptPubKey); + else + return true; // do not check further tokens txns + } + + // for token v1 we do not have create tx in validation + // let's find TKL vout and check if previous tx + for (int i = 0; i < tx.vout.size(); i ++) { + //uint256 tokenid; + //std::string errstr; + if (tx.vout[i].scriptPubKey.IsPayToCryptoCondition()) + { + CScript ccdata; + vuint8_t vopdrop; + if (!(ccdata = GetCCDropAsOpret(tx.vout[i].scriptPubKey)).empty() && + GetOpReturnData(ccdata, vopdrop) && + vopdrop.size() > 2 && + vopdrop[0] == EVAL_TOKENS) + { + if( !ValidatePrevTxTokelOpretV1(cp, eval, tx, ccdata) ) + return false; // eval is set + } + } + } + + // if last vout v1 opreturn exists + if (vopret.size() > 2 && + vopret[0] == EVAL_TOKENS) + { + if (!ValidatePrevTxTokelOpretV1(cp, eval, tx, tx.vout.back().scriptPubKey)) + return false; + } + return true; // no prev tx is token create tx +} + diff --git a/src/cc/CCTokelData.h b/src/cc/CCTokelData.h new file mode 100644 index 00000000000..ec438ea57f3 --- /dev/null +++ b/src/cc/CCTokelData.h @@ -0,0 +1,39 @@ +#ifndef CC_TKLDATA_H +#define CC_TKLDATA_H + +#include "CCinclude.h" + +const uint8_t TKLDATA_NULL_EVAL = 0; +const uint8_t TKLDATA_VERSION = 1; +const uint64_t TKLROYALTY_DIVISOR = 1000; + +// tkl Prop id: +enum tklPropId : uint8_t { + TKLPROP_NONE = 0x0, + TKLPROP_ID = 0x1, + TKLPROP_URL = 0x2, + TKLPROP_ROYALTY = 0x3, + TKLPROP_ARBITRARY = 0x4 +}; + +// tkl property type +enum tklPropType : uint8_t { + TKLTYP_INVALID = 0x0, + TKLTYP_INT64 = 0x1, + TKLTYP_VUINT8 = 0x2 +}; + +typedef void tklWriteSS(CDataStream &ss, const UniValue &val); +typedef UniValue tklReadSS(CDataStream &ss); + + + +typedef std::tuple tklPropDesc_t; + +bool GetTokelDataAsInt64(const vuint8_t &vdata, tklPropId propId, int64_t &val); +bool GetTokelDataAsVuint8(const vuint8_t &vdata, tklPropId propId, vuint8_t &val); +vuint8_t ParseTokelJson(const UniValue &jsonParams); + +bool TokelDataValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); + +#endif diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index f4c1137c5cd..4245177ba42 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -133,7 +133,7 @@ bool GetAssetorigaddrs(struct CCcontract_info *cp, char *origCCaddr, char *origN cpTokens = CCinit(&tokensC, A::TokensEvalCode()); if (vintxFuncId == 's' || vintxFuncId == 'S' || vintxFuncId == 'b' || vintxFuncId == 'B') { - cpTokens->evalcodeNFT = cp->evalcodeNFT; // add non-fungible evalcode if present + cpTokens->evalcodeAdd = cp->evalcodeAdd; // add non-fungible evalcode if present if (!GetTokensCCaddress(cpTokens, origCCaddr, pubkey2pk(origpubkey), A::IsMixed())) // tokens to single-eval token or token+nonfungible return false; } diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index d05f4824550..f3ebf782b55 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -18,7 +18,7 @@ #include "CCtokens.h" #include "CCassets.h" -#include "CCNFTData.h" +#include "CCTokelData.h" static bool IsTxidInActiveChain(uint256 txid) @@ -40,7 +40,7 @@ static bool IsTxidInActiveChain(uint256 txid) } template -UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeNFT) +UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) { UniValue result(UniValue::VARR); const char *funcname = __func__; @@ -152,11 +152,11 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeNFT) char assetsTokensUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; TokenDataTuple tokenData; - vuint8_t vopretNFT; + vuint8_t vextraData; if (refassetid != zeroid) { - GetTokenData(NULL, refassetid, tokenData, vopretNFT); - if (vopretNFT.size() > 0) - cpAssets->evalcodeNFT = vopretNFT[0]; + GetTokenData(NULL, refassetid, tokenData, vextraData); + if (vextraData.size() > 0) + cpAssets->evalcodeAdd = vextraData[0]; } GetTokensCCaddress(cpAssets, assetsTokensUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); SetCCunspents(unspentOutputsTokens, assetsTokensUnspendableAddr, true); @@ -173,11 +173,11 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeNFT) itTokens++) addOrders(cpAssets, itTokens); - if (evalcodeNFT != 0) { //this would be mytokenorders + if (evalcodeAdd != 0) { //this would be mytokenorders char assetsNFTUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; // try also dual eval tokenasks (and we do not need bids (why? bids are on assets global addr anyway.)): - cpAssets->evalcodeNFT = evalcodeNFT; + cpAssets->evalcodeAdd = evalcodeAdd; GetTokensCCaddress(cpAssets, assetsNFTUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); SetCCunspents(unspentOutputsNFTs, assetsNFTUnspendableAddr,true); @@ -300,19 +300,19 @@ UniValue CreateSell(const CPubKey &mypk, int64_t txfee, int64_t numtokens, uint2 return (""); } - uint8_t evalcodeNFT = cpTokens->evalcodeNFT ? cpTokens->evalcodeNFT : 0; + uint8_t evalcodeAdd = cpTokens->evalcodeAdd ? cpTokens->evalcodeAdd : 0; CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); - mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), evalcodeNFT, numtokens, unspendableAssetsPubkey)); + mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), evalcodeAdd, numtokens, unspendableAssetsPubkey)); mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk)); //marker (seems, it is not for my tokenorders, not used yet) CAmount CCchange = inputs - numtokens; if (CCchange != 0LL) { // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) - mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : T::EvalCode(), CCchange, mypk)); + mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), CCchange, mypk)); } // cond to spend NFT from mypk - CCwrapper wrCond(T::MakeTokensCCcond1(evalcodeNFT, mypk)); + CCwrapper wrCond(T::MakeTokensCCcond1(evalcodeAdd, mypk)); CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpTokens, mtx, mypk, txfee, @@ -518,12 +518,12 @@ UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 } TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - GetTokenData(NULL, assetid, tokenData, vopretNonfungible); - if (vopretNonfungible.size() > 0) - cpAssets->evalcodeNFT = vopretNonfungible.begin()[0]; + vuint8_t vextraData; + GetTokenData(NULL, assetid, tokenData, vextraData); + if (vextraData.size() > 0) + cpAssets->evalcodeAdd = vextraData.begin()[0]; - mtx.vout.push_back(T::MakeTokensCC1vout(cpAssets->evalcodeNFT ? cpAssets->evalcodeNFT : T::EvalCode(), askamount, mypk)); // one-eval token vout + mtx.vout.push_back(T::MakeTokensCC1vout(cpAssets->evalcodeAdd ? cpAssets->evalcodeAdd : T::EvalCode(), askamount, mypk)); // one-eval token vout // mtx.vout.push_back(CTxOut(ASSETS_MARKER_AMOUNT, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // we dont need marker for cancelled orders // init assets 'unspendable' privkey and pubkey @@ -531,7 +531,7 @@ UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); // add additional eval-tokens unspendable assets privkey: - CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), cpAssets->evalcodeNFT, unspendableAssetsPk)); + CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), cpAssets->evalcodeAdd, unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, @@ -570,15 +570,15 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 cpTokens = CCinit(&tokensC, T::EvalCode()); TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - uint8_t evalcodeNFT = 0; - uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - GetTokenData(NULL, assetid, tokenData, vopretNonfungible); - if (vopretNonfungible.size() > 0) { - evalcodeNFT = vopretNonfungible.begin()[0]; - GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); - if (royaltyFract > NFTROYALTY_DIVISOR-1) - royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit + vuint8_t vextraData; + uint8_t evalcodeAdd = 0; + int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + GetTokenData(NULL, assetid, tokenData, vextraData); + if (vextraData.size() > 0) { + evalcodeAdd = vextraData.begin()[0]; + GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); + if (royaltyFract > TKLROYALTY_DIVISOR-1) + royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } vuint8_t ownerpubkey = std::get<0>(tokenData); @@ -621,7 +621,7 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 CCerror = "incorrect units or price"; return (""); } - CAmount royaltyValue = royaltyFract > 0 ? paid_amount / NFTROYALTY_DIVISOR * royaltyFract : 0; + CAmount royaltyValue = royaltyFract > 0 ? paid_amount / TKLROYALTY_DIVISOR * royaltyFract : 0; CAmount tokensChange = inputs - fill_units; uint8_t unspendableAssetsPrivkey[32]; @@ -638,17 +638,17 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to mypk normal if (royaltyFract > 0) // note it makes vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner - mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : T::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator + mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator if (orig_units - fill_units > 0) // order is not finished yet mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey if (tokensChange != 0LL) - mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : T::EvalCode(), tokensChange, mypk)); // change in single-eval tokens + mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), tokensChange, mypk)); // change in single-eval tokens CCwrapper wrCond1(MakeCCcond1(A::EvalCode(), unspendableAssetsPk)); // spend coins CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); - CCwrapper wrCond2(T::MakeTokensCCcond1(evalcodeNFT, mypk)); // spend my tokens to fill buy + CCwrapper wrCond2(T::MakeTokensCCcond1(evalcodeAdd, mypk)); // spend my tokens to fill buy CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpTokens, mtx, mypk, txfee, @@ -697,15 +697,15 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a } TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - uint8_t evalcodeNFT = 0; - uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - GetTokenData(NULL, assetid, tokenData, vopretNonfungible); - if (vopretNonfungible.size() > 0) { - evalcodeNFT = vopretNonfungible.begin()[0]; - GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); - if (royaltyFract > NFTROYALTY_DIVISOR-1) - royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit + vuint8_t vextraData; + uint8_t evalcodeAdd = 0; + int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + GetTokenData(NULL, assetid, tokenData, vextraData); + if (vextraData.size() > 0) { + evalcodeAdd = vextraData.begin()[0]; + GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); + if (royaltyFract > TKLROYALTY_DIVISOR-1) + royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } vuint8_t ownerpubkey = std::get<0>(tokenData); @@ -738,7 +738,7 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a } paid_nValue = paid_unit_price * fillunits; - CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / NFTROYALTY_DIVISOR * royaltyFract : 0; + CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / TKLROYALTY_DIVISOR * royaltyFract : 0; if (assetid2 != zeroid) { // inputs = AddAssetInputs(cpAssets, mtx, mypk, assetid2, paid_nValue, 60); // not implemented yet @@ -769,10 +769,10 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a } // vout.0 tokens remainder to unspendable cc addr: - mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), evalcodeNFT, orig_assetoshis - fillunits, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr + mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), evalcodeAdd, orig_assetoshis - fillunits, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: - mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : T::EvalCode(), fillunits, mypk)); + mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), fillunits, mypk)); mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr if (royaltyFract > 0) // note it makes the vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner @@ -784,10 +784,10 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), evalcodeNFT, unspendableAssetsPk)); + CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), evalcodeAdd, unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); - //cpAssets->evalcodeNFT = evalcodeNFT; // set nft eval for signing + //cpAssets->evalcodeAdd = evalcodeAdd; // set token eval for signing UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { mypk }, diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 99c0d4ceea3..18d92ceb92c 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -31,7 +31,7 @@ #include "CCGateways.h" #include "CCtokens.h" #include "CCImportGateway.h" -#include "CCNFTData.h" +#include "CCTokelData.h" /* @@ -276,9 +276,9 @@ uint8_t Assetsv2CCpriv[32] = { 0x46, 0x58, 0x3b, 0x18, 0xee, 0x16, 0x63, 0x51, 0 #undef FUNCNAME #undef EVALCODE -// ParamNFT -#define FUNCNAME IsNFTDataInput -#define EVALCODE EVAL_NFTDATA +// Tokel TokenData validator +#define FUNCNAME IsTokelDataInput +#define EVALCODE EVAL_TOKELDATA #include "CCcustom.inc" #undef FUNCNAME #undef EVALCODE @@ -484,9 +484,9 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) cp->ismyvin = IsAssetsv2Input; break; - case EVAL_NFTDATA: - cp->validate = NFTDataValidate; - cp->ismyvin = IsNFTDataInput; + case EVAL_TOKELDATA: + cp->validate = TokelDataValidate; + cp->ismyvin = IsTokelDataInput; break; default: diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 29079e6f1bb..594f2a42e0f 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -232,8 +232,8 @@ struct CCVintxProbe { struct CCcontract_info { uint8_t evalcode; //!< cc contract eval code, set by CCinit function - uint8_t evalcodeNFT; //!< additional eval code for spending from three-eval-code vouts with EVAL_TOKENS, cc evalcode, cc evalcode NFT - //!< or vouts with two evalcodes: EVAL_TOKENS, evalcodeNFT. + uint8_t evalcodeAdd; //!< additional eval code for spending from three-eval-code vouts with EVAL_TOKENS, cc evalcode, cc evalcode NFT + //!< or vouts with two evalcodes: EVAL_TOKENS, evalcodeAdd. //!< Set by AddTokenCCInputs function char unspendableCCaddr[64]; //!< global contract cryptocondition address, set by CCinit function @@ -293,7 +293,7 @@ struct CCcontract_info void init_to_zeros() { // init to zeros: evalcode = 0; - evalcodeNFT = 0; + evalcodeAdd = 0; memset(CCpriv, '\0', sizeof(CCpriv) / sizeof(CCpriv[0])); @@ -1222,6 +1222,10 @@ void CCLogPrintStream(const char *category, int level, const char *functionName, /// @see LOGSTREAM #define LOGSTREAMFN(category, level, logoperator) CCLogPrintStream( category, level, __func__, [&](std::ostringstream &stream) {logoperator;} ) +extern struct CCcontract_info CCinfos[]; +extern std::string MYCCLIBNAME; +bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn); + /// class CCERROR to replace old single threaded CCerror global var /// CCERROR is instanciated as thread_local and allows safely set error in cc rpc calls /// Note: we cannot use std::string as the 'message' member as it would fail in thread_local mode diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 581cd0d0de8..fbec6164292 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -22,6 +22,8 @@ */ #include "CCtokens_impl.h" +#include "CCTokelData.h" + thread_local uint32_t tokenValIndentSize = 0; // for debug logging @@ -128,11 +130,11 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const } uint256 tokenIdOpret; - std::vector oprets; + std::vector vdatas; std::vector voutPubkeysInOpret; // token opret most important checks (tokenid == reftokenid, tokenid is non-zero, tx is 'tokenbase'): - funcId = DecodeTokenOpRetV1(opret, tokenIdOpret, voutPubkeysInOpret, oprets); + funcId = DecodeTokenOpRetV1(opret, tokenIdOpret, voutPubkeysInOpret, vdatas); if (funcId == 0) { // bad opreturn // errorStr = "can't decode opreturn data"; @@ -166,10 +168,10 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const { // get up to two eval codes from cc data: uint8_t evalCode1 = 0, evalCode2 = 0; - if (oprets.size() >= 1) { - evalCode1 = oprets[0].size() > 0 ? oprets[0][0] : 0; - if (oprets.size() >= 2) - evalCode2 = oprets[1].size() > 0 ? oprets[1][0] : 0; + if (vdatas.size() >= 1) { + evalCode1 = vdatas[0].size() > 0 ? vdatas[0][0] : 0; + if (vdatas.size() >= 2) + evalCode2 = vdatas[1].size() > 0 ? vdatas[1][0] : 0; } // get optional nft eval code: @@ -253,16 +255,16 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const vscript_t vorigPubkey; std::string dummyName, dummyDescription; - std::vector oprets; + std::vector vdatas; - if (DecodeTokenCreateOpRetV1(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, oprets) == 0) { + if (DecodeTokenCreateOpRetV1(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, vdatas) == 0) { LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << funcname << "()" << " could not decode create opret" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); return 0; } CPubKey origPubkey = pubkey2pk(vorigPubkey); vuint8_t vopretNFT; - GetOpReturnCCBlob(oprets, vopretNFT); + GetOpReturnCCBlob(vdatas, vopretNFT); // calc cc outputs for origPubkey CAmount ccOutputs = 0; @@ -320,14 +322,15 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const std::vector> testVouts; uint8_t version; - DecodeTokenOpRetV1(tx.vout.back().scriptPubKey, tokenIdOpret, voutPubkeysInOpret, oprets); - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << funcname << "()" << " oprets.size()=" << oprets.size() << std::endl); + std::vector vdatas; + DecodeTokenOpRetV1(tx.vout.back().scriptPubKey, tokenIdOpret, voutPubkeysInOpret, vdatas); + LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << funcname << "()" << " vdatas.size()=" << vdatas.size() << std::endl); // get assets/channels/gateways token data in vopretExtra: //FilterOutNonCCOprets(oprets, vopretExtra); // NOTE: only 1 additional evalcode in token opret is currently supported: - if (oprets.size() > 0) - vopretExtra = oprets[0]; + if (vdatas.size() > 0) + vopretExtra = vdatas[0]; LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << funcname << "()" << " vopretExtra=" << HexStr(vopretExtra) << std::endl); // get non-fungible data @@ -443,23 +446,38 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const { vscript_t vorigPubkey; std::string dummyName, dummyDescription; - std::vector oprets; + std::vector vdatas; uint8_t version; - if (DecodeTokenCreateOpRetV1(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, oprets) == 0) { + if (DecodeTokenCreateOpRetV1(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, vdatas) == 0) { LOGSTREAM(cctokens_log, CCLOG_INFO, stream << indentStr << funcname << "()" << " could not decode create opret" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); return 0; } CPubKey origPubkey = pubkey2pk(vorigPubkey); vuint8_t vopretNFT; - GetOpReturnCCBlob(oprets, vopretNFT); + GetOpReturnCCBlob(vdatas, vopretNFT); if (origPubkey == GetUnspendable(cp, NULL)) { errorStr = "cannot create tokens with token shared pubkey"; return -1; } + /* + if (vdatas.size() > 1) { + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " invalid vdata size for txid=" << tx.GetHash().GetHex() << " v=" << v << " isLastVoutOpret=" << isLastVoutOpret << std::endl); + return -1; // could not be more than 1 vdata in opreturn + } + std::string tdataError; + std::cerr << __func__ << " vdatas.size()=" << vdatas.size() << std::endl; + if (vdatas.size() > 0) + std::cerr << __func__ << " vdatas[0]=" << HexStr(vdatas[0]) << std::endl; + if (vdatas.size() > 0 && !CheckTokelData(vdatas[0], tdataError)) { + errorStr = tdataError; + return -1; // invalid tokendata + } + */ + // TODO: add voutPubkeys for 'c' tx /* this would not work for imported tokens: @@ -549,20 +567,32 @@ CAmount TokensV2::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const } uint256 tokenIdOpret; - std::vector oprets; + std::vector vdatas; std::vector vpksdummy; // token opret most important checks (tokenid == reftokenid, tokenid is non-zero, tx is 'tokenbase'): - funcId = TokensV2::DecodeTokenOpRet(opret, tokenIdOpret, vpksdummy, oprets); + funcId = TokensV2::DecodeTokenOpRet(opret, tokenIdOpret, vpksdummy, vdatas); if (funcId == 0) { // bad opreturn errorStr = "can't decode opreturn data"; - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " skipping vout with non token opret for txid=" << tx.GetHash().GetHex() << " v=" << v << " isLastVoutOpret=" << isLastVoutOpret << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " found token vout with non-token opret for txid=" << tx.GetHash().GetHex() << " v=" << v << " isLastVoutOpret=" << isLastVoutOpret << std::endl); return -1; // not token vout, skip } // basic checks: if (IsTokenCreateFuncid(funcId)) { + /* + if (vdatas.size() > 1) { + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " invalid vdata size for txid=" << tx.GetHash().GetHex() << " v=" << v << " isLastVoutOpret=" << isLastVoutOpret << std::endl); + return -1; // could not be more than 1 vdata in opreturn + } + std::string tdataError; + if (vdatas.size() > 0 && !CheckTokelData(vdatas[0], tdataError)) { + errorStr = tdataError; + return -1; // invalid tokendata + } + */ + // set returned tokend to tokenbase txid: reftokenid = tx.GetHash(); } @@ -660,6 +690,9 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction & if (tx.vout.size() < 1) return eval->Invalid("no vouts"); + if (std::count_if(tx.vout.begin(), tx.vout.end(), [](const CTxOut &v){ vuint8_t vd; return GetOpReturnData(v.scriptPubKey, vd); }) > 1) + return eval->Invalid("only one opreturn supported"); + std::string errorStr; if (!TokensExactAmounts(true, cp, eval, tx, errorStr)) { @@ -766,6 +799,9 @@ bool Tokensv2Validate(struct CCcontract_info *cp, Eval* eval, const CTransaction if (tx.vout.size() < 1) return report_validation_error(__func__, eval, tx, "no vouts"); + if (std::count_if(tx.vout.begin(), tx.vout.end(), [](const CTxOut &v){ vuint8_t vd; return GetOpReturnData(v.scriptPubKey, vd); }) > 1) + return eval->Invalid("only one opreturn supported"); + std::string errorStr; // these checks now are in TokensExactAmounts diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index bd6dd36ef30..ee2cbd7c53b 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -24,6 +24,7 @@ #include "CCinclude.h" const CAmount TOKENS_MARKER_VALUE = 10000; +const uint8_t TOKENS_OPRETURN_VERSION = 1; // implementation of basic token functions @@ -42,7 +43,7 @@ bool Tokensv2Validate(struct CCcontract_info *cp,Eval* eval,const CTransaction & /// @param maxinputs maximum number of inputs to add. If 0 then CC_MAXVINS define is used //CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, const CPubKey &pk, uint256 tokenid, CAmount total, int32_t maxinputs, bool useMempool = false); -/// Adds token inputs to transaction object. If tokenid is a non-fungible token then the function will set evalCodeNFT variable in the cp object to the eval code from tokencreate tx NFT data to spend NFT outputs properly +/// Adds token inputs to transaction object. If tokenid is a non-fungible token then the function will set evalcodeAdd variable in the cp object to the eval code from tokencreate tx NFT data to spend NFT outputs properly /// @param cp CCcontract_info structure /// @param mtx mutable transaction object /// @param tokenaddr address where token inputs to add @@ -52,7 +53,7 @@ bool Tokensv2Validate(struct CCcontract_info *cp,Eval* eval,const CTransaction & /// @see AddTokenCCInputs //CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, const char *tokenaddr, uint256 tokenid, CAmount total, int32_t maxinputs, bool useMempool = false); -/// Adds token inputs to transaction object. If tokenid is a non-fungible token then the function will set evalCodeNFT variable in the cp object to the eval code from tokencreate tx NFT data to spend NFT outputs properly +/// Adds token inputs to transaction object. If tokenid is a non-fungible token then the function will set evalcodeAdd variable in the cp object to the eval code from tokencreate tx NFT data to spend NFT outputs properly /// @param cp CCcontract_info structure /// @param mtx mutable transaction object /// @param pk pubkey from which the token cc address will be created and token inputs are added diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index f91abad169f..ec32fa6d3ff 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -26,13 +26,12 @@ // get non-fungible data from 'tokenbase' tx (the data might be empty) template -bool GetTokenData(Eval *eval, uint256 tokenid, TokenDataTuple &tokenData, vscript_t &vopretNonfungible) +bool GetTokenData(Eval *eval, uint256 tokenid, TokenDataTuple &tokenData, vscript_t &vextraData) { CTransaction tokenbasetx; uint256 hashBlock; tokenData = std::make_tuple(vuint8_t(), std::string(), std::string()); - vopretNonfungible.clear(); if (!GetTxUnconfirmedOpt(eval, tokenid, tokenbasetx, hashBlock)) { LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << "could not load token creation tx=" << tokenid.GetHex() << std::endl); @@ -43,12 +42,12 @@ bool GetTokenData(Eval *eval, uint256 tokenid, TokenDataTuple &tokenData, vscrip if (tokenbasetx.vout.size() > 0) { std::vector origpubkey; std::string name, description; - std::vector oprets; + std::vector vdatas; uint8_t funcid; - if (IsTokenCreateFuncid(V::DecodeTokenCreateOpRet(tokenbasetx.vout.back().scriptPubKey, origpubkey, name, description, oprets))) { - if (oprets.size() > 0) - vopretNonfungible = oprets[0]; + if (IsTokenCreateFuncid(V::DecodeTokenCreateOpRet(tokenbasetx.vout.back().scriptPubKey, origpubkey, name, description, vdatas))) { + if (vdatas.size() > 0) + vextraData = vdatas[0]; tokenData = std::make_tuple(origpubkey, name, description); return true; } @@ -86,14 +85,14 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c if (cp->evalcode != V::EvalCode()) LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << funcname << "()" << " warning: EVAL_TOKENS *cp is needed but used evalcode=" << (int)cp->evalcode << std::endl); - if (cp->evalcodeNFT == 0) // if not set yet (in TransferToken or this func overload) + if (cp->evalcodeAdd == 0) // if not set yet (in TransferToken or this func overload) { // check if this is a NFT TokenDataTuple tokenData; - vscript_t vopretNonfungible; - GetTokenData(NULL, tokenid, tokenData, vopretNonfungible); - if (vopretNonfungible.size() > 0) - cp->evalcodeNFT = vopretNonfungible.begin()[0]; // set evalcode of NFT, for signing + vscript_t vextraData; + GetTokenData(NULL, tokenid, tokenData, vextraData); + if (vextraData.size() > 0) + cp->evalcodeAdd = vextraData.begin()[0]; // set evalcode of NFT, for signing } // make lambda to use it for either index kind: @@ -179,12 +178,12 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c // check if this is a NFT TokenDataTuple tokenData; - vscript_t vopretNonfungible; - GetTokenData(NULL, tokenid, tokenData, vopretNonfungible); - if (vopretNonfungible.size() > 0) - cp->evalcodeNFT = vopretNonfungible.begin()[0]; // set evalcode of NFT + vscript_t vextraData; + GetTokenData(NULL, tokenid, tokenData, vextraData); + if (vextraData.size() > 0) + cp->evalcodeAdd = vextraData.begin()[0]; // set evalcode of NFT - GetTokensCCaddress(cp, tokenaddr, pk, V::IsMixed()); // GetTokensCCaddress will use 'evalcodeNFT' + GetTokensCCaddress(cp, tokenaddr, pk, V::IsMixed()); // GetTokensCCaddress will use 'evalcodeAdd' return AddTokenCCInputs(cp, mtx, tokenaddr, tokenid, total, maxinputs, useMempool); } @@ -245,9 +244,9 @@ UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info * } uint8_t destEvalCode = V::EvalCode(); - if (cp->evalcodeNFT != 0) // if set in AddTokenCCInputs + if (cp->evalcodeAdd != 0) // if set in AddTokenCCInputs { - destEvalCode = cp->evalcodeNFT; + destEvalCode = cp->evalcodeAdd; } if (probecond.first != nullptr) @@ -360,9 +359,9 @@ UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokeni if ((inputs = AddTokenCCInputs(cp, mtx, tokenaddr, tokenid, total, CC_MAXVINS, useMempool)) >= total) // NOTE: AddTokenCCInputs might set cp->additionalEvalCode which is used in FinalizeCCtx! { uint8_t destEvalCode = V::EvalCode(); - if (cp->evalcodeNFT != 0) // if set in AddTokenCCInputs + if (cp->evalcodeAdd != 0) // if set in AddTokenCCInputs { - destEvalCode = cp->evalcodeNFT; + destEvalCode = cp->evalcodeAdd; } if (inputs > total) @@ -461,10 +460,10 @@ std::string TokenTransfer(CAmount txfee, uint256 tokenid, uint8_t M, const std:: cp = CCinit(&C, V::EvalCode()); TokenDataTuple tokenData; - vscript_t vopretNonfungible; - GetTokenData(NULL, tokenid, tokenData, vopretNonfungible); - if (vopretNonfungible.size() > 0) - cp->evalcodeNFT = vopretNonfungible.begin()[0]; // set evalcode of NFT + vscript_t vextraData; + GetTokenData(NULL, tokenid, tokenData, vextraData); + if (vextraData.size() > 0) + cp->evalcodeAdd = vextraData.begin()[0]; // set evalcode of NFT GetTokensCCaddress(cp, tokenaddr, mypk, V::IsMixed()); UniValue sigData = TokenTransferExt(CPubKey(), txfee, tokenid, tokenaddr, {}, M, destpubkeys, total, true); @@ -485,11 +484,11 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << CCerror << "=" << tokensupply << std::endl); return NullUniValue; } - if (!nonfungibleData.empty() && tokensupply != 1) { + /*if (!nonfungibleData.empty() && tokensupply != 1) { CCerror = "for non-fungible tokens tokensupply should be equal to 1"; LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << CCerror << std::endl); return NullUniValue; - } + }*/ cp = CCinit(&C, V::EvalCode()); if (name.size() > 32 || description.size() > 4096) // this is also checked on rpc level @@ -539,8 +538,11 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup mtx.vout.push_back(V::MakeCC1vout(additionalMarkerEvalCode, TOKENS_MARKER_VALUE, GetUnspendable(cpNFT, NULL))); } - // prevent adding dust change in tokens - sigData = V::FinalizeCCTx(isRemote, FINALIZECCTX_NO_CHANGE_WHEN_DUST, cp, mtx, mypk, txfee, V::EncodeTokenCreateOpRet(vscript_t(mypk.begin(), mypk.end()), name, description, { nonfungibleData })); + std::vector vdatas; + if (!nonfungibleData.empty()) + vdatas.push_back(nonfungibleData); + // prevent adding dust change in tokens + sigData = V::FinalizeCCTx(isRemote, FINALIZECCTX_NO_CHANGE_WHEN_DUST, cp, mtx, mypk, txfee, V::EncodeTokenCreateOpRet(vscript_t(mypk.begin(), mypk.end()), name, description, vdatas)); if (!ResultHasTx(sigData)) { CCerror = "couldnt finalize token tx"; return NullUniValue; @@ -601,7 +603,7 @@ UniValue TokenInfo(uint256 tokenid) CTransaction tokenbaseTx; std::vector origpubkey; std::vector oprets; - vscript_t vopretNonfungible; + vscript_t vextraData; std::string name, description; uint8_t version; @@ -643,9 +645,9 @@ UniValue TokenInfo(uint256 tokenid) result.push_back(Pair("description", description)); if (oprets.size() > 0) - vopretNonfungible = oprets[0]; - if( !vopretNonfungible.empty() ) - result.push_back(Pair("data", HexStr(vopretNonfungible))); + vextraData = oprets[0]; + if( !vextraData.empty() ) + result.push_back(Pair("data", HexStr(vextraData))); result.push_back(Pair("version", DecodeTokenOpretVersion(tokenbaseTx.vout.back().scriptPubKey))); result.push_back(Pair("IsMixed", V::EvalCode() == TokensV2::EvalCode() ? "yes" : "no")); @@ -802,7 +804,7 @@ static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 std::vector vDeadPubkeys, voutPubkeysDummy; std::vector oprets; TokenDataTuple tokenData; - vscript_t vopretExtra, vopretNonfungible; + vscript_t vopretExtra, vextraData; uint8_t evalCode = V::EvalCode(); // if both payloads are empty maybe it is a transfer to non-payload-one-eval-token vout like GatewaysClaim uint8_t evalCode2 = 0; // will be checked if zero or not @@ -830,9 +832,9 @@ static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 LOGSTREAMFN(cctokens_log, CCLOG_DEBUG2, stream << "vopretExtra=" << HexStr(vopretExtra) << std::endl); - GetTokenData(eval, reftokenid, tokenData, vopretNonfungible); - if (vopretNonfungible.size() > 0) - evalCode = vopretNonfungible.begin()[0]; + GetTokenData(eval, reftokenid, tokenData, vextraData); + if (vextraData.size() > 0) + evalCode = vextraData.begin()[0]; if (vopretExtra.size() > 0) evalCode2 = vopretExtra.begin()[0]; @@ -938,9 +940,9 @@ static bool CheckMarkerSpending(struct CCcontract_info *cp, Eval *eval, const CT if (burnedAmount > 0) { TokenDataTuple tokenData; - vscript_t vopretNonfungible; - GetTokenData(eval, tokenid, tokenData, vopretNonfungible); - if (!vopretNonfungible.empty()) + vscript_t vextraData; + GetTokenData(eval, tokenid, tokenData, vextraData); + if (!vextraData.empty()) { CTransaction tokenbaseTx; uint256 hashBlock; diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index 977b86ddd30..d3bc0d6e9b2 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -25,10 +25,6 @@ #define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos) #endif -//#ifndef MAY2020_NNELECTION_HARDFORK -//#define MAY2020_NNELECTION_HARDFORK 1590926400 -//#endif - // return true if new v1 version activation time is passed or chain is always works v1 // return false if v0 is still active @@ -112,8 +108,8 @@ CScript EncodeTokenCreateOpRetV1(const std::vector &origpubkey, const s CScript opret; uint8_t evalcode = EVAL_TOKENS; - uint8_t funcid = 'C'; // 'C' indicates v1 - uint8_t version = 1; + uint8_t funcid = 'C'; // 'C' indicates opreturn version 1 (with the version field) + uint8_t version = TOKENS_OPRETURN_VERSION; opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << version << origpubkey << name << description; for (const auto &o : oprets) { @@ -127,7 +123,7 @@ CScript EncodeTokenCreateOpRetV2(const std::vector &origpubkey, const s CScript opret; uint8_t evalcode = EVAL_TOKENSV2; uint8_t funcid = 'c'; - uint8_t version = 1; + uint8_t version = TOKENS_OPRETURN_VERSION; opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << version << origpubkey << name << description; for (const auto &o : oprets) { @@ -147,9 +143,9 @@ CScript EncodeTokenOpRetV1(uint256 tokenid, const std::vector &voutPubk */ CScript opret; - uint8_t tokenFuncId = 'T'; // 'T' indicates v1 + uint8_t tokenFuncId = 'T'; // 'T' indicates opreturn version 1 (with the version field) uint8_t evalCodeInOpret = EVAL_TOKENS; - uint8_t version = 1; + uint8_t version = TOKENS_OPRETURN_VERSION; tokenid = revuint256(tokenid); @@ -179,7 +175,7 @@ CScript EncodeTokenOpRetV2(uint256 tokenid, const std::vector &oprets CScript opret; uint8_t tokenFuncId = 't'; uint8_t evalCodeInOpret = EVAL_TOKENSV2; - uint8_t version = 1; + uint8_t version = TOKENS_OPRETURN_VERSION; tokenid = revuint256(tokenid); @@ -364,7 +360,7 @@ uint8_t DecodeTokenOpRetV2(const CScript scriptPubKey, uint256 &tokenid, std::ve LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "incorrect evalcode in tokens v2 opret" << std::endl); return (uint8_t)0; } - if (version != 1) { + if (version != TOKENS_OPRETURN_VERSION) { LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "incorrect version in tokens v2 opret" << std::endl); return (uint8_t)0; } diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index f2d3ad955f7..3e3ea8bf30e 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -104,7 +104,7 @@ UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_inf // 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->evalcodeNFT, mypk); + mytokenscond = MakeTokensCCcond1(cp->evalcode, cp->evalcodeAdd, mypk); // to spend from single-eval EVAL_TOKENS mypk cpTokens = CCinit(&tokensC, EVAL_TOKENS); @@ -113,7 +113,7 @@ UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_inf // 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->evalcodeNFT, unspendablepk); + othertokenscond = MakeTokensCCcond1(cp->evalcode, cp->evalcodeAdd, 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. @@ -296,7 +296,7 @@ UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_inf 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->evalcodeNFT, cp->tokens1of2pk[0], cp->tokens1of2pk[1]); + othercond1of2tokens = MakeTokensCCcond1of2(cp->evalcode, cp->evalcodeAdd, cp->tokens1of2pk[0], cp->tokens1of2pk[1]); cond = othercond1of2tokens; } else @@ -528,7 +528,7 @@ UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info cond.reset(MakeCCcond1(cp->evalcode, mypk)); } else if (strcmp(destaddr, mynftaddr) == 0) { privkey = myprivkey; - cond.reset(MakeTokensv2CCcond1(cp->evalcode, cp->evalcodeNFT, mypk)); + cond.reset(MakeTokensv2CCcond1(cp->evalcode, cp->evalcodeAdd, mypk)); } else { const uint8_t nullpriv[32] = {'\0'}; // use vector of dest addresses and conds to probe vintxconds diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 038a8b7c0c2..53bdc2e0064 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -439,7 +439,7 @@ 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->evalcodeNFT, pk, mixed)); + return(_GetTokensCCaddress(destaddr, cp->evalcode, cp->evalcodeAdd, pk, mixed)); } bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2, bool mixed) @@ -458,12 +458,12 @@ bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey { CCwrapper payoutCond; if (!mixed) - payoutCond.reset(MakeTokensCCcond1of2(cp->evalcode, cp->evalcodeNFT, pk1, pk2)); + payoutCond.reset(MakeTokensCCcond1of2(cp->evalcode, cp->evalcodeAdd, pk1, pk2)); else - payoutCond.reset(MakeTokensv2CCcond1of2(cp->evalcode, cp->evalcodeNFT, pk1, pk2)); + payoutCond.reset(MakeTokensv2CCcond1of2(cp->evalcode, cp->evalcodeAdd, pk1, pk2)); destaddr[0] = 0; - if (payoutCond != nullptr) // if evalcodeNFT not set then it is dual-eval cc else three-eval cc + if (payoutCond != nullptr) // if evalcodeAdd not set then it is dual-eval cc else three-eval cc { if (mixed) CCtoAnon(payoutCond.get()); @@ -1011,18 +1011,22 @@ CAmount TotalPubkeyCCInputs(Eval *eval, const CTransaction &tx, const CPubKey &p return total; } -bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector paramsNull,const CTransaction &ctx, unsigned int nIn, std::shared_ptr evalcodeChecker) +bool ProcessCC(struct CCcontract_info* cp, Eval* eval, std::vector paramsNull, const CTransaction& ctx, unsigned int nIn, std::shared_ptr evalcodeChecker) { - CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector origpubkey; + CTransaction createTx; + uint256 assetid, assetid2, hashBlock; + uint8_t funcid; + int32_t height, i, n, from_mempool = 0; + int64_t amount; + std::vector 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 ) + 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 ) - { + if ((KOMODO_CONNECTING & (1 << 30)) != 0) { from_mempool = 1; - height &= ((1<<30) - 1); + height &= ((1 << 30) - 1); } if (cp->validate == NULL) return eval->Invalid("validation not supported for eval code"); @@ -1034,69 +1038,65 @@ bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector param // return(true); //fprintf(stderr,"process CC %02x\n",cp->evalcode); CCclearvars(cp); - if ( paramsNull.size() != 0 ) // Don't expect params + 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 ) - { + else if ((*cp->validate)(cp, eval, ctx, nIn) != 0) { //fprintf(stderr,"done CC %02x\n",cp->evalcode); //cp->prevtxid = txid; - if (evalcodeChecker.get()!=NULL) evalcodeChecker->MarkEvalCode(ctx.GetHash(),cp->evalcode); - return(true); + if (evalcodeChecker.get() != NULL) + evalcodeChecker->MarkEvalCode(ctx.GetHash(), cp->evalcode); + return (true); } //fprintf(stderr,"invalid CC %02x\n",cp->evalcode); - return(false); + return (false); } -extern struct CCcontract_info CCinfos[0x100]; -extern std::string MYCCLIBNAME; -bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn); - -bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector paramsNull,const CTransaction &txTo,unsigned int nIn,std::shared_ptr evalcodeChecker) +bool CClib_Dispatch(const CC* cond, Eval* eval, std::vector paramsNull, const CTransaction& txTo, unsigned int nIn, std::shared_ptr evalcodeChecker) { - uint8_t evalcode; int32_t height,from_mempool; struct CCcontract_info *cp; - if ( ASSETCHAINS_CCLIB != MYCCLIBNAME ) - { - fprintf(stderr,"-ac_cclib=%s vs myname %s\n",ASSETCHAINS_CCLIB.c_str(),MYCCLIBNAME.c_str()); + uint8_t evalcode; + int32_t height, from_mempool; + struct CCcontract_info* cp; + if (ASSETCHAINS_CCLIB != MYCCLIBNAME) { + fprintf(stderr, "-ac_cclib=%s vs myname %s\n", ASSETCHAINS_CCLIB.c_str(), MYCCLIBNAME.c_str()); 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 ) + 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 ) - { + if ((KOMODO_CONNECTING & (1 << 30)) != 0) { from_mempool = 1; - height &= ((1<<30) - 1); + height &= ((1 << 30) - 1); } evalcode = cond->code[0]; - if (evalcodeChecker.get()!=NULL && evalcodeChecker->CheckEvalCode(txTo.GetHash(),evalcode)!=0) return true; - if ( evalcode >= EVAL_FIRSTUSER && evalcode <= EVAL_LASTUSER ) - { + if (evalcodeChecker.get() != NULL && evalcodeChecker->CheckEvalCode(txTo.GetHash(), evalcode) != 0) + return true; + if (evalcode >= EVAL_FIRSTUSER && evalcode <= EVAL_LASTUSER) { cp = &CCinfos[(int32_t)evalcode]; - if ( cp->didinit == 0 ) - { - if ( CClib_initcp(cp,evalcode) == 0 ) + if (cp->didinit == 0) { + if (CClib_initcp(cp, evalcode) == 0) cp->didinit = 1; - else return eval->Invalid("unsupported CClib evalcode"); + else + return eval->Invalid("unsupported CClib evalcode"); } CCclearvars(cp); - if ( paramsNull.size() != 0 ) // Don't expect params + if (paramsNull.size() != 0) // Don't expect params return eval->Invalid("Cannot have params"); - else if ( CClib_validate(cp,height,eval,txTo,nIn) != 0 ) - { - if (evalcodeChecker.get()!=NULL) evalcodeChecker->MarkEvalCode(txTo.GetHash(),evalcode); - return(true); + else if (CClib_validate(cp, height, eval, txTo, nIn) != 0) { + if (evalcodeChecker.get() != NULL) + evalcodeChecker->MarkEvalCode(txTo.GetHash(), evalcode); + return (true); } - return(false); //eval->Invalid("error in CClib_validate"); + return (false); //eval->Invalid("error in CClib_validate"); } return eval->Invalid("cclib CC must have evalcode between 16 and 127"); } -void OS_randombytes(unsigned char *x,long xlen); -extern bits256 curve25519_basepoint9(); +//void OS_randombytes(unsigned char *x,long xlen); +//extern bits256 curve25519_basepoint9(); int32_t _SuperNET_cipher(uint8_t nonce[crypto_box_NONCEBYTES],uint8_t *cipher,uint8_t *message,int32_t len,bits256 destpub,bits256 srcpriv,uint8_t *buf) { @@ -1500,7 +1500,8 @@ CScript GetCCDropAsOpret(const CScript &scriptPubKey) } } - /*if (vParams.size() >= 1) // allow more data after cc opret + /* parse OP_DROP without verus header (such opdrops are not supported anymore): + if (vParams.size() >= 1) // allow more data after cc opret { //uint8_t version; //uint8_t evalCode; @@ -1525,8 +1526,7 @@ CScript GetCCDropAsOpret(const CScript &scriptPubKey) opret << OP_RETURN << vParams[0]; // no verus header, treat vParams[0] as cc data and return as opret return true; } - } - */ + } */ } return CScript(); } diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index efd77a569e2..d6505dfec0b 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -17,7 +17,7 @@ #include "CCassets.h" #include "CCtokens_impl.h" #include "CCassetsCore_impl.h" -#include "CCNFTData.h" +#include "CCTokelData.h" const int32_t CCVOUT = 1; const int32_t NORMALVOUT = 0; @@ -167,7 +167,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const uint256 hashBlock, assetid, assetid2; int32_t ccvins = -1, ccvouts = -1; int64_t unit_price, vin_unit_price; - vuint8_t vorigpubkey, vin_origpubkey, vopretNonfungible; + vuint8_t vorigpubkey, vin_origpubkey, vextraData; TokenDataTuple tokenData; uint8_t funcid, evalCodeInOpret; char destaddr[KOMODO_ADDRESS_BUFSIZE], origNormalAddr[KOMODO_ADDRESS_BUFSIZE], ownerNormalAddr[KOMODO_ADDRESS_BUFSIZE]; @@ -184,10 +184,11 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("AssetValidate: no vins"); if (tx.vout.size() == 0) return eval->Invalid("AssetValidate: no vouts"); + if((funcid = A::DecodeAssetTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCodeInOpret, assetid, assetid2, unit_price, vorigpubkey)) == 0 ) return eval->Invalid("AssetValidate: invalid opreturn payload"); - // reinit cpAssets as we could set evalcodeNFT in it + // reinit cpAssets as we could set evalcodeAdd in it struct CCcontract_info *cpAssets, assetsC; cpAssets = CCinit(&assetsC, A::EvalCode()); @@ -196,13 +197,13 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const cpTokens = CCinit(&tokensC, T::EvalCode()); // non-fungible tokens support: - GetTokenData(eval, assetid, tokenData, vopretNonfungible); - uint64_t royaltyFract = 0; // royalty is N in N/1000 fraction - if (vopretNonfungible.size() > 0) { - cpAssets->evalcodeNFT = vopretNonfungible.begin()[0]; - GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); - if (royaltyFract > NFTROYALTY_DIVISOR-1) - royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit + GetTokenData(eval, assetid, tokenData, vextraData); + int64_t royaltyFract = 0; // royalty is N in N/1000 fraction + if (vextraData.size() > 0) { + cpAssets->evalcodeAdd = vextraData.begin()[0]; + GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); + if (royaltyFract > TKLROYALTY_DIVISOR-1) + royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } vuint8_t ownerpubkey = std::get<0>(tokenData); @@ -258,8 +259,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("invalid vout1 marker for original pubkey"); else if( TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vorigpubkey)) == 0 ) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for bid"); - else if (unit_price <= 0) - return eval->Invalid("invalid unit price"); + else if (unit_price <= ASSETS_NORMAL_DUST) + return eval->Invalid("invalid or too low unit price"); else if (tx.vout[0].nValue < unit_price) return eval->Invalid("invalid bid amount too low"); @@ -382,7 +383,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (!ValidateBidRemainder(unit_price, tx.vout[0].nValue, vin_assetoshis, received_value, paid_units)) // check real price and coins spending from global addr return eval->Invalid("vout" + std::to_string(2+r) + " mismatched remainder for fillbid"); if (royaltyFract > 0) { - if ((tx.vout[1].nValue + tx.vout[2].nValue) / NFTROYALTY_DIVISOR * royaltyFract != tx.vout[2].nValue) // validate royalty value + if ((tx.vout[1].nValue + tx.vout[2].nValue) / TKLROYALTY_DIVISOR * royaltyFract != tx.vout[2].nValue) // validate royalty value return eval->Invalid("vout2 invalid royalty amount for fillask"); if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest return eval->Invalid("vout2 invalid royalty detination for fillask"); @@ -419,8 +420,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("invalid vout1 marker for originator pubkey"); else if (TotalPubkeyNormalInputs(eval, tx, origpk) == 0) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for ask"); - else if (unit_price <= 0) - return eval->Invalid("invalid unit price"); + else if (unit_price <= ASSETS_NORMAL_DUST) + return eval->Invalid("invalid or too low unit price"); if (tx.vout[2].scriptPubKey.IsPayToCryptoCondition()) if (!tx.vout[2].scriptPubKey.IsPayToCCV2() || tx.vout[2].scriptPubKey.SpkHasEvalcodeCCV2(T::EvalCode())) // have token change @@ -486,7 +487,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const else if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, origNormalAddr, 0LL, 0)) // coins to originator normal addr return eval->Invalid("vout2 should be cc for fillask"); if (royaltyFract > 0) { - if ((tx.vout[2].nValue + tx.vout[3].nValue) / NFTROYALTY_DIVISOR * royaltyFract != tx.vout[3].nValue) // validate royalty value + if ((tx.vout[2].nValue + tx.vout[3].nValue) / TKLROYALTY_DIVISOR * royaltyFract != tx.vout[3].nValue) // validate royalty value return eval->Invalid("vout3 invalid royalty amount for fillask"); if (!A::ConstrainVout(tx.vout[3], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest return eval->Invalid("vout3 invalid royalty detination for fillask"); diff --git a/src/cc/eval.h b/src/cc/eval.h index 342eb442718..42f8676d682 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -61,7 +61,7 @@ EVAL(EVAL_KOGS, 0xf4) \ EVAL(EVAL_TOKENSV2, 0xf5) \ EVAL(EVAL_ASSETSV2, 0xf6) \ - EVAL(EVAL_NFTDATA, 0xf7) \ + EVAL(EVAL_TOKELDATA, 0xf7) \ // evalcodes 0x10 to 0x7f are reserved for cclib dynamic CC diff --git a/src/cc/gamescc.cpp b/src/cc/gamescc.cpp index b9dd3fa4792..e3c33be98d7 100644 --- a/src/cc/gamescc.cpp +++ b/src/cc/gamescc.cpp @@ -255,15 +255,15 @@ uint8_t games_registeropretdecode(uint256 &gametxid,uint256 &tokenid,uint256 &pl { std::string name, description; std::vector vorigPubkey; std::vector oprets; - std::vector vopretNonfungible, vopret, vopretDummy,origpubkey; + std::vector vextraData, vopret, vopretDummy,origpubkey; uint8_t f,*script; std::vector voutPubkeys; tokenid = zeroid; GetOpReturnData(scriptPubKey, vopret); script = (uint8_t *)vopret.data(); if ( script[1] == 'c' && (f= DecodeTokenCreateOpRetV1(scriptPubKey,origpubkey,name,description,oprets)) == 'c' ) { - GetOpReturnCCBlob(oprets, vopretNonfungible); - vopret = vopretNonfungible; + GetOpReturnCCBlob(oprets, vextraData); + vopret = vextraData; } else if ( script[1] != 'R' && (f= DecodeTokenOpRetV1(scriptPubKey, tokenid, voutPubkeys, oprets)) != 0 ) { @@ -290,21 +290,21 @@ uint8_t games_finishopretdecode(uint256 &gametxid, uint256 &tokenid, int32_t &re std::string name, description; std::vector vorigPubkey; std::vector oprets, opretsDummy; TokenDataTuple tokenData; - std::vector vopretNonfungible, vopret, vopretDummy,origpubkey; + std::vector vextraData, vopret, vopretDummy,origpubkey; uint8_t f,*script; std::vector voutPubkeys; tokenid = zeroid; GetOpReturnData(scriptPubKey, vopret); script = (uint8_t *)vopret.data(); if ( script[1] == 'c' && (f= DecodeTokenCreateOpRetV1(scriptPubKey,origpubkey,name,description, oprets)) == 'c' ) { - GetOpReturnCCBlob(oprets, vopretNonfungible); - vopret = vopretNonfungible; + GetOpReturnCCBlob(oprets, vextraData); + vopret = vextraData; } else if ( script[1] != 'H' && script[1] != 'Q' && (f= DecodeTokenOpRetV1(scriptPubKey, tokenid, voutPubkeys, opretsDummy)) != 0 ) { //fprintf(stderr,"decode opret %c tokenid.%s\n",script[1],tokenid.GetHex().c_str()); - GetTokenData(NULL, reftokenid, tokenData, vopretNonfungible); //load nonfungible data from the 'tokenbase' tx - vopret = vopretNonfungible; + GetTokenData(NULL, reftokenid, tokenData, vextraData); //load nonfungible data from the 'tokenbase' tx + vopret = vextraData; } if ( vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> gametxid; ss >> symbol; ss >> pname; ss >> regslot; ss >> pk; ss >> playerdata) != 0 && e == EVAL_GAMES && (f == 'H' || f == 'Q') ) { @@ -1612,9 +1612,9 @@ UniValue games_finish(uint64_t txfee,struct CCcontract_info *cp,cJSON *params,ch opret = games_finishopret(funcid, gametxid, regslot, mypk, newdata,pname); char seedstr[32]; sprintf(seedstr,"%llu",(long long)seed); - std::vector vopretNonfungible; - GetOpReturnData(opret, vopretNonfungible); - rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeTokenCreateOpRet('c', Mypubkey(), std::string(seedstr), gametxid.GetHex(), vopretNonfungible)); + std::vector vextraData; + GetOpReturnData(opret, vextraData); + rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeTokenCreateOpRet('c', Mypubkey(), std::string(seedstr), gametxid.GetHex(), vextraData)); } memset(mypriv,0,sizeof(mypriv)); return(games_rawtxresult(result,rawtx,1)); diff --git a/src/cc/old/CCassetsCore_v0.cpp b/src/cc/old/CCassetsCore_v0.cpp index d8d27f34d96..a313f832e03 100644 --- a/src/cc/old/CCassetsCore_v0.cpp +++ b/src/cc/old/CCassetsCore_v0.cpp @@ -389,11 +389,11 @@ bool GetAssetorigaddrs(struct CCcontract_info *cp, char *origCCaddr, char *origN if (vintxFuncId == 's' || vintxFuncId == 'S') { // bGetCCaddr = GetCCaddress(cpTokens, origCCaddr, pubkey2pk(origpubkey)); - cpTokens->evalcodeNFT = cp->evalcodeNFT; // add non-fungible if present + cpTokens->evalcodeAdd = cp->evalcodeAdd; // add non-fungible if present bGetCCaddr = GetTokensCCaddress(cpTokens, origCCaddr, pubkey2pk(origpubkey)); // tokens to single-eval token or token+nonfungible } else if (vintxFuncId == 'b' || vintxFuncId == 'B') { - cpTokens->evalcodeNFT = cp->evalcodeNFT; // add non-fungible if present + cpTokens->evalcodeAdd = cp->evalcodeAdd; // add non-fungible if present bGetCCaddr = GetTokensCCaddress(cpTokens, origCCaddr, pubkey2pk(origpubkey)); // tokens to single-eval token or token+nonfungible } else { diff --git a/src/cc/old/CCassetstx_v0.cpp b/src/cc/old/CCassetstx_v0.cpp index 63bd3da2a20..588e29bb3e1 100644 --- a/src/cc/old/CCassetstx_v0.cpp +++ b/src/cc/old/CCassetstx_v0.cpp @@ -123,7 +123,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t additionalEvalCode) if (refassetid != zeroid) { GetNonfungibleData(refassetid, vopretNonfungible); if (vopretNonfungible.size() > 0) - cpAssets->evalcodeNFT = vopretNonfungible.begin()[0]; + cpAssets->evalcodeAdd = vopretNonfungible.begin()[0]; } GetTokensCCaddress(cpAssets, assetsTokensUnspendableAddr, GetUnspendable(cpAssets, NULL)); SetCCunspents(unspentOutputsTokens, assetsTokensUnspendableAddr,true); @@ -144,7 +144,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t additionalEvalCode) char assetsDualEvalTokensUnspendableAddr[64]; // try also dual eval tokenasks (and we do not need bids): - cpAssets->evalcodeNFT = additionalEvalCode; + cpAssets->evalcodeAdd = additionalEvalCode; GetTokensCCaddress(cpAssets, assetsDualEvalTokensUnspendableAddr, GetUnspendable(cpAssets, NULL)); SetCCunspents(unspentOutputsDualEvalTokens, assetsDualEvalTokensUnspendableAddr,true); @@ -354,16 +354,16 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p // if this is non-fungible tokens: if( !vopretNonfungible.empty() ) // set its evalcode - cpAssets->evalcodeNFT = vopretNonfungible.begin()[0]; + cpAssets->evalcodeAdd = vopretNonfungible.begin()[0]; CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); - mtx.vout.push_back(MakeTokensCC1vout(EVAL_ASSETS, cpAssets->evalcodeNFT, askamount, unspendableAssetsPubkey)); + mtx.vout.push_back(MakeTokensCC1vout(EVAL_ASSETS, cpAssets->evalcodeAdd, askamount, unspendableAssetsPubkey)); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk)); //marker (seems, it is not for tokenorders) if (inputs > askamount) CCchange = (inputs - askamount); if (CCchange != 0) // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) - mtx.vout.push_back(MakeTokensCC1vout((cpAssets->evalcodeNFT) ? cpAssets->evalcodeNFT : EVAL_TOKENS, CCchange, mypk)); + mtx.vout.push_back(MakeTokensCC1vout((cpAssets->evalcodeAdd) ? cpAssets->evalcodeAdd : EVAL_TOKENS, CCchange, mypk)); std::vector voutTokenPubkeys; voutTokenPubkeys.push_back(unspendableAssetsPubkey); @@ -545,9 +545,9 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) } if (vopretNonfungible.size() > 0) - cpAssets->evalcodeNFT = vopretNonfungible.begin()[0]; + cpAssets->evalcodeAdd = vopretNonfungible.begin()[0]; - mtx.vout.push_back(MakeTokensCC1vout(cpAssets->evalcodeNFT == 0 ? EVAL_TOKENS : cpAssets->evalcodeNFT, askamount, mypk)); // one-eval token vout + mtx.vout.push_back(MakeTokensCC1vout(cpAssets->evalcodeAdd == 0 ? EVAL_TOKENS : cpAssets->evalcodeAdd, askamount, mypk)); // one-eval token vout mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); std::vector voutTokenPubkeys; @@ -783,7 +783,7 @@ std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 a std::vector voutTokenPubkeys; voutTokenPubkeys.push_back(mypk); - cpAssets->evalcodeNFT = additionalTokensEvalcode2; + cpAssets->evalcodeAdd = additionalTokensEvalcode2; return(FinalizeCCTx(0, cpAssets, mtx, mypk, txfee, EncodeTokenOpRet(assetid, voutTokenPubkeys, diff --git a/src/cc/old/CCtokens_v0.cpp b/src/cc/old/CCtokens_v0.cpp index 0f057ad597c..964691cfe92 100644 --- a/src/cc/old/CCtokens_v0.cpp +++ b/src/cc/old/CCtokens_v0.cpp @@ -626,14 +626,14 @@ int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, C GetNonfungibleData(tokenid, vopretNonfungible); if (vopretNonfungible.size() > 0) - cp->evalcodeNFT = vopretNonfungible.begin()[0]; + cp->evalcodeAdd = vopretNonfungible.begin()[0]; GetTokensCCaddress(cp, tokenaddr, pk); SetCCunspents(unspentOutputs, tokenaddr,true); if (unspentOutputs.empty()) { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "AddTokenCCInputs() no utxos for token dual/three eval addr=" << tokenaddr << " evalcode=" << (int)cp->evalcode << " additionalTokensEvalcode2=" << (int)cp->evalcodeNFT << std::endl); + LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "AddTokenCCInputs() no utxos for token dual/three eval addr=" << tokenaddr << " evalcode=" << (int)cp->evalcode << " additionalTokensEvalcode2=" << (int)cp->evalcodeAdd << std::endl); } threshold = total / (maxinputs != 0 ? maxinputs : CC_MAXVINS); diff --git a/src/cc/old/assets_v0.cpp b/src/cc/old/assets_v0.cpp index 1f6b693f2dc..eb0e5e5af08 100644 --- a/src/cc/old/assets_v0.cpp +++ b/src/cc/old/assets_v0.cpp @@ -171,7 +171,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti // non-fungible tokens support: GetNonfungibleData(assetid, vopretNonfungible); if (vopretNonfungible.size() > 0) - cpAssets->evalcodeNFT = vopretNonfungible.begin()[0]; + cpAssets->evalcodeAdd = vopretNonfungible.begin()[0]; // find dual-eval tokens unspendable addr: GetTokensCCaddress(cpAssets, tokensDualEvalUnspendableCCaddr, GetUnspendable(cpAssets, NULL)); diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index ac372803169..f95b7ed4e35 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -138,7 +138,7 @@ template UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& mypk) { uint256 tokenid; - uint8_t evalcodeNFT = 0; + uint8_t evalcodeAdd = 0; const CPubKey emptypk; if ( fHelp || params.size() > 2 ) @@ -157,12 +157,12 @@ UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp } } if (params.size() == 2) - evalcodeNFT = strtol(params[1].get_str().c_str(), NULL, 0); // supports also 0xEE-like values + evalcodeAdd = strtol(params[1].get_str().c_str(), NULL, 0); // supports also 0xEE-like values if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - return AssetOrders(tokenid, emptypk, evalcodeNFT); + return AssetOrders(tokenid, emptypk, evalcodeAdd); else - return tokensv0::AssetOrders(tokenid, emptypk, evalcodeNFT); + return tokensv0::AssetOrders(tokenid, emptypk, evalcodeAdd); } UniValue tokenorders(const UniValue& params, bool fHelp, const CPubKey& remotepk) @@ -184,16 +184,16 @@ UniValue mytokenorders(const std::string& name, const UniValue& params, bool fHe "if evalcode is set then returns mypubkey's token orders for non-fungible tokens with this evalcode\n" "\n"); if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - uint8_t evalcodeNFT = 0; + uint8_t evalcodeAdd = 0; if (params.size() == 1) - evalcodeNFT = strtol(params[0].get_str().c_str(), NULL, 0); // supports also 0xEE-like values + evalcodeAdd = strtol(params[0].get_str().c_str(), NULL, 0); // supports also 0xEE-like values CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - return AssetOrders(zeroid, mypk, evalcodeNFT); + return AssetOrders(zeroid, mypk, evalcodeAdd); else - return tokensv0::AssetOrders(zeroid, Mypubkey(), evalcodeNFT); + return tokensv0::AssetOrders(zeroid, Mypubkey(), evalcodeAdd); } UniValue mytokenorders(const UniValue& params, bool fHelp, const CPubKey& remotepk) @@ -254,20 +254,20 @@ UniValue tokenv2balance(const UniValue& params, bool fHelp, const CPubKey& remot } template -static UniValue tokencreate(const std::string& fname, const UniValue& params, bool fHelp, const CPubKey& remotepk) +static UniValue tokencreate(const std::string& fname, const UniValue& params, const vuint8_t &vtokenData, bool fHelp, const CPubKey& remotepk) { UniValue result(UniValue::VOBJ); std::string name, description, hextx; - std::vector nonfungibleData; - int64_t supply; // changed from uin64_t to int64_t for this 'if ( supply <= 0 )' to work as expected + std::vector tokenData; + CAmount supply; // changed from uin64_t to int64_t for this 'if ( supply <= 0 )' to work as expected CCerror.clear(); - if ( fHelp || params.size() > 4 || params.size() < 2 ) - throw runtime_error(fname + " name supply [description][nft data]\n"); - if ( ensure_CCrequirements(V::EvalCode()) < 0 ) + //if (fHelp || params.size() > 4 || params.size() < 2) + // throw runtime_error(fname + " name supply [description] [tokens data]\n"); + if (ensure_CCrequirements(V::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - + if (!EnsureWalletIsAvailable(false)) throw runtime_error("wallet is required"); LOCK2(cs_main, pwalletMain->cs_wallet); // remote call not supported yet @@ -286,18 +286,8 @@ static UniValue tokencreate(const std::string& fname, const UniValue& params, bo if (description.size() > 4096) return MakeResultError("Token description must be <= " + std::to_string(4096)); // allowed > MAX_SCRIPT_ELEMENT_SIZE } - - if (params.size() >= 4) { - nonfungibleData = ParseHex(params[3].get_str()); - // looks like bigger than 520 data is available in opreturn - // if (nonfungibleData.size() > MAX_SCRIPT_ELEMENT_SIZE) // script element limit - // return MakeResultError("Non-fungible data size must be <= " + std::to_string(MAX_SCRIPT_ELEMENT_SIZE)); - - if( nonfungibleData.empty() ) - return MakeResultError("Non-fungible data incorrect"); - } - hextx = CreateTokenLocal(0, supply, name, description, nonfungibleData); + hextx = CreateTokenLocal(0, supply, name, description, tokenData); RETURN_IF_ERROR(CCerror); if( hextx.size() > 0 ) @@ -308,13 +298,107 @@ static UniValue tokencreate(const std::string& fname, const UniValue& params, bo UniValue tokencreate(const UniValue& params, bool fHelp, const CPubKey& remotepk) { - return tokencreate("tokencreate", params, fHelp, remotepk); + if (fHelp || params.size() > 4 || params.size() < 2) + throw runtime_error("tokencreate name supply [description] [tokens data]\n" + "create tokens\n" + " name - token name string\n" + " supply - token supply in coins\n" + " description - opt description" + " tokens data - an opt hex string with token data. If first byte is non-null it means a evalcode of a cc which tokens will be routed:\n" + " { \"url\":, \"id\":, \"royalty\":, \"arbitrary\": }\n" + ); + + vuint8_t tokenData; + if (params.size() >= 4) { + tokenData = ParseHex(params[3].get_str()); + if (tokenData.empty()) + return MakeResultError("Token data incorrect"); + } + return tokencreate("tokencreate", params, tokenData, fHelp, remotepk); } UniValue tokenv2create(const UniValue& params, bool fHelp, const CPubKey& remotepk) { - return tokencreate("tokenv2create", params, fHelp, remotepk); +if (fHelp || params.size() > 4 || params.size() < 2) + throw runtime_error("tokenv2create name supply [description] [tokens data]\n" + "create tokens version 2\n" + " name - token name string\n" + " supply - token supply in coins\n" + " description - opt description" + " tokens data - an opt hex string with token data. If first byte is non-null it means a evalcode of a cc which tokens will be routed:\n" + " { \"url\":, \"id\":, \"royalty\":, \"arbitrary\": }\n" + ); + + vuint8_t tokenData; + if (params.size() >= 4) { + tokenData = ParseHex(params[3].get_str()); + if (tokenData.empty()) + return MakeResultError("Tokel token data incorrect"); + } + return tokencreate("tokenv2create", params, tokenData, fHelp, remotepk); } +UniValue tokencreatetokel(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() > 4 || params.size() < 2) + throw runtime_error("tokencreatetokel name supply [description] [tokens data]\n" + "create tokens with tokel project data\n" + " name - token name string\n" + " supply - token supply in coins\n" + " description - opt description" + " tokens data - an opt json object with tokel token properties:\n" + " { \"url\":, \"id\":, \"royalty\":, \"arbitrary\": }\n" + ); + + vuint8_t tokenData; + if (params.size() >= 4) { + UniValue jsonParams; + + if (params[3].getType() == UniValue::VOBJ) + jsonParams = params[3].get_array(); + else if (params[3].getType() == UniValue::VSTR) // json in quoted string '{...}' + jsonParams.read(params[3].get_str().c_str()); + if (jsonParams.getType() != UniValue::VOBJ /*|| jsonParams.empty()*/) + throw runtime_error("parameter 4 must be a json object\n"); + + tokenData = ParseTokelJson(jsonParams); + if (tokenData.empty()) + return MakeResultError("Tokel token data incorrect"); + } + + return tokencreate("tokencreate", params, tokenData, fHelp, remotepk); +} +UniValue tokenv2createtokel(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() > 4 || params.size() < 2) + throw runtime_error("tokencreatetokel name supply [description] [tokens data]\n" + "create tokens with tokel project data\n" + " name - token name string\n" + " supply - token supply in coins\n" + " description - opt description" + " tokens data - an opt json object with with tokel token properties:\n" + " { \"url\":, \"id\":, \"royalty\":, \"arbitrary\": }\n" + ); + + vuint8_t tokenData; + if (params.size() >= 4) { + UniValue jsonParams; + + if (params[3].getType() == UniValue::VOBJ) + jsonParams = params[3].get_array(); + else if (params[3].getType() == UniValue::VSTR) // json in quoted string '{...}' + jsonParams.read(params[3].get_str().c_str()); + std::cerr << __func__ << " type=" << (int)jsonParams.getType() << " keys size=" << jsonParams.getKeys().size() << std::endl; + if (jsonParams.getType() != UniValue::VOBJ /*|| jsonParams.empty()*/) + throw runtime_error("parameter 4 must be a json object\n"); + + tokenData = ParseTokelJson(jsonParams); + if (tokenData.empty()) + return MakeResultError("Token data incorrect"); + } + return tokencreate("tokenv2create", params, tokenData, fHelp, remotepk); +} + + template static UniValue tokentransfer(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) { @@ -488,11 +572,11 @@ UniValue tokentransfermany(const std::string& name, const UniValue& params, bool for (const auto &tokenid : tokenids) { TokenDataTuple tokenData; - vuint8_t vnftData; - GetTokenData(NULL, tokenid, tokenData, vnftData); + vuint8_t vtokenData; + GetTokenData(NULL, tokenid, tokenData, vtokenData); CCwrapper probeCond; - if (vnftData.size() > 0) - probeCond.reset( V::MakeTokensCCcond1(vnftData[0], mypk) ); + if (vtokenData.size() > 0) + probeCond.reset( V::MakeTokensCCcond1(vtokenData[0], mypk) ); else probeCond.reset( MakeCCcond1(V::EvalCode(), mypk) ); @@ -500,7 +584,7 @@ UniValue tokentransfermany(const std::string& name, const UniValue& params, bool Myprivkey(mypriv); char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; - cpTokens->evalcodeNFT = vnftData.size() > 0 ? vnftData[0] : 0; + cpTokens->evalcodeAdd = vtokenData.size() > 0 ? vtokenData[0] : 0; GetTokensCCaddress(cpTokens, tokenaddr, mypk, V::IsMixed()); UniValue addtxResult = TokenAddTransferVout(mtx, cpTokens, remotepk, tokenid, tokenaddr, { destpk }, {probeCond, mypriv}, amount, false); @@ -1014,6 +1098,8 @@ static const CRPCCommand commands[] = //{ "tokens", "tokenfillswap", &tokenfillswap, true }, { "tokens", "tokenconvert", &tokenconvert, true }, { "ccutils", "addccv2signature", &addccv2signature, true }, + { "tokens", "tokencreatetokel", &tokencreatetokel, true }, + { "tokens v2", "tokenv2createtokel", &tokenv2createtokel, true }, }; void RegisterTokensRPCCommands(CRPCTable &tableRPC) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index f6cf924461e..3ced66e93d2 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -10,7 +10,7 @@ #include "cc/CCassets.h" #include "cc/CCassetstx_impl.h" -#include "cc/CCNFTData.h" +#include "cc/CCTokelData.h" #include "cc/eval.h" @@ -61,7 +61,7 @@ class EvalMock : public Eval //std::cerr <<__func__ << " hash=" << hash.GetHex() << std::endl; auto r = txs.find(hash); if (r != txs.end()) { - std::cerr <<__func__ << " hash=" << hash.GetHex() << " found" << std::endl; + //std::cerr <<__func__ << " hash=" << hash.GetHex() << " found" << std::endl; txOut = r->second; if (blocks.count(hash) > 0) hashBlock = hash; @@ -73,7 +73,7 @@ class EvalMock : public Eval static EvalMock eval; -static CTransaction txnormal1, txnormal2, txnormal3, txnormal4, txnormalg, txask1, txbid1, txbid2, txtokencreate1, txtokencreate2, txtokencreate3, txtokencreateUnused; +static CTransaction txnormal1, txnormal2, txnormal3, txnormal4, txnormalg, txask1, txask2, txbid1, txbid2, txtokencreate1, txtokencreate2, txtokencreate3, txtokencreateUnused; static uint256 tokenid1, tokenid2, tokenid3, tokenidUnused; // RJXkCF7mn2DRpUZ77XBNTKCe55M2rJbTcu @@ -265,8 +265,8 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ } else if (strcmp(destaddr, mytokenaddr) == 0) { privkey = myprivkey; - cond.reset(MakeTokensv2CCcond1(cp->evalcode, cp->evalcodeNFT, mypk)); - std::cerr << __func__ << " found mytokenaddr=" << mytokenaddr << " evalcode=" << (int)cp->evalcode << " evalcodeNFT=" << (int)cp->evalcodeNFT << std::endl; + cond.reset(MakeTokensv2CCcond1(cp->evalcode, cp->evalcodeAdd, mypk)); + std::cerr << __func__ << " found mytokenaddr=" << mytokenaddr << " evalcode=" << (int)cp->evalcode << " evalcodeAdd=" << (int)cp->evalcodeAdd << std::endl; } else { const uint8_t nullpriv[32] = {'\0'}; // use vector of dest addresses and conds to probe vintxconds @@ -371,7 +371,7 @@ class TestAssetsCC : public ::testing::Test { bool bCheck = checker.CheckCryptoCondition(vout.scriptPubKey.GetCCV2SPK(), &error); if (!bCheck) { - std::cerr << __func__ << " CheckCryptoCondition error=" << ScriptErrorString(error) << std::endl; + std::cerr << __func__ << " CheckCryptoCondition error=" << ScriptErrorString(error) << " eval=" << eval.state.GetRejectReason() << std::endl; return false; } std::cerr << __func__ << " cc_verify okay for vout.nValue=" << vout.nValue << std::endl; @@ -418,10 +418,13 @@ class TestAssetsCC : public ::testing::Test { eval.AddTx(txtokencreateUnused); tokenidUnused = txtokencreateUnused.GetHash(); - txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 1000, 1000/2); + txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 500); eval.AddTx(txask1); - txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 1000, 1000/2); + txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 500); + eval.AddTx(txask2); + + txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, 500); eval.AddTx(txbid1); @@ -464,13 +467,13 @@ class TestAssetsCC : public ::testing::Test { } - static CMutableTransaction MakeTokenV2AskTx(struct CCcontract_info *cpTokens, CPubKey pk, uint256 tokenid, CAmount askamount, CAmount unit_price) + static CMutableTransaction MakeTokenV2AskTx(struct CCcontract_info *cpTokens, CPubKey pk, uint256 tokenid, CAmount numtokens, CAmount unit_price) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); struct CCcontract_info *cpAssets, C; //struct CCcontract_info *cpTokens, tokensC; - uint8_t evalcodeNFT = 0; + uint8_t evalcodeAdd = 0; //CAmount askamount = 1000; //CAmount numtokens = 2; CAmount txfee = 10000; @@ -479,7 +482,7 @@ class TestAssetsCC : public ::testing::Test { //cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); //CAmount unit_price = askamount / numtokens; - CAmount numtokens = askamount / unit_price; + CAmount askamount = numtokens * unit_price; if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { std::cerr << __func__ << " cant add normal inputs" << std::endl; @@ -493,16 +496,16 @@ class TestAssetsCC : public ::testing::Test { } CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeNFT, numtokens, unspendableAssetsPubkey)); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens, unspendableAssetsPubkey)); mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk)); CAmount CCchange = inputs - numtokens; if (CCchange != 0LL) { // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), CCchange, pk)); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), CCchange, pk)); } // cond to spend NFT from mypk - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(evalcodeNFT, pk)); + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(evalcodeAdd, pk)); CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey // sign vins: @@ -515,17 +518,16 @@ class TestAssetsCC : public ::testing::Test { return mtx; } - static CMutableTransaction MakeTokenV2BidTx(struct CCcontract_info *cpAssets, CPubKey pk, uint256 tokenid, CAmount bidamount, CAmount unit_price) + static CMutableTransaction MakeTokenV2BidTx(struct CCcontract_info *cpAssets, CPubKey pk, uint256 tokenid, CAmount numtokens, CAmount unit_price) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); //struct CCcontract_info *cpAssets, C; - //CAmount bidamount = 1000; + CAmount bidamount = numtokens * unit_price; //CAmount numtokens = 2; CAmount txfee = 10000; //cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! - //CAmount unit_price = bidamount / numtokens; if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { @@ -546,7 +548,7 @@ class TestAssetsCC : public ::testing::Test { return mtx; } - static CMutableTransaction MakeTokenV2FillAskTx(struct CCcontract_info *cpAssets, CPubKey pk, uint256 tokenid, uint256 asktxid, CAmount fill_units, CAmount paid_unit_price) + static CMutableTransaction MakeTokenV2FillAskTx(struct CCcontract_info *cpAssets, CPubKey pk, uint256 tokenid, uint256 asktxid, CAmount fill_units, CAmount paid_unit_price, UniValue &data) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); struct CCcontract_info *cpTokens, tokensC; @@ -569,18 +571,18 @@ class TestAssetsCC : public ::testing::Test { CAmount orig_assetoshis = asktx.vout[askvout].nValue; TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - uint8_t evalcodeNFT = 0; - uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - if (!GetTokenData(&eval, tokenid, tokenData, vopretNonfungible)) { + vuint8_t vextraData; + uint8_t evalcodeAdd = 0; + int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { std::cerr << __func__ << " cant get tokendata" << std::endl; return CTransaction(); } - if (vopretNonfungible.size() > 0) { - evalcodeNFT = vopretNonfungible.begin()[0]; - GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); - if (royaltyFract > NFTROYALTY_DIVISOR-1) - royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit + if (vextraData.size() > 0) { + evalcodeAdd = vextraData.begin()[0]; + GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); + if (royaltyFract > TKLROYALTY_DIVISOR-1) + royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } vuint8_t ownerpubkey = std::get<0>(tokenData); @@ -591,7 +593,7 @@ class TestAssetsCC : public ::testing::Test { paid_unit_price = unit_price; CAmount paid_nValue = paid_unit_price * fill_units; - CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / NFTROYALTY_DIVISOR * royaltyFract : 0; + CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / TKLROYALTY_DIVISOR * royaltyFract : 0; if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { std::cerr << __func__ << " cant add normal inputs" << std::endl; @@ -600,10 +602,10 @@ class TestAssetsCC : public ::testing::Test { mtx.vin.push_back(CTxIn(asktx.GetHash(), askvout, CScript())); // spend order tx // vout.0 tokens remainder to unspendable cc addr: - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeNFT, orig_assetoshis - fill_units, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, orig_assetoshis - fill_units, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), fill_units, pk)); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), fill_units, pk)); mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr if (royaltyFract > 0) // note it makes the vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner @@ -614,7 +616,7 @@ class TestAssetsCC : public ::testing::Test { uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeNFT, unspendableAssetsPk)); + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeAdd, unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); if (!TestFinalizeTx(mtx, cpAssets, testKeys[pk], txfee, @@ -623,7 +625,10 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " cant finalise tx" << std::endl; return CTransaction(); } - + data.pushKV("ownerpubkey", HexStr(ownerpubkey)); + data.pushKV("origpubkey", HexStr(origpubkey)); + data.pushKV("unit_price", unit_price); + return mtx; } @@ -656,18 +661,18 @@ class TestAssetsCC : public ::testing::Test { } TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - uint8_t evalcodeNFT = 0; - uint64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - if (!GetTokenData(&eval, tokenid, tokenData, vopretNonfungible)) { + vuint8_t vextraData; + uint8_t evalcodeAdd = 0; + int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { std::cerr << __func__ << " cant get token data" << std::endl; return CTransaction(); } - if (vopretNonfungible.size() > 0) { - evalcodeNFT = vopretNonfungible.begin()[0]; - GetNftDataAsUint64(vopretNonfungible, NFTPROP_ROYALTY, royaltyFract); - if (royaltyFract > NFTROYALTY_DIVISOR-1) - royaltyFract = NFTROYALTY_DIVISOR-1; // royalty upper limit + if (vextraData.size() > 0) { + evalcodeAdd = vextraData.begin()[0]; + GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); + if (royaltyFract > TKLROYALTY_DIVISOR-1) + royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } vuint8_t ownerpubkey = std::get<0>(tokenData); @@ -703,7 +708,7 @@ class TestAssetsCC : public ::testing::Test { return CTransaction(); } - CAmount royaltyValue = royaltyFract > 0 ? paid_amount / NFTROYALTY_DIVISOR * royaltyFract : 0; + CAmount royaltyValue = royaltyFract > 0 ? paid_amount / TKLROYALTY_DIVISOR * royaltyFract : 0; CAmount tokensChange = tokenInputs - fill_units; uint8_t unspendableAssetsPrivkey[32]; @@ -719,19 +724,19 @@ class TestAssetsCC : public ::testing::Test { mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG)); // vout1 coins to mypk normal if (royaltyFract > 0) // note it makes vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator if (orig_units - fill_units > 0) // order is not finished yet mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey if (tokensChange != 0LL) - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeNFT ? evalcodeNFT : TokensV2::EvalCode(), tokensChange, pk)); // change in single-eval tokens + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), tokensChange, pk)); // change in single-eval tokens CMutableTransaction mtx2(mtx); // copy CCwrapper wrCond1(MakeCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); // spend coins CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); - CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(evalcodeNFT, pk)); // spend my tokens to fill buy + CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(evalcodeAdd, pk)); // spend my tokens to fill buy CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey if (!TestFinalizeTx(mtx, cpTokens, testKeys[pk], txfee, @@ -740,6 +745,7 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " could not finalize tx" << std::endl; return CTransaction(); } + data.pushKV("ownerpubkey", HexStr(ownerpubkey)); data.pushKV("origpubkey", HexStr(origpubkey)); data.pushKV("unit_price", unit_price); @@ -761,14 +767,14 @@ class TestAssetsCC : public ::testing::Test { CAmount askamount = asktx.vout[ASSETS_GLOBALADDR_VOUT].nValue; TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - if (!GetTokenData(&eval, tokenid, tokenData, vopretNonfungible)) { + vuint8_t vextraData; + if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { std::cerr << __func__ << " could not load token data" << std::endl; return CTransaction(); } - uint8_t evalcodeNFT = 0; - if (vopretNonfungible.size() > 0) - evalcodeNFT = vopretNonfungible[0]; + uint8_t evalcodeAdd = 0; + if (vextraData.size() > 0) + evalcodeAdd = vextraData[0]; vuint8_t ownerpubkey = std::get<0>(tokenData); if (TestAddNormalInputs(mtx, ownerpubkey, txfee) == 0LL) { @@ -791,13 +797,13 @@ class TestAssetsCC : public ::testing::Test { return CTransaction(); } - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(cpAssets->evalcodeNFT ? cpAssets->evalcodeNFT : TokensV2::EvalCode(), askamount, ownerpubkey)); // one-eval token vout + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(cpAssets->evalcodeAdd ? cpAssets->evalcodeAdd : TokensV2::EvalCode(), askamount, ownerpubkey)); // one-eval token vout // init assets 'unspendable' privkey and pubkey uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), cpAssets->evalcodeNFT, unspendableAssetsPk)); + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), cpAssets->evalcodeAdd, unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); if (!TestFinalizeTx(mtx, cpAssets, testKeys[ownerpubkey], txfee, @@ -827,16 +833,16 @@ class TestAssetsCC : public ::testing::Test { CAmount bidamount = bidtx.vout[ASSETS_GLOBALADDR_VOUT].nValue; TokenDataTuple tokenData; - vuint8_t vopretNonfungible; - if (!GetTokenData(&eval, tokenid, tokenData, vopretNonfungible)) { + vuint8_t vextraData; + if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { std::cerr << __func__ << " could not load token data" << std::endl; return CTransaction(); } - uint8_t evalcodeNFT = 0; - if (vopretNonfungible.size() > 0) - evalcodeNFT = vopretNonfungible[0]; + uint8_t evalcodeAdd = 0; + if (vextraData.size() > 0) + evalcodeAdd = vextraData[0]; vuint8_t ownerpubkey = std::get<0>(tokenData); if (TestAddNormalInputs(mtx, ownerpubkey, txfee) == 0LL) { @@ -894,12 +900,107 @@ TEST_F(TestAssetsCC, tokenv2ask) { struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + CAmount numtokens = 2LL; + CPubKey mypk = pk1; + uint256 mytokenid = tokenid1; + uint8_t evalcodeAdd = 0; + + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 1000, 1000/2); + CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, mypk, mytokenid, numtokens, 501); // price more than dust ASSERT_FALSE(CTransaction(mtx).IsNull()); + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, mtx); + // test: valid tokenv2ask EXPECT_TRUE(TestRunCCEval(mtx)); + + { + // test: invalid unit_price == 0 + CMutableTransaction mtx1(mtx); + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', zeroid, 0, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + EXPECT_FALSE(TestRunCCEval(mtx1)); + } + { + // test: invalid token dest pubkey (not global) + CMutableTransaction mtx1(mtx); + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { pkunused }, // bad pk instead of global + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + EXPECT_TRUE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 + } + { + // test: bad origpk in opreturn (not the tx signer) + CMutableTransaction mtx1(mtx); + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pkunused.begin(), pkunused.end())) }))); // not matched origpk (should be pk1) + EXPECT_FALSE(TestRunCCEval(mtx1)); + } + { + // test: only one opreturn supported + CMutableTransaction mtx1(mtx); + // mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + EXPECT_FALSE(TestRunCCEval(mtx1)); + } + { + // test: send to non-global assets destination + CMutableTransaction mtx1(mtx); + mtx1.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens, pkunused); + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 + } + { + // test: add extra global addr vout + CMutableTransaction mtx1(mtx); + // add two vouts with numtokens/2 (to have token balance correct). Assets cc should fail however: + mtx1.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens/2, unspendableAssetsPubkey); + mtx1.vout.insert(mtx1.vout.begin(), TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens/2, unspendableAssetsPubkey)); + mtx1.vout.pop_back(); // remove old opreturn + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 + } + { + // test: add extra global addr null vout + CMutableTransaction mtx1(mtx); + // add two vouts with numtokens/2 (to have token balance correct). Assets cc should fail however: + mtx1.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens, unspendableAssetsPubkey); + mtx1.vout.insert(mtx1.vout.begin(), TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, 0, unspendableAssetsPubkey)); + mtx1.vout.pop_back(); // remove old opreturn + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 + } + { + // test: add extra marker + CMutableTransaction mtx1(mtx); + ASSERT_TRUE(mtx.vout.size() > 2); + mtx1.vout.insert(mtx1.vout.begin()+1, mtx1.vout[1]); // copy marker + mtx1.vout.pop_back(); // remove old opreturn + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 + } } TEST_F(TestAssetsCC, tokenv2bid) @@ -909,35 +1010,117 @@ TEST_F(TestAssetsCC, tokenv2bid) cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - CMutableTransaction mtx = MakeTokenV2BidTx(cpAssets, pk2, tokenid1, 1000, 1000/2); + CMutableTransaction mtx = MakeTokenV2BidTx(cpAssets, pk2, tokenid1, 2, 501); // price more than dust ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2bid EXPECT_TRUE(TestRunCCEval(mtx)); - CMutableTransaction mtx1(mtx); + { + CMutableTransaction mtx1(mtx); - // test: too low bid amount < unit_price - mtx1.vout[0] = TokensV2::MakeCC1vout(AssetsV2::EvalCode(), 9999, unspendableAssetsPubkey); - mtx1.vout.pop_back(); + // test: too low bid amount < unit_price + mtx1.vout[0] = TokensV2::MakeCC1vout(AssetsV2::EvalCode(), 9999, unspendableAssetsPubkey); + mtx1.vout.pop_back(); - ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], txfee, - TokensV2::EncodeTokenOpRet(tokenid1, {}, - { AssetsV2::EncodeAssetOpRet('b', zeroid, 10000, vuint8_t(pk2.begin(), pk2.end())) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail + ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(tokenid1, {}, + { AssetsV2::EncodeAssetOpRet('b', zeroid, 10000, vuint8_t(pk2.begin(), pk2.end())) }))); + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail + } } TEST_F(TestAssetsCC, tokenv2fillask) { - + UniValue data(UniValue::VOBJ); struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); - CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, txask1.GetHash(), 2, 0); + CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, txask1.GetHash(), 2, 0, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2fillask EXPECT_TRUE(TestRunCCEval(mtx)); + + //vuint8_t ownerpubkey = ParseHex(data["ownerpubkey"].getValStr()); + + // test: spend invalid tokenid + { + CMutableTransaction mtx1(mtx); + mtx1.vin.back() = CTxIn(txask1.GetHash(), ASSETS_GLOBALADDR_VOUT, CScript()); // spend order tx + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txask1); + ASSERT_TRUE(funcid != 0); + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], 10000, + TokensV2::EncodeTokenOpRet(tokenidUnused, { pk2 }, + { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))); + + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail + } + { + // test: use opposite funcid + CMutableTransaction mtx1(mtx); + + CAmount txfee = 10000; + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txbid1); + + mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx + ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(origpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); // 'S' -> 'B' + + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid + } + // test: spend yet another order + { + CMutableTransaction mtx2(mtx); + mtx2.vin.push_back( CTxIn(txask2.GetHash(), ASSETS_GLOBALADDR_VOUT, CScript()) ); // spend yet another order tx + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txask2); + ASSERT_TRUE(funcid != 0); + mtx2.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx2, cpAssets, testKeys[pk2], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, + { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))); + + EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail + } + { + // test: change unit_price in opret + CMutableTransaction mtx2(mtx); + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txask1); // get orig pk, orig value + ASSERT_TRUE(funcid != 0); + mtx2.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx2, cpAssets, testKeys[pk2], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, + { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price+1, origpubkey) } ))); + + EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail + } + { + // test: changed origpk in assets opreturn + CMutableTransaction mtx1(mtx); + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txask1); // get orig pk, orig value + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], 10000, + TokensV2::EncodeTokenOpRet(tokenid1, { pk2 }, + { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, vuint8_t(pkunused.begin(), pkunused.end())) }))); // not matched origpk (should be pk1) + EXPECT_FALSE(TestRunCCEval(mtx1)); + } } @@ -952,20 +1135,53 @@ TEST_F(TestAssetsCC, tokenv2fillbid) // test: valid tokenv2fillbid EXPECT_TRUE(TestRunCCEval(mtx)); - CMutableTransaction mtx1(mtx); + { + // test: fill with another tokenid + CMutableTransaction mtx1(mtx); - CAmount txfee = 10000; - vuint8_t origpubkey = ParseHex(data["origpubkey"].getValStr()); - CAmount unit_price = data["unit_price"].get_int64(); + CAmount txfee = 10000; + vuint8_t ownerpubkey = ParseHex(data["ownerpubkey"].getValStr()); + vuint8_t origpubkey = ParseHex(data["origpubkey"].getValStr()); + CAmount unit_price = data["unit_price"].get_int64(); - // test: fill with another tokenid - mtx1.vin[1] = CTxIn(txtokencreate3.GetHash(), 1, CScript()); // spend other tokenid3 - mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx - ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, - TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); + mtx1.vin[1] = CTxIn(txtokencreate3.GetHash(), 1, CScript()); // spend other tokenid3 + mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(origpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: can't fill with another tokenid3 + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: can't fill with another tokenid3 + } + { + // test: use opposite funcid + CMutableTransaction mtx1(mtx); + + CAmount txfee = 10000; + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txbid1); // get orig pk, orig value + + mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(origpubkey) }, + { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) }))); // 'B' -> 'S' + + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid + } + { + // test: changed origpk in opreturn + CMutableTransaction mtx1(mtx); + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txbid1); // get orig pk, orig value + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, + { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, vuint8_t(pkunused.begin(), pkunused.end())) }))); // not matched origpk (should be pk1) + EXPECT_FALSE(TestRunCCEval(mtx1)); + } } TEST_F(TestAssetsCC, tokenv2cancelask) @@ -993,39 +1209,44 @@ TEST_F(TestAssetsCC, tokenv2cancelask) // test: valid tokenv2cancelask EXPECT_TRUE(TestRunCCEval(mtx)); - - // test: invalid pk in assets opreturn - CMutableTransaction mtx2(mtx); - mtx2.vout.pop_back(); - mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(pk2.begin(), pk2.end())) } ))); - EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret not checked - - // test: another pk in token opret - CMutableTransaction mtx3(mtx); - mtx3.vout.pop_back(); - mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { pkunused }, - { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked - - // test: invalid pk where to funds sent - CMutableTransaction mtx4(mtx); - mtx4.vout[0] = TokensV2::MakeTokensCC1vout(cpAssets->evalcodeNFT ? cpAssets->evalcodeNFT : TokensV2::EvalCode(), askamount, pk2); - EXPECT_FALSE(TestRunCCEval(mtx4)); // must fail - - // test: invalid tokenid in token opret - CMutableTransaction mtx5(mtx); - mtx5.vout.pop_back(); - mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - EXPECT_FALSE(TestRunCCEval(mtx5)); // must fail: cant send to another tokenid - - // test: invalid funcid in token opret - CMutableTransaction mtx6(mtx); - mtx6.vout.pop_back(); - mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - EXPECT_FALSE(TestRunCCEval(mtx6)); // must fail + { + // test: invalid pk in assets opreturn + CMutableTransaction mtx2(mtx); + mtx2.vout.pop_back(); + mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(pk2.begin(), pk2.end())) } ))); + EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret not checked + } + { + // test: another pk in token opret + CMutableTransaction mtx3(mtx); + mtx3.vout.pop_back(); + mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { pkunused }, + { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked + } + { + // test: invalid pk where to funds sent + CMutableTransaction mtx4(mtx); + mtx4.vout[0] = TokensV2::MakeTokensCC1vout(cpAssets->evalcodeAdd ? cpAssets->evalcodeAdd : TokensV2::EvalCode(), askamount, pk2); + EXPECT_FALSE(TestRunCCEval(mtx4)); // must fail + } + { + // test: invalid tokenid in token opret + CMutableTransaction mtx5(mtx); + mtx5.vout.pop_back(); + mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + EXPECT_FALSE(TestRunCCEval(mtx5)); // must fail: cant send to another tokenid + } + { + // test: invalid funcid in token opret + CMutableTransaction mtx6(mtx); + mtx6.vout.pop_back(); + mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + EXPECT_FALSE(TestRunCCEval(mtx6)); // must fail + } } } @@ -1053,44 +1274,50 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) // test: valid tokenv2cancelbid EXPECT_TRUE(TestRunCCEval(mtx)); - - // test: invalid pk in assets opreturn - CMutableTransaction mtx2(mtx); - mtx2.vout.pop_back(); - mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(pk1.begin(), pk1.end())) } ))); - EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret is not checked - - // test: invalid pk in token opret - CMutableTransaction mtx3(mtx); - mtx3.vout.pop_back(); - mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pkunused }, - { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked - - // test: invalid pk where to funds sent - CMutableTransaction mtx4(mtx); - mtx4.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(pkunused)) << OP_CHECKSIG); - EXPECT_FALSE(TestRunCCEval(mtx4)); // must fail as can't send the remainder to another pk - - // test: invalid tokenid in token opret - CMutableTransaction mtx5(mtx); - mtx5.vout.pop_back(); - mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - EXPECT_FALSE(TestRunCCEval(mtx5)); - - // test: invalid funcid in token opret - CMutableTransaction mtx6(mtx); - mtx6.vout.pop_back(); - mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pk2 }, - { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - EXPECT_FALSE(TestRunCCEval(mtx6)); - - // test: send dust to normals - //CMutableTransaction mtx7(mtx); - //mtx7.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG); - //EXPECT_FALSE(TestRunCCEval(mtx7)); // must fail: dust should stay on cc global output + { + // test: invalid pk in assets opreturn + CMutableTransaction mtx2(mtx); + mtx2.vout.pop_back(); + mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(pk1.begin(), pk1.end())) } ))); + EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret is not checked + } + { + // test: invalid pk in token opret + CMutableTransaction mtx3(mtx); + mtx3.vout.pop_back(); + mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pkunused }, + { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked + } + { + // test: invalid pk where to funds sent + CMutableTransaction mtx4(mtx); + mtx4.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(pkunused)) << OP_CHECKSIG); + EXPECT_FALSE(TestRunCCEval(mtx4)); // must fail as can't send the remainder to another pk + } + { + // test: invalid tokenid in token opret + CMutableTransaction mtx5(mtx); + mtx5.vout.pop_back(); + mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { ownerpubkey }, + { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + EXPECT_FALSE(TestRunCCEval(mtx5)); + } + { + // test: invalid funcid in token opret + CMutableTransaction mtx6(mtx); + mtx6.vout.pop_back(); + mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pk2 }, + { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + EXPECT_FALSE(TestRunCCEval(mtx6)); + } + { + // test: send dust to normals - bad test params here + //CMutableTransaction mtx7(mtx); + //mtx7.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG); + //EXPECT_FALSE(TestRunCCEval(mtx7)); // must fail: dust should stay on cc global output + } } } @@ -1110,53 +1337,56 @@ TEST_F(TestAssetsCC, tokenv2create) CAmount txfee = 0; std::string name = "T2"; std::string description = "desc2"; + { + // test: token sent to another pk + CMutableTransaction mtx1(mtx); + mtx1.vout[1] = TokensV2::MakeTokensCC1vout(0, 10, pk2); + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + EXPECT_TRUE(TestRunCCEval(mtx1)); // allow sending created tokens to any pk!! + } + { + // test: invalid pk in opreturn: + CMutableTransaction mtx2(mtx); + mtx2.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { }))); + EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail + } + { + // test: no token vouts, sent to normal + CMutableTransaction mtx3(mtx); + mtx3.vout[1] = CTxOut(10, CScript() << ParseHex(HexStr(pk1)) << OP_CHECKSIG); + mtx3.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx3, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + EXPECT_FALSE(TestRunCCEval(mtx3)); // fail for no token cc vouts + } + { + // test: no token vouts, sent to cc v1 + CMutableTransaction mtx4(mtx); + mtx4.vout[1] = TokensV1::MakeCC1vout(EVAL_ASSETS, 10, pk2); // sent to cc v1 vout + mtx4.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx4, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + EXPECT_FALSE(TestRunCCEval(mtx4)); // fail for no token cc vouts + } + { + // test: invalid token created with global pk: + CMutableTransaction mtx5 = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + uint8_t privkeyg[32]; + CPubKey pkg = GetUnspendable(cpTokens, privkeyg); - // test: token sent to another pk - CMutableTransaction mtx1(mtx); - mtx1.vout[1] = TokensV2::MakeTokensCC1vout(0, 10, pk2); - mtx1.vout.pop_back(); - ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk1], txfee, - TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); - EXPECT_TRUE(TestRunCCEval(mtx1)); // allow sending created tokens to any pk!! - - // test: invalid pk in opreturn: - CMutableTransaction mtx2(mtx); - mtx2.vout.pop_back(); - ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk1], txfee, - TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { }))); - EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail - - - // test: no token vouts, sent to normal - CMutableTransaction mtx3(mtx); - mtx3.vout[1] = CTxOut(10, CScript() << ParseHex(HexStr(pk1)) << OP_CHECKSIG); - mtx3.vout.pop_back(); - ASSERT_TRUE(TestFinalizeTx(mtx3, cpTokens, testKeys[pk1], txfee, - TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); - EXPECT_FALSE(TestRunCCEval(mtx3)); // fail for no token cc vouts - - // test: no token vouts, sent to cc v1 - CMutableTransaction mtx4(mtx); - mtx4.vout[1] = TokensV1::MakeCC1vout(EVAL_ASSETS, 10, pk2); // sent to cc v1 vout - mtx4.vout.pop_back(); - ASSERT_TRUE(TestFinalizeTx(mtx4, cpTokens, testKeys[pk1], txfee, - TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); - EXPECT_FALSE(TestRunCCEval(mtx4)); // fail for no token cc vouts - - // test: invalid token created with global pk: - CMutableTransaction mtx5 = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - uint8_t privkeyg[32]; - CPubKey pkg = GetUnspendable(cpTokens, privkeyg); - - mtx5.vin.push_back(CTxIn(txnormalg.GetHash(), 0)); - mtx5.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cpTokens, NULL))); - mtx5.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); - - ASSERT_TRUE(TestFinalizeTx(mtx5, cpTokens, privkeyg, txfee, - TokensV2::EncodeTokenCreateOpRet(vscript_t(pkg.begin(), pkg.end()), name, description, { }))); - EXPECT_FALSE(TestRunCCEval(mtx5)); // must fail + mtx5.vin.push_back(CTxIn(txnormalg.GetHash(), 0)); + mtx5.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cpTokens, NULL))); + mtx5.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); + ASSERT_TRUE(TestFinalizeTx(mtx5, cpTokens, privkeyg, txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pkg.begin(), pkg.end()), name, description, { }))); + EXPECT_FALSE(TestRunCCEval(mtx5)); // must fail + } } } /* namespace CCAssetsTests */ From 0c3dbb7bdb902497efcf939896b045aa3ed47a1f Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 1 Jul 2021 21:37:01 +0500 Subject: [PATCH 027/348] tui assets test updated for tokencreatetokel rpcs --- src/tui/tui_assets_orders.py | 37 +++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index c13efa12b9b..8d00be4173a 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -28,11 +28,12 @@ def check_tx(r): if isinstance(str_hex, str) : # print("r has hex, true") if str_hex.find('coins') >= 0 or str_hex.find('tokens') >= 0 or str_hex.find('assets') >= 0 : # try to detect old code returning no coins err as success + print("bad tx result:", r) return False else : return True if r.get('result') == "error" : - # print("r has error, false") + print("bad tx result:", r) return False # print("r has unknown, true") return True @@ -67,26 +68,30 @@ def run_tokens_create(rpc): print("created token:", tokenid2) print("creating NFT 1 with 00...") - result = call_rpc(rpc1, "token"+v+"create", "NFT-00-1", str(0.00000001), "nft eval 00", "00010203") + # result = call_rpc(rpc1, "token"+v+"create", "NFT-00-1", str(0.00000001), "nft eval 00", "00010203") + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-00-1", str(0.00000001), "nft eval 00", '{}') assert(check_tx(result)) nft00id1 = rpc1.sendrawtransaction(result['hex']) print("created token:", nft00id1) print("creating NFT 2 with 00...") - result = call_rpc(rpc1, "token"+v+"create", "NFT-00-2", str(0.00000001), "nft eval 00", "00010203") + # result = call_rpc(rpc1, "token"+v+"create", "NFT-00-2", str(0.00000001), "nft eval 00", "00010203") + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-00-2", str(0.00000001), "nft eval 00", '{"arbitrary":"010203"}') assert(check_tx(result)) nft00id2 = rpc1.sendrawtransaction(result['hex']) print("created token:", nft00id2) # tokel nft data F7 evalcode print("creating NFT with F7, no royalty, with arbitary data...") - result = call_rpc(rpc1, "token"+v+"create", "NFT-F7-1", str(0.00000001), "nft eval=f7 arbitrary=hello", "F70101ee020d687474703a2f2f6d792e6f7267040568656c6c6f") + # result = call_rpc(rpc1, "token"+v+"create", "NFT-F7-1", str(0.00000001), "nft eval=f7 arbitrary=hello", "F70101ee020d687474703a2f2f6d792e6f7267040568656c6c6f") + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-1", str(0.00000001), "nft eval=00 royalty=0", '{"royalty":0}') assert(check_tx(result)) nftf7id1 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id1) print("creating NFT with F7 and royalty 0xAA...") - result = call_rpc(rpc1, "token"+v+"create", "NFT-F7-2", str(0.00000001), "nft eval=f7 roaylty=AA", "F70101ee020d687474703a2f2f6d792e6f726703AA") + # result = call_rpc(rpc1, "token"+v+"create", "NFT-F7-2", str(0.00000001), "nft eval=f7 roaylty=AA", "F70101ee020d687474703a2f2f6d792e6f726703AA") + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-2", str(0.00000001), "nft eval=f7 roaylty=99", '{"royalty":99}') assert(check_tx(result)) nftf7id2 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id2) @@ -117,6 +122,7 @@ def run_tokens_create(rpc): print("starting MofN tests for nftf7id1...") run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) + print("token/assets tests finished okay") time.sleep(3) exit @@ -522,14 +528,27 @@ def run_assets_orders(rpc1, rpc2, v, tokenid, total, units, isnft): print("creating token"+v+"cancelbid tx #3...") cancelid = call_token_rpc_send_tx(rpc1, "token"+v+"cancelbid", 'bid is empty', tokenid, fillbidid3) - # create tokenbid to test dust + # create tokenbid to self to test dust print("creating token"+v+"bid tx #4...") - bidid4 = call_token_rpc_send_tx(rpc1, "token"+v+"bid", '', str(1), tokenid, str(0.0000_01)) - + bidid4 = call_token_rpc_send_tx(rpc1, "token"+v+"bid", '', str(1), tokenid, str(0.0000_0600)) # price more than dust + # fill bid to self with dust print("creating token"+v+"fillbid tx #4 (to create dust)...") - fillbidid4 = call_token_rpc_send_tx(rpc1, "token"+v+"fillbid", '', tokenid, bidid4, str(1), str(0.0000_005)) + # enable his if dust is enabled on normals in the chain: + # fillbidid4 = call_token_rpc_send_tx(rpc1, "token"+v+"fillbid", '', tokenid, bidid4, str(1), str(0.0000_005)) # fill with dust price (<=500sat) + # if dust not enabled we should get error: + fillbidid4 = call_token_rpc(rpc1, "token"+v+"fillbid", '', tokenid, bidid4, str(1), str(0.0000_005)) # fill with dust price (<=500sat) + assert fillbidid4['hex'], "token"+v+"fillbid" + ' tx not created' + try : + print("trying to sendrawtransaction tokenfillbid tx with dust... ") + result = rpc1.sendrawtransaction(fillbidid4['hex']) + print("sendrawtransaction tokenfillbid tx with dust returned:", result) + assert not result, 'sending tokenfillbid tx with dust should return error' + except RpcException as e : + print ('got a normal exception for tokenfillbid tx with dust', e.message) + pass # should be error + # balance does not change as this is a tx to self # check balance after retries = 24 From 2aa3b3f5745428c266a863eb8e75a7c9cdd28311 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 1 Jul 2021 22:29:35 +0500 Subject: [PATCH 028/348] fixed wrong tokendata var some tokens consts added fixed compactsize for int64 in tokel data --- src/cc/CCTokelData.cpp | 10 ++++++---- src/cc/CCtokens.h | 2 ++ src/cc/CCtokens_impl.h | 4 ++-- src/rpc/tokensrpc.cpp | 11 +++++------ 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index 922b699adfe..9e9592114f8 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -28,9 +28,10 @@ static UniValue tklReadString(CDataStream &ss) static UniValue tklReadInt64(CDataStream &ss) { - int64_t i64val; - ::Unserialize(ss, i64val); - UniValue ret(i64val); + uint64_t ui64val; + //::Unserialize(ss, i64val); + ss >> COMPACTSIZE(ui64val); + UniValue ret((int64_t)ui64val); return ret; } @@ -52,7 +53,8 @@ static void tklWriteInt64(CDataStream &ss, const UniValue &val) { int64_t i64val = 0; ParseInt64(val.getValStr(), &i64val); - ::Serialize(ss, i64val); + //::Serialize(ss, i64val); + ss << COMPACTSIZE((uint64_t)i64val); } static void tklWriteVuint8(CDataStream &ss, const UniValue &val) diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index ee2cbd7c53b..ca34b8a3215 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -25,6 +25,8 @@ const CAmount TOKENS_MARKER_VALUE = 10000; const uint8_t TOKENS_OPRETURN_VERSION = 1; +const int TOKENS_MAX_NAME_LENGTH = 32; +const int TOKENS_MAX_DESC_LENGTH = 4096; // implementation of basic token functions diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index ec32fa6d3ff..37ef50b9146 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -491,10 +491,10 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup }*/ cp = CCinit(&C, V::EvalCode()); - if (name.size() > 32 || description.size() > 4096) // this is also checked on rpc level + if (name.size() > TOKENS_MAX_NAME_LENGTH || description.size() > TOKENS_MAX_DESC_LENGTH) // this is also checked on rpc level { LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "name len=" << name.size() << " or description len=" << description.size() << " is too big" << std::endl); - CCerror = "name should be <= 32, description should be <= " + std::to_string(4096); + CCerror = "name or description too long"; return NullUniValue; } if (txfee == 0) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index f95b7ed4e35..93dd26f9ec9 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -258,7 +258,6 @@ static UniValue tokencreate(const std::string& fname, const UniValue& params, co { UniValue result(UniValue::VOBJ); std::string name, description, hextx; - std::vector tokenData; CAmount supply; // changed from uin64_t to int64_t for this 'if ( supply <= 0 )' to work as expected CCerror.clear(); @@ -273,8 +272,8 @@ static UniValue tokencreate(const std::string& fname, const UniValue& params, co LOCK2(cs_main, pwalletMain->cs_wallet); // remote call not supported yet name = params[0].get_str(); - if (name.size() == 0 || name.size() > 32) - return MakeResultError("Token name must not be empty and up to 32 characters"); + if (name.size() == 0 || name.size() > TOKENS_MAX_NAME_LENGTH) + return MakeResultError("Token name must not be empty and up to " + std::to_string(TOKENS_MAX_DESC_LENGTH)); supply = AmountFromValue(params[1]); if (supply <= 0) @@ -283,11 +282,11 @@ static UniValue tokencreate(const std::string& fname, const UniValue& params, co if (params.size() >= 3) { description = params[2].get_str(); - if (description.size() > 4096) - return MakeResultError("Token description must be <= " + std::to_string(4096)); // allowed > MAX_SCRIPT_ELEMENT_SIZE + if (description.size() > TOKENS_MAX_DESC_LENGTH) + return MakeResultError("Token description must be <= " + std::to_string(TOKENS_MAX_DESC_LENGTH)); // allowed > MAX_SCRIPT_ELEMENT_SIZE } - hextx = CreateTokenLocal(0, supply, name, description, tokenData); + hextx = CreateTokenLocal(0, supply, name, description, vtokenData); RETURN_IF_ERROR(CCerror); if( hextx.size() > 0 ) From 4382f7120fcd204061c31928c2130323324b7c68 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 2 Jul 2021 00:58:46 +0500 Subject: [PATCH 029/348] fix dust calc for royalty in assets cc; fix evalcode F7 in tokel json parsing --- src/cc/CCTokelData.cpp | 14 +++----------- src/cc/CCassetstx_impl.h | 15 ++++++++++++--- src/cc/assets.cpp | 25 ++++++++++++++++++------- src/rpc/tokensrpc.cpp | 5 ++--- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index 9e9592114f8..2f5ed77d032 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -102,13 +102,7 @@ static tklPropDesc_t GetTokelDataDesc(tklPropId id) vuint8_t ParseTokelJson(const UniValue &jsonParams) { - uint8_t evalcode = 0; - /*size_t ikey; - if (jsonParams["evalcode"].isStr()) { - evalcode = strtol(jsonParams["evalcode"].getValStr().c_str(), NULL, 16); - if (evalcode < 0 || evalcode > 0xFF) - throw std::runtime_error("invalid evalcode in token data"); - }*/ + uint8_t evalcode = EVAL_TOKELDATA; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << evalcode << (uint8_t)TKLDATA_VERSION; for(int i = 0; i < jsonParams.getKeys().size(); i ++) @@ -149,7 +143,6 @@ static bool ParseTokelData(const vuint8_t &vdata, std::map CDataStream ss(vdata, SER_NETWORK, PROTOCOL_VERSION); ::Unserialize(ss, evalCode); ::Unserialize(ss, version); - bool ssErrof = false; while(!ss.eof()) { uint8_t id; ::Unserialize(ss, id); @@ -162,12 +155,11 @@ static bool ParseTokelData(const vuint8_t &vdata, std::map sError = "duplicate tokel data property type"; return false; } - //if (itDesc->second.second) // if mandatory - // mandatoryCount ++; UniValue val = (*std::get<2>(entry))(ss); // read ss propMap.insert(std::make_pair((tklPropId)id, val)); - } + propMapOut = propMap; + return true; } catch(...) { sError = "could not parse tokel token data"; return false; diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index f3ebf782b55..3693d17d6ca 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -622,6 +622,9 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 return (""); } CAmount royaltyValue = royaltyFract > 0 ? paid_amount / TKLROYALTY_DIVISOR * royaltyFract : 0; + // check for dust: + if (royaltyValue <= ASSETS_NORMAL_DUST) + royaltyValue = 0; CAmount tokensChange = inputs - fill_units; uint8_t unspendableAssetsPrivkey[32]; @@ -636,8 +639,10 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 else mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to mypk normal - if (royaltyFract > 0) // note it makes vout even if roaltyValue is 0 + if (royaltyValue > 0) { // note it makes vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner + std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_amount - royaltyValue=" << paid_amount - royaltyValue << std::endl; + } mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator if (orig_units - fill_units > 0) // order is not finished yet mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey @@ -739,7 +744,9 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a paid_nValue = paid_unit_price * fillunits; CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / TKLROYALTY_DIVISOR * royaltyFract : 0; - + // check for dust: + if (royaltyValue <= ASSETS_NORMAL_DUST) + royaltyValue = 0; if (assetid2 != zeroid) { // inputs = AddAssetInputs(cpAssets, mtx, mypk, assetid2, paid_nValue, 60); // not implemented yet CCerror = "swaps not implemented"; @@ -774,8 +781,10 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), fillunits, mypk)); mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr - if (royaltyFract > 0) // note it makes the vout even if roaltyValue is 0 + if (royaltyValue > 0) { // note it makes the vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner + std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_nValue - royaltyValue=" << paid_nValue - royaltyValue << std::endl; + } if (orig_assetoshis - fillunits > 0) // we dont need the marker if order is filled mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index d6505dfec0b..4ac07758f3a 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -326,9 +326,15 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("invalid unit price"); else { - int32_t r = royaltyFract > 0 ? 1 : 0; + if (royaltyFract < 0LL || royaltyFract >= TKLROYALTY_DIVISOR) + return eval->Invalid("invalid royalty value"); - CAmount assetoshis = tx.vout[0].nValue + tx.vout[1].nValue + (r ? tx.vout[2].nValue : 0); + CAmount royaltyValue = royaltyFract > 0 ? tx.vout[1].nValue / (TKLROYALTY_DIVISOR - royaltyFract) * royaltyFract : 0LL; + if (royaltyValue <= ASSETS_NORMAL_DUST) + royaltyValue = 0LL; // reset if dust + int32_t r = royaltyValue > 0LL ? 1 : 0; + + CAmount assetoshis = tx.vout[0].nValue + tx.vout[1].nValue + (r ? tx.vout[2].nValue : 0LL); if( vin_assetoshis != assetoshis ) // coins -> global cc address (remainder) + normal self address return eval->Invalid("input cc value does not equal to vout0+1" + std::string(r ? "+2" : "") + " for fillbid"); @@ -378,11 +384,11 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const ccvouts ++; } - CAmount received_value = royaltyFract > 0 ? tx.vout[1].nValue + tx.vout[2].nValue : tx.vout[1].nValue; // vout1 paid value to seller, vout2 royalty to owner + CAmount received_value = r ? tx.vout[1].nValue + tx.vout[2].nValue : tx.vout[1].nValue; // vout1 paid value to seller, vout2 royalty to owner CAmount paid_units = tx.vout[2+r].nValue; if (!ValidateBidRemainder(unit_price, tx.vout[0].nValue, vin_assetoshis, received_value, paid_units)) // check real price and coins spending from global addr return eval->Invalid("vout" + std::to_string(2+r) + " mismatched remainder for fillbid"); - if (royaltyFract > 0) { + if (r) { if ((tx.vout[1].nValue + tx.vout[2].nValue) / TKLROYALTY_DIVISOR * royaltyFract != tx.vout[2].nValue) // validate royalty value return eval->Invalid("vout2 invalid royalty amount for fillask"); if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest @@ -478,15 +484,20 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const { if (vin_tokens != tx.vout[0].nValue + tx.vout[1].nValue) return eval->Invalid("locked value doesnt match vout0+1 fillask"); + if (royaltyFract < 0LL || royaltyFract >= TKLROYALTY_DIVISOR) + return eval->Invalid("invalid royalty value"); - CAmount paid_value = royaltyFract > 0 ? tx.vout[2].nValue+tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner + CAmount royaltyValue = royaltyFract > 0 ? tx.vout[2].nValue / (TKLROYALTY_DIVISOR - royaltyFract) * royaltyFract : 0LL; + if (royaltyValue <= ASSETS_NORMAL_DUST) + royaltyValue = 0LL; // reset if dust + CAmount paid_value = royaltyValue > 0 ? tx.vout[2].nValue + tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner if (!ValidateAskRemainder(unit_price, tx.vout[0].nValue, vin_tokens, tx.vout[1].nValue, paid_value)) return eval->Invalid("mismatched vout0 remainder for fillask"); else if (!A::ConstrainVout(tx.vout[1], CCVOUT, NULL, 0LL, T::EvalCode())) // do not check tokens buyer's 'self' cc addr return eval->Invalid("vout1 should be cc for fillask"); else if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, origNormalAddr, 0LL, 0)) // coins to originator normal addr return eval->Invalid("vout2 should be cc for fillask"); - if (royaltyFract > 0) { + if (royaltyValue > 0) { if ((tx.vout[2].nValue + tx.vout[3].nValue) / TKLROYALTY_DIVISOR * royaltyFract != tx.vout[3].nValue) // validate royalty value return eval->Invalid("vout3 invalid royalty amount for fillask"); if (!A::ConstrainVout(tx.vout[3], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest @@ -495,7 +506,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (!A::ConstrainVout(tx.vout[0], CCVOUT, tokensDualEvalUnspendableCCaddr, 0LL, A::EvalCode())) // tokens remainder on global addr return eval->Invalid("invalid vout0 should pay to tokens/assets global address for fillask"); if (tx.vout[0].nValue > 0) { - int32_t markerVout = royaltyFract > 0 ? 4 : 3; + int32_t markerVout = royaltyValue > 0 ? 4 : 3; // marker should exist if remainder not empty if( tx.vout.size() <= markerVout || A::ConstrainVout(tx.vout[markerVout], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr return eval->Invalid("invalid marker vout for original pubkey"); diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 93dd26f9ec9..3e5030018ae 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -356,7 +356,7 @@ UniValue tokencreatetokel(const UniValue& params, bool fHelp, const CPubKey& rem jsonParams = params[3].get_array(); else if (params[3].getType() == UniValue::VSTR) // json in quoted string '{...}' jsonParams.read(params[3].get_str().c_str()); - if (jsonParams.getType() != UniValue::VOBJ /*|| jsonParams.empty()*/) + if (jsonParams.getType() != UniValue::VOBJ) throw runtime_error("parameter 4 must be a json object\n"); tokenData = ParseTokelJson(jsonParams); @@ -386,8 +386,7 @@ UniValue tokenv2createtokel(const UniValue& params, bool fHelp, const CPubKey& r jsonParams = params[3].get_array(); else if (params[3].getType() == UniValue::VSTR) // json in quoted string '{...}' jsonParams.read(params[3].get_str().c_str()); - std::cerr << __func__ << " type=" << (int)jsonParams.getType() << " keys size=" << jsonParams.getKeys().size() << std::endl; - if (jsonParams.getType() != UniValue::VOBJ /*|| jsonParams.empty()*/) + if (jsonParams.getType() != UniValue::VOBJ) throw runtime_error("parameter 4 must be a json object\n"); tokenData = ParseTokelJson(jsonParams); From 6c7add8adb5ca60c8f05c6654c12756bbe29b324 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 2 Jul 2021 01:02:59 +0500 Subject: [PATCH 030/348] tests added for royalty in tui_assets_orders --- src/tui/tui_assets_orders.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 8d00be4173a..cf28fc5aaa1 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -54,7 +54,7 @@ def run_tokens_create(rpc): for v in ["", "v2"] : - # for v in ["v2"] : + #for v in ["v2"] : print("creating fungible token 1...") result = call_rpc(rpc1, "token"+v+"create", "T1", str(0.000001)) # 100 assert(check_tx(result)) @@ -89,13 +89,19 @@ def run_tokens_create(rpc): nftf7id1 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id1) - print("creating NFT with F7 and royalty 0xAA...") + print("creating NFT with F7 and royalty...") # result = call_rpc(rpc1, "token"+v+"create", "NFT-F7-2", str(0.00000001), "nft eval=f7 roaylty=AA", "F70101ee020d687474703a2f2f6d792e6f726703AA") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-2", str(0.00000001), "nft eval=f7 roaylty=99", '{"royalty":99}') assert(check_tx(result)) nftf7id2 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id2) + print("creating NFT with F7 and dust royalty...") + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-3", str(0.00000001), "nft eval=f7 roaylty=1", '{"royalty":1}') + assert(check_tx(result)) + nftf7id3 = rpc1.sendrawtransaction(result['hex']) + print("created token:", nftf7id3) + # first try transfer tokens to a pk and back, then run assets tests print("starting transfer tests for tokenid version=" + v + "...") run_transfers(rpc1, rpc2, v, tokenid1, tokenid2, 10) @@ -112,6 +118,10 @@ def run_tokens_create(rpc): run_assets_orders(rpc1, rpc2, v, nft00id1, 1, 1, True) print("starting assets tests for nftf7id1 version=" + v + "...") run_assets_orders(rpc1, rpc2, v, nftf7id1, 1, 1, True) + print("starting assets tests for nftf7id2 version=" + v + "...") + run_assets_orders(rpc1, rpc2, v, nftf7id2, 1, 1, True) + print("starting assets tests for nftf7id3 version=" + v + "...") + run_assets_orders(rpc1, rpc2, v, nftf7id3, 1, 1, True) if v == "v2" : print("running MofN tests for tokens v2:") @@ -121,7 +131,7 @@ def run_tokens_create(rpc): run_MofN_transfers(rpc1, rpc2, rpc3, nft00id1, 1) print("starting MofN tests for nftf7id1...") run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) - + print("token/assets tests finished okay") time.sleep(3) @@ -163,8 +173,8 @@ def call_token_rpc_send_tx(rpc, rpcname, stop_error, *args) : print(rpcname + " tx sent") return txid except RpcException as e : - if e.message.find('replacement in mempool') or e.message.find('missing inputs') : - print('double spending in mempool - retrying...') + if e.message.find('replacement in mempool') >= 0 or e.message.find('missing inputs') >= 0 : + print('double spending in mempool', e.message, 'retrying...') pass else : assert False, e From ba2355fa5b01df5f8e893788286c200b23264892 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 2 Jul 2021 17:09:36 +0500 Subject: [PATCH 031/348] lock mempool added in myGet_mempool_txs --- src/cc/CCutils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 53bdc2e0064..47a4f194ce5 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -779,7 +779,8 @@ int32_t myGet_mempool_txs(std::vector &txs,uint8_t evalcode,uint8_ } return (NSPV_mempoolresult.numtxids); } - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) + LOCK(mempool.cs); + BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx) { txs.push_back(e.GetTx()); i++; From e008719d59c9f6b5c50e1219237bce46e3147fe8 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 2 Jul 2021 17:11:40 +0500 Subject: [PATCH 032/348] added version to oracles opreturns added some tx boundary checks in validation added flag to prevent dust change to oracles FinalizeCCtx calls code refactoring: removed extra vars --- src/cc/oracles.cpp | 1243 ++++++++++++++++++++++---------------------- src/komodo_defs.h | 1 + 2 files changed, 632 insertions(+), 612 deletions(-) diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 398212bd8d8..4fcd3288a7c 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -13,6 +13,7 @@ * * ******************************************************************************/ +#include "komodo_defs.h" #include "CCOracles.h" #include @@ -92,213 +93,212 @@ vout.n-1: opreturn with oracletxid, prevbatontxid and data in proper format */ -extern int32_t komodo_get_current_height(); +//extern int32_t komodo_get_current_height(); #define PUBKEY_SPOOFING_FIX_ACTIVATION 1563148800 #define CC_MARKER_VALUE 10000 -#define CC_TXFEE 10000 +#define CC_TXFEE 10000 // start of consensus code -CScript EncodeOraclesCreateOpRet(uint8_t funcid,std::string name,std::string description,std::string format) +CScript EncodeOraclesCreateOpRet(uint8_t funcid, std::string name, std::string description, std::string format) { - CScript opret; uint8_t evalcode = EVAL_ORACLES; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << name << format << description); - return(opret); + CScript opret; + uint8_t evalcode = EVAL_ORACLES; + uint8_t version = 1; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << version << name << format << description); + return opret; } -uint8_t DecodeOraclesCreateOpRet(const CScript &scriptPubKey,std::string &name,std::string &description,std::string &format) +uint8_t DecodeOraclesCreateOpRet(const CScript& scriptPubKey, std::string& name, std::string& description, std::string& format) { - std::vector vopret; uint8_t *script,e,f,funcid; - GetOpReturnData(scriptPubKey,vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && script[0] == EVAL_ORACLES ) - { - if ( script[1] == 'C' ) - { - if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> name; ss >> format; ss >> description) != 0 ) - { - return(script[1]); - } else fprintf(stderr,"DecodeOraclesCreateOpRet unmarshal error for C\n"); + std::vector vopret; + uint8_t e, f, funcid, version; + GetOpReturnData(scriptPubKey, vopret); + if (vopret.size() > 2 && vopret[0] == EVAL_ORACLES) { + if (vopret[1] == 'C') { + if (E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> version; ss >> name; ss >> format; ss >> description) != 0) { + return vopret[1]; + } else + fprintf(stderr, "DecodeOraclesCreateOpRet unmarshal error for C\n"); } } - return(0); + return 0; } -CScript EncodeOraclesOpRet(uint8_t funcid,uint256 oracletxid,CPubKey pk,int64_t num) +CScript EncodeOraclesOpRet(uint8_t funcid, uint256 oracletxid, CPubKey pk, int64_t num) { - CScript opret; uint8_t evalcode = EVAL_ORACLES; + CScript opret; + uint8_t evalcode = EVAL_ORACLES; + uint8_t version = 1; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << oracletxid << pk << num); - return(opret); + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << version << oracletxid << pk << num); + return opret; } -uint8_t DecodeOraclesOpRet(const CScript &scriptPubKey,uint256 &oracletxid,CPubKey &pk,int64_t &num) +uint8_t DecodeOraclesOpRet(const CScript& scriptPubKey, uint256& oracletxid, CPubKey& pk, int64_t& num) { - std::vector vopret; uint8_t *script,e,f; + std::vector vopret; + uint8_t e, f, version; - GetOpReturnData(scriptPubKey,vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && script[0] == EVAL_ORACLES ) - { - if (script[0] == EVAL_ORACLES && (script[1]== 'R' || script[1] == 'S' || script[1] == 'F') && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> pk; ss >> num)!=0) - return(f); - else return(script[1]); + GetOpReturnData(scriptPubKey, vopret); + if (vopret.size() > 2 && vopret[0] == EVAL_ORACLES) { + if (vopret[0] == EVAL_ORACLES && (vopret[1] == 'R' || vopret[1] == 'S' || vopret[1] == 'F') && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> version; ss >> oracletxid; ss >> pk; ss >> num) != 0) + return f; + else + return vopret[1]; } - return(0); + return 0; } -CScript EncodeOraclesData(uint8_t funcid,uint256 oracletxid,uint256 batontxid,CPubKey pk,std::vector data) +CScript EncodeOraclesData(uint8_t funcid, uint256 oracletxid, uint256 batontxid, CPubKey pk, std::vector data) { - CScript opret; uint8_t evalcode = EVAL_ORACLES; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << oracletxid << batontxid << pk << data); - return(opret); + CScript opret; + uint8_t evalcode = EVAL_ORACLES; + uint8_t version = 1; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << version << oracletxid << batontxid << pk << data); + return (opret); } -uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint256 &batontxid,CPubKey &pk,std::vector &data) +uint8_t DecodeOraclesData(const CScript& scriptPubKey, uint256& oracletxid, uint256& batontxid, CPubKey& pk, std::vector& data) { - std::vector vopret; uint8_t *script,e,f; - GetOpReturnData(scriptPubKey,vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> batontxid; ss >> pk; ss >> data) != 0 ) - { - if ( e == EVAL_ORACLES && f == 'D' ) - return(f); + std::vector vopret; + uint8_t e, f, version; + GetOpReturnData(scriptPubKey, vopret); + if (vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> version; ss >> oracletxid; ss >> batontxid; ss >> pk; ss >> data) != 0) { + if (e == EVAL_ORACLES && f == 'D') + return (f); //else fprintf(stderr,"DecodeOraclesData evalcode.%d f.%c\n",e,f); } //else fprintf(stderr,"DecodeOraclesData not enough opereturn data\n"); - return(0); + return (0); } -CPubKey OracleBatonPk(char *batonaddr,struct CCcontract_info *cp) +CPubKey OracleBatonPk(char* batonaddr, struct CCcontract_info* cp) { - static secp256k1_context *ctx; + static secp256k1_context* ctx; size_t clen = CPubKey::PUBLIC_KEY_SIZE; - secp256k1_pubkey pubkey; CPubKey batonpk; uint8_t priv[32]; int32_t i; - if ( ctx == 0 ) + secp256k1_pubkey pubkey; + CPubKey batonpk; + uint8_t priv[32]; + if (ctx == 0) ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); Myprivkey(priv); cp->unspendableEvalcode2 = EVAL_ORACLES; - for (i=0; i<32; i++) + for (int32_t i = 0; i < 32; i++) cp->unspendablepriv2[i] = (priv[i] ^ cp->CCpriv[i]); - while ( secp256k1_ec_seckey_verify(ctx,cp->unspendablepriv2) == 0 ) - { + while (secp256k1_ec_seckey_verify(ctx, cp->unspendablepriv2) == 0) { // for (i=0; i<32; i++) // fprintf(stderr,"%02x",cp->unspendablepriv2[i]); - fprintf(stderr," invalid privkey\n"); - if ( secp256k1_ec_privkey_tweak_add(ctx,cp->unspendablepriv2,priv) != 0 ) + fprintf(stderr, " invalid privkey\n"); + if (secp256k1_ec_privkey_tweak_add(ctx, cp->unspendablepriv2, priv) != 0) break; } - if ( secp256k1_ec_pubkey_create(ctx,&pubkey,cp->unspendablepriv2) != 0 ) - { - secp256k1_ec_pubkey_serialize(ctx,(unsigned char*)batonpk.begin(),&clen,&pubkey,SECP256K1_EC_COMPRESSED); + if (secp256k1_ec_pubkey_create(ctx, &pubkey, cp->unspendablepriv2) != 0) { + secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)batonpk.begin(), &clen, &pubkey, SECP256K1_EC_COMPRESSED); cp->unspendablepk2 = batonpk; - Getscriptaddress(batonaddr,MakeCC1vout(cp->evalcode,0,batonpk).scriptPubKey); + Getscriptaddress(batonaddr, MakeCC1vout(cp->evalcode, 0, batonpk).scriptPubKey); //fprintf(stderr,"batonpk.(%s) -> %s\n",(char *)HexStr(batonpk).c_str(),batonaddr); - strcpy(cp->unspendableaddr2,batonaddr); - } else fprintf(stderr,"error creating pubkey\n"); - memset(priv,0,sizeof(priv)); - return(batonpk); + strcpy(cp->unspendableaddr2, batonaddr); + } else + fprintf(stderr, "error creating pubkey\n"); + memset(priv, 0, sizeof(priv)); + return (batonpk); } -int64_t OracleCurrentDatafee(uint256 reforacletxid,char *markeraddr,CPubKey publisher) +int64_t OracleCurrentDatafee(uint256 reforacletxid, char* markeraddr, CPubKey publisher) { - uint256 txid,oracletxid,hashBlock; int64_t datafee=0,dfee; int32_t dheight=0,vout,height,numvouts; CTransaction tx; CPubKey pk; - std::vector > unspentOutputs; struct CCcontract_info *cp,C; + uint256 txid, oracletxid, hashBlock; + int64_t datafee = 0, dfee; + int32_t dheight = 0, vout, height; + CTransaction tx; + CPubKey pk; + std::vector> unspentOutputs; + struct CCcontract_info *cp, C; - cp = CCinit(&C,EVAL_ORACLES); - SetCCunspents(unspentOutputs,markeraddr,false); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { + cp = CCinit(&C, EVAL_ORACLES); + SetCCunspents(unspentOutputs, markeraddr, false); + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; height = (int32_t)it->second.blockHeight; // if ( (GetLatestTimestamp(komodo_currentheight()) 0 ) - if ( FetchCCtx(txid,tx,cp) && (numvouts = tx.vout.size()) > 0 ) // version1 is true for tokel + if (FetchCCtx(txid, tx, cp) && tx.vout.size() > 0) // version1 is true for tokel { - if ( DecodeOraclesOpRet(tx.vout[numvouts-1].scriptPubKey,oracletxid,pk,dfee) == 'R' ) - { - if ( oracletxid == reforacletxid && pk == publisher ) - { - if ( height > dheight || (height == dheight && dfee < datafee) ) - { + if (DecodeOraclesOpRet(tx.vout.back().scriptPubKey, oracletxid, pk, dfee) == 'R') { + if (oracletxid == reforacletxid && pk == publisher) { + if (height > dheight || (height == dheight && dfee < datafee)) { dheight = height; datafee = dfee; - if ( 0 && dheight != 0 ) - fprintf(stderr,"set datafee %.8f height.%d\n",(double)datafee/COIN,height); + if (0 && dheight != 0) + fprintf(stderr, "set datafee %.8f height.%d\n", (double)datafee / COIN, height); } } } } } - return(datafee); + return (datafee); } -int64_t OracleDatafee(CScript &scriptPubKey,uint256 oracletxid,CPubKey publisher) +int64_t OracleDatafee(CScript& scriptPubKey, uint256 oracletxid, CPubKey publisher) { - CTransaction oracletx; char markeraddr[64]; uint256 hashBlock; std::string name,description,format; int32_t numvouts; int64_t datafee = 0; - if ( myGetTransaction(oracletxid,oracletx,hashBlock) != 0 && (numvouts= oracletx.vout.size()) > 0 ) - { - if ( DecodeOraclesCreateOpRet(oracletx.vout[numvouts-1].scriptPubKey,name,description,format) == 'C' ) - { - CCtxidaddr(markeraddr,oracletxid); - datafee = OracleCurrentDatafee(oracletxid,markeraddr,publisher); - } - else - { - fprintf(stderr,"Could not decode op_ret from transaction %s\nscriptPubKey: %s\n", oracletxid.GetHex().c_str(), oracletx.vout[numvouts-1].scriptPubKey.ToString().c_str()); + CTransaction oracletx; + char markeraddr[64]; + uint256 hashBlock; + std::string name, description, format; + int64_t datafee = 0; + if (myGetTransaction(oracletxid, oracletx, hashBlock) && oracletx.vout.size() > 0) { + if (DecodeOraclesCreateOpRet(oracletx.vout.back().scriptPubKey, name, description, format) == 'C') { + CCtxidaddr(markeraddr, oracletxid); + datafee = OracleCurrentDatafee(oracletxid, markeraddr, publisher); + } else { + fprintf(stderr, "Could not decode op_ret from transaction %s\nscriptPubKey: %s\n", oracletxid.GetHex().c_str(), oracletx.vout.back().scriptPubKey.ToString().c_str()); } } - return(datafee); + return (datafee); } -static uint256 myIs_baton_spentinmempool(uint256 batontxid,int32_t batonvout) +static uint256 myIs_baton_spentinmempool(uint256 batontxid, int32_t batonvout) { std::vector tmp_txs; - myGet_mempool_txs(tmp_txs,EVAL_ORACLES,'D'); - for (std::vector::const_iterator it=tmp_txs.begin(); it!=tmp_txs.end(); it++) - { - const CTransaction &tx = *it; - if ( tx.vout.size() > 0 && tx.vin.size() > 1 && batontxid == tx.vin[1].prevout.hash && batonvout == tx.vin[1].prevout.n ) - { - const uint256 &txid = tx.GetHash(); + myGet_mempool_txs(tmp_txs, EVAL_ORACLES, 'D'); + for (std::vector::const_iterator it = tmp_txs.begin(); it != tmp_txs.end(); it++) { + const CTransaction& tx = *it; + if (tx.vout.size() > 0 && tx.vin.size() > 1 && batontxid == tx.vin[1].prevout.hash && batonvout == tx.vin[1].prevout.n) { + const uint256& txid = tx.GetHash(); //char str[65]; fprintf(stderr,"found baton spent in mempool %s\n",uint256_str(str,txid)); - return(txid); + return (txid); } } - return(batontxid); + return (batontxid); } -uint256 OracleBatonUtxo(uint64_t value,struct CCcontract_info *cp,uint256 reforacletxid,char *batonaddr,CPubKey publisher,std::vector &dataarg) +uint256 OracleBatonUtxo(uint64_t value, struct CCcontract_info* cp, uint256 reforacletxid, char* batonaddr, CPubKey publisher, std::vector& dataarg) { - uint256 txid,oracletxid,hashBlock,btxid,batontxid = zeroid; int64_t dfee; int32_t dheight=0,vout,height,numvouts; - CTransaction tx; CPubKey pk; uint8_t *ptr; std::vector vopret,data; - std::vector > unspentOutputs; + uint256 txid, oracletxid, hashBlock, btxid, batontxid = zeroid; + int64_t dfee; + int32_t dheight = 0, vout, height; + CTransaction tx; + CPubKey pk; + std::vector vopret, data; + std::vector> unspentOutputs; - SetCCunspents(unspentOutputs,batonaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { + SetCCunspents(unspentOutputs, batonaddr, true); + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; height = (int32_t)it->second.blockHeight; - if ( it->second.satoshis != value ) - { + if (it->second.satoshis != value) { //fprintf(stderr,"it->second.satoshis %llu != %llu txfee\n",(long long)it->second.satoshis,(long long)value); continue; } - if ( FetchCCtx(txid,tx,cp) && (numvouts= tx.vout.size()) > 0 ) - { - GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret); - if ( vopret.size() > 2 ) - { - ptr = (uint8_t *)vopret.data(); - if ( (ptr[1] == 'D' && DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D') || (ptr[1] == 'R' && DecodeOraclesOpRet(tx.vout[numvouts-1].scriptPubKey,oracletxid,pk,dfee) == 'R') ) - { - if ( oracletxid == reforacletxid && pk == publisher ) - { - if ( height > dheight ) - { + if (FetchCCtx(txid, tx, cp) && tx.vout.size() > 0) { + GetOpReturnData(tx.vout.back().scriptPubKey, vopret); + if (vopret.size() > 2) { + if ((vopret[1] == 'D' && DecodeOraclesData(tx.vout.back().scriptPubKey, oracletxid, btxid, pk, data) == 'D') || (vopret[1] == 'R' && DecodeOraclesOpRet(tx.vout.back().scriptPubKey, oracletxid, pk, dfee) == 'R')) { + if (oracletxid == reforacletxid && pk == publisher) { + if (height > dheight) { dheight = height; batontxid = txid; - if ( ptr[1] == 'D' ) + if (vopret[1] == 'D') dataarg = data; //char str[65]; fprintf(stderr,"set batontxid %s height.%d\n",uint256_str(str,batontxid),height); } @@ -307,40 +307,43 @@ uint256 OracleBatonUtxo(uint64_t value,struct CCcontract_info *cp,uint256 refora } } } - while ( myIsutxo_spentinmempool(ignoretxid,ignorevin,batontxid,1) != 0 ) - batontxid = myIs_baton_spentinmempool(batontxid,1); - return(batontxid); + while (myIsutxo_spentinmempool(ignoretxid, ignorevin, batontxid, 1) != 0) + batontxid = myIs_baton_spentinmempool(batontxid, 1); + return (batontxid); } -uint256 OraclesBatontxid(uint256 reforacletxid,CPubKey refpk) +uint256 OraclesBatontxid(uint256 reforacletxid, CPubKey refpk) { - std::vector > unspentOutputs; - CTransaction regtx; uint256 hash,txid,batontxid,oracletxid; CPubKey pk; int32_t numvouts,height,maxheight=0; int64_t datafee; char markeraddr[64],batonaddr[64]; std::vector data; struct CCcontract_info *cp,C; + std::vector> unspentOutputs; + CTransaction regtx; + uint256 hash, txid, batontxid, oracletxid; + CPubKey pk; + int32_t height, maxheight = 0; + int64_t datafee; + char markeraddr[64], batonaddr[64]; + std::vector data; + struct CCcontract_info *cp, C; batontxid = zeroid; - cp = CCinit(&C,EVAL_ORACLES); - CCtxidaddr(markeraddr,reforacletxid); - SetCCunspents(unspentOutputs,markeraddr,false); + cp = CCinit(&C, EVAL_ORACLES); + CCtxidaddr(markeraddr, reforacletxid); + SetCCunspents(unspentOutputs, markeraddr, false); //char str[67]; fprintf(stderr,"markeraddr.(%s) %s\n",markeraddr,pubkey33_str(str,(uint8_t *)&refpk)); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { txid = it->first.txhash; //fprintf(stderr,"check %s\n",uint256_str(str,txid)); height = (int32_t)it->second.blockHeight; - if ( FetchCCtx(txid,regtx,cp) ) - { - if ( regtx.vout.size() > 0 && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R' && oracletxid == reforacletxid && pk == refpk ) - { - Getscriptaddress(batonaddr,regtx.vout[1].scriptPubKey); - batontxid = OracleBatonUtxo(CC_MARKER_VALUE,cp,oracletxid,batonaddr,pk,data); + if (FetchCCtx(txid, regtx, cp)) { + if (regtx.vout.size() >= 2 && DecodeOraclesOpRet(regtx.vout.back().scriptPubKey, oracletxid, pk, datafee) == 'R' && oracletxid == reforacletxid && pk == refpk) { + Getscriptaddress(batonaddr, regtx.vout[1].scriptPubKey); + batontxid = OracleBatonUtxo(CC_MARKER_VALUE, cp, oracletxid, batonaddr, pk, data); break; } } } - return(batontxid); + return (batontxid); } - /*int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format) { std::vector > unspentOutputs; @@ -380,73 +383,65 @@ uint256 OraclesBatontxid(uint256 reforacletxid,CPubKey refpk) return(0); }*/ -int64_t IsOraclesvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +int64_t IsOraclesvout(struct CCcontract_info* cp, const CTransaction& tx, int32_t v) { //char destaddr[64]; - if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) - { + if (tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0) { //if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) - return(tx.vout[v].nValue); + return (tx.vout[v].nValue); } - return(0); + return (0); } -bool OraclesDataValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,uint256 oracletxid,CPubKey publisher,int64_t datafee) +bool OraclesDataValidate(struct CCcontract_info* cp, Eval* eval, const CTransaction& tx, uint256 oracletxid, CPubKey publisher, int64_t datafee) { static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; CScript scriptPubKey; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - if ( OracleDatafee(scriptPubKey,oracletxid,publisher) != datafee ) + CTransaction vinTx; + uint256 hashBlock, activehash; + int64_t inputs = 0, outputs = 0, assetoshis; + CScript scriptPubKey; + if (OracleDatafee(scriptPubKey, oracletxid, publisher) != datafee) return eval->Invalid("mismatched datafee"); - scriptPubKey = MakeCC1vout(cp->evalcode,0,publisher).scriptPubKey; - for (i=0; ievalcode, 0, publisher).scriptPubKey; + for (int32_t i = 0; i < tx.vin.size(); i++) { //fprintf(stderr,"vini.%d\n",i); - if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 ) - { - if ( i == 0 ) + if ((*cp->ismyvin)(tx.vin[i].scriptSig) != 0) { + if (i == 0) return eval->Invalid("unexpected vin.0 is CC"); //fprintf(stderr,"vini.%d check mempool\n",i); - else if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) + else if (eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock) == 0) return eval->Invalid("cant find vinTx"); - else - { + else { //fprintf(stderr,"vini.%d check hash and vout\n",i); //if ( hashBlock == zerohash ) // return eval->Invalid("cant Oracles from mempool"); - if ( (assetoshis= IsOraclesvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 ) - { - if ( i == 1 && vinTx.vout[1].scriptPubKey != tx.vout[1].scriptPubKey ) + if ((assetoshis = IsOraclesvout(cp, vinTx, tx.vin[i].prevout.n)) != 0) { + if (i == 1 && vinTx.vout[1].scriptPubKey != tx.vout[1].scriptPubKey) return eval->Invalid("baton violation"); - else if ( i != 1 && scriptPubKey == vinTx.vout[tx.vin[i].prevout.n].scriptPubKey ) + else if (i != 1 && scriptPubKey == vinTx.vout[tx.vin[i].prevout.n].scriptPubKey) inputs += assetoshis; } } } } - for (i=0; iInvalid("invalid CC vout CC destination"); + else + return eval->Invalid("invalid CC vout CC destination"); } } } } - if ( inputs != outputs+datafee ) - { - fprintf(stderr,"inputs %llu vs outputs %llu + datafee %llu\n",(long long)inputs,(long long)outputs,(long long)datafee); + if (inputs != outputs + datafee) { + fprintf(stderr, "inputs %llu vs outputs %llu + datafee %llu\n", (long long)inputs, (long long)outputs, (long long)datafee); return eval->Invalid("mismatched inputs != outputs + datafee"); - } - else return(true); + } else + return true; } /*nt32_t GetLatestTimestamp(int32_t height) @@ -455,566 +450,590 @@ bool OraclesDataValidate(struct CCcontract_info *cp,Eval* eval,const CTransactio return(komodo_heightstamp(height)); } */ -bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) +bool OraclesValidate(struct CCcontract_info* cp, Eval* eval, const CTransaction& tx, uint32_t nIn) { - uint256 oracletxid,batontxid,txid; int32_t numvins,numvouts,preventCCvins,preventCCvouts; int64_t amount; uint256 hashblock; - uint8_t *script; std::vector vopret,data; CPubKey publisher,tmppk,oraclespk; char tmpaddress[64],vinaddress[64],oraclesaddr[64]; - CTransaction tmptx; std::string name,desc,format; + uint256 oracletxid, batontxid, txid; + int32_t preventCCvins, preventCCvouts; + int64_t amount; + uint256 hashblock; + std::vector vopret; + std::vector data; + + CPubKey publisher, tmppk, oraclespk; + char tmpaddress[64], vinaddress[64], oraclesaddr[64]; + CTransaction tmptx; + std::string name, desc, format; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; - if ( numvouts < 1 ) + if (tx.vout.size() < 1) return eval->Invalid("no vouts"); - else - { + else { //if (GetLatestTimestamp(komodo_currentheight())>=JUNE2021_NNELECTION_HARDFORK) if (true) // always true for tokel { - CCOpretCheck(eval,tx,true,true,true); - ExactAmounts(eval,tx,CC_TXFEE); + CCOpretCheck(eval, tx, true, true, true); + ExactAmounts(eval, tx, CC_TXFEE); } - GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret); - if ( vopret.size() > 2 ) - { - oraclespk=GetUnspendable(cp,0); - Getscriptaddress(oraclesaddr,CScript() << ParseHex(HexStr(oraclespk)) << OP_CHECKSIG); - script = (uint8_t *)vopret.data(); - switch ( script[1] ) - { - case 'C': // create - // vins.*: normal inputs - // vout.0: marker to oracle normal address - // vout.1: change, if any - // vout.n-1: opreturn with name and description and format for data - return eval->Invalid("unexpected OraclesValidate for create"); - break; - case 'F': // fund (activation on Jul 15th 2019 00:00) - // vins.*: normal inputs - // vout.0: CC marker fee to oracle CC address of users pubkey - // vout.1: change, if any - // vout.n-1: opreturn with createtxid, pubkey and amount - return eval->Invalid("unexpected OraclesValidate for create"); - break; - case 'R': // register - // vin.0: normal inputs - // vin.1: CC input from pubkeys oracle CC addres - to prove that register came from pubkey that is registred (activation on Jul 15th 2019 00:00) - // vout.0: marker to oracle normal address - // vout.1: baton CC utxo - // vout.2: marker from oraclesfund tx to normal pubkey address (activation on Jul 15th 2019 00:00) - // vout.n-2: change, if any - // vout.n-1: opreturn with createtxid, pubkey and price per data point - if (GetLatestTimestamp(eval->GetCurrentHeight())>PUBKEY_SPOOFING_FIX_ACTIVATION) - { - if ((numvouts=tx.vout.size()) < 1 || DecodeOraclesOpRet(tx.vout[numvouts-1].scriptPubKey,oracletxid,tmppk,amount)!='R') - return eval->Invalid("invalid oraclesregister OP_RETURN data!"); - else if (myGetTransaction(oracletxid,tmptx,hashblock) == 0) - return eval->Invalid("invalid oraclescreate txid!"); - else if ((numvouts=tmptx.vout.size()) < 1 || DecodeOraclesCreateOpRet(tmptx.vout[numvouts-1].scriptPubKey,name,desc,format)!='C') - return eval->Invalid("invalid oraclescreate OP_RETURN data!"); - else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 ) - return eval->Invalid("vin.0 is normal for oraclescreate!"); - else if (ConstrainVout(tmptx.vout[0],0,oraclesaddr,CC_MARKER_VALUE)==0) - return eval->Invalid("invalid marker for oraclescreate!"); - else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) - return eval->Invalid("vin.0 is normal for oraclesregister!"); - else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || DecodeOraclesOpRet(tmptx.vout[tmptx.vout.size()-1].scriptPubKey,txid,tmppk,amount)!='F' - || !GetCCaddress(cp,tmpaddress,tmppk) || ConstrainVout(tmptx.vout[tx.vin[1].prevout.n],1,tmpaddress,CC_MARKER_VALUE)==0 || oracletxid!=txid) - return eval->Invalid("invalid vin.1 for oraclesregister, it must be CC vin or pubkey not same as vin pubkey, register and fund tx must be done from owner of pubkey that registers to oracle!!"); - else if (CCtxidaddr(tmpaddress,oracletxid).IsValid() && ConstrainVout(tx.vout[0],0,tmpaddress,CC_MARKER_VALUE)==0) - return eval->Invalid("invalid marker for oraclesregister!"); - else if (!Getscriptaddress(tmpaddress,CScript() << ParseHex(HexStr(tmppk)) << OP_CHECKSIG) || ConstrainVout(tx.vout[2],0,tmpaddress,CC_MARKER_VALUE)==0) - return eval->Invalid("pubkey in OP_RETURN and in vout.2 not matching, register must be done from owner of pubkey that registers to oracle!"); - } - else return eval->Invalid("unexpected OraclesValidate for register"); - break; - case 'S': // subscribe - // vins.*: normal inputs - // vout.0: subscription fee to publishers CC address - // vout.1: change, if any - // vout.n-1: opreturn with createtxid, registered provider's pubkey, amount - return eval->Invalid("unexpected OraclesValidate for subscribe"); - break; - case 'D': // data - // vin.0: normal input - // vin.1: baton CC utxo (most of the time) - // vin.2+: subscription vout.0 - // vout.0: change to publishers CC address - // vout.1: baton CC utxo - // vout.2: payment for dataprovider - // vout.3: change, if any - if ( numvins >= 2 && numvouts >= 3 && DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,batontxid,publisher,data) == 'D' ) - { - if ( OraclesDataValidate(cp,eval,tx,oracletxid,publisher,tx.vout[2].nValue) != 0 ) - { - return(true); - } else return(false); - } - return eval->Invalid("unexpected OraclesValidate 'D' tx invalid"); - break; - default: - fprintf(stderr,"illegal oracles funcid.(%c)\n",script[1]); - return eval->Invalid("unexpected OraclesValidate funcid"); - break; + GetOpReturnData(tx.vout.back().scriptPubKey, vopret); + if (vopret.size() > 2) { + oraclespk = GetUnspendable(cp, 0); + Getscriptaddress(oraclesaddr, CScript() << ParseHex(HexStr(oraclespk)) << OP_CHECKSIG); + switch (vopret[1]) { + case 'C': // create + // vins.*: normal inputs + // vout.0: marker to oracle normal address + // vout.1: change, if any + // vout.n-1: opreturn with name and description and format for data + return eval->Invalid("unexpected OraclesValidate for create"); + case 'F': // fund (activation on Jul 15th 2019 00:00) + // vins.*: normal inputs + // vout.0: CC marker fee to oracle CC address of users pubkey + // vout.1: change, if any + // vout.n-1: opreturn with createtxid, pubkey and amount + return eval->Invalid("unexpected OraclesValidate for create"); + case 'R': // register + // vin.0: normal inputs + // vin.1: CC input from pubkeys oracle CC addres - to prove that register came from pubkey that is registred (activation on Jul 15th 2019 00:00) + // vout.0: marker to oracle normal address + // vout.1: baton CC utxo + // vout.2: marker from oraclesfund tx to normal pubkey address (activation on Jul 15th 2019 00:00) + // vout.n-2: change, if any + // vout.n-1: opreturn with createtxid, pubkey and price per data point + if (GetLatestTimestamp(eval->GetCurrentHeight()) > PUBKEY_SPOOFING_FIX_ACTIVATION) { + if (tx.vout.size() < 1 || DecodeOraclesOpRet(tx.vout.back().scriptPubKey, oracletxid, tmppk, amount) != 'R') + return eval->Invalid("invalid oraclesregister OP_RETURN data!"); + else if (!eval->GetTxUnconfirmed(oracletxid, tmptx, hashblock)) + return eval->Invalid("invalid oraclescreate txid!"); + else if (tmptx.vout.size() < 1 || DecodeOraclesCreateOpRet(tmptx.vout.back().scriptPubKey, name, desc, format) != 'C') + return eval->Invalid("invalid oraclescreate OP_RETURN data!"); + else if (IsCCInput(tmptx.vin[0].scriptSig) != 0) + return eval->Invalid("vin.0 is normal for oraclescreate!"); + else if (ConstrainVout(tmptx.vout[0], 0, oraclesaddr, CC_MARKER_VALUE) == false) + return eval->Invalid("invalid marker for oraclescreate!"); + else if (tx.vin.size() < 2) + return eval->Invalid("vin number too low"); + else if (IsCCInput(tx.vin[0].scriptSig) != 0) + return eval->Invalid("vin.0 is normal for oraclesregister!"); + else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash, tmptx, hashblock) == 0 || DecodeOraclesOpRet(tmptx.vout[tmptx.vout.size() - 1].scriptPubKey, txid, tmppk, amount) != 'F' || !GetCCaddress(cp, tmpaddress, tmppk) || ConstrainVout(tmptx.vout[tx.vin[1].prevout.n], 1, tmpaddress, CC_MARKER_VALUE) == 0 || oracletxid != txid) + return eval->Invalid("invalid vin.1 for oraclesregister, it must be CC vin or pubkey not same as vin pubkey, register and fund tx must be done from owner of pubkey that registers to oracle!!"); + else if (CCtxidaddr(tmpaddress, oracletxid).IsValid() && ConstrainVout(tx.vout[0], 0, tmpaddress, CC_MARKER_VALUE) == 0) + return eval->Invalid("invalid marker for oraclesregister!"); + else if (!Getscriptaddress(tmpaddress, CScript() << ParseHex(HexStr(tmppk)) << OP_CHECKSIG) || ConstrainVout(tx.vout[2], 0, tmpaddress, CC_MARKER_VALUE) == 0) + return eval->Invalid("pubkey in OP_RETURN and in vout.2 not matching, register must be done from owner of pubkey that registers to oracle!"); + } else + return eval->Invalid("unexpected OraclesValidate for register"); + break; + case 'S': // subscribe + // vins.*: normal inputs + // vout.0: subscription fee to publishers CC address + // vout.1: change, if any + // vout.n-1: opreturn with createtxid, registered provider's pubkey, amount + return eval->Invalid("unexpected OraclesValidate for subscribe"); + case 'D': // data + // vin.0: normal input + // vin.1: baton CC utxo (most of the time) + // vin.2+: subscription vout.0 + // vout.0: change to publishers CC address + // vout.1: baton CC utxo + // vout.2: payment for dataprovider + // vout.3: change, if any + if (tx.vin.size() >= 2 && tx.vout.size() >= 3 && DecodeOraclesData(tx.vout.back().scriptPubKey, oracletxid, batontxid, publisher, data) == 'D') { + if (OraclesDataValidate(cp, eval, tx, oracletxid, publisher, tx.vout[2].nValue) != 0) { + return true; + } else + return false; + } + return eval->Invalid("unexpected OraclesValidate 'D' tx invalid"); + default: + fprintf(stderr, "illegal oracles funcid.(%c)\n", vopret[1]); + return eval->Invalid("unexpected OraclesValidate funcid"); } - } else return eval->Invalid("unexpected oracles missing funcid"); - return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts)); + } else + return eval->Invalid("unexpected oracles missing funcid"); + return PreventCC(eval, tx, preventCCvins, tx.vin.size(), preventCCvouts, tx.vout.size()); } - return(true); + return true; } // end of consensus code // helper functions for rpc calls in rpcwallet.cpp -int64_t AddOracleInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,uint256 oracletxid,CPubKey pk,int64_t total,int32_t maxinputs) +int64_t AddOracleInputs(struct CCcontract_info* cp, CMutableTransaction& mtx, uint256 oracletxid, CPubKey pk, int64_t total, int32_t maxinputs) { - char coinaddr[64],funcid; int64_t nValue,price,totalinputs = 0; uint256 tmporacletxid,tmpbatontxid,txid,hashBlock; - std::vector origpubkey,data; CTransaction vintx; int32_t numvouts,vout,n = 0; - std::vector > unspentOutputs; CPubKey tmppk; int64_t tmpnum; + char coinaddr[64], funcid; + int64_t nValue, price, totalinputs = 0; + uint256 tmporacletxid, tmpbatontxid, txid, hashBlock; + std::vector origpubkey, data; + CTransaction oracletx; + int32_t vout, n = 0; + std::vector> unspentOutputs; + CPubKey tmppk; + int64_t tmpnum; - GetCCaddress(cp,coinaddr,pk); - SetCCunspents(unspentOutputs,coinaddr,true); + GetCCaddress(cp, coinaddr, pk); + SetCCunspents(unspentOutputs, coinaddr, true); //fprintf(stderr,"addoracleinputs from (%s)\n",coinaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; //char str[65]; fprintf(stderr,"oracle check %s/v%d\n",uint256_str(str,txid),vout); - if ( myGetTransaction(txid,vintx,hashBlock) != 0 && (numvouts=vintx.vout.size()-1)>0) - { - if ((funcid=DecodeOraclesOpRet(vintx.vout[numvouts].scriptPubKey,tmporacletxid,tmppk,tmpnum))!=0 && (funcid=='S' || funcid=='D')) - { - if (funcid=='D' && ValidateCCtx(vintx,cp) && DecodeOraclesData(vintx.vout[numvouts].scriptPubKey,tmporacletxid,tmpbatontxid,tmppk,data)==0) - fprintf(stderr,"invalid oraclesdata transaction \n"); - else if (tmporacletxid==oracletxid) - { + if (myGetTransaction(txid, oracletx, hashBlock) && oracletx.vout.size() > 1) { + if ((funcid = DecodeOraclesOpRet(oracletx.vout.back().scriptPubKey, tmporacletxid, tmppk, tmpnum)) != 0 && (funcid == 'S' || funcid == 'D')) { + if (funcid == 'D' && ValidateCCtx(oracletx, cp) && DecodeOraclesData(oracletx.vout.back().scriptPubKey, tmporacletxid, tmpbatontxid, tmppk, data) == 0) + fprintf(stderr, "invalid oraclesdata transaction \n"); + else if (tmporacletxid == oracletxid) { // get valid CC payments - if ( (nValue= IsOraclesvout(cp,vintx,vout)) >= CC_MARKER_VALUE && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { - if ( total != 0 && maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); + if ((nValue = IsOraclesvout(cp, oracletx, vout)) >= CC_MARKER_VALUE && myIsutxo_spentinmempool(ignoretxid, ignorevin, txid, vout) == 0) { + if (total != 0 && maxinputs != 0) + mtx.vin.push_back(CTxIn(txid, vout, CScript())); nValue = it->second.satoshis; totalinputs += nValue; n++; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) + if ((total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) break; } //else fprintf(stderr,"nValue %.8f or utxo memspent\n",(double)nValue/COIN); - } + } } - } else fprintf(stderr,"couldnt find transaction\n"); + } else + fprintf(stderr, "couldnt find transaction\n"); } - return(totalinputs); + return (totalinputs); } -int64_t LifetimeOraclesFunds(struct CCcontract_info *cp,uint256 oracletxid,CPubKey publisher) +int64_t LifetimeOraclesFunds(struct CCcontract_info* cp, uint256 oracletxid, CPubKey publisher) { - char coinaddr[64]; CPubKey pk; int64_t total=0,num; uint256 txid,hashBlock,subtxid; CTransaction subtx; + char coinaddr[64]; + CPubKey pk; + int64_t total = 0, num; + uint256 txid, hashBlock, subtxid; + CTransaction subtx; std::vector txids; - GetCCaddress(cp,coinaddr,publisher); - SetCCtxids(txids,coinaddr,true,cp->evalcode,0,oracletxid,'S'); + GetCCaddress(cp, coinaddr, publisher); + SetCCtxids(txids, coinaddr, true, cp->evalcode, 0, oracletxid, 'S'); //fprintf(stderr,"scan lifetime of %s\n",coinaddr); - for (std::vector::const_iterator it=txids.begin(); it!=txids.end(); it++) - { + for (std::vector::const_iterator it = txids.begin(); it != txids.end(); it++) { txid = *it; - if ( myGetTransaction(txid,subtx,hashBlock) != 0 ) - { - if ( subtx.vout.size() > 0 && DecodeOraclesOpRet(subtx.vout[subtx.vout.size()-1].scriptPubKey,subtxid,pk,num) == 'S' && subtxid == oracletxid && pk == publisher ) - { + if (myGetTransaction(txid, subtx, hashBlock) != 0) { + if (subtx.vout.size() > 0 && DecodeOraclesOpRet(subtx.vout[subtx.vout.size() - 1].scriptPubKey, subtxid, pk, num) == 'S' && subtxid == oracletxid && pk == publisher) { total += subtx.vout[0].nValue; } } } - return(total); + return (total); } -int64_t AddMyOraclesFunds(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 oracletxid) +int64_t AddMyOraclesFunds(struct CCcontract_info* cp, CMutableTransaction& mtx, CPubKey pk, uint256 oracletxid) { - char coinaddr[64],funcid; int64_t nValue,tmpamount; uint256 tmporacletxid,txid,hashBlock,ignoretxid; int32_t numvouts,vout,ignorevin; - std::vector > unspentOutputs; CTransaction vintx; CPubKey tmppk; + char coinaddr[64], funcid; + int64_t nValue, tmpamount; + uint256 tmporacletxid, txid, hashBlock, ignoretxid; + int32_t vout, ignorevin; + std::vector> unspentOutputs; + CTransaction vintx; + CPubKey tmppk; - GetCCaddress(cp,coinaddr,pk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { + GetCCaddress(cp, coinaddr, pk); + SetCCunspents(unspentOutputs, coinaddr, true); + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; nValue = it->second.satoshis; - if ( myGetTransaction(txid,vintx,hashBlock) != 0 && (numvouts=vintx.vout.size())>0) - { - if ((funcid=DecodeOraclesOpRet(vintx.vout[numvouts-1].scriptPubKey,tmporacletxid,tmppk,tmpamount))!=0 && funcid=='F' && tmppk==pk - && tmporacletxid==oracletxid && tmpamount==nValue && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout)==0) - { - mtx.vin.push_back(CTxIn(txid,vout,CScript())); + if (myGetTransaction(txid, vintx, hashBlock) != 0 && vintx.vout.size() > 0) { + if ((funcid = DecodeOraclesOpRet(vintx.vout.back().scriptPubKey, tmporacletxid, tmppk, tmpamount)) != 0 && funcid == 'F' && tmppk == pk && tmporacletxid == oracletxid && tmpamount == nValue && myIsutxo_spentinmempool(ignoretxid, ignorevin, txid, vout) == 0) { + mtx.vin.push_back(CTxIn(txid, vout, CScript())); return (nValue); } - } else fprintf(stderr,"couldnt find transaction\n"); + } else + fprintf(stderr, "couldnt find transaction\n"); } std::vector tmp_txs; - myGet_mempool_txs(tmp_txs,EVAL_ORACLES,'F'); - for (std::vector::const_iterator it=tmp_txs.begin(); it!=tmp_txs.end(); it++) - { - const CTransaction &txmempool = *it; - const uint256 &hash = txmempool.GetHash(); - nValue=txmempool.vout[0].nValue; + myGet_mempool_txs(tmp_txs, EVAL_ORACLES, 'F'); + for (std::vector::const_iterator it = tmp_txs.begin(); it != tmp_txs.end(); it++) { + const CTransaction& txmempool = *it; + const uint256& hash = txmempool.GetHash(); + nValue = txmempool.vout[0].nValue; - if ((funcid=DecodeOraclesOpRet(txmempool.vout[txmempool.vout.size()-1].scriptPubKey,tmporacletxid,tmppk,tmpamount))!=0 && funcid=='F' - && tmppk==pk && tmporacletxid==oracletxid && tmpamount==nValue && myIsutxo_spentinmempool(ignoretxid,ignorevin,hash,0)==0) - { - mtx.vin.push_back(CTxIn(hash,0,CScript())); + if ((funcid = DecodeOraclesOpRet(txmempool.vout[txmempool.vout.size() - 1].scriptPubKey, tmporacletxid, tmppk, tmpamount)) != 0 && funcid == 'F' && tmppk == pk && tmporacletxid == oracletxid && tmpamount == nValue && myIsutxo_spentinmempool(ignoretxid, ignorevin, hash, 0) == 0) { + mtx.vin.push_back(CTxIn(hash, 0, CScript())); return (nValue); } } return (0); } -UniValue OracleCreate(const CPubKey& pk, int64_t txfee,std::string name,std::string description,std::string format) +UniValue OracleCreate(const CPubKey& pk, int64_t txfee, std::string name, std::string description, std::string format) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,Oraclespk; struct CCcontract_info *cp,C; char fmt; + CPubKey mypk, Oraclespk; + struct CCcontract_info *cp, C; + char fmt; - cp = CCinit(&C,EVAL_ORACLES); - if ( name.size() > 32) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "name."<< (int32_t)name.size() << " must be less then 32"); + cp = CCinit(&C, EVAL_ORACLES); + if (name.size() > 32) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "name." << (int32_t)name.size() << " must be less then 32"); if (description.size() > 4096) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "description."<< (int32_t)description.size() << " must be less then 4096"); - if (format.size() > 4096 ) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "format."<< (int32_t)format.size() << " must be less then 4096"); - if ( name.size() == 0 ) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "name must not be empty"); - for(int i = 0; i < format.size(); i++) - { - fmt=format[i]; - switch (fmt) - { - case 's': case 'S': case 'd': case 'D': - case 'c': case 'C': case 't': case 'T': - case 'i': case 'I': case 'l': case 'L': - case 'h': break; - default: CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid format type"); + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "description." << (int32_t)description.size() << " must be less then 4096"); + if (format.size() > 4096) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "format." << (int32_t)format.size() << " must be less then 4096"); + if (name.size() == 0) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "name must not be empty"); + for (int i = 0; i < format.size(); i++) { + fmt = format[i]; + switch (fmt) { + case 's': + case 'S': + case 'd': + case 'D': + case 'c': + case 'C': + case 't': + case 'T': + case 'i': + case 'I': + case 'l': + case 'L': + case 'h': + break; + default: + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "invalid format type"); } - } - if ( txfee == 0 ) - txfee = ASSETCHAINS_CCZEROTXFEE[EVAL_ORACLES]?0:CC_TXFEE; - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - Oraclespk = GetUnspendable(cp,0); - if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3,pk.IsValid()) > 0 ) - { - mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(Oraclespk)) << OP_CHECKSIG)); - return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeOraclesCreateOpRet('C',name,description,format))); } - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "error adding normal inputs"); + if (txfee == 0) + txfee = ASSETCHAINS_CCZEROTXFEE[EVAL_ORACLES] ? 0 : CC_TXFEE; + mypk = pk.IsValid() ? pk : pubkey2pk(Mypubkey()); + Oraclespk = GetUnspendable(cp, 0); + if (AddNormalinputs(mtx, mypk, txfee + CC_MARKER_VALUE, 0x1000, pk.IsValid()) > 0) { + mtx.vout.push_back(CTxOut(CC_MARKER_VALUE, CScript() << ParseHex(HexStr(Oraclespk)) << OP_CHECKSIG)); + return (FinalizeCCTxExt(pk.IsValid(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cp, mtx, mypk, txfee, EncodeOraclesCreateOpRet('C', name, description, format))); + } + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "error adding normal inputs"); } -UniValue OracleFund(const CPubKey& pk, int64_t txfee,uint256 oracletxid) +UniValue OracleFund(const CPubKey& pk, int64_t txfee, uint256 oracletxid) { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction tx; - CPubKey mypk,oraclespk; struct CCcontract_info *cp,C; std::string name,desc,format; int32_t numvouts; uint256 hashBlock; - - if (GetLatestTimestamp(komodo_currentheight())evalcode,CC_MARKER_VALUE,mypk)); - return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('F',oracletxid,mypk,CC_MARKER_VALUE))); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CTransaction tx; + CPubKey mypk, oraclespk; + struct CCcontract_info *cp, C; + std::string name, desc, format; + uint256 hashBlock; + + if (GetLatestTimestamp(komodo_currentheight()) < PUBKEY_SPOOFING_FIX_ACTIVATION) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "oraclesfund not active yet, activation scheduled for July 15th"); + if (!myGetTransaction(oracletxid, tx, hashBlock) || tx.vout.size() <= 0) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); + if (DecodeOraclesCreateOpRet(tx.vout.back().scriptPubKey, name, desc, format) != 'C') + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); + cp = CCinit(&C, EVAL_ORACLES); + if (txfee == 0) + txfee = ASSETCHAINS_CCZEROTXFEE[EVAL_ORACLES] ? 0 : CC_TXFEE; + mypk = pk.IsValid() ? pk : pubkey2pk(Mypubkey()); + if (AddNormalinputs(mtx, mypk, txfee + CC_MARKER_VALUE, 0x1000, pk.IsValid())) { + mtx.vout.push_back(MakeCC1vout(cp->evalcode, CC_MARKER_VALUE, mypk)); + return (FinalizeCCTxExt(pk.IsValid(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cp, mtx, mypk, txfee, EncodeOraclesOpRet('F', oracletxid, mypk, CC_MARKER_VALUE))); } - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "error adding normal inputs"); + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "error adding normal inputs"); } -UniValue OracleRegister(const CPubKey& pk, int64_t txfee,uint256 oracletxid,int64_t datafee) +UniValue OracleRegister(const CPubKey& pk, int64_t txfee, uint256 oracletxid, int64_t datafee) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,markerpubkey,batonpk,oraclespk; struct CCcontract_info *cp,C; char markeraddr[64],batonaddr[64]; - std::string name,desc,format; int32_t numvouts; uint256 hashBlock; CTransaction tx; + CPubKey mypk, markerpubkey, batonpk, oraclespk; + struct CCcontract_info *cp, C; + char markeraddr[64], batonaddr[64]; + std::string name, desc, format; + uint256 hashBlock; + CTransaction tx; - cp = CCinit(&C,EVAL_ORACLES); - if ( txfee == 0 ) - txfee = ASSETCHAINS_CCZEROTXFEE[EVAL_ORACLES]?0:CC_TXFEE; - if (myGetTransaction(oracletxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); - if (DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,desc,format)!='C') - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); - if ( datafee < txfee ) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "datafee must be txfee or more"); - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - oraclespk = GetUnspendable(cp,0); - batonpk = OracleBatonPk(batonaddr,cp); - markerpubkey = CCtxidaddr(markeraddr,oracletxid); - if (AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,4,pk.IsValid())) - { - if (GetLatestTimestamp(komodo_currentheight())>PUBKEY_SPOOFING_FIX_ACTIVATION && AddMyOraclesFunds(cp,mtx,mypk,oracletxid)!=CC_MARKER_VALUE) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "error adding inputs from your Oracles CC address, please fund it first with oraclesfund rpc!"); - mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); - mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,batonpk)); - if (GetLatestTimestamp(komodo_get_current_height())>PUBKEY_SPOOFING_FIX_ACTIVATION) mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('R',oracletxid,mypk,datafee))); + cp = CCinit(&C, EVAL_ORACLES); + if (txfee == 0) + txfee = ASSETCHAINS_CCZEROTXFEE[EVAL_ORACLES] ? 0 : CC_TXFEE; + if (!myGetTransaction(oracletxid, tx, hashBlock)|| tx.vout.size() <= 0) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); + if (DecodeOraclesCreateOpRet(tx.vout.back().scriptPubKey, name, desc, format) != 'C') + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); + if (datafee < txfee) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "datafee must be txfee or more"); + mypk = pk.IsValid() ? pk : pubkey2pk(Mypubkey()); + oraclespk = GetUnspendable(cp, 0); + batonpk = OracleBatonPk(batonaddr, cp); + markerpubkey = CCtxidaddr(markeraddr, oracletxid); + if (AddNormalinputs(mtx, mypk, txfee + 2 * CC_MARKER_VALUE, 0x1000, pk.IsValid())) { + if (GetLatestTimestamp(komodo_currentheight()) > PUBKEY_SPOOFING_FIX_ACTIVATION && AddMyOraclesFunds(cp, mtx, mypk, oracletxid) != CC_MARKER_VALUE) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "error adding inputs from your Oracles CC address, please fund it first with oraclesfund rpc!"); + mtx.vout.push_back(CTxOut(CC_MARKER_VALUE, CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); + mtx.vout.push_back(MakeCC1vout(cp->evalcode, CC_MARKER_VALUE, batonpk)); + if (GetLatestTimestamp(komodo_get_current_height()) > PUBKEY_SPOOFING_FIX_ACTIVATION) + mtx.vout.push_back(CTxOut(CC_MARKER_VALUE, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + return (FinalizeCCTxExt(pk.IsValid(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cp, mtx, mypk, txfee, EncodeOraclesOpRet('R', oracletxid, mypk, datafee))); } - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "error adding normal inputs"); + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "error adding normal inputs"); } -UniValue OracleSubscribe(const CPubKey& pk, int64_t txfee,uint256 oracletxid,CPubKey publisher,int64_t amount) +UniValue OracleSubscribe(const CPubKey& pk, int64_t txfee, uint256 oracletxid, CPubKey publisher, int64_t amount) { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction tx; - CPubKey mypk,markerpubkey; struct CCcontract_info *cp,C; char markeraddr[64]; std::string name,desc,format; int32_t numvouts; uint256 hashBlock; - cp = CCinit(&C,EVAL_ORACLES); - if ( txfee == 0 ) - txfee = ASSETCHAINS_CCZEROTXFEE[EVAL_ORACLES]?0:CC_TXFEE; - if (myGetTransaction(oracletxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); - if (DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,desc,format)!='C') - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - markerpubkey = CCtxidaddr(markeraddr,oracletxid); - if ( AddNormalinputs(mtx,mypk,amount + txfee + CC_MARKER_VALUE,64,pk.IsValid()) > 0 ) - { - mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,publisher)); - mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); - return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('S',oracletxid,mypk,amount))); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CTransaction tx; + CPubKey mypk, markerpubkey; + struct CCcontract_info *cp, C; + char markeraddr[64]; + std::string name, desc, format; + uint256 hashBlock; + cp = CCinit(&C, EVAL_ORACLES); + if (txfee == 0) + txfee = ASSETCHAINS_CCZEROTXFEE[EVAL_ORACLES] ? 0 : CC_TXFEE; + if (!myGetTransaction(oracletxid, tx, hashBlock) || tx.vout.size() <= 0) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); + if (DecodeOraclesCreateOpRet(tx.vout.back().scriptPubKey, name, desc, format) != 'C') + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); + mypk = pk.IsValid() ? pk : pubkey2pk(Mypubkey()); + markerpubkey = CCtxidaddr(markeraddr, oracletxid); + if (AddNormalinputs(mtx, mypk, amount + txfee + CC_MARKER_VALUE, 0x1000, pk.IsValid()) > 0) { + mtx.vout.push_back(MakeCC1vout(cp->evalcode, amount, publisher)); + mtx.vout.push_back(CTxOut(CC_MARKER_VALUE, CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); + return (FinalizeCCTxExt(pk.IsValid(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cp, mtx, mypk, txfee, EncodeOraclesOpRet('S', oracletxid, mypk, amount))); } - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "error adding normal inputs"); + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "error adding normal inputs"); } -UniValue OracleData(const CPubKey& pk, int64_t txfee,uint256 oracletxid,std::vector data) +UniValue OracleData(const CPubKey& pk, int64_t txfee, uint256 oracletxid, std::vector data) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CScript pubKey; CPubKey mypk,batonpk; int64_t offset,datafee,inputs,CCchange = 0; struct CCcontract_info *cp,C; uint256 batontxid,hashBlock; - char coinaddr[64],batonaddr[64]; std::vector prevdata; CTransaction tx; std::string name,description,format; int32_t len,numvouts; + CScript pubKey; + CPubKey mypk, batonpk; + int64_t offset, datafee, inputs, CCchange = 0; + struct CCcontract_info *cp, C; + uint256 batontxid, hashBlock; + char coinaddr[64], batonaddr[64]; + std::vector prevdata; + CTransaction tx; + std::string name, description, format; + int32_t len; - cp = CCinit(&C,EVAL_ORACLES); - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - if ( data.size() > 8192 ) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "datasize " << (int32_t)data.size() << " is too big"); - if ( (datafee= OracleDatafee(pubKey,oracletxid,mypk)) <= 0 ) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "datafee " << (double)datafee/COIN << "is illegal"); - if ( myGetTransaction(oracletxid,tx,hashBlock) != 0 && (numvouts=tx.vout.size()) > 0 ) + cp = CCinit(&C, EVAL_ORACLES); + mypk = pk.IsValid() ? pk : pubkey2pk(Mypubkey()); + if (data.size() > 8192) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "datasize " << (int32_t)data.size() << " is too big"); + if ((datafee = OracleDatafee(pubKey, oracletxid, mypk)) <= 0) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "datafee " << (double)datafee / COIN << "is illegal"); + if (myGetTransaction(oracletxid, tx, hashBlock) && tx.vout.size() > 0) { + if (DecodeOraclesCreateOpRet(tx.vout.back().scriptPubKey, name, description, format) == 'C') { + if (oracle_parse_data_format(data, format) == 0) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "data does not match length or content format specification"); + } else + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "invalid oracle txid opret data"); + } else + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "invalid oracle txid"); + if (txfee == 0) + txfee = ASSETCHAINS_CCZEROTXFEE[EVAL_ORACLES] ? 0 : CC_TXFEE; + GetCCaddress(cp, coinaddr, mypk); + if (AddNormalinputs(mtx, mypk, txfee + CC_MARKER_VALUE, 0x1000, pk.IsValid()) > 0) // have enough funds even if baton utxo not there { - if ( DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,description,format) == 'C' ) - { - if (oracle_parse_data_format(data,format)==0) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "data does not match length or content format specification"); - } + batonpk = OracleBatonPk(batonaddr, cp); + batontxid = OracleBatonUtxo(CC_MARKER_VALUE, cp, oracletxid, batonaddr, mypk, prevdata); + if (batontxid != zeroid) // not impossible to fail, but hopefully a very rare event + mtx.vin.push_back(CTxIn(batontxid, 1, CScript())); else - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid oracle txid opret data"); - } - else - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid oracle txid"); - if ( txfee == 0 ) - txfee = ASSETCHAINS_CCZEROTXFEE[EVAL_ORACLES]?0:CC_TXFEE; - GetCCaddress(cp,coinaddr,mypk); - if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3,pk.IsValid()) > 0 ) // have enough funds even if baton utxo not there - { - batonpk = OracleBatonPk(batonaddr,cp); - batontxid = OracleBatonUtxo(CC_MARKER_VALUE,cp,oracletxid,batonaddr,mypk,prevdata); - if ( batontxid != zeroid ) // not impossible to fail, but hopefully a very rare event - mtx.vin.push_back(CTxIn(batontxid,1,CScript())); - else fprintf(stderr,"warning: couldnt find baton utxo %s\n",batonaddr); - if ( (inputs= AddOracleInputs(cp,mtx,oracletxid,mypk,datafee,60)) >= datafee ) - { - if ( inputs > datafee ) + fprintf(stderr, "warning: couldnt find baton utxo %s\n", batonaddr); + if ((inputs = AddOracleInputs(cp, mtx, oracletxid, mypk, datafee, 60)) >= datafee) { + if (inputs > datafee) CCchange = (inputs - datafee); - mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,mypk)); - mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,batonpk)); - mtx.vout.push_back(CTxOut(datafee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeOraclesData('D',oracletxid,batontxid,mypk,data))); + mtx.vout.push_back(MakeCC1vout(cp->evalcode, CCchange, mypk)); + mtx.vout.push_back(MakeCC1vout(cp->evalcode, CC_MARKER_VALUE, batonpk)); + mtx.vout.push_back(CTxOut(datafee, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + return FinalizeCCTxExt(pk.IsValid(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cp, mtx, mypk, txfee, EncodeOraclesData('D', oracletxid, batontxid, mypk, data)); } else - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "couldnt find enough oracle inputs " << coinaddr << ", limit 1 per utxo"); + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "couldnt find enough oracle inputs " << coinaddr << ", limit 1 per utxo"); } - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "couldnt add normal inputs"); + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "couldnt add normal inputs"); } -UniValue OracleDataSample(uint256 reforacletxid,uint256 txid) +UniValue OracleDataSample(uint256 reforacletxid, uint256 txid) { - UniValue result(UniValue::VOBJ); CTransaction tx,oracletx; uint256 hashBlock,btxid,oracletxid; std::string error; struct CCcontract_info *cp,C; - CPubKey pk; std::string name,description,format; int32_t numvouts; std::vector data; char str[67], *formatstr = 0; - - cp = CCinit(&C,EVAL_ORACLES); - result.push_back(Pair("result","success")); - if ( myGetTransaction(reforacletxid,oracletx,hashBlock) != 0 && (numvouts=oracletx.vout.size()) > 0 ) - { - if ( DecodeOraclesCreateOpRet(oracletx.vout[numvouts-1].scriptPubKey,name,description,format) == 'C' ) - { - if ( FetchCCtx(txid,tx,cp) && (numvouts=tx.vout.size()) > 0 ) - { - if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid ) - { - if ( (formatstr= (char *)format.c_str()) == 0 ) - formatstr = (char *)""; - result.push_back(Pair("txid",uint256_str(str,txid))); - result.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size()))); - return(result); - } - else error="invalid data tx"; - } - else error="cannot find data txid"; - } - else error="invalid oracles txid"; - } - else error="cannot find oracles txid"; - result.push_back(Pair("result","error")); - result.push_back(Pair("error",error)); - return(result); + UniValue result(UniValue::VOBJ); + CTransaction datatx, oracletx; + uint256 hashBlock, btxid, oracletxid; + std::string error; + struct CCcontract_info *cp, C; + CPubKey pk; + std::string name, description, format; + std::vector data; + char str[67], *formatstr = 0; + + cp = CCinit(&C, EVAL_ORACLES); + result.push_back(Pair("result", "success")); + if (myGetTransaction(reforacletxid, oracletx, hashBlock) != 0 && oracletx.vout.size() > 0) { + if (DecodeOraclesCreateOpRet(oracletx.vout.back().scriptPubKey, name, description, format) == 'C') { + if (FetchCCtx(txid, datatx, cp) && datatx.vout.size() > 0) { + if (DecodeOraclesData(datatx.vout.back().scriptPubKey, oracletxid, btxid, pk, data) == 'D' && reforacletxid == oracletxid) { + if ((formatstr = (char*)format.c_str()) == 0) + formatstr = (char*)""; + result.push_back(Pair("txid", uint256_str(str, txid))); + result.push_back(Pair("data", OracleFormat((uint8_t*)data.data(), (int32_t)data.size(), formatstr, (int32_t)format.size()))); + return (result); + } else + error = "invalid data tx"; + } else + error = "cannot find data txid"; + } else + error = "invalid oracles txid"; + } else + error = "cannot find oracles txid"; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", error)); + return (result); } -UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num) +UniValue OracleDataSamples(uint256 reforacletxid, char* batonaddr, int32_t num) { - UniValue result(UniValue::VOBJ),b(UniValue::VARR); CTransaction tx,oracletx; uint256 txid,hashBlock,btxid,oracletxid; - CPubKey pk; std::string name,description,format; int32_t numvouts,n=0,vout; std::vector data; char *formatstr = 0, addr[64]; - std::vector txids; int64_t nValue; struct CCcontract_info *cp,C; + UniValue result(UniValue::VOBJ), b(UniValue::VARR); + CTransaction tx, oracletx; + uint256 txid, hashBlock, btxid, oracletxid; + CPubKey pk; + std::string name, description, format; + int32_t n = 0, vout; + std::vector data; + char *formatstr = 0, addr[64]; + std::vector txids; + int64_t nValue; + struct CCcontract_info *cp, C; - cp = CCinit(&C,EVAL_ORACLES); - result.push_back(Pair("result","success")); - if ( myGetTransaction(reforacletxid,oracletx,hashBlock) != 0 && (numvouts=oracletx.vout.size()) > 0 ) - { - if ( DecodeOraclesCreateOpRet(oracletx.vout[numvouts-1].scriptPubKey,name,description,format) == 'C' ) - { + cp = CCinit(&C, EVAL_ORACLES); + result.push_back(Pair("result", "success")); + if (myGetTransaction(reforacletxid, oracletx, hashBlock) != 0 && oracletx.vout.size() > 0) { + if (DecodeOraclesCreateOpRet(oracletx.vout.back().scriptPubKey, name, description, format) == 'C') { std::vector tmp_txs; - myGet_mempool_txs(tmp_txs,EVAL_ORACLES,'D'); - for (std::vector::const_iterator it=tmp_txs.begin(); it!=tmp_txs.end(); it++) - { - const CTransaction &txmempool = *it; - const uint256 &hash = txmempool.GetHash(); - if ((numvouts=txmempool.vout.size())>0 && ValidateCCtx(txmempool,cp) && txmempool.vout[1].nValue==CC_MARKER_VALUE && DecodeOraclesData(txmempool.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid ) - { - Getscriptaddress(addr,txmempool.vout[1].scriptPubKey); - if (strcmp(addr,batonaddr)!=0) continue; - if ( (formatstr= (char *)format.c_str()) == 0 ) - formatstr = (char *)""; + myGet_mempool_txs(tmp_txs, EVAL_ORACLES, 'D'); + for (std::vector::const_iterator it = tmp_txs.begin(); it != tmp_txs.end(); it++) { + const CTransaction& txmempool = *it; + const uint256& hash = txmempool.GetHash(); + if (txmempool.vout.size() >= 2 && ValidateCCtx(txmempool, cp) && txmempool.vout[1].nValue == CC_MARKER_VALUE && DecodeOraclesData(txmempool.vout.back().scriptPubKey, oracletxid, btxid, pk, data) == 'D' && reforacletxid == oracletxid) { + Getscriptaddress(addr, txmempool.vout[1].scriptPubKey); + if (strcmp(addr, batonaddr) != 0) + continue; + if ((formatstr = (char*)format.c_str()) == 0) + formatstr = (char*)""; UniValue a(UniValue::VOBJ); - a.push_back(Pair("txid",hash.GetHex())); - a.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size()))); + a.push_back(Pair("txid", hash.GetHex())); + a.push_back(Pair("data", OracleFormat((uint8_t*)data.data(), (int32_t)data.size(), formatstr, (int32_t)format.size()))); b.push_back(a); - if ( ++n >= num && num != 0) - { - result.push_back(Pair("samples",b)); - return(result); + if (++n >= num && num != 0) { + result.push_back(Pair("samples", b)); + return (result); } } } - SetCCtxids(txids,batonaddr,true,EVAL_ORACLES,CC_MARKER_VALUE,reforacletxid,'D'); - if (txids.size()>0) - { - for (std::vector::const_iterator it=txids.end()-1; it!=txids.begin(); it--) - { - txid=*it; - if (FetchCCtx(txid,tx,cp) && (numvouts=tx.vout.size()) > 0 ) - { - if ( tx.vout[1].nValue==CC_MARKER_VALUE && DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid ) - { - if ( (formatstr= (char *)format.c_str()) == 0 ) - formatstr = (char *)""; + SetCCtxids(txids, batonaddr, true, EVAL_ORACLES, CC_MARKER_VALUE, reforacletxid, 'D'); + if (txids.size() > 0) { + for (std::vector::const_iterator it = txids.end() - 1; it != txids.begin(); it--) { + txid = *it; + if (FetchCCtx(txid, tx, cp) && tx.vout.size() >= 2) { + if (tx.vout[1].nValue == CC_MARKER_VALUE && DecodeOraclesData(tx.vout.back().scriptPubKey, oracletxid, btxid, pk, data) == 'D' && reforacletxid == oracletxid) { + if ((formatstr = (char*)format.c_str()) == NULL) + formatstr = (char*)""; UniValue a(UniValue::VOBJ); - a.push_back(Pair("txid",txid.GetHex())); - a.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size()))); + a.push_back(Pair("txid", txid.GetHex())); + a.push_back(Pair("data", OracleFormat((uint8_t*)data.data(), (int32_t)data.size(), formatstr, (int32_t)format.size()))); b.push_back(a); - if ( ++n >= num && num != 0) - { - result.push_back(Pair("samples",b)); - return(result); + if (++n >= num && num != 0) { + result.push_back(Pair("samples", b)); + return (result); } } } } } - } - else - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); - } - else - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); - result.push_back(Pair("samples",b)); - return(result); + } else + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); + } else + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); + result.push_back(Pair("samples", b)); + return (result); } UniValue OracleInfo(uint256 origtxid) { - UniValue result(UniValue::VOBJ),a(UniValue::VARR); - std::vector > unspentOutputs; int32_t height; + UniValue result(UniValue::VOBJ), a(UniValue::VARR); + std::vector> unspentOutputs; + int32_t height; CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction tx; std::string name,description,format; uint256 hashBlock,txid,oracletxid,batontxid; CPubKey pk; - struct CCcontract_info *cp,C; int64_t datafee,funding; char str[67],markeraddr[64],numstr[64],batonaddr[64]; std::vector data; - std::map> publishers; + CTransaction tx; + std::string name, description, format; + uint256 hashBlock, txid, oracletxid, batontxid; + CPubKey pk; + struct CCcontract_info *cp, C; + int64_t datafee, funding; + char markeraddr[64], batonaddr[64]; + std::map> publishers; - cp = CCinit(&C,EVAL_ORACLES); - CCtxidaddr(markeraddr,origtxid); - if ( myGetTransaction(origtxid,tx,hashBlock) == 0 ) - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); - else - { - if ( tx.vout.size() > 0 && DecodeOraclesCreateOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,name,description,format) == 'C' ) - { - result.push_back(Pair("result","success")); - result.push_back(Pair("txid",uint256_str(str,origtxid))); - result.push_back(Pair("name",name)); - result.push_back(Pair("description",description)); - result.push_back(Pair("format",format)); - result.push_back(Pair("marker",markeraddr)); - SetCCunspents(unspentOutputs,markeraddr,false); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { + cp = CCinit(&C, EVAL_ORACLES); + CCtxidaddr(markeraddr, origtxid); + if (!myGetTransaction(origtxid, tx, hashBlock)) + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); + else { + if (tx.vout.size() > 0 && DecodeOraclesCreateOpRet(tx.vout.back().scriptPubKey, name, description, format) == 'C') { + result.push_back(Pair("result", "success")); + result.push_back(Pair("txid", origtxid.GetHex())); + result.push_back(Pair("name", name)); + result.push_back(Pair("description", description)); + result.push_back(Pair("format", format)); + result.push_back(Pair("marker", markeraddr)); + SetCCunspents(unspentOutputs, markeraddr, false); + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { txid = it->first.txhash; height = (int32_t)it->second.blockHeight; - if ( FetchCCtx(txid,tx,cp) && tx.vout.size() > 0 && - DecodeOraclesOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R' && oracletxid == origtxid ) - { - if (publishers.find(pk)==publishers.end() || height>publishers[pk].second) - { - publishers[pk].first=txid; - publishers[pk].second=height; + if (FetchCCtx(txid, tx, cp) && tx.vout.size() > 0 && + DecodeOraclesOpRet(tx.vout.back().scriptPubKey, oracletxid, pk, datafee) == 'R' && oracletxid == origtxid) { + if (publishers.find(pk) == publishers.end() || height > publishers[pk].second) { + publishers[pk].first = txid; + publishers[pk].second = height; } } } - for (std::map>::iterator it = publishers.begin(); it != publishers.end(); ++it) - { - if ( FetchCCtx(it->second.first,tx,cp) && DecodeOraclesOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R') - { + for (std::map>::iterator it = publishers.begin(); it != publishers.end(); ++it) { + if (FetchCCtx(it->second.first, tx, cp) && DecodeOraclesOpRet(tx.vout.back().scriptPubKey, oracletxid, pk, datafee) == 'R') { UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("publisher",pubkey33_str(str,(uint8_t *)pk.begin()))); - Getscriptaddress(batonaddr,tx.vout[1].scriptPubKey); - batontxid = OracleBatonUtxo(CC_MARKER_VALUE,cp,oracletxid,batonaddr,pk,data); - obj.push_back(Pair("baton",batonaddr)); - obj.push_back(Pair("batontxid",uint256_str(str,batontxid))); - funding = LifetimeOraclesFunds(cp,oracletxid,pk); - sprintf(numstr,"%.8f",(double)funding/COIN); - obj.push_back(Pair("lifetime",numstr)); - funding = AddOracleInputs(cp,mtx,oracletxid,pk,0,0); - sprintf(numstr,"%.8f",(double)funding/COIN); - obj.push_back(Pair("funds",numstr)); - sprintf(numstr,"%.8f",(double)datafee/COIN); - obj.push_back(Pair("datafee",numstr)); + std::vector data; + + obj.push_back(Pair("publisher", HexStr(pk))); + Getscriptaddress(batonaddr, tx.vout[1].scriptPubKey); + batontxid = OracleBatonUtxo(CC_MARKER_VALUE, cp, oracletxid, batonaddr, pk, data); + obj.push_back(Pair("baton", batonaddr)); + obj.push_back(Pair("batontxid", batontxid.GetHex())); + CAmount lifefunding = LifetimeOraclesFunds(cp, oracletxid, pk); + obj.push_back(Pair("lifetime", ValueFromAmount(lifefunding))); + CAmount funding = AddOracleInputs(cp, mtx, oracletxid, pk, 0, 0); + obj.push_back(Pair("funds", ValueFromAmount(funding))); + obj.push_back(Pair("datafee", ValueFromAmount(datafee))); a.push_back(obj); } } - result.push_back(Pair("registered",a)); - } - else - CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); + result.push_back(Pair("registered", a)); + } else + CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); } - return(result); + return (result); } UniValue OraclesList() { - UniValue result(UniValue::VARR); std::vector txids; struct CCcontract_info *cp,C; uint256 txid,hashBlock; CTransaction createtx; std::string name,description,format; char str[65]; - cp = CCinit(&C,EVAL_ORACLES); - SetCCtxids(txids,cp->normaladdr,false,cp->evalcode,CC_MARKER_VALUE,zeroid,'C'); - for (std::vector::const_iterator it=txids.begin(); it!=txids.end(); it++) - { + UniValue result(UniValue::VARR); + std::vector txids; + struct CCcontract_info *cp, C; + uint256 txid, hashBlock; + CTransaction createtx; + std::string name, description, format; + char str[65]; + cp = CCinit(&C, EVAL_ORACLES); + SetCCtxids(txids, cp->normaladdr, false, cp->evalcode, CC_MARKER_VALUE, zeroid, 'C'); + for (std::vector::const_iterator it = txids.begin(); it != txids.end(); it++) { txid = *it; - if ( myGetTransaction(txid,createtx,hashBlock) != 0 ) - { - if ( createtx.vout.size() > 0 && DecodeOraclesCreateOpRet(createtx.vout[createtx.vout.size()-1].scriptPubKey,name,description,format) == 'C' ) - { - result.push_back(uint256_str(str,txid)); + if (myGetTransaction(txid, createtx, hashBlock) != 0) { + if (createtx.vout.size() > 0 && DecodeOraclesCreateOpRet(createtx.vout.back().scriptPubKey, name, description, format) == 'C') { + result.push_back(uint256_str(str, txid)); } } } - return(result); + return (result); } diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 58c8e9d880e..71c9c264016 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -509,6 +509,7 @@ bool komodo_txnotarizedconfirmed(uint256 txid,int32_t minconfirms=1); int32_t komodo_blockload(CBlock& block, CBlockIndex *pindex); uint32_t komodo_chainactive_timestamp(); uint32_t GetLatestTimestamp(int32_t height); +int32_t komodo_get_current_height(); #ifndef KOMODO_NSPV_FULLNODE #define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) From 961d31db7da11f0fcd2ab37d71c085d48bfe0eb0 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 3 Jul 2021 11:13:30 +0500 Subject: [PATCH 033/348] removed extra vars in oracles info rpcs; added maxvins for AddOracleInputs calls; --- src/cc/oracles.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 4fcd3288a7c..194aeced354 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -749,7 +749,7 @@ UniValue OracleRegister(const CPubKey& pk, int64_t txfee, uint256 oracletxid, in cp = CCinit(&C, EVAL_ORACLES); if (txfee == 0) txfee = ASSETCHAINS_CCZEROTXFEE[EVAL_ORACLES] ? 0 : CC_TXFEE; - if (!myGetTransaction(oracletxid, tx, hashBlock)|| tx.vout.size() <= 0) + if (!myGetTransaction(oracletxid, tx, hashBlock) || tx.vout.size() <= 0) CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); if (DecodeOraclesCreateOpRet(tx.vout.back().scriptPubKey, name, desc, format) != 'C') CCERR_RESULT("oraclescc", CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); @@ -836,7 +836,7 @@ UniValue OracleData(const CPubKey& pk, int64_t txfee, uint256 oracletxid, std::v mtx.vin.push_back(CTxIn(batontxid, 1, CScript())); else fprintf(stderr, "warning: couldnt find baton utxo %s\n", batonaddr); - if ((inputs = AddOracleInputs(cp, mtx, oracletxid, mypk, datafee, 60)) >= datafee) { + if ((inputs = AddOracleInputs(cp, mtx, oracletxid, mypk, datafee, 0x1000)) >= datafee) { if (inputs > datafee) CCchange = (inputs - datafee); mtx.vout.push_back(MakeCC1vout(cp->evalcode, CCchange, mypk)); @@ -1024,14 +1024,14 @@ UniValue OraclesList() uint256 txid, hashBlock; CTransaction createtx; std::string name, description, format; - char str[65]; + cp = CCinit(&C, EVAL_ORACLES); SetCCtxids(txids, cp->normaladdr, false, cp->evalcode, CC_MARKER_VALUE, zeroid, 'C'); for (std::vector::const_iterator it = txids.begin(); it != txids.end(); it++) { txid = *it; if (myGetTransaction(txid, createtx, hashBlock) != 0) { if (createtx.vout.size() > 0 && DecodeOraclesCreateOpRet(createtx.vout.back().scriptPubKey, name, description, format) == 'C') { - result.push_back(uint256_str(str, txid)); + result.push_back(txid.GetHex()); } } } From 6739eaf1b5627e5e8d9758f6028375ba66e684da Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 3 Jul 2021 11:15:24 +0500 Subject: [PATCH 034/348] in oracles rpc: RAII-style locks used; changed to standard AmountFromValue(); datafee always in satoshis --- src/wallet/rpcwallet.cpp | 151 ++++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 73 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 46b7f7a3211..15e64fccc23 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -38,6 +38,7 @@ #include "script/interpreter.h" #include "zcash/zip32.h" #include "notaries_staked.h" +#include "sync_ext.h" #include "utiltime.h" #include "asyncrpcoperation.h" @@ -6728,144 +6729,148 @@ UniValue gatewaysprocessed(const UniValue& params, bool fHelp, const CPubKey& my UniValue oracleslist(const UniValue& params, bool fHelp, const CPubKey& mypk) { - if ( fHelp || params.size() > 0 ) + if (fHelp || params.size() > 0) throw runtime_error("oracleslist\n"); - if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) + if (ensure_CCrequirements(EVAL_ORACLES) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - return(OraclesList()); + return (OraclesList()); } UniValue oraclesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) { uint256 txid; - if ( fHelp || params.size() != 1 ) + if (fHelp || params.size() != 1) throw runtime_error("oraclesinfo oracletxid\n"); - if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) + if (ensure_CCrequirements(EVAL_ORACLES) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - txid = Parseuint256((char *)params[0].get_str().c_str()); - return(OracleInfo(txid)); + txid = Parseuint256((char*)params[0].get_str().c_str()); + return (OracleInfo(txid)); } UniValue oraclesfund(const UniValue& params, bool fHelp, const CPubKey& mypk) { - UniValue result(UniValue::VOBJ); uint256 txid; - if ( fHelp || params.size() != 1 ) + UniValue result(UniValue::VOBJ); + uint256 txid; + if (fHelp || params.size() != 1) throw runtime_error("oraclesfund oracletxid\n"); - if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) + if (ensure_CCrequirements(EVAL_ORACLES) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - Lock2NSPV(mypk); - txid = Parseuint256((char *)params[0].get_str().c_str()); - result = OracleFund(mypk,0,txid); - if ( result[JSON_HEXTX].getValStr().size() > 0 ) - { + CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !mypk.IsValid()); // dont lock wallet for nspv calls + txid = Parseuint256((char*)params[0].get_str().c_str()); + result = OracleFund(mypk, 0, txid); + if (result[JSON_HEXTX].getValStr().size() > 0) { result.push_back(Pair("result", "success")); } - Unlock2NSPV(mypk); - return(result); + return (result); } UniValue oraclesregister(const UniValue& params, bool fHelp, const CPubKey& mypk) { - UniValue result(UniValue::VOBJ); uint256 txid; int64_t datafee; - if ( fHelp || params.size() != 2 ) - throw runtime_error("oraclesregister oracletxid datafee\n"); - if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) + UniValue result(UniValue::VOBJ); + uint256 txid; + if (fHelp || params.size() != 2) + throw runtime_error("oraclesregister oracletxid datafee\n" + " datafee in satoshis"); + if (ensure_CCrequirements(EVAL_ORACLES) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - Lock2NSPV(mypk); - txid = Parseuint256((char *)params[0].get_str().c_str()); - if ( (datafee= atol((char *)params[1].get_str().c_str())) == 0 ) - datafee = atof((char *)params[1].get_str().c_str()) * COIN + 0.00000000499999; - result = OracleRegister(mypk,0,txid,datafee); - if ( result[JSON_HEXTX].getValStr().size() > 0 ) - { + CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !mypk.IsValid()); // dont lock wallet for nspv calls + txid = Parseuint256((char*)params[0].get_str().c_str()); + CAmount datafee = atoll((char *)params[1].get_str().c_str()); + result = OracleRegister(mypk, 0, txid, datafee); + if (result[JSON_HEXTX].getValStr().size() > 0) { result.push_back(Pair("result", "success")); } - Unlock2NSPV(mypk); - return(result); + return (result); } UniValue oraclessubscribe(const UniValue& params, bool fHelp, const CPubKey& mypk) { - UniValue result(UniValue::VOBJ); uint256 txid; int64_t amount; std::vector pubkey; - if ( fHelp || params.size() != 3 ) + UniValue result(UniValue::VOBJ); + uint256 txid; + std::vector pubkey; + + if (fHelp || params.size() != 3) throw runtime_error("oraclessubscribe oracletxid publisher amount\n"); - if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) + if (ensure_CCrequirements(EVAL_ORACLES) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - Lock2NSPV(mypk); - txid = Parseuint256((char *)params[0].get_str().c_str()); + CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !mypk.IsValid()); // dont lock wallet for nspv calls + txid = Parseuint256((char*)params[0].get_str().c_str()); pubkey = ParseHex(params[1].get_str().c_str()); - amount = atof((char *)params[2].get_str().c_str()) * COIN + 0.00000000499999; - result = OracleSubscribe(mypk,0,txid,pubkey2pk(pubkey),amount); - if ( result[JSON_HEXTX].getValStr().size() > 0 ) - { + CAmount amount = AmountFromValue(params[2]); + result = OracleSubscribe(mypk, 0, txid, pubkey2pk(pubkey), amount); + if (result[JSON_HEXTX].getValStr().size() > 0) { result.push_back(Pair("result", "success")); } - Unlock2NSPV(mypk); - return(result); + return (result); } UniValue oraclessample(const UniValue& params, bool fHelp, const CPubKey& mypk) { - UniValue result(UniValue::VOBJ); uint256 oracletxid,txid; int32_t num; char *batonaddr; - if ( fHelp || params.size() != 2 ) + UniValue result(UniValue::VOBJ); + uint256 oracletxid, txid; + int32_t num; + char* batonaddr; + if (fHelp || params.size() != 2) throw runtime_error("oraclessample oracletxid txid\n"); - if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) + if (ensure_CCrequirements(EVAL_ORACLES) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - oracletxid = Parseuint256((char *)params[0].get_str().c_str()); - txid = Parseuint256((char *)params[1].get_str().c_str()); - return(OracleDataSample(oracletxid,txid)); + oracletxid = Parseuint256((char*)params[0].get_str().c_str()); + txid = Parseuint256((char*)params[1].get_str().c_str()); + return (OracleDataSample(oracletxid, txid)); } UniValue oraclessamples(const UniValue& params, bool fHelp, const CPubKey& mypk) { - UniValue result(UniValue::VOBJ); uint256 txid; int32_t num; char *batonaddr; - if ( fHelp || params.size() != 3 ) + UniValue result(UniValue::VOBJ); + uint256 txid; + int32_t num; + char* batonaddr; + if (fHelp || params.size() != 3) throw runtime_error("oraclessamples oracletxid batonaddress num\n"); - if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) + if (ensure_CCrequirements(EVAL_ORACLES) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - txid = Parseuint256((char *)params[0].get_str().c_str()); - batonaddr = (char *)params[1].get_str().c_str(); - num = atoi((char *)params[2].get_str().c_str()); - return(OracleDataSamples(txid,batonaddr,num)); + txid = Parseuint256((char*)params[0].get_str().c_str()); + batonaddr = (char*)params[1].get_str().c_str(); + num = atoi((char*)params[2].get_str().c_str()); + return (OracleDataSamples(txid, batonaddr, num)); } UniValue oraclesdata(const UniValue& params, bool fHelp, const CPubKey& mypk) { - UniValue result(UniValue::VOBJ); uint256 txid; std::vector data; - if ( fHelp || params.size() != 2 ) + UniValue result(UniValue::VOBJ); + uint256 txid; + std::vector data; + if (fHelp || params.size() != 2) throw runtime_error("oraclesdata oracletxid hexstr\n"); - if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) + if (ensure_CCrequirements(EVAL_ORACLES) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - Lock2NSPV(mypk); - txid = Parseuint256((char *)params[0].get_str().c_str()); + CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !mypk.IsValid()); // dont lock wallet for nspv calls + txid = Parseuint256((char*)params[0].get_str().c_str()); data = ParseHex(params[1].get_str().c_str()); - result = OracleData(mypk,0,txid,data); - if ( result[JSON_HEXTX].getValStr().size() > 0 ) - { + result = OracleData(mypk, 0, txid, data); + if (result[JSON_HEXTX].getValStr().size() > 0) { result.push_back(Pair("result", "success")); } - Unlock2NSPV(mypk); - return(result); + return (result); } UniValue oraclescreate(const UniValue& params, bool fHelp, const CPubKey& mypk) { - UniValue result(UniValue::VOBJ); std::string name,description,format; - if ( fHelp || params.size() != 3 ) + UniValue result(UniValue::VOBJ); + std::string name, description, format; + if (fHelp || params.size() != 3) throw runtime_error("oraclescreate name description format\n"); - if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) + if (ensure_CCrequirements(EVAL_ORACLES) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - Lock2NSPV(mypk); + CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !mypk.IsValid()); // dont lock wallet for nspv calls name = params[0].get_str(); description = params[1].get_str(); format = params[2].get_str(); - result = OracleCreate(mypk,0,name,description,format); - if ( result[JSON_HEXTX].getValStr().size() > 0 ) - { + result = OracleCreate(mypk, 0, name, description, format); + if (result[JSON_HEXTX].getValStr().size() > 0) { result.push_back(Pair("result", "success")); } - Unlock2NSPV(mypk); - return(result); + return (result); } UniValue FSMcreate(const UniValue& params, bool fHelp, const CPubKey& mypk) From 9b1232fe7acd71768d35f7c84f1372357883ebd9 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 3 Jul 2021 11:16:11 +0500 Subject: [PATCH 035/348] test_oracles.py fixed to catch rpc exception --- qa/pytest_komodo/cc_modules/test_oracles.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/qa/pytest_komodo/cc_modules/test_oracles.py b/qa/pytest_komodo/cc_modules/test_oracles.py index 8c971614b8c..71c078ed7a9 100644 --- a/qa/pytest_komodo/cc_modules/test_oracles.py +++ b/qa/pytest_komodo/cc_modules/test_oracles.py @@ -8,7 +8,7 @@ import time from util import assert_success, assert_error, mine_and_waitconfirms,\ send_and_mine, rpc_connect, wait_some_blocks, generate_random_string, komodo_teardown - +from slickrpc.exc import RpcException @pytest.mark.usefixtures("proxy_connection") def test_oracles(test_params): @@ -73,8 +73,12 @@ def test_oracles(test_params): list_fund_txid = [] for f in valid_formats: # trying to register with negative datafee - result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "-100") - assert_error(result) + try : + result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "-100") + assert_error(result) + except RpcException as e : # catching AmountFromValue(-100) exception + print('got normal exception', e) + pass # trying to register with zero datafee result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "0") From 87efe311e64b86df5b78a23d7f5232fcd9a263bf Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 4 Jul 2021 12:13:36 +0500 Subject: [PATCH 036/348] token help fixed --- src/rpc/tokensrpc.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 3e5030018ae..1f88d4bcd09 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -254,7 +254,7 @@ UniValue tokenv2balance(const UniValue& params, bool fHelp, const CPubKey& remot } template -static UniValue tokencreate(const std::string& fname, const UniValue& params, const vuint8_t &vtokenData, bool fHelp, const CPubKey& remotepk) +static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, bool fHelp, const CPubKey& remotepk) { UniValue result(UniValue::VOBJ); std::string name, description, hextx; @@ -303,8 +303,7 @@ UniValue tokencreate(const UniValue& params, bool fHelp, const CPubKey& remotepk " name - token name string\n" " supply - token supply in coins\n" " description - opt description" - " tokens data - an opt hex string with token data. If first byte is non-null it means a evalcode of a cc which tokens will be routed:\n" - " { \"url\":, \"id\":, \"royalty\":, \"arbitrary\": }\n" + " tokens data - an opt hex string with token data. If the first byte is non-null it means a evalcode of a cc which tokens will be routed\n" ); vuint8_t tokenData; @@ -313,7 +312,7 @@ UniValue tokencreate(const UniValue& params, bool fHelp, const CPubKey& remotepk if (tokenData.empty()) return MakeResultError("Token data incorrect"); } - return tokencreate("tokencreate", params, tokenData, fHelp, remotepk); + return tokencreate(params, tokenData, fHelp, remotepk); } UniValue tokenv2create(const UniValue& params, bool fHelp, const CPubKey& remotepk) { @@ -323,8 +322,7 @@ if (fHelp || params.size() > 4 || params.size() < 2) " name - token name string\n" " supply - token supply in coins\n" " description - opt description" - " tokens data - an opt hex string with token data. If first byte is non-null it means a evalcode of a cc which tokens will be routed:\n" - " { \"url\":, \"id\":, \"royalty\":, \"arbitrary\": }\n" + " tokens data - an opt hex string with token data. If the first byte is non-null it means a evalcode of a cc which tokens will be routed\n" ); vuint8_t tokenData; @@ -333,7 +331,7 @@ if (fHelp || params.size() > 4 || params.size() < 2) if (tokenData.empty()) return MakeResultError("Tokel token data incorrect"); } - return tokencreate("tokenv2create", params, tokenData, fHelp, remotepk); + return tokencreate(params, tokenData, fHelp, remotepk); } UniValue tokencreatetokel(const UniValue& params, bool fHelp, const CPubKey& remotepk) @@ -364,12 +362,12 @@ UniValue tokencreatetokel(const UniValue& params, bool fHelp, const CPubKey& rem return MakeResultError("Tokel token data incorrect"); } - return tokencreate("tokencreate", params, tokenData, fHelp, remotepk); + return tokencreate(params, tokenData, fHelp, remotepk); } UniValue tokenv2createtokel(const UniValue& params, bool fHelp, const CPubKey& remotepk) { if (fHelp || params.size() > 4 || params.size() < 2) - throw runtime_error("tokencreatetokel name supply [description] [tokens data]\n" + throw runtime_error("tokenv2createtokel name supply [description] [tokens data]\n" "create tokens with tokel project data\n" " name - token name string\n" " supply - token supply in coins\n" @@ -393,7 +391,7 @@ UniValue tokenv2createtokel(const UniValue& params, bool fHelp, const CPubKey& r if (tokenData.empty()) return MakeResultError("Token data incorrect"); } - return tokencreate("tokenv2create", params, tokenData, fHelp, remotepk); + return tokencreate(params, tokenData, fHelp, remotepk); } From a2096e2a11b2d1c64f6359f1b8383efc6f7a7b4a Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 4 Jul 2021 12:13:58 +0500 Subject: [PATCH 037/348] comments added in test --- src/tui/tui_assets_orders.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index cf28fc5aaa1..265b7eb8561 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -112,6 +112,7 @@ def run_tokens_create(rpc): print("token transfers tests finished okay") time.sleep(3) + # assets cc tests: print("starting assets tests for tokenid1 version=" + v + "...") run_assets_orders(rpc1, rpc2, v, tokenid1, 10, 8, False) print("starting assets tests for nft00id1 version=" + v + "...") @@ -123,7 +124,7 @@ def run_tokens_create(rpc): print("starting assets tests for nftf7id3 version=" + v + "...") run_assets_orders(rpc1, rpc2, v, nftf7id3, 1, 1, True) - if v == "v2" : + if v == "v2" : # MofN supported for tokens cc v2 only print("running MofN tests for tokens v2:") print("starting MofN tests for tokenid1...") run_MofN_transfers(rpc1, rpc2, rpc3, tokenid1, 10) From a1b8fcd37ff6d2760c6d403ce4d709398058e9a8 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 4 Jul 2021 12:45:21 +0500 Subject: [PATCH 038/348] added debug logging for bad coinbase spending --- src/komodo_utils.h | 2 ++ src/main.cpp | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/komodo_utils.h b/src/komodo_utils.h index e3a9e58dbd7..5ae77b16b9e 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -2280,6 +2280,8 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); fprintf(stderr,"ac_cbmaturity must be >0, shutting down\n"); StartShutdown(); } + LogPrintf("%s set COINBASE_MATURITY=%d\n", __func__, COINBASE_MATURITY); + //fprintf(stderr,"ASSETCHAINS_RPCPORT (%s) %u\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_RPCPORT); } if ( ASSETCHAINS_RPCPORT == 0 ) diff --git a/src/main.cpp b/src/main.cpp index ebdd821de8b..76db1c99438 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2812,11 +2812,12 @@ int GetSpendHeight(const CCoinsViewCache& inputs) namespace Consensus { bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams) { + LogPrintf("%s have COINBASE_MATURITY=%d\n", __func__, COINBASE_MATURITY); + // This doesn't trigger the DoS code on purpose; if it did, it would make it easier // for an attacker to attempt to split the network. if (!inputs.HaveInputs(tx)) return state.Invalid(error("CheckInputs(): %s inputs unavailable", tx.GetHash().ToString())); - // are the JoinSplit's requirements met? if (!inputs.HaveJoinSplitRequirements(tx)) return state.Invalid(error("CheckInputs(): %s JoinSplit requirements not met", tx.GetHash().ToString())); @@ -2840,6 +2841,7 @@ namespace Consensus { { uint64_t unlockTime = komodo_block_unlocktime(coins->nHeight); if (nSpendHeight < unlockTime) { + LogPrintf("%s bad coinbase spend nSpendHeight (%d) < unlockTime %d\n", __func__, nSpendHeight, unlockTime); return state.DoS(10, error("CheckInputs(): tried to spend coinbase that is timelocked until block %d", unlockTime), REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); @@ -2848,6 +2850,7 @@ namespace Consensus { // Ensure that coinbases are matured, no DoS as retry may work later if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) { + LogPrintf("%s bad coinbase spend nSpendHeight (%d) - coins->nHeight %d < COINBASE_MATURITY %d\n", __func__, nSpendHeight, coins->nHeight, COINBASE_MATURITY); return state.Invalid( error("CheckInputs(): tried to spend coinbase at depth %d/%d", nSpendHeight - coins->nHeight, (int32_t)COINBASE_MATURITY), REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); From 5e55b371b9ca222bc146f784fc314688341df724 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 4 Jul 2021 12:46:54 +0500 Subject: [PATCH 039/348] fixed royalty parse --- src/cc/CCTokelData.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index 2f5ed77d032..76a0539fa2a 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -198,14 +198,17 @@ static bool CheckTokelData(const vuint8_t &vdata, std::string &sError) { std::map propMap; if( ParseTokelData(vdata, propMap, sError) ) { - int64_t val; - if (!ParseInt64(propMap[TKLPROP_ROYALTY].getValStr(), &val)) { - sError = "could not parse tokel royalty"; - return false; - } - if (val < 0 || val >= TKLROYALTY_DIVISOR) { - sError = "invalid tokel royalty value (must be in 0...999)"; - return false; + // check props if present + if (propMap.count(TKLPROP_ROYALTY) > 0) { + int64_t val; + if (!ParseInt64(propMap[TKLPROP_ROYALTY].getValStr(), &val)) { + sError = "could not parse tokel royalty"; + return false; + } + if (val < 0 || val >= TKLROYALTY_DIVISOR) { + sError = "invalid tokel royalty value (must be in 0...999)"; + return false; + } } return true; } From 1a5340e0b015bf1d4e304f859d6297639151d3aa Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 4 Jul 2021 13:27:08 +0500 Subject: [PATCH 040/348] removed debug log to check bad coinbase spend --- src/komodo_utils.h | 2 -- src/main.cpp | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 5ae77b16b9e..e3a9e58dbd7 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -2280,8 +2280,6 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); fprintf(stderr,"ac_cbmaturity must be >0, shutting down\n"); StartShutdown(); } - LogPrintf("%s set COINBASE_MATURITY=%d\n", __func__, COINBASE_MATURITY); - //fprintf(stderr,"ASSETCHAINS_RPCPORT (%s) %u\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_RPCPORT); } if ( ASSETCHAINS_RPCPORT == 0 ) diff --git a/src/main.cpp b/src/main.cpp index 76db1c99438..572e137390d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2812,8 +2812,6 @@ int GetSpendHeight(const CCoinsViewCache& inputs) namespace Consensus { bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams) { - LogPrintf("%s have COINBASE_MATURITY=%d\n", __func__, COINBASE_MATURITY); - // This doesn't trigger the DoS code on purpose; if it did, it would make it easier // for an attacker to attempt to split the network. if (!inputs.HaveInputs(tx)) @@ -2841,7 +2839,6 @@ namespace Consensus { { uint64_t unlockTime = komodo_block_unlocktime(coins->nHeight); if (nSpendHeight < unlockTime) { - LogPrintf("%s bad coinbase spend nSpendHeight (%d) < unlockTime %d\n", __func__, nSpendHeight, unlockTime); return state.DoS(10, error("CheckInputs(): tried to spend coinbase that is timelocked until block %d", unlockTime), REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); @@ -2850,7 +2847,6 @@ namespace Consensus { // Ensure that coinbases are matured, no DoS as retry may work later if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) { - LogPrintf("%s bad coinbase spend nSpendHeight (%d) - coins->nHeight %d < COINBASE_MATURITY %d\n", __func__, nSpendHeight, coins->nHeight, COINBASE_MATURITY); return state.Invalid( error("CheckInputs(): tried to spend coinbase at depth %d/%d", nSpendHeight - coins->nHeight, (int32_t)COINBASE_MATURITY), REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); From cd17271c1799dc5366021671fc7295362f138cfc Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 4 Jul 2021 15:36:54 +0500 Subject: [PATCH 041/348] added tokenv2infotokel rpc --- src/cc/CCTokelData.cpp | 26 ++++++++++++++++++++++---- src/cc/CCTokelData.h | 2 ++ src/cc/CCtokens_impl.h | 13 +++++++++---- src/rpc/tokensrpc.cpp | 25 ++++++++++++++++++++++++- 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index 76a0539fa2a..938e9c30297 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -121,7 +121,7 @@ vuint8_t ParseTokelJson(const UniValue &jsonParams) return vuint8_t(ss.begin(), ss.end()); } -static bool ParseTokelData(const vuint8_t &vdata, std::map &propMapOut, std::string &sError) +static bool UnmarshalTokelVData(const vuint8_t &vdata, std::map &propMapOut, std::string &sError) { if (vdata.size() >= 2 && vdata[0] == EVAL_TOKELDATA) { @@ -169,11 +169,29 @@ static bool ParseTokelData(const vuint8_t &vdata, std::map return false; } +UniValue ParseTokelVData(const vuint8_t &vdata) +{ + std::map propMap; + std::string sError; + UniValue result(UniValue::VOBJ); + + UnmarshalTokelVData(vdata, propMap, sError); + int i = 0; + for (auto const &p : propMap) { + tklPropDesc_t entry = GetTokelDataDesc(p.first); + if (std::get<0>(entry) != TKLTYP_INVALID) + result.pushKV(std::get<1>(entry), p.second); + else + result.pushKV(std::string("unknown")+std::to_string(++i), p.second); + } + return result; +} + bool GetTokelDataAsInt64(const vuint8_t &vdata, tklPropId propId, int64_t &val) { std::map propMap; std::string sError; - ParseTokelData(vdata, propMap, sError); + UnmarshalTokelVData(vdata, propMap, sError); if (propMap.count(propId) > 0 && propMap[propId].isNum()) { ParseInt64(propMap[propId].getValStr(), &val); return true; @@ -186,7 +204,7 @@ bool GetTokelDataAsVuint8(const vuint8_t &vdata, tklPropId propId, vuint8_t &val std::map propMap; std::string sError; - ParseTokelData(vdata, propMap, sError); + UnmarshalTokelVData(vdata, propMap, sError); if (propMap.count(propId) > 0) { val = ParseHex(propMap[propId].getValStr()); return true; @@ -197,7 +215,7 @@ bool GetTokelDataAsVuint8(const vuint8_t &vdata, tklPropId propId, vuint8_t &val static bool CheckTokelData(const vuint8_t &vdata, std::string &sError) { std::map propMap; - if( ParseTokelData(vdata, propMap, sError) ) { + if( UnmarshalTokelVData(vdata, propMap, sError) ) { // check props if present if (propMap.count(TKLPROP_ROYALTY) > 0) { int64_t val; diff --git a/src/cc/CCTokelData.h b/src/cc/CCTokelData.h index ec438ea57f3..d2199aa1c60 100644 --- a/src/cc/CCTokelData.h +++ b/src/cc/CCTokelData.h @@ -33,6 +33,8 @@ typedef std::tuple tklPropDes bool GetTokelDataAsInt64(const vuint8_t &vdata, tklPropId propId, int64_t &val); bool GetTokelDataAsVuint8(const vuint8_t &vdata, tklPropId propId, vuint8_t &val); vuint8_t ParseTokelJson(const UniValue &jsonParams); +UniValue ParseTokelVData(const vuint8_t &vdata); + bool TokelDataValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 37ef50b9146..58e28ae4b7b 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -595,8 +595,8 @@ CAmount GetTokenBalance(CPubKey pk, uint256 tokenid, bool usemempool) return(AddTokenCCInputs(cp, mtx, pk, tokenid, 0, 0, usemempool)); } -template -UniValue TokenInfo(uint256 tokenid) +template +UniValue TokenInfo(uint256 tokenid, E parseExtraData) { UniValue result(UniValue::VOBJ); uint256 hashBlock; @@ -636,7 +636,6 @@ UniValue TokenInfo(uint256 tokenid) result.push_back(Pair("owner", HexStr(origpubkey))); result.push_back(Pair("name", name)); - CAmount supply = 0, output; for (int v = 0; v < tokenbaseTx.vout.size(); v++) if ((output = IsTokensvout(cpTokens, NULL, tokenbaseTx, v, tokenid)) > 0) @@ -646,8 +645,14 @@ UniValue TokenInfo(uint256 tokenid) if (oprets.size() > 0) vextraData = oprets[0]; - if( !vextraData.empty() ) + if( !vextraData.empty() ) { result.push_back(Pair("data", HexStr(vextraData))); + UniValue extraDataAsJson = parseExtraData(vextraData); + if (!extraDataAsJson.isNull()) + result.push_back(Pair("dataAsJson", extraDataAsJson)); + + } + result.push_back(Pair("version", DecodeTokenOpretVersion(tokenbaseTx.vout.back().scriptPubKey))); result.push_back(Pair("IsMixed", V::EvalCode() == TokensV2::EvalCode() ? "yes" : "no")); diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 1f88d4bcd09..de662beff5a 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -122,7 +122,7 @@ static UniValue tokeninfo(const std::string& name, const UniValue& params, bool if ( ensure_CCrequirements(V::EvalCode()) < 0 ) throw runtime_error(CC_REQUIREMENTS_MSG); tokenid = Parseuint256((char *)params[0].get_str().c_str()); - return TokenInfo(tokenid); + return TokenInfo(tokenid, [](const vuint8_t &data){ return NullUniValue; }); } UniValue tokeninfo(const UniValue& params, bool fHelp, const CPubKey& remotepk) @@ -134,6 +134,27 @@ UniValue tokenv2info(const UniValue& params, bool fHelp, const CPubKey& remotepk return tokeninfo("tokenv2info", params, fHelp, remotepk); } +template +static UniValue tokeninfotokel(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + uint256 tokenid; + if ( fHelp || params.size() != 1 ) + throw runtime_error(name + " tokenid\n"); + if ( ensure_CCrequirements(V::EvalCode()) < 0 ) + throw runtime_error(CC_REQUIREMENTS_MSG); + tokenid = Parseuint256((char *)params[0].get_str().c_str()); + return TokenInfo(tokenid, ParseTokelVData); +} + +UniValue tokeninfotokel(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + return tokeninfotokel("tokeninfotokel", params, fHelp, remotepk); +} +UniValue tokenv2infotokel(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + return tokeninfotokel("tokenv2infotokel", params, fHelp, remotepk); +} + template UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& mypk) { @@ -1096,6 +1117,8 @@ static const CRPCCommand commands[] = { "ccutils", "addccv2signature", &addccv2signature, true }, { "tokens", "tokencreatetokel", &tokencreatetokel, true }, { "tokens v2", "tokenv2createtokel", &tokenv2createtokel, true }, + { "tokens", "tokeninfotokel", &tokeninfotokel, true }, + { "tokens v2", "tokenv2infotokel", &tokenv2infotokel, true }, }; void RegisterTokensRPCCommands(CRPCTable &tableRPC) From ab28659791676a2bc7fb73b3cfa518b1bbaa24bf Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 4 Jul 2021 15:42:48 +0500 Subject: [PATCH 042/348] tokencreate help fixed --- src/rpc/tokensrpc.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index de662beff5a..98cb94dcc6a 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -323,8 +323,8 @@ UniValue tokencreate(const UniValue& params, bool fHelp, const CPubKey& remotepk "create tokens\n" " name - token name string\n" " supply - token supply in coins\n" - " description - opt description" - " tokens data - an opt hex string with token data. If the first byte is non-null it means a evalcode of a cc which tokens will be routed\n" + " description - optional description" + " tokens data - an optional hex string with token data. If the first byte is non-null it means a evalcode which these tokens will be routed into\n" ); vuint8_t tokenData; @@ -342,8 +342,8 @@ if (fHelp || params.size() > 4 || params.size() < 2) "create tokens version 2\n" " name - token name string\n" " supply - token supply in coins\n" - " description - opt description" - " tokens data - an opt hex string with token data. If the first byte is non-null it means a evalcode of a cc which tokens will be routed\n" + " description - optional description" + " tokens data - an optional hex string with token data. If the first byte is non-null it means a evalcode which these tokens will be routed into\n" ); vuint8_t tokenData; @@ -363,7 +363,7 @@ UniValue tokencreatetokel(const UniValue& params, bool fHelp, const CPubKey& rem " name - token name string\n" " supply - token supply in coins\n" " description - opt description" - " tokens data - an opt json object with tokel token properties:\n" + " tokens data - an optional json object with tokel token properties:\n" " { \"url\":, \"id\":, \"royalty\":, \"arbitrary\": }\n" ); From 70ac6ca184d84e98bef6478c16d0257f7459c89c Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 4 Jul 2021 15:43:17 +0500 Subject: [PATCH 043/348] assets py test comments fixed --- src/tui/tui_assets_orders.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 265b7eb8561..0c40bf0f1df 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -67,36 +67,32 @@ def run_tokens_create(rpc): tokenid2 = rpc1.sendrawtransaction(result['hex']) print("created token:", tokenid2) - print("creating NFT 1 with 00...") - # result = call_rpc(rpc1, "token"+v+"create", "NFT-00-1", str(0.00000001), "nft eval 00", "00010203") + print("creating tokel NFT 1 with empty data...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-00-1", str(0.00000001), "nft eval 00", '{}') assert(check_tx(result)) nft00id1 = rpc1.sendrawtransaction(result['hex']) print("created token:", nft00id1) - print("creating NFT 2 with 00...") - # result = call_rpc(rpc1, "token"+v+"create", "NFT-00-2", str(0.00000001), "nft eval 00", "00010203") + print("creating tokel NFT 2 with arbitrary data...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-00-2", str(0.00000001), "nft eval 00", '{"arbitrary":"010203"}') assert(check_tx(result)) nft00id2 = rpc1.sendrawtransaction(result['hex']) print("created token:", nft00id2) # tokel nft data F7 evalcode - print("creating NFT with F7, no royalty, with arbitary data...") - # result = call_rpc(rpc1, "token"+v+"create", "NFT-F7-1", str(0.00000001), "nft eval=f7 arbitrary=hello", "F70101ee020d687474703a2f2f6d792e6f7267040568656c6c6f") + print("creating tokel NFT with royalty 0...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-1", str(0.00000001), "nft eval=00 royalty=0", '{"royalty":0}') assert(check_tx(result)) nftf7id1 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id1) - print("creating NFT with F7 and royalty...") - # result = call_rpc(rpc1, "token"+v+"create", "NFT-F7-2", str(0.00000001), "nft eval=f7 roaylty=AA", "F70101ee020d687474703a2f2f6d792e6f726703AA") + print("creating tokel NFT with royalty 99...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-2", str(0.00000001), "nft eval=f7 roaylty=99", '{"royalty":99}') assert(check_tx(result)) nftf7id2 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id2) - print("creating NFT with F7 and dust royalty...") + print("creating tokel NFT with royalty 1 (to test dust)...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-3", str(0.00000001), "nft eval=f7 roaylty=1", '{"royalty":1}') assert(check_tx(result)) nftf7id3 = rpc1.sendrawtransaction(result['hex']) From 295cd32a3477bd107b89fb67e0bcfa1501094a73 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 19:06:30 +0500 Subject: [PATCH 044/348] fix dust royalty calc --- src/cc/CCassetstx_impl.h | 8 +++- src/cc/assets.cpp | 80 +++++++++++++++++++++------------------- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index 3693d17d6ca..9233411ae01 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -745,8 +745,12 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / TKLROYALTY_DIVISOR * royaltyFract : 0; // check for dust: - if (royaltyValue <= ASSETS_NORMAL_DUST) - royaltyValue = 0; + //if (royaltyValue <= ASSETS_NORMAL_DUST) + // royaltyValue = 0; + // more accurate check matching to AssetValidate's check + if (royaltyFract > 0 && paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) // if value paid to seller less than when the royalty is minimum + royaltyValue = 0LL; + if (assetid2 != zeroid) { // inputs = AddAssetInputs(cpAssets, mtx, mypk, assetid2, paid_nValue, 60); // not implemented yet CCerror = "swaps not implemented"; diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 4ac07758f3a..50a4b722f3a 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -175,17 +175,14 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const char tokensDualEvalUnspendableCCaddr[KOMODO_ADDRESS_BUFSIZE], origAssetsCCaddr[KOMODO_ADDRESS_BUFSIZE], globalAssetsCCaddr[KOMODO_ADDRESS_BUFSIZE]; CAmount vin_tokens = 0; - CAmount vin_assetoshis = 0; - - int32_t numvins = tx.vin.size(); - int32_t numvouts = tx.vout.size(); + CAmount vin_coins = 0; if (tx.vin.size() == 0) return eval->Invalid("AssetValidate: no vins"); if (tx.vout.size() == 0) return eval->Invalid("AssetValidate: no vouts"); - if((funcid = A::DecodeAssetTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCodeInOpret, assetid, assetid2, unit_price, vorigpubkey)) == 0 ) + if((funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCodeInOpret, assetid, assetid2, unit_price, vorigpubkey)) == 0 ) return eval->Invalid("AssetValidate: invalid opreturn payload"); // reinit cpAssets as we could set evalcodeAdd in it @@ -220,7 +217,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if( IsCCInput(tx.vin[0].scriptSig) != false ) // vin0 should be normal vin return eval->Invalid("illegal asset cc vin0"); - else if( numvouts < 2 ) + else if(tx.vout.size() < 2) return eval->Invalid("too few vouts"); // it was if(numvouts < 1) but it refers at least to vout[1] below if (assetid == zeroid) @@ -251,13 +248,13 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const char origTokenAddr[KOMODO_ADDRESS_BUFSIZE]; //preventCCvouts = 2; - if (numvouts < 3) + if (tx.vout.size() < 3) return eval->Invalid("too few vouts"); - else if( A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, 0LL, A::EvalCode()) == false ) + else if(A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, 0LL, A::EvalCode()) == false) return eval->Invalid("invalid funding for bid"); - else if( A::ConstrainVout(tx.vout[1], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr + else if(A::ConstrainVout(tx.vout[1], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false) // marker to originator asset cc addr return eval->Invalid("invalid vout1 marker for original pubkey"); - else if( TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vorigpubkey)) == 0 ) // check tx is signed by originator pubkey + else if(TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vorigpubkey)) == 0) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for bid"); else if (unit_price <= ASSETS_NORMAL_DUST) return eval->Invalid("invalid or too low unit price"); @@ -283,16 +280,16 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //vout.n-1: opreturn [EVAL_ASSETS] ['o'] ccvins = 2; // order and marker ccvouts = 0; - vin_assetoshis = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origCCaddrDummy, origNormalAddr, tx, assetid); - if (vin_assetoshis == 0) + vin_coins = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origCCaddrDummy, origNormalAddr, tx, assetid); + if (vin_coins == 0) return false; // eval already set if (tx.vout[0].nValue > ASSETS_NORMAL_DUST) { - if (!A::ConstrainVout(tx.vout[0], NORMALVOUT, origNormalAddr, vin_assetoshis, 0)) + if (!A::ConstrainVout(tx.vout[0], NORMALVOUT, origNormalAddr, vin_coins, 0)) return eval->Invalid("invalid refund for cancelbid"); } else { // dust must go to global cc address - if (!A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, vin_assetoshis, 0)) + if (!A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, vin_coins, 0)) return eval->Invalid("invalid dust refund for cancelbid"); ccvouts ++; } @@ -313,12 +310,12 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //vout.n-1: opreturn [EVAL_ASSETS] ['B'] [assetid] [remaining asset required] [origpubkey] ccvins = 1; ccvouts = 0; // at least tokens output - vin_assetoshis = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid); - if (vin_assetoshis == 0) + vin_coins = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid); + if (vin_coins == 0) return false; // eval already set - else if( numvouts < 3 ) + else if(tx.vout.size() < 3) return eval->Invalid("not enough vouts for fillbid"); - else if( vin_origpubkey != vorigpubkey ) // originator pk does not change in the new opret + else if(vin_origpubkey != vorigpubkey) // originator pk does not change in the new opret return eval->Invalid("mismatched opreturn originator pubkeys for fillbid"); else if (unit_price != vin_unit_price) return eval->Invalid("mismatched unit price for fillbid"); @@ -329,13 +326,19 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (royaltyFract < 0LL || royaltyFract >= TKLROYALTY_DIVISOR) return eval->Invalid("invalid royalty value"); - CAmount royaltyValue = royaltyFract > 0 ? tx.vout[1].nValue / (TKLROYALTY_DIVISOR - royaltyFract) * royaltyFract : 0LL; + CAmount royaltyValue = royaltyFract > 0 ? vin_coins / TKLROYALTY_DIVISOR * royaltyFract : 0; if (royaltyValue <= ASSETS_NORMAL_DUST) royaltyValue = 0LL; // reset if dust int32_t r = royaltyValue > 0LL ? 1 : 0; + /*int32_t r = 0; + if (royaltyFract > 0 && tx.vout[1].nValue > ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) // if vout1 > min + r = 1; + if (royaltyFract > 0) + std::cerr << __func__ << " r=" << r << " tx.vout[1].nValue=" << tx.vout[1].nValue << " min-vout1=" << (ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) << std::endl;*/ + //std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << std::endl; CAmount assetoshis = tx.vout[0].nValue + tx.vout[1].nValue + (r ? tx.vout[2].nValue : 0LL); - if( vin_assetoshis != assetoshis ) // coins -> global cc address (remainder) + normal self address + if( vin_coins != assetoshis ) // coins -> global cc address (remainder) + normal self address return eval->Invalid("input cc value does not equal to vout0+1" + std::string(r ? "+2" : "") + " for fillbid"); // coins remainder @@ -386,7 +389,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const CAmount received_value = r ? tx.vout[1].nValue + tx.vout[2].nValue : tx.vout[1].nValue; // vout1 paid value to seller, vout2 royalty to owner CAmount paid_units = tx.vout[2+r].nValue; - if (!ValidateBidRemainder(unit_price, tx.vout[0].nValue, vin_assetoshis, received_value, paid_units)) // check real price and coins spending from global addr + if (!ValidateBidRemainder(unit_price, tx.vout[0].nValue, vin_coins, received_value, paid_units)) // check real price and coins spending from global addr return eval->Invalid("vout" + std::to_string(2+r) + " mismatched remainder for fillbid"); if (r) { if ((tx.vout[1].nValue + tx.vout[2].nValue) / TKLROYALTY_DIVISOR * royaltyFract != tx.vout[2].nValue) // validate royalty value @@ -418,7 +421,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const char origTokenAddr[KOMODO_ADDRESS_BUFSIZE]; CPubKey origpk = pubkey2pk(vorigpubkey); ccvouts = 2; - if (numvouts < 3) + if (tx.vout.size() < 3) return eval->Invalid("too few vouts"); else if (A::ConstrainVout(tx.vout[0], CCVOUT, tokensDualEvalUnspendableCCaddr, 0LL, T::EvalCode()) == false) // tokens sent to global addr return eval->Invalid("invalid vout0 global two eval address for sell"); @@ -474,9 +477,9 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const vin_tokens = AssetValidateSellvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid); if (vin_tokens == 0) return false; // eval is already set - else if( numvouts < 3 ) + else if (tx.vout.size() < 3) return eval->Invalid("not enough vouts for fillask"); - else if( vin_origpubkey != vorigpubkey ) + else if (vin_origpubkey != vorigpubkey) return eval->Invalid("mismatched origpubkeys for fillask"); else if (unit_price != vin_unit_price) return eval->Invalid("mismatched unit price for fillask"); @@ -487,28 +490,31 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (royaltyFract < 0LL || royaltyFract >= TKLROYALTY_DIVISOR) return eval->Invalid("invalid royalty value"); - CAmount royaltyValue = royaltyFract > 0 ? tx.vout[2].nValue / (TKLROYALTY_DIVISOR - royaltyFract) * royaltyFract : 0LL; - if (royaltyValue <= ASSETS_NORMAL_DUST) - royaltyValue = 0LL; // reset if dust - CAmount paid_value = royaltyValue > 0 ? tx.vout[2].nValue + tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner + int32_t r = royaltyFract > 0 ? 1 : 0; + // check if royalty not dust + if (royaltyFract > 0 && tx.vout[2].nValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) // if value paid to seller less than when the royalty is minimum + r = 0; + //if (royaltyValue <= ASSETS_NORMAL_DUST) + // royaltyValue = 0LL; // reset if dust + CAmount paid_value = r > 0 ? tx.vout[2].nValue + tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner if (!ValidateAskRemainder(unit_price, tx.vout[0].nValue, vin_tokens, tx.vout[1].nValue, paid_value)) return eval->Invalid("mismatched vout0 remainder for fillask"); else if (!A::ConstrainVout(tx.vout[1], CCVOUT, NULL, 0LL, T::EvalCode())) // do not check tokens buyer's 'self' cc addr return eval->Invalid("vout1 should be cc for fillask"); else if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, origNormalAddr, 0LL, 0)) // coins to originator normal addr return eval->Invalid("vout2 should be cc for fillask"); - if (royaltyValue > 0) { + if (r > 0) { if ((tx.vout[2].nValue + tx.vout[3].nValue) / TKLROYALTY_DIVISOR * royaltyFract != tx.vout[3].nValue) // validate royalty value return eval->Invalid("vout3 invalid royalty amount for fillask"); if (!A::ConstrainVout(tx.vout[3], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest - return eval->Invalid("vout3 invalid royalty detination for fillask"); + return eval->Invalid("vout3 invalid royalty destination for fillask"); } if (!A::ConstrainVout(tx.vout[0], CCVOUT, tokensDualEvalUnspendableCCaddr, 0LL, A::EvalCode())) // tokens remainder on global addr return eval->Invalid("invalid vout0 should pay to tokens/assets global address for fillask"); if (tx.vout[0].nValue > 0) { - int32_t markerVout = royaltyValue > 0 ? 4 : 3; + int32_t markerVout = r > 0 ? 4 : 3; // marker should exist if remainder not empty - if( tx.vout.size() <= markerVout || A::ConstrainVout(tx.vout[markerVout], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr + if (tx.vout.size() <= markerVout || A::ConstrainVout(tx.vout[markerVout], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false) // marker to originator asset cc addr return eval->Invalid("invalid marker vout for original pubkey"); ccvouts ++; } @@ -533,17 +539,16 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // eval->Invalid("asset2 inputs != outputs"); ////////// not implemented yet //////////// - if( (vin_tokens = AssetValidateSellvin(cpTokens, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 ) + /*if( (vin_tokens = AssetValidateSellvin(cpTokens, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 ) return(false); - else if( numvouts < 3 ) + else if(tx.vout.size() < 3) return eval->Invalid("not enough vouts for fillex"); - else if( vin_origpubkey != vorigpubkey ) + else if(vin_origpubkey != vorigpubkey) return eval->Invalid("mismatched origpubkeys for fillex"); else if (unit_price != vin_unit_price) return eval->Invalid("mismatched unit price for fillex"); else { - /* if( tokens != tx.vout[0].nValue + tx.vout[1].nValue ) return eval->Invalid("locked value doesnt match vout0+1 fillex"); else if( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != false ) @@ -573,8 +578,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if( ConstrainVout(tx.vout[0], CCVOUT, (char *)cpAssets->unspendableCCaddr, 0) == false ) // TODO: unsure about this, but this is not impl yet anyway return eval->Invalid("mismatched vout0 AssetsCCaddr for fillex"); } - */ - } + }*/ ////////// not implemented yet //////////// break; From a962fadba8a9173309df8b80a4b217433c4b0295 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 19:07:31 +0500 Subject: [PATCH 045/348] added royalty cases for test-komodo-cc regression tests --- src/test-komodo-cc/test-assets.cpp | 145 ++++++++++++++++++++++------- 1 file changed, 110 insertions(+), 35 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 3ced66e93d2..ff25b685bbb 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -131,7 +131,7 @@ CAmount TestAddTokenInputs(CMutableTransaction &mtx, CPubKey mypk, uint256 token CTransaction tx; //std::cerr << __func__ << " utxoaddr=" << utxoaddr << " mypkaddr=" << mypkaddr << " tx=" << t.second.GetHash().GetHex() << " v=" << v << std::endl; if (strcmp(utxoaddr, mypkaddr) == 0 && - IsTokensvout(cp, &eval, t.second, v, tokenid )) { + IsTokensvout(cp, &eval, t.second, v, tokenid)) { mtx.vin.push_back(CTxIn(t.second.GetHash(), v)); totalInputs += t.second.vout[v].nValue; if (totalInputs >= amount) @@ -418,13 +418,13 @@ class TestAssetsCC : public ::testing::Test { eval.AddTx(txtokencreateUnused); tokenidUnused = txtokencreateUnused.GetHash(); - txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 500); + txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1); eval.AddTx(txask1); - txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 500); + txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1); eval.AddTx(txask2); - txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, 500); + txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1); eval.AddTx(txbid1); @@ -441,7 +441,7 @@ class TestAssetsCC : public ::testing::Test { return CTransaction(mtx); } - static CMutableTransaction MakeTokenV2CreateTx(CPubKey pk, CAmount amount) + static CMutableTransaction MakeTokenV2CreateTx(CPubKey pk, CAmount amount, const UniValue &utokeldata = NullUniValue) { struct CCcontract_info *cp, C; cp = CCinit(&C, TokensV2::EvalCode()); @@ -457,8 +457,15 @@ class TestAssetsCC : public ::testing::Test { mtx.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, amount, pk)); + std::vector vextras; + vuint8_t vtokeldata; + if (!utokeldata.isNull()) + vtokeldata = ParseTokelJson(utokeldata); + if (!vtokeldata.empty()) + vextras.push_back(vtokeldata); + if (!TestFinalizeTx(mtx, cp, testKeys[pk], txfee, - TokensV2::EncodeTokenCreateOpRet(vscript_t(pk.begin(), pk.end()), name, description, { }))) { + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk.begin(), pk.end()), name, description, vextras))) { std::cerr << __func__ << " could finalize tx" << std::endl; return CTransaction(); } @@ -470,18 +477,11 @@ class TestAssetsCC : public ::testing::Test { static CMutableTransaction MakeTokenV2AskTx(struct CCcontract_info *cpTokens, CPubKey pk, uint256 tokenid, CAmount numtokens, CAmount unit_price) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cpAssets, C; - //struct CCcontract_info *cpTokens, tokensC; - - uint8_t evalcodeAdd = 0; - //CAmount askamount = 1000; - //CAmount numtokens = 2; - CAmount txfee = 10000; + struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); - //cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - //CAmount unit_price = askamount / numtokens; + CAmount txfee = 10000; CAmount askamount = numtokens * unit_price; if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { @@ -489,6 +489,18 @@ class TestAssetsCC : public ::testing::Test { return CTransaction(); } + TokenDataTuple tokenData; + vuint8_t vextraData; + uint8_t evalcodeAdd = 0; + int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { + std::cerr << __func__ << " cant get tokendata" << std::endl; + return CTransaction(); + } + if (vextraData.size() > 0) { + evalcodeAdd = vextraData[0]; + } + CAmount inputs = TestAddTokenInputs(mtx, pk, tokenid, numtokens); if (inputs == 0) { std::cerr << __func__ << " cant add token inputs" << std::endl; @@ -548,7 +560,7 @@ class TestAssetsCC : public ::testing::Test { return mtx; } - static CMutableTransaction MakeTokenV2FillAskTx(struct CCcontract_info *cpAssets, CPubKey pk, uint256 tokenid, uint256 asktxid, CAmount fill_units, CAmount paid_unit_price, UniValue &data) + static CMutableTransaction MakeTokenV2FillAskTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, uint256 asktxid, CAmount fill_units, CAmount paid_unit_price, UniValue &data) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); struct CCcontract_info *cpTokens, tokensC; @@ -579,7 +591,7 @@ class TestAssetsCC : public ::testing::Test { return CTransaction(); } if (vextraData.size() > 0) { - evalcodeAdd = vextraData.begin()[0]; + evalcodeAdd = vextraData[0]; GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); if (royaltyFract > TKLROYALTY_DIVISOR-1) royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit @@ -594,8 +606,10 @@ class TestAssetsCC : public ::testing::Test { CAmount paid_nValue = paid_unit_price * fill_units; CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / TKLROYALTY_DIVISOR * royaltyFract : 0; + if (royaltyFract > 0 && paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) // if value paid to seller less than when the royalty is minimum + royaltyValue = 0LL; - if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { std::cerr << __func__ << " cant add normal inputs" << std::endl; return CTransaction(); } @@ -605,9 +619,9 @@ class TestAssetsCC : public ::testing::Test { mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, orig_assetoshis - fill_units, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), fill_units, pk)); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), fill_units, mypk)); mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr - if (royaltyFract > 0) // note it makes the vout even if roaltyValue is 0 + if (royaltyValue > 0) // note it makes the vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner if (orig_assetoshis - fill_units > 0) // we dont need the marker if order is filled @@ -619,8 +633,8 @@ class TestAssetsCC : public ::testing::Test { CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeAdd, unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); - if (!TestFinalizeTx(mtx, cpAssets, testKeys[pk], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { pk }, + if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { mypk }, { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))) { std::cerr << __func__ << " cant finalise tx" << std::endl; return CTransaction(); @@ -633,7 +647,7 @@ class TestAssetsCC : public ::testing::Test { } - static CMutableTransaction MakeTokenV2FillBidTx(struct CCcontract_info *cpTokens, CPubKey pk, uint256 tokenid, uint256 bidtxid, CAmount bid_amount, CAmount unit_price, UniValue &data) + static CMutableTransaction MakeTokenV2FillBidTx(struct CCcontract_info *cpTokens, CPubKey mypk, uint256 tokenid, uint256 bidtxid, CAmount fill_units, CAmount unit_price, UniValue &data) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); struct CCcontract_info *cpAssets, C; @@ -644,7 +658,7 @@ class TestAssetsCC : public ::testing::Test { //CAmount bid_amount; CAmount orig_units; //CAmount unit_price = 0; - CAmount fill_units = 2; + //CAmount fill_units = 2; CAmount txfee = 10000; uint256 assetidOpret; CAmount paid_unit_price = 0; // not set @@ -679,7 +693,7 @@ class TestAssetsCC : public ::testing::Test { vuint8_t origpubkey; std::cerr << __func__ << " bidtx=" << bidtx.GetHash().GetHex() << " " << HexStr(E_MARSHAL(ss << bidtx)) << " vouts=" << bidtx.vout.size() << std::endl; - bid_amount = bidtx.vout[bidvout].nValue; + CAmount bid_amount = bidtx.vout[bidvout].nValue; if (GetOrderParams(origpubkey, unit_price, assetidOpret, bidtx) == 0) { // get orig pk, orig value std::cerr << __func__ << " cant get order data" << std::endl; return CTransaction(); @@ -694,21 +708,27 @@ class TestAssetsCC : public ::testing::Test { if (paid_unit_price <= 0LL) paid_unit_price = unit_price; - if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { std::cerr << __func__ << " cant add normal inputs" << std::endl; return CTransaction(); } - mtx.vin.push_back(CTxIn(txtokencreate2.GetHash(), 1, CScript())); // spend token tx + CAmount tokenInputs = TestAddTokenInputs(mtx, mypk, tokenid, fill_units); + if (tokenInputs == 0LL) { + std::cerr << __func__ << " cant add token inputs" << std::endl; + return CTransaction(); + } + //mtx.vin.push_back(CTxIn(tokenid, 1, CScript())); // spend token tx mtx.vin.push_back(CTxIn(bidtx.GetHash(), bidvout, CScript())); // spend order tx - CAmount tokenInputs = txtokencreate2.vout[1].nValue; - if (!SetBidFillamounts(unit_price, paid_amount, bid_amount, fill_units, orig_units, paid_unit_price)) { std::cerr << __func__ << " SetBidFillamounts return false" << std::endl; return CTransaction(); } CAmount royaltyValue = royaltyFract > 0 ? paid_amount / TKLROYALTY_DIVISOR * royaltyFract : 0; + if (royaltyValue <= ASSETS_NORMAL_DUST) + royaltyValue = 0LL; + std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << std::endl; CAmount tokensChange = tokenInputs - fill_units; uint8_t unspendableAssetsPrivkey[32]; @@ -716,30 +736,30 @@ class TestAssetsCC : public ::testing::Test { if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { // bidder has coins for more tokens or only dust is sent back to global address mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bid_amount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder or the dust is sent back to cc global addr - if (bid_amount - paid_amount <= ASSETS_NORMAL_DUST) + if (orig_units - fill_units == 0) std::cerr << __func__ << " dust detected (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; } else mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator - mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG)); // vout1 coins to mypk normal - if (royaltyFract > 0) // note it makes vout even if roaltyValue is 0 + mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to mypk normal + if (royaltyValue > 0) // note it makes vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator if (orig_units - fill_units > 0) // order is not finished yet mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey if (tokensChange != 0LL) - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), tokensChange, pk)); // change in single-eval tokens + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), tokensChange, mypk)); // change in single-eval tokens CMutableTransaction mtx2(mtx); // copy CCwrapper wrCond1(MakeCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); // spend coins CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); - CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(evalcodeAdd, pk)); // spend my tokens to fill buy + CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(evalcodeAdd, mypk)); // spend my tokens to fill buy CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey - if (!TestFinalizeTx(mtx, cpTokens, testKeys[pk], txfee, + if (!TestFinalizeTx(mtx, cpTokens, testKeys[mypk], txfee, TokensV2::EncodeTokenOpRet(tokenid, { pubkey2pk(origpubkey) }, { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))) { std::cerr << __func__ << " could not finalize tx" << std::endl; @@ -1184,6 +1204,61 @@ TEST_F(TestAssetsCC, tokenv2fillbid) } } +TEST_F(TestAssetsCC, tokenv2fillbid_royalty) +{ + for(int r = 0; r < 1000; r += 100) + { + UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx + UniValue tokeldata(UniValue::VOBJ); + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + struct CCcontract_info *cpAssets, assetsC; + cpAssets = CCinit(&assetsC, AssetsV2::EvalCode()); + + tokeldata.pushKV("royalty", r); + CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); + uint256 mytokenid = mytxtokencreate.GetHash(); + eval.AddTx(mytxtokencreate); + + CTransaction mytxbid = MakeTokenV2BidTx(cpAssets, pk2, mytokenid, 1, ASSETS_NORMAL_DUST*2+1); + eval.AddTx(mytxbid); + + CMutableTransaction mytxfill = MakeTokenV2FillBidTx(cpTokens, pk1, mytokenid, mytxbid.GetHash(), 1, 0, data); + ASSERT_FALSE(CTransaction(mytxfill).IsNull()); + + // test: valid tokenv2fillbid + EXPECT_TRUE(TestRunCCEval(mytxfill)); + } +} + +TEST_F(TestAssetsCC, tokenv2fillask_royalty) +{ + for(int r = 0; r < 1000; r += 100) + { + UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx + UniValue tokeldata(UniValue::VOBJ); + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + struct CCcontract_info *cpAssets, assetsC; + cpAssets = CCinit(&assetsC, AssetsV2::EvalCode()); + + tokeldata.pushKV("royalty", r); + CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); + uint256 mytokenid = mytxtokencreate.GetHash(); + eval.AddTx(mytxtokencreate); + + CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, 1, ASSETS_NORMAL_DUST*2+1); + eval.AddTx(mytxask); + + CMutableTransaction mytxfill = MakeTokenV2FillAskTx(cpAssets, pk2, mytokenid, mytxask.GetHash(), 1, 0, data); + ASSERT_FALSE(CTransaction(mytxfill).IsNull()); + + // test: valid tokenv2fillbid + EXPECT_TRUE(TestRunCCEval(mytxfill)); + } +} + + TEST_F(TestAssetsCC, tokenv2cancelask) { struct CCcontract_info *cpAssets, C; From e7ee533cb6f49d8e00bffcb7f1e41a078d63d991 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 19:08:00 +0500 Subject: [PATCH 046/348] added royalty dust cases for tui assets tests --- src/tui/tui_assets_orders.py | 43 +++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 0c40bf0f1df..86950f9885c 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -68,36 +68,42 @@ def run_tokens_create(rpc): print("created token:", tokenid2) print("creating tokel NFT 1 with empty data...") - result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-00-1", str(0.00000001), "nft eval 00", '{}') + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-00-1", str(0.00000001), "nft tokel empty", '{}') assert(check_tx(result)) nft00id1 = rpc1.sendrawtransaction(result['hex']) print("created token:", nft00id1) print("creating tokel NFT 2 with arbitrary data...") - result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-00-2", str(0.00000001), "nft eval 00", '{"arbitrary":"010203"}') + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-00-2", str(0.00000001), "nft tokel arbitrary", '{"arbitrary":"010203"}') assert(check_tx(result)) nft00id2 = rpc1.sendrawtransaction(result['hex']) print("created token:", nft00id2) # tokel nft data F7 evalcode print("creating tokel NFT with royalty 0...") - result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-1", str(0.00000001), "nft eval=00 royalty=0", '{"royalty":0}') + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-1", str(0.00000001), "nft tokel royalty=0", '{"royalty":0}') assert(check_tx(result)) nftf7id1 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id1) print("creating tokel NFT with royalty 99...") - result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-2", str(0.00000001), "nft eval=f7 roaylty=99", '{"royalty":99}') + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-2", str(0.00000001), "nft tokel royalty=99", '{"royalty":99}') assert(check_tx(result)) nftf7id2 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id2) print("creating tokel NFT with royalty 1 (to test dust)...") - result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-3", str(0.00000001), "nft eval=f7 roaylty=1", '{"royalty":1}') + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-3", str(0.00000001), "nft tokel royalty=1", '{"royalty":1}') assert(check_tx(result)) nftf7id3 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id3) + print("creating tokel NFT with royalty 500 (to test dust)...") + result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-4", str(0.00000001), "nft tokel royalty=500", '{"royalty":500}') + assert(check_tx(result)) + nftf7id4 = rpc1.sendrawtransaction(result['hex']) + print("created token:", nftf7id4) + # first try transfer tokens to a pk and back, then run assets tests print("starting transfer tests for tokenid version=" + v + "...") run_transfers(rpc1, rpc2, v, tokenid1, tokenid2, 10) @@ -110,15 +116,18 @@ def run_tokens_create(rpc): # assets cc tests: print("starting assets tests for tokenid1 version=" + v + "...") - run_assets_orders(rpc1, rpc2, v, tokenid1, 10, 8, False) + run_assets_orders(rpc1, rpc2, v, tokenid1, 10, 8, 0.0001, False) print("starting assets tests for nft00id1 version=" + v + "...") - run_assets_orders(rpc1, rpc2, v, nft00id1, 1, 1, True) + run_assets_orders(rpc1, rpc2, v, nft00id1, 1, 1, 0.0001, True) print("starting assets tests for nftf7id1 version=" + v + "...") - run_assets_orders(rpc1, rpc2, v, nftf7id1, 1, 1, True) + run_assets_orders(rpc1, rpc2, v, nftf7id1, 1, 1, 0.0001, True) print("starting assets tests for nftf7id2 version=" + v + "...") - run_assets_orders(rpc1, rpc2, v, nftf7id2, 1, 1, True) + run_assets_orders(rpc1, rpc2, v, nftf7id2, 1, 1, 0.0001, True) print("starting assets tests for nftf7id3 version=" + v + "...") - run_assets_orders(rpc1, rpc2, v, nftf7id3, 1, 1, True) + run_assets_orders(rpc1, rpc2, v, nftf7id3, 1, 1, 0.0001, True) + print("starting assets tests for nftf7id4 with unit price creating dust royalty and checking that round correct, version=" + v + "...") + run_assets_orders(rpc1, rpc2, v, nftf7id4, 1, 1, 0.0000_1001, True) + if v == "v2" : # MofN supported for tokens cc v2 only print("running MofN tests for tokens v2:") @@ -127,8 +136,7 @@ def run_tokens_create(rpc): print("starting MofN tests for nft00id1...") run_MofN_transfers(rpc1, rpc2, rpc3, nft00id1, 1) print("starting MofN tests for nftf7id1...") - run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) - + run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) print("token/assets tests finished okay") time.sleep(3) @@ -277,7 +285,6 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): print("creating tokenv2transfer tokenid1 tx spending 1of2 back to pk2...", json.dumps(param)) txid = call_token_rpc_send_tx(rpc2, "tokenv2transfer", '', json.dumps(param)) assert(check_txid(txid)) - else : # if nft send 1 back to pk1 for the next test param["destpubkeys"] = [ pubkey1 ] @@ -447,13 +454,13 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): print("tx 3of3 back sent") -def run_assets_orders(rpc1, rpc2, v, tokenid, total, units, isnft): +def run_assets_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, isnft): retries = 24 delay = 10 askunits = bidunits = units - unitprice = 0.0001 + # unitprice = 0.0001 # wait for mempool to empty to get correct balance: retries = 24 @@ -539,9 +546,9 @@ def run_assets_orders(rpc1, rpc2, v, tokenid, total, units, isnft): print("creating token"+v+"bid tx #4...") bidid4 = call_token_rpc_send_tx(rpc1, "token"+v+"bid", '', str(1), tokenid, str(0.0000_0600)) # price more than dust - # fill bid to self with dust - print("creating token"+v+"fillbid tx #4 (to create dust)...") - # enable his if dust is enabled on normals in the chain: + # fill bid to self with dust price + print("creating token"+v+"fillbid tx #4 (to check failure on dust unit price)...") + # enable this if dust is enabled on normals in the chain: # fillbidid4 = call_token_rpc_send_tx(rpc1, "token"+v+"fillbid", '', tokenid, bidid4, str(1), str(0.0000_005)) # fill with dust price (<=500sat) # if dust not enabled we should get error: fillbidid4 = call_token_rpc(rpc1, "token"+v+"fillbid", '', tokenid, bidid4, str(1), str(0.0000_005)) # fill with dust price (<=500sat) From d04134ff6c462505a4e0a6f6f7dc928ea36b1645 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 21:38:49 +0500 Subject: [PATCH 047/348] added begin/end height to tokenv2list rpc refactoring: SetCCtxid with indexOutputs param renamed to SetAddressIndexOutputs --- src/cc/CCinclude.h | 8 ++-- src/cc/CCtokens.cpp | 57 +++++++++++++++++++---------- src/cc/CCtokens.h | 2 +- src/cc/CCtx.cpp | 75 +++++++++++++++++++------------------- src/cc/CCutils.cpp | 21 ++++++----- src/cc/cclib.cpp | 6 +-- src/cc/faucet.cpp | 6 +-- src/cc/heir.cpp | 2 +- src/cc/payments.cpp | 2 +- src/cc/prices.cpp | 6 +-- src/komodo_nSPV_defs.h | 6 +-- src/komodo_nSPV_fullnode.h | 4 +- src/komodo_nSPV_wallet.h | 33 ++++++++++------- src/rpc/tokensrpc.cpp | 13 +++++-- 14 files changed, 137 insertions(+), 104 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 594f2a42e0f..f2c87b654be 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -946,13 +946,15 @@ void SetCCunspentsCCIndex(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId); -/// SetCCtxids returns a vector of all outputs on an address +/// SetAddressIndexOutputs searches address index for a vector of outputs on an address /// @param[out] addressIndex vector of pairs of address index key and amount /// @param coinaddr address where the unspent outputs are searched /// @param CCflag if true the function searches for cc outputs, otherwise for normal outputs -void SetCCtxids(std::vector > &addressIndex,char *coinaddr,bool CCflag = true); +/// @param beginHeight if beginHeight and endHeight positive the function searches for cc outputs starting from this height +/// @param endHeight if beginHeight and endHeight positive the function searches for cc outputs till this height +void SetAddressIndexOutputs(std::vector>& addressIndex, char* coinaddr, bool ccflag, int32_t beginHeight = 0, int32_t endHeight = 0); -/// overloaded SetCCtxids returns a vector of filtered txids which have outputs on an address +/// SetCCtxids searches address index for a vector of filtered txids which have outputs on an address /// @param[out] txids returned vector of txids /// @param coinaddr address where the unspent outputs are searched /// @param ccflag if true the function searches for cc outputs, otherwise for normal outputs diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index fbec6164292..4cf660b7042 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -908,9 +908,10 @@ UniValue TokenList() return CreateTokenLocal(txfee, tokensupply, name, description, nonfungibleData); }*/ -UniValue TokenV2List() +UniValue TokenV2List(int32_t beginHeight, int32_t endHeight) { UniValue result(UniValue::VARR); + const bool CC_OUTPUTS_TRUE = true; struct CCcontract_info *cp, C; cp = CCinit(&C, EVAL_TOKENSV2); @@ -928,28 +929,44 @@ UniValue TokenV2List() } }; - if (fUnspentCCIndex) - { - std::vector > unspentOutputs; - - SetCCunspentsCCIndex(unspentOutputs, cp->unspendableCCaddr, zeroid); // find by burnable validated cc addr marker - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "unspentOutputs.size()=" << unspentOutputs.size() << std::endl); - for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { - addTokenId(it->first.creationid, it->second.opreturn); - } + if (beginHeight > 0) { + if (endHeight <= 0) + endHeight = chainActive.Height(); + std::vector> addressIndexOutputs; + SetAddressIndexOutputs(addressIndexOutputs, cp->unspendableCCaddr, CC_OUTPUTS_TRUE, beginHeight, endHeight); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetAddressIndexOutputs addressIndexOutputs.size()=" << addressIndexOutputs.size() << std::endl); + for (const auto it : addressIndexOutputs) { + CTransaction creationtx; + uint256 hashBlock; + if (!it.first.spending && + myGetTransaction(it.first.txhash, creationtx, hashBlock) && creationtx.vout.size() > 0) + addTokenId(it.first.txhash, creationtx.vout.back().scriptPubKey); + } } else { - bool CC_INPUTS_TRUE = true; - std::vector > unspentOutputs; - - SetCCunspents(unspentOutputs, cp->unspendableCCaddr, CC_INPUTS_TRUE); - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "unspentOutputs.size()=" << unspentOutputs.size() << std::endl); - for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { - CTransaction creationtx; - uint256 hashBlock; - if (myGetTransaction(it->first.txhash, creationtx, hashBlock) && creationtx.vout.size() > 0) - addTokenId(it->first.txhash, creationtx.vout.back().scriptPubKey); + if (fUnspentCCIndex) + { + std::vector > unspentOutputs; + + SetCCunspentsCCIndex(unspentOutputs, cp->unspendableCCaddr, zeroid); // find by burnable validated cc addr marker + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetCCunspentsCCIndex unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + for (const auto &it : unspentOutputs) { + addTokenId(it.first.creationid, it.second.opreturn); + } + } + else + { + std::vector > unspentOutputs; + + SetCCunspents(unspentOutputs, cp->unspendableCCaddr, CC_OUTPUTS_TRUE); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + for (const auto it : unspentOutputs) { + CTransaction creationtx; + uint256 hashBlock; + if (myGetTransaction(it.first.txhash, creationtx, hashBlock) && creationtx.vout.size() > 0) + addTokenId(it.first.txhash, creationtx.vout.back().scriptPubKey); + } } } diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index ca34b8a3215..63b92c2e313 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -273,7 +273,7 @@ CTxOut MakeTokensCC1of2voutMixed(uint8_t evalcode, uint8_t evalcode2, CAmount nV CTxOut MakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, uint8_t M, const std::vector & pks, vscript_t* pvData = nullptr); UniValue TokenList(); -UniValue TokenV2List(); +UniValue TokenV2List(int32_t beginHeight, int32_t endHeight); inline bool IsTokenCreateFuncid(uint8_t funcid) { return funcid == 'c'; } inline bool IsTokenTransferFuncid(uint8_t funcid) { return funcid == 't'; } diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 3e3ea8bf30e..7086cbde761 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -841,6 +841,9 @@ void SetCCunspentsCCIndex(std::vector > searchKeys; + + if (!coinaddr) + return; CBitcoinAddress address(coinaddr); if (address.GetIndexKey(hashBytes, type, true) == 0) @@ -855,66 +858,62 @@ void SetCCunspentsCCIndex(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId) { + if (!coinaddr) + return; CBitcoinAddress address( coinaddr ); uint160 hashBytes; int type; if (address.GetIndexKey(hashBytes, type, true)) { - mempool.getUnspentCCIndex({ std::make_pair(hashBytes, creationId) }, unspentOutputs); } } -void SetCCtxids(std::vector > &addressIndex,char *coinaddr,bool ccflag) +void SetAddressIndexOutputs(std::vector>& addressIndex, char* coinaddr, bool ccflag, int32_t beginHeight, int32_t endHeight) { - int32_t type=0,i,n; char *ptr; std::string addrstr; uint160 hashBytes; std::vector > addresses; - if ( KOMODO_NSPV_SUPERLITE ) - { - NSPV_CCtxids(addressIndex,coinaddr,ccflag); + int32_t type = 0; + uint160 hashBytes; + std::vector> addresses; + if (KOMODO_NSPV_SUPERLITE) { + NSPV_CCindexOutputs(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 ) + if (!coinaddr) 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 ) + CBitcoinAddress address(coinaddr); + 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, beginHeight, endHeight) == 0) return; } } -void SetCCtxids(std::vector &txids,char *coinaddr,bool ccflag, uint8_t evalcode, int64_t amount, uint256 filtertxid, uint8_t func) +void SetCCtxids(std::vector& txids, char* coinaddr, bool ccflag, uint8_t evalcode, int64_t amount, 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 ( KOMODO_NSPV_SUPERLITE ) - { - NSPV_CCtxids(txids,coinaddr,ccflag,evalcode,filtertxid,func); + int32_t type = 0; + uint160 hashBytes; + std::vector> addresses; + std::vector> addressIndex; + if (KOMODO_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 ) + if (!coinaddr) 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 ) + + CBitcoinAddress address(coinaddr); + 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 ((amount==0 && it1->second>=0) || (amount>0 && it1->second==amount)) txids.push_back(it1->first.txhash); + for (std::vector>::const_iterator it1 = addressIndex.begin(); it1 != addressIndex.end(); it1++) { + if ((amount == 0 && it1->second >= 0) || (amount > 0 && it1->second == amount)) + txids.push_back(it1->first.txhash); } - } + } } int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout,int32_t CCflag) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 47a4f194ce5..f85514932bd 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -788,17 +788,20 @@ int32_t myGet_mempool_txs(std::vector &txs,uint8_t evalcode,uint8_ return(i); } -int32_t CCCointxidExists(char const *logcategory,uint256 txid, uint256 cointxid) +int32_t CCCointxidExists(char const* logcategory, uint256 txid, uint256 cointxid) { - char txidaddr[64]; std::string coin; int32_t numvouts; uint256 hashBlock; - std::vector > addressIndex; - CCtxidaddr_tweak(txidaddr,cointxid); - SetCCtxids(addressIndex,txidaddr,false); - for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) - { - return(-1); + char txidaddr[64]; + std::string coin; + int32_t numvouts; + uint256 hashBlock; + + std::vector> addressIndex; + CCtxidaddr_tweak(txidaddr, cointxid); + SetAddressIndexOutputs(addressIndex, txidaddr, false); + for (std::vector>::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++) { + return (-1); } - return(myIs_coinaddr_inmempoolvout(logcategory,txid,txidaddr)); + return (myIs_coinaddr_inmempoolvout(logcategory, txid, txidaddr)); } bool CompareHexVouts(std::string hex1, std::string hex2) diff --git a/src/cc/cclib.cpp b/src/cc/cclib.cpp index f9a4ad6e7d3..39faa2ba664 100644 --- a/src/cc/cclib.cpp +++ b/src/cc/cclib.cpp @@ -426,7 +426,7 @@ bool CClibExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - std::vector > txids; + std::vector > addressIndexOutputs; if ( cp->evalcode != EVAL_FAUCET2 ) { #ifdef BUILD_ROGUE @@ -482,8 +482,8 @@ bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C else if ( (hash[0] & 0xff) != 0 || (hash[31] & 0xff) != 0 ) return eval->Invalid("invalid faucetget txid"); Getscriptaddress(destaddr,tx.vout[i].scriptPubKey); - SetCCtxids(txids,destaddr,tx.vout[i].scriptPubKey.IsPayToCryptoCondition()); - for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + SetAddressIndexOutputs(addressIndexOutputs,destaddr,tx.vout[i].scriptPubKey.IsPayToCryptoCondition()); + for (std::vector >::const_iterator it=addressIndexOutputs.begin(); it!=addressIndexOutputs.end(); it++) { //int height = it->first.blockHeight; if ( CCduration(numblocks,it->first.txhash) > 0 && numblocks > 3 ) diff --git a/src/cc/faucet.cpp b/src/cc/faucet.cpp index 2c0a08451f1..e8c28bb5029 100644 --- a/src/cc/faucet.cpp +++ b/src/cc/faucet.cpp @@ -81,7 +81,7 @@ bool FaucetExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - std::vector > txids; + std::vector > addressIndexOutputs; numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; @@ -119,8 +119,8 @@ bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx else if ( (hash[0] & 0xff) != 0 || (hash[31] & 0xff) != 0 ) return eval->Invalid("invalid faucetget txid"); Getscriptaddress(destaddr,tx.vout[i].scriptPubKey); - SetCCtxids(txids,destaddr,tx.vout[i].scriptPubKey.IsPayToCryptoCondition()); - for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + SetAddressIndexOutputs(addressIndexOutputs,destaddr,tx.vout[i].scriptPubKey.IsPayToCryptoCondition()); + for (std::vector >::const_iterator it=addressIndexOutputs.begin(); it!=addressIndexOutputs.end(); it++) { //int height = it->first.blockHeight; if ( CCduration(numblocks,it->first.txhash) > 0 && numblocks > 3 ) diff --git a/src/cc/heir.cpp b/src/cc/heir.cpp index 406f9f424c3..db565af5c97 100644 --- a/src/cc/heir.cpp +++ b/src/cc/heir.cpp @@ -547,7 +547,7 @@ template int64_t LifetimeHeirContractFunds(struct CCcontract_info Helper::GetCoinsOrTokensCCaddress1of2(coinaddr, ownerPubkey, heirPubkey); // get the address of cryptocondition '1 of 2 pubkeys' std::vector> addressIndexes; - SetCCtxids(addressIndexes, coinaddr,true); + SetAddressIndexOutputs(addressIndexes, coinaddr, true); int64_t total = 0; for (std::vector>::const_iterator it = addressIndexes.begin(); it != addressIndexes.end(); it++) { diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 0c6edb284dc..d042edf0e04 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -1545,7 +1545,7 @@ UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr) int32_t top=0,bottom=0,minimum=10000; std::vector> excludeScriptPubKeys; int8_t fixedAmount = 0; Paymentspk = GetUnspendable(cp,0); GetCCaddress1of2(cp,markeraddr,Paymentspk,Paymentspk); - SetCCtxids(addressIndex,markeraddr,true); + SetAddressIndexOutputs(addressIndex,markeraddr,true); for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { txid = it->first.txhash; diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 61c7d785573..fc9c5294dca 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -2193,7 +2193,7 @@ UniValue PricesList(uint32_t filter, CPubKey mypk) }; - SetCCtxids(addressIndex, cp->normaladdr, false); // old normal marker + SetAddressIndexOutputs(addressIndex, cp->normaladdr, false); // old normal marker for (std::vector >::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++) { if( it->first.index == NVOUT_NORMALMARKER ) @@ -2201,7 +2201,7 @@ UniValue PricesList(uint32_t filter, CPubKey mypk) } /* for future when switch to cc marker only - SetCCtxids(addressIndexCC, cp->unspendableCCaddr, true); // cc marker + SetAddressIndexOutputs(addressIndexCC, cp->unspendableCCaddr, true); // cc marker for (std::vector >::const_iterator it = addressIndexCC.begin(); it != addressIndexCC.end(); it++) { priceslist(it, 1); @@ -2333,7 +2333,7 @@ void prices_getorderbook(std::map > & bookmatc cp = CCinit(&C, EVAL_PRICES); // add all bets: - SetCCtxids(addressIndex, cp->normaladdr, false); // old normal marker + SetAddressIndexOutputs(addressIndex, cp->normaladdr, false); // old normal marker for (std::vector >::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++) { if (it->first.index == NVOUT_NORMALMARKER) diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 0ddaa3cb498..18a10338d4f 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -190,8 +190,8 @@ struct NSPV_remoterpcresp }; -void NSPV_CCunspents(std::vector > &unspentOutputs,char *coinaddr,bool ccflag); -void NSPV_CCtxids(std::vector > &txids,char *coinaddr,bool ccflag); -void NSPV_CCtxids(std::vector &txids,char *coinaddr,bool ccflag, uint8_t evalcode,uint256 filtertxid, uint8_t func); +void NSPV_CCunspents(std::vector>& unspentOutputs, char* coinaddr, bool ccflag); +void NSPV_CCindexOutputs(std::vector>& indexOutputs, char* coinaddr, bool ccflag); +void NSPV_CCtxids(std::vector& txids, char* coinaddr, bool ccflag, uint8_t evalcode, uint256 filtertxid, uint8_t func); #endif // KOMODO_NSPV_DEFSH diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 568bfff90ac..bd306331f20 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -450,7 +450,7 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC { int32_t maxlen,txheight,ind=0,n = 0,len = 0; CTransaction tx; uint256 hashBlock; std::vector > txids; - SetCCtxids(txids,coinaddr,isCC); + SetAddressIndexOutputs(txids,coinaddr,isCC); ptr->nodeheight = chainActive.LastTip()->GetHeight(); maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; maxlen /= sizeof(*ptr->txids); @@ -501,7 +501,7 @@ int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector>16; uint8_t eval=(vout>>8)&0xFF, func=vout&0xFF; CTransaction tx; - SetCCtxids(tmp_txids,coinaddr,isCC); + SetAddressIndexOutputs(tmp_txids,coinaddr,isCC); if ( skipcount < 0 ) skipcount = 0; if ( skipcount >= tmp_txids.size() ) skipcount = tmp_txids.size()-1; diff --git a/src/komodo_nSPV_wallet.h b/src/komodo_nSPV_wallet.h index f745629b747..658d782c976 100644 --- a/src/komodo_nSPV_wallet.h +++ b/src/komodo_nSPV_wallet.h @@ -493,42 +493,47 @@ void NSPV_utxos2CCunspents(struct NSPV_utxosresp *ptr,std::vector > &txids) +void NSPV_resp2indexOutputs(struct NSPV_txidsresp* ptr, std::vector>& indexOutputs) { - CAddressIndexKey key; int64_t value; int32_t i,type; uint160 hashBytes; std::string addrstr(ptr->coinaddr); - if ( ptr->txids != NULL && ptr->numtxids > 0 ) - { + if (!ptr->coinaddr) + return; + + CAddressIndexKey key; + int64_t value; + int32_t i, type; + uint160 hashBytes; + std::string addrstr(ptr->coinaddr); + + if (ptr->txids != NULL && ptr->numtxids > 0) { CBitcoinAddress address(addrstr); - if ( address.GetIndexKey(hashBytes, type, ptr->CCflag) == 0 ) - { - fprintf(stderr,"couldnt get indexkey\n"); + if (address.GetIndexKey(hashBytes, type, ptr->CCflag) == 0) { + fprintf(stderr, "couldnt get indexkey\n"); return; } - for (i = 0; i < ptr->numtxids; i ++) - { + for (i = 0; i < ptr->numtxids; i++) { key.type = type; key.hashBytes = hashBytes; key.txhash = ptr->txids[i].txid; key.index = ptr->txids[i].vout; key.blockHeight = ptr->txids[i].height; value = ptr->txids[i].satoshis; - txids.push_back(std::make_pair(key, value)); + indexOutputs.push_back(std::make_pair(key, value)); } } } -void NSPV_CCunspents(std::vector > &outputs,char *coinaddr,bool ccflag) +void NSPV_CCunspents(std::vector > &outputs, char *coinaddr, bool ccflag) { int32_t filter = 0; NSPV_addressutxos(coinaddr,ccflag,0,filter); NSPV_utxos2CCunspents(&NSPV_utxosresult,outputs); } -void NSPV_CCtxids(std::vector > &txids,char *coinaddr,bool ccflag) +void NSPV_CCindexOutputs(std::vector>& indexOutputs, char* coinaddr, bool ccflag) { int32_t filter = 0; - NSPV_addresstxids(coinaddr,ccflag,0,filter); - NSPV_txids2CCtxids(&NSPV_txidsresult,txids); + NSPV_addresstxids(coinaddr, ccflag, 0, filter); + NSPV_resp2indexOutputs(&NSPV_txidsresult, indexOutputs); } void NSPV_CCtxids(std::vector &txids,char *coinaddr,bool ccflag, uint8_t evalcode,uint256 filtertxid, uint8_t func) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 98cb94dcc6a..7430016b632 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -105,13 +105,20 @@ UniValue tokenlist(const UniValue& params, bool fHelp, const CPubKey& remotepk) UniValue tokenv2list(const UniValue& params, bool fHelp, const CPubKey& remotepk) { uint256 tokenid; - if (fHelp || params.size() > 0) - throw runtime_error("tokenv2list\n"); + if (fHelp || params.size() > 2) + throw runtime_error("tokenv2list [begin-height] [end-height]\n"); if (ensure_CCrequirements(EVAL_TOKENSV2) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - return TokenV2List();} + int32_t beginHeight = 0; + int32_t endHeight = 0; + if (params.size() > 0) + beginHeight = atoi(params[0].get_str().c_str()); + if (params.size() > 1) + endHeight = atoi(params[1].get_str().c_str()); + return TokenV2List(beginHeight, endHeight); +} template static UniValue tokeninfo(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) From 818c7b6f0acd76ad11d5259881fda2b96058de53 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 21:39:31 +0500 Subject: [PATCH 048/348] make cclib.so added to Makefile.am --- src/Makefile.am | 24 +++++++++++++++--------- src/cc/Makefile | 6 +++--- src/cc/Makefile_custom | 12 ++++++------ zcutil/build-mac-dtest.sh | 12 +++++++----- zcutil/build-mac.sh | 20 +++++++------------- zcutil/build-win-dtest.sh | 14 +++++++++----- zcutil/build-win.sh | 15 ++++++++++----- zcutil/build.sh | 15 ++++++--------- 8 files changed, 63 insertions(+), 55 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 6179524f7a0..e093bcdb73c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -66,6 +66,16 @@ if ENABLE_WALLET LIBBITCOIN_WALLET=libbitcoin_wallet.a endif +if TARGET_DARWIN +LIBDYNCUSTOMCONSENSUS = cc/libcc.dylib +endif +if TARGET_WINDOWS +LIBDYNCUSTOMCONSENSUS = cc/libcc.dll +endif +if TARGET_LINUX +LIBDYNCUSTOMCONSENSUS = cc/libcc.so +endif + $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " @@ -90,6 +100,9 @@ $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptoconditions/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " +$(LIBDYNCUSTOMCONSENSUS): $(wildcard *.h) $(wildcard cc/*.h) $(wildcard cryptoconditions/include/*) + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) -f Makefile_custom + # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: EXTRA_LIBRARIES += \ @@ -598,15 +611,7 @@ komodod_LDADD += \ $(LIBVERUS_PORTABLE_CRYPTO) \ $(LIBZCASH_LIBS) -if TARGET_DARWIN -komodod_LDADD += libcc.dylib $(LIBSECP256K1) -endif -if TARGET_WINDOWS -komodod_LDADD += libcc.dll $(LIBSECP256K1) -endif -if TARGET_LINUX -komodod_LDADD += libcc.so $(LIBSECP256K1) -endif +komodod_LDADD += $(LIBDYNCUSTOMCONSENSUS) $(LIBSECP256K1) if ENABLE_PROTON komodod_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) @@ -772,6 +777,7 @@ clean-local: rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno -rm -f config.h rm -f cc/customcc.so + -$(MAKE) -C cc clean .rc.o: @test -f $(WINDRES) diff --git a/src/cc/Makefile b/src/cc/Makefile index 3e988f27935..2bcd44dc9ff 100644 --- a/src/cc/Makefile +++ b/src/cc/Makefile @@ -10,9 +10,9 @@ RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program $(info $(OS)) OS := $(shell uname -s) $(info $(OS)) -TARGET = ../libcc.so -TARGET_DARWIN = ../libcc.dylib -TARGET_WIN = ../libcc.dll +TARGET = libcc.so +TARGET_DARWIN = libcc.dylib +TARGET_WIN = libcc.dll SOURCES = cclib.cpp #HEADERS = $(shell echo ../cryptoconditions/include/*.h) diff --git a/src/cc/Makefile_custom b/src/cc/Makefile_custom index 4391a106039..d43fa8fe356 100755 --- a/src/cc/Makefile_custom +++ b/src/cc/Makefile_custom @@ -10,9 +10,9 @@ RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program $(info $(OS)) OS := $(shell uname -s) $(info $(OS)) -TARGET = customcc.so -TARGET_DARWIN = customcc.dylib -TARGET_WIN = customcc.dll +TARGET = libcc.so +TARGET_DARWIN = libcc.dylib +TARGET_WIN = libcc.dll SOURCES = cclib.cpp #HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ HEADERS = CCinclude.h CCtokens.h @@ -23,16 +23,16 @@ $(TARGET): $(SOURCES) $(HEADERS) $(info Building cclib to src/) ifeq ($(OS),Darwin) $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) -c $(SOURCES) - cp $(TARGET_DARWIN) ../libcc.dylib + # cp $(TARGET_DARWIN) ../libcc.dylib else ifeq ($(HOST),x86_64-w64-mingw32) $(info WINDOWS) $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) -c $(SOURCES) - cp $(TARGET_WIN) ../libcc.dll + # cp $(TARGET_WIN) ../libcc.dll #else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host else $(info LINUX) $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES) - cp $(TARGET) ../libcc.so + # cp $(TARGET) ../libcc.so endif clean: diff --git a/zcutil/build-mac-dtest.sh b/zcutil/build-mac-dtest.sh index 8104c720009..d73bbe2d2ce 100755 --- a/zcutil/build-mac-dtest.sh +++ b/zcutil/build-mac-dtest.sh @@ -40,15 +40,17 @@ fi TRIPLET=`./depends/config.guess` PREFIX="$(pwd)/depends/$TRIPLET" +# make dependences make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 #BUILD CCLIB +# WD=$PWD +# cd src/cc +# echo $PWD +# ./makecustom +# cd $WD +# cclib building now added to src/Makefile.am -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64 -DTESTMODE" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index dd5b578e50a..5f7c1d5f7be 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -48,19 +48,13 @@ PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 #BUILD CCLIB - -WD=$PWD - -cd src/cc -echo $PWD -echo Making cclib... -./makecustom - -cd ./priceslibs -echo Making prices feeds custom libs... -make all - -cd $WD +# WD=$PWD +# cd src/cc +# echo $PWD +# echo Making cclib... +# ./makecustom +# cd $WD +# cclib building now added to src/Makefile.am ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ diff --git a/zcutil/build-win-dtest.sh b/zcutil/build-win-dtest.sh index 00a64de5bf7..2cf85e7bcee 100755 --- a/zcutil/build-win-dtest.sh +++ b/zcutil/build-win-dtest.sh @@ -9,13 +9,17 @@ set -eu -o pipefail set -x cd "$(dirname "$(readlink -f "$0")")/.." +# make dependences cd depends/ && make HOST=$HOST V=1 NO_QT=1 cd ../ -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD + +#BUILD CCLIB +# WD=$PWD +# cd src/cc +# echo $PWD +# ./makecustom +# cd $WD +# cclib building now added to src/Makefile.am ./autogen.sh CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" CPPFLAGS=-DTESTMODE ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index e8c0465d98b..a445ef873b7 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -9,13 +9,18 @@ set -eu -o pipefail set -x cd "$(dirname "$(readlink -f "$0")")/.." +# make dependences cd depends/ && make HOST=$HOST V=1 NO_QT=1 cd ../ -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD + +#BUILD CCLIB +# WD=$PWD +# cd src/cc +# echo $PWD +# ./makecustom +# cd $WD +# cclib building now added to src/Makefile.am + ./autogen.sh CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared diff --git a/zcutil/build.sh b/zcutil/build.sh index 6f625b185aa..9033ac32fbc 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -102,14 +102,11 @@ HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' #BUILD CCLIB - -WD=$PWD - -cd src/cc -echo $PWD -./makecustom - - -cd $WD +#WD=$PWD +#cd src/cc +#echo $PWD +#./makecustom +#cd $WD +# cclib building now added to src/Makefile.am "$MAKE" "$@" V=1 From 3cda5d886bc3e0492434894f651274646957b637 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 22:23:06 +0500 Subject: [PATCH 049/348] removed extra func defs --- src/cc/CCutils.cpp | 4 ++-- src/wallet/rpcwallet.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index f85514932bd..32a4804142f 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -20,6 +20,7 @@ #include "CCinclude.h" #include "CCtokens.h" #include "komodo_structs.h" +#include "komodo_defs.h" #include "key_io.h" @@ -619,7 +620,6 @@ bool Myprivkey(uint8_t myprivkey[]) static int32_t onetimeflag; static uint8_t sessionpriv[32]; if ( onetimeflag == 0 ) { - void OS_randombytes(unsigned char *x,long xlen); OS_randombytes(sessionpriv,32); fprintf(stderr,"privkey for pubkey not found -> generate session specific privkey\n"); onetimeflag = 1; @@ -794,7 +794,7 @@ int32_t CCCointxidExists(char const* logcategory, uint256 txid, uint256 cointxid std::string coin; int32_t numvouts; uint256 hashBlock; - + std::vector> addressIndex; CCtxidaddr_tweak(txidaddr, cointxid); SetAddressIndexOutputs(addressIndex, txidaddr, false); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 15e64fccc23..fa5dce4eb89 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -191,7 +191,7 @@ char *komodo_chainname() return(ASSETCHAINS_SYMBOL[0] == 0 ? (char *)"KMD" : ASSETCHAINS_SYMBOL); } -void OS_randombytes(unsigned char *x,long xlen); +// void OS_randombytes(unsigned char *x,long xlen); UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) { From e652c5dedb3404ca38705bfb06d4f9701453d20b Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 22:23:41 +0500 Subject: [PATCH 050/348] added clean libcc.so; removed unused makefile --- src/Makefile.am | 3 ++- src/cc/Makefile | 34 ---------------------------------- 2 files changed, 2 insertions(+), 35 deletions(-) delete mode 100644 src/cc/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index e093bcdb73c..3451a6e09fd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -776,7 +776,8 @@ clean-local: -$(MAKE) -C cryptoconditions clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno -rm -f config.h - rm -f cc/customcc.so + -rm -f cc/customcc.so cc/customcc.dll cc/customcc.dylib # clean now unused file + -rm -f libcc.so libcc.dll libcc.dylib # clean now unused file -$(MAKE) -C cc clean .rc.o: diff --git a/src/cc/Makefile b/src/cc/Makefile deleted file mode 100644 index 2bcd44dc9ff..00000000000 --- a/src/cc/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -SHELL = /bin/sh -CC = gcc -CC_DARWIN = g++-6 -CC_WIN = x86_64-w64-mingw32-gcc-posix -CFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup -dynamiclib -CFLAGS = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -CFLAGS_WIN = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -DEBUGFLAGS = -O0 -D _DEBUG -RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program -$(info $(OS)) -OS := $(shell uname -s) -$(info $(OS)) -TARGET = libcc.so -TARGET_DARWIN = libcc.dylib -TARGET_WIN = libcc.dll -SOURCES = cclib.cpp -#HEADERS = $(shell echo ../cryptoconditions/include/*.h) - -all: $(TARGET) - -$(TARGET): $(SOURCES) - $(info Building cclib to src/) -ifeq ($(OS),Darwin) - $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) $(SOURCES) -else ifeq ($(OS),Linux) - $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(SOURCES) -#else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host -else - $(info WINDOWS) - $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) $(SOURCES) -endif - -clean: - rm -rf $(TARGET) From 6a40d03544e4438be62752dce15595ce57343018 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 22:30:33 +0500 Subject: [PATCH 051/348] fixed win OS_randombytes def --- src/komodo_defs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 71c9c264016..8db4492586e 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -532,8 +532,8 @@ struct komodo_staking *komodo_addutxo(struct komodo_staking *array, int32_t *num void komodo_createminerstransactions(); uint32_t komodo_segid32(char *coinaddr); -#ifndef _WIN32 -void OS_randombytes(unsigned char *x, long xlen); -#endif +// #ifndef _WIN32 +void OS_randombytes(unsigned char *x, long xlen); // this func impl exists for win too +// #endif #endif From a98adb08d07dfb9754c635a9427d0812b2b2d471 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 22:55:38 +0500 Subject: [PATCH 052/348] fix tokel data init for mingw compile --- src/cc/CCTokelData.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index 938e9c30297..2c8236399c6 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -65,10 +65,10 @@ static void tklWriteVuint8(CDataStream &ss, const UniValue &val) typedef std::map tklPropDesc_map; static const tklPropDesc_map tklPropDesc = { - { TKLPROP_ID, { TKLTYP_INT64, "id", &tklReadInt64, &tklWriteInt64 }}, - { TKLPROP_URL, { TKLTYP_VUINT8, "url", &tklReadString, &tklWriteString }}, - { TKLPROP_ROYALTY, { TKLTYP_INT64, "royalty", &tklReadInt64, &tklWriteInt64 }}, - { TKLPROP_ARBITRARY, { TKLTYP_VUINT8, "arbitrary", &tklReadVuint8, &tklWriteVuint8 }} + { TKLPROP_ID, std::make_tuple(TKLTYP_INT64, std::string("id"), &tklReadInt64, &tklWriteInt64) }, + { TKLPROP_URL, std::make_tuple(TKLTYP_VUINT8, std::string("url"), &tklReadString, &tklWriteString) }, + { TKLPROP_ROYALTY, std::make_tuple(TKLTYP_INT64, std::string("royalty"), &tklReadInt64, &tklWriteInt64) }, + { TKLPROP_ARBITRARY, std::make_tuple(TKLTYP_VUINT8, std::string("arbitrary"), &tklReadVuint8, &tklWriteVuint8) } }; /*typedef struct { From a03b8210eda85def0049772f0a2e4f9e0a1e9b42 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 23:49:29 +0500 Subject: [PATCH 053/348] fixed HOST env for libcc makefile for mingw; changed libcc ext to default --- src/Makefile.am | 12 ++---------- src/cc/Makefile_custom | 22 ++++++++++------------ 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 3451a6e09fd..9272344d530 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -66,15 +66,7 @@ if ENABLE_WALLET LIBBITCOIN_WALLET=libbitcoin_wallet.a endif -if TARGET_DARWIN -LIBDYNCUSTOMCONSENSUS = cc/libcc.dylib -endif -if TARGET_WINDOWS -LIBDYNCUSTOMCONSENSUS = cc/libcc.dll -endif -if TARGET_LINUX -LIBDYNCUSTOMCONSENSUS = cc/libcc.so -endif +LIBDYNCUSTOMCONSENSUS = cc/libcc.a $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " @@ -101,7 +93,7 @@ $(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptocond $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " $(LIBDYNCUSTOMCONSENSUS): $(wildcard *.h) $(wildcard cc/*.h) $(wildcard cryptoconditions/include/*) - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) -f Makefile_custom + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) -f Makefile_custom HOST=$(host) # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: diff --git a/src/cc/Makefile_custom b/src/cc/Makefile_custom index d43fa8fe356..cab58c49577 100755 --- a/src/cc/Makefile_custom +++ b/src/cc/Makefile_custom @@ -1,8 +1,8 @@ SHELL = /bin/sh -CC = gcc +CC = g++-8 CC_DARWIN = g++-8 -CC_WIN = x86_64-w64-mingw32-gcc-posix -CFLAGS_DARWIN = -DBUILD_CUSTOMCC -std=c++11 -arch x86_64 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib +CC_WIN = x86_64-w64-mingw32-g++-posix +CFLAGS_DARWIN = -DBUILD_CUSTOMCC -std=c++11 -arch x86_64 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib CFLAGS = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared CFLAGS_WIN = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/x86_64-w64-mingw32/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared DEBUGFLAGS = -O0 -D _DEBUG @@ -10,29 +10,27 @@ RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program $(info $(OS)) OS := $(shell uname -s) $(info $(OS)) -TARGET = libcc.so -TARGET_DARWIN = libcc.dylib -TARGET_WIN = libcc.dll +$(info $(HOST)) +$(info $(host)) +$(info $(OS)) +TARGET = libcc.a SOURCES = cclib.cpp #HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -HEADERS = CCinclude.h CCtokens.h +HEADERS = *.h all: $(TARGET) $(TARGET): $(SOURCES) $(HEADERS) $(info Building cclib to src/) ifeq ($(OS),Darwin) - $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) -c $(SOURCES) - # cp $(TARGET_DARWIN) ../libcc.dylib + $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES) else ifeq ($(HOST),x86_64-w64-mingw32) $(info WINDOWS) - $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) -c $(SOURCES) - # cp $(TARGET_WIN) ../libcc.dll + $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES) #else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host else $(info LINUX) $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES) - # cp $(TARGET) ../libcc.so endif clean: From 23ac5c43c62bf1902085fe325c8ca594c8362847 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 5 Jul 2021 23:54:04 +0500 Subject: [PATCH 054/348] fixed clean cmd for libcc.a --- src/Makefile.am | 2 +- src/cc/Makefile_custom | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 9272344d530..de18ebf2ebe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -770,7 +770,7 @@ clean-local: -rm -f config.h -rm -f cc/customcc.so cc/customcc.dll cc/customcc.dylib # clean now unused file -rm -f libcc.so libcc.dll libcc.dylib # clean now unused file - -$(MAKE) -C cc clean + -$(MAKE) -C cc -f Makefile_custom clean .rc.o: @test -f $(WINDRES) diff --git a/src/cc/Makefile_custom b/src/cc/Makefile_custom index cab58c49577..ee98ca1b440 100755 --- a/src/cc/Makefile_custom +++ b/src/cc/Makefile_custom @@ -11,8 +11,6 @@ $(info $(OS)) OS := $(shell uname -s) $(info $(OS)) $(info $(HOST)) -$(info $(host)) -$(info $(OS)) TARGET = libcc.a SOURCES = cclib.cpp #HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ From 37ce2b72d13dedc1321d7da393c565edca603269 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 6 Jul 2021 00:06:38 +0500 Subject: [PATCH 055/348] relaxing gcc ver for libcc --- src/cc/Makefile_custom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc/Makefile_custom b/src/cc/Makefile_custom index ee98ca1b440..bfc1b336175 100755 --- a/src/cc/Makefile_custom +++ b/src/cc/Makefile_custom @@ -1,5 +1,5 @@ SHELL = /bin/sh -CC = g++-8 +CC = g++ CC_DARWIN = g++-8 CC_WIN = x86_64-w64-mingw32-g++-posix CFLAGS_DARWIN = -DBUILD_CUSTOMCC -std=c++11 -arch x86_64 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib From d62499b59b7db567906f29fbe928f2fa0c6916b1 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 6 Jul 2021 00:28:21 +0500 Subject: [PATCH 056/348] added sh to buil prices lib on win --- src/cc/priceslibs/Makefile | 2 +- src/cc/priceslibs/build-win.sh | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/cc/priceslibs/build-win.sh diff --git a/src/cc/priceslibs/Makefile b/src/cc/priceslibs/Makefile index 872a4a29337..9c0baa0a7be 100644 --- a/src/cc/priceslibs/Makefile +++ b/src/cc/priceslibs/Makefile @@ -16,4 +16,4 @@ libnistrandomparser.dll: NistRandomParser.cpp cjsonpointer.cpp cjsonpointer.h .. $(CXX) $(CXXFLAGS_WIN) -shared NistRandomParser.cpp cjsonpointer.cpp ../../cJSON.c -o $@ -std=c++11 -static-libgcc -static-libstdc++ clean: - rm libpricessampleparser.* libnistrandomparser.*. \ No newline at end of file + -rm libpricessampleparser.* libnistrandomparser.*. \ No newline at end of file diff --git a/src/cc/priceslibs/build-win.sh b/src/cc/priceslibs/build-win.sh new file mode 100644 index 00000000000..957212e8dfe --- /dev/null +++ b/src/cc/priceslibs/build-win.sh @@ -0,0 +1,11 @@ +#!/bin/bash +export HOST=x86_64-w64-mingw32 +CXX=x86_64-w64-mingw32-g++-posix +CC=x86_64-w64-mingw32-gcc-posix +PREFIX="$(pwd)/depends/$HOST" + +set -eu -o pipefail +set -x + +echo Making prices feeds custom libs... +CC="${CC} -g " CXX="${CXX} -g " make dll \ No newline at end of file From fb3b0c53d65a1a441835577770cff0f8ddb4f962 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 6 Jul 2021 00:30:06 +0500 Subject: [PATCH 057/348] add x mode to build prices lib --- src/cc/priceslibs/build-win.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 src/cc/priceslibs/build-win.sh diff --git a/src/cc/priceslibs/build-win.sh b/src/cc/priceslibs/build-win.sh old mode 100644 new mode 100755 From 691475dabd008a8c8355841444b438ea1ea8c95c Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 10 Jul 2021 14:57:12 +0500 Subject: [PATCH 058/348] added check for coinbase maturity in AddNormalInputs --- src/cc/CCinclude.h | 10 +- src/cc/CCtx.cpp | 261 +++++++++++++++++++++++++-------------------- 2 files changed, 151 insertions(+), 120 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index f2c87b654be..c5211d1537f 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -981,7 +981,7 @@ int64_t NSPV_AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total /// @returns amount of added normal inputs or amount of all normal inputs in the wallet /// @see AddNormalinputsLocal /// @see AddNormalinputsRemote -int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs, bool remote=false); +CAmount AddNormalinputs(CMutableTransaction &mtx, CPubKey mypk, CAmount total, int32_t maxinputs, bool remote=false); /// Local version for cc runnnig on the same node, adds normal (not cc) inputs to the transaction object vin array for the specified total amount using available utxos in the wallet, to fund the transaction /// @param mtx mutable transaction object @@ -989,7 +989,7 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3 /// @param total amount of inputs to add. If total equals to 0 the function does not add inputs but returns amount of all available normal inputs in the wallet /// @param maxinputs maximum number of inputs to add /// @returns amount of added normal inputs or amount of all normal inputs in the wallet -int64_t AddNormalinputsLocal(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs); +CAmount AddNormalinputsLocal(CMutableTransaction &mtx, CPubKey mypk, CAmount total,int32_t maxinputs); /// AddNormalinputs2 adds normal (not cc) inputs to the transaction object vin array for the specified total amount using utxos on my pubkey's TX_PUBKEY address (my pubkey is set by -pubkey command line parameter), to fund the transaction. /// 'My pubkey' is the -pubkey parameter of komodod. @@ -997,7 +997,7 @@ int64_t AddNormalinputsLocal(CMutableTransaction &mtx,CPubKey mypk,int64_t total /// @param total amount of inputs to add. If total equals to 0 the function does not add inputs but returns amount of all available normal inputs in the wallet /// @param maxinputs maximum number of inputs to add /// @returns amount of added normal inputs or amount of all normal inputs on my pubkey's address -int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinputs); +CAmount AddNormalinputs2(CMutableTransaction &mtx, CAmount total, int32_t maxinputs); /// Remote version, does not use local wallet, adds normal (not cc) inputs to the transaction object vin array for the specified total amount using available utxos on mypk, to fund the transaction /// @param mtx mutable transaction object @@ -1005,7 +1005,7 @@ int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinput /// @param total amount of inputs to add. If total equals to 0 the function does not add inputs but returns amount of all available normal inputs in the wallet /// @param maxinputs maximum number of inputs to add /// @returns amount of added normal inputs or amount of all normal inputs in the wallet -int64_t AddNormalinputsRemote(CMutableTransaction &mtx, CPubKey mypk, int64_t total, int32_t maxinputs, bool mempool = false); +CAmount AddNormalinputsRemote(CMutableTransaction &mtx, CPubKey mypk, CAmount total, int32_t maxinputs, bool mempool = false); /// CCutxovalue returns amount of an utxo. The function does this without loading the utxo transaction, by using address index only /// @param coinaddr address where the utxo is searched @@ -1016,7 +1016,7 @@ int64_t AddNormalinputsRemote(CMutableTransaction &mtx, CPubKey mypk, int64_t to int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout,int32_t CCflag); /// @private -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); +int32_t CC_vinselect(int32_t *aboveip, CAmount *abovep, int32_t *belowip, CAmount *belowp, struct CC_utxo utxos[], int32_t numunspents, CAmount value); /// @private void CCAddVintxCond(struct CCcontract_info *cp, const CCwrapper &condWrapped, const uint8_t *priv = NULL); diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 7086cbde761..81ccc2efdbe 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -1068,9 +1068,10 @@ int64_t CCtoken_balanceV2(char *coinaddr,uint256 reftokenid) } // finds two utxo indexes that are closest to the passed value from below or above: -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) +int32_t CC_vinselect(int32_t *aboveip, CAmount *abovep, int32_t *belowip, CAmount *belowp, struct CC_utxo utxos[], int32_t numunspents, CAmount value) { - int32_t i,abovei,belowi; int64_t above,below,gap,atx_value; + int32_t i,abovei,belowi; + CAmount above,below,gap,atx_value; abovei = belowi = -1; for (above=below=i=0; i vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up; - if ( KOMODO_NSPV_SUPERLITE ) - return(NSPV_AddNormalinputs(mtx,mypk,total,maxinputs,&NSPV_U)); + if (hashBlock.IsNull()) + return 0; + AssertLockHeld(cs_main); + + // Find the block it claims to be in + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi == mapBlockIndex.end()) + return 0; + CBlockIndex* pindex = (*mi).second; + if (!pindex || !chainActive.Contains(pindex)) + return 0; + return chainActive.Height() - pindex->GetHeight() + 1; +} - // if (mypk != pubkey2pk(Mypubkey())) //remote superlite mypk, do not use wallet since it is not locked for non-equal pks (see rpcs with nspv support)! - // return(AddNormalinputs3(mtx, mypk, total, maxinputs)); +static int CoinbaseGetBlocksToMaturity(const CTransaction &tx, uint256 hashBlock) +{ + if (!tx.IsCoinBase()) + return 0; + int32_t depth = MyGetDepthInMainChain(tx, hashBlock); + int32_t ut = tx.UnlockTime(0); + int32_t toMaturity = (ut - chainActive.Height()) < 0 ? 0 : ut - chainActive.Height(); + //printf("depth.%i, unlockTime.%i, toMaturity.%i\n", depth, ut, toMaturity); + ut = (COINBASE_MATURITY - depth) < 0 ? 0 : COINBASE_MATURITY - depth; + return(ut < toMaturity ? toMaturity : ut); +} + +CAmount AddNormalinputsLocal(CMutableTransaction& mtx, CPubKey mypk, CAmount total, int32_t maxinputs) +{ + int32_t abovei, belowi, ind, vout, n = 0; + CAmount sum, above, below; + CAmount remains, nValue, totalinputs = 0; + // CAmount threshold = 0LL; + uint256 txid, hashBlock; + std::vector vecOutputs; + CTransaction tx; + struct CC_utxo *utxos, *up; + if (KOMODO_NSPV_SUPERLITE) + return (NSPV_AddNormalinputs(mtx, mypk, total, maxinputs, &NSPV_U)); + + // if (mypk != pubkey2pk(Mypubkey())) //remote superlite mypk, do not use wallet since it is not locked for non-equal pks (see rpcs with nspv support)! + // return(AddNormalinputs3(mtx, mypk, total, maxinputs)); #ifdef ENABLE_WALLET assert(pwalletMain != NULL); const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); - utxos = (struct CC_utxo *)calloc(CC_MAXVINS,sizeof(*utxos)); - if ( maxinputs > CC_MAXVINS ) + utxos = (struct CC_utxo*)calloc(CC_MAXVINS, sizeof(*utxos)); + if (maxinputs > CC_MAXVINS) maxinputs = CC_MAXVINS; - if ( maxinputs > 0 ) - threshold = total/maxinputs; - else threshold = total; - sum = 0; - BOOST_FOREACH(const COutput& out, vecOutputs) - { - if ( out.fSpendable != 0 && (vecOutputs.size() < maxinputs || out.tx->vout[out.i].nValue >= threshold) ) - { + /*if (maxinputs > 0) + threshold = total / maxinputs; + else + threshold = total;*/ + sum = 0LL; + BOOST_FOREACH (const COutput& out, vecOutputs) { + if (out.fSpendable != 0 && (vecOutputs.size() < maxinputs || out.tx->vout[out.i].nValue > 0LL)) { // threshold not used as may lead to insufficient inputs messages txid = out.tx->GetHash(); vout = out.i; - if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0 ) - { - //fprintf(stderr,"check %.8f to vins array.%d of %d %s/v%d\n",(double)out.tx->vout[out.i].nValue/COIN,n,maxutxos,txid.GetHex().c_str(),(int32_t)vout); - if ( mtx.vin.size() > 0 ) + if (myGetTransaction(txid, tx, hashBlock) != false && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0) { { - for (i=0; i 0) { + std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; continue; + } } - if ( n > 0 ) - { - for (i=0; ivout[out.i].nValue/COIN,n,maxutxos,txid.GetHex().c_str(),(int32_t)vout); + if (mtx.vin.size() > 0) { + if (std::find_if(mtx.vin.begin(), mtx.vin.end(), [&](const CTxIn &vin){ return vin.prevout.hash == txid && vin.prevout.n == vout; }) != mtx.vin.end()) + continue; //already added } - if ( myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { + if (n > 0) { + if (std::find_if(utxos, utxos+n, [&](const CC_utxo &utxo){ return utxo.txid == txid && utxo.vout == vout; }) != utxos+n) + continue; //already added + } + if (myIsutxo_spentinmempool(ignoretxid, ignorevin, txid, vout) == 0) { up = &utxos[n++]; up->txid = txid; up->nValue = out.tx->vout[out.i].nValue; up->vout = vout; sum += up->nValue; //fprintf(stderr,"add %.8f to vins array.%d of %d\n",(double)up->nValue/COIN,n,maxutxos); - if ( n >= maxinputs || sum >= total ) + if (n >= maxinputs || sum >= total) break; } } } } remains = total; - for (i=0; i0; i++) - { + for (int32_t i = 0; i < maxinputs && n > 0; i++) { below = above = 0; abovei = belowi = -1; - if ( CC_vinselect(&abovei,&above,&belowi,&below,utxos,n,remains) < 0 ) - { - printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,n,(double)remains/COIN,(double)total/COIN); + if (CC_vinselect(&abovei, &above, &belowi, &below, utxos, n, remains) < 0) { + printf("error finding unspent i.%d of %d, %.8f vs %.8f\n", i, n, (double)remains / COIN, (double)total / COIN); free(utxos); - return(0); + return (0); } - if ( belowi < 0 || abovei >= 0 ) + if (belowi < 0 || abovei >= 0) ind = abovei; - else ind = belowi; - if ( ind < 0 ) - { - printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,n,(double)remains/COIN,(double)total/COIN,abovei,belowi,ind); + else + ind = belowi; + if (ind < 0) { + printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n", i, n, (double)remains / COIN, (double)total / COIN, abovei, belowi, ind); free(utxos); - return(0); + return (0); } up = &utxos[ind]; - mtx.vin.push_back(CTxIn(up->txid,up->vout,CScript())); + mtx.vin.push_back(CTxIn(up->txid, up->vout, CScript())); totalinputs += up->nValue; remains -= up->nValue; utxos[ind] = utxos[--n]; - memset(&utxos[n],0,sizeof(utxos[n])); + memset(&utxos[n], 0, sizeof(utxos[n])); //fprintf(stderr,"totalinputs %.8f vs total %.8f i.%d vs max.%d\n",(double)totalinputs/COIN,(double)total/COIN,i,maxinputs); - if ( totalinputs >= total || (i+1) >= maxinputs ) + if (totalinputs >= total || (i + 1) >= maxinputs) break; } free(utxos); - if ( totalinputs >= total ) - { + if (totalinputs >= total) { //fprintf(stderr,"return totalinputs %.8f\n",(double)totalinputs/COIN); - return(totalinputs); + return (totalinputs); } #endif - return(0); + return (0); } // always uses -pubkey param as mypk -int64_t AddNormalinputs2(CMutableTransaction &mtx, int64_t total, int32_t maxinputs) +CAmount AddNormalinputs2(CMutableTransaction &mtx, CAmount total, int32_t maxinputs) { CPubKey mypk = pubkey2pk(Mypubkey()); return AddNormalinputsRemote(mtx, mypk, total, maxinputs); } // has additional mypk param for nspv calls -int64_t AddNormalinputsRemote(CMutableTransaction &mtx, CPubKey mypk, int64_t total, int32_t maxinputs, bool useMempool) +CAmount AddNormalinputsRemote(CMutableTransaction& mtx, CPubKey mypk, CAmount total, int32_t maxinputs, bool useMempool) { - int32_t abovei,belowi,ind,vout,i,n = 0; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; char coinaddr[64]; uint256 txid,hashBlock; CTransaction tx; struct CC_utxo *utxos,*up; - std::vector > unspentOutputs; - - if ( KOMODO_NSPV_SUPERLITE ) - return(NSPV_AddNormalinputs(mtx,mypk,total,maxinputs,&NSPV_U)); - utxos = (struct CC_utxo *)calloc(CC_MAXVINS,sizeof(*utxos)); - if ( maxinputs > CC_MAXVINS ) + int32_t abovei, belowi, ind, vout, n = 0; + CAmount sum, /*threshold,*/ above, below; + CAmount remains, nValue, totalinputs = 0; + char coinaddr[64]; + uint256 txid, hashBlock; + CTransaction tx; + struct CC_utxo *utxos, *up; + std::vector> unspentOutputs; + + if (KOMODO_NSPV_SUPERLITE) + return (NSPV_AddNormalinputs(mtx, mypk, total, maxinputs, &NSPV_U)); + utxos = (struct CC_utxo*)calloc(CC_MAXVINS, sizeof(*utxos)); + if (maxinputs > CC_MAXVINS) maxinputs = CC_MAXVINS; - if ( maxinputs > 0 ) - threshold = total/maxinputs; - else threshold = total; + /*if (maxinputs > 0) + threshold = total / maxinputs; + else + threshold = total;*/ sum = 0; - Getscriptaddress(coinaddr,CScript() << vscript_t(mypk.begin(), mypk.end()) << OP_CHECKSIG); + Getscriptaddress(coinaddr, CScript() << vscript_t(mypk.begin(), mypk.end()) << OP_CHECKSIG); if (!useMempool) - SetCCunspents(unspentOutputs,coinaddr,false); + SetCCunspents(unspentOutputs, coinaddr, false); else - SetCCunspentsWithMempool(unspentOutputs,coinaddr,false); - - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { + SetCCunspentsWithMempool(unspentOutputs, coinaddr, false); + + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; //if ( it->second.satoshis < threshold ) // continue; // do not use threshold - if( it->second.satoshis == 0 ) - continue; //skip null outputs + if (it->second.satoshis == 0) + continue; //skip null outputs - if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0 ) - { - //fprintf(stderr,"check %.8f to vins array.%d of %d %s/v%d\n",(double)tx.vout[vout].nValue/COIN,n,maxinputs,txid.GetHex().c_str(),(int32_t)vout); - if ( mtx.vin.size() > 0 ) + if (myGetTransaction(txid, tx, hashBlock) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0) { { - for (i=0; i 0) { + std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; continue; + } } - if ( n > 0 ) - { - for (i=0; i 0) { + if (std::find_if(mtx.vin.begin(), mtx.vin.end(), [&](const CTxIn &vin){ return vin.prevout.hash == txid && vin.prevout.n == vout; }) != mtx.vin.end()) + continue; //already added } - if (myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0) - { + if (n > 0) { + if (std::find_if(utxos, utxos+n, [&](const CC_utxo &utxo){ return utxo.txid == txid && utxo.vout == vout; }) != utxos+n) + continue; //already added + } + if (myIsutxo_spentinmempool(ignoretxid, ignorevin, txid, vout) == 0) { up = &utxos[n++]; up->txid = txid; up->nValue = it->second.satoshis; up->vout = vout; sum += up->nValue; //fprintf(stderr,"add %.8f to vins array.%d of %d\n",(double)up->nValue/COIN,n,maxinputs); - if ( n >= maxinputs || sum >= total ) + if (n >= maxinputs || sum >= total) break; } } } remains = total; - for (i=0; i0; i++) - { + for (int32_t i = 0; i < maxinputs && n > 0; i++) { below = above = 0; abovei = belowi = -1; - if ( CC_vinselect(&abovei,&above,&belowi,&below,utxos,n,remains) < 0 ) - { - printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,n,(double)remains/COIN,(double)total/COIN); + if (CC_vinselect(&abovei, &above, &belowi, &below, utxos, n, remains) < 0) { + printf("error finding unspent i.%d of %d, %.8f vs %.8f\n", i, n, (double)remains / COIN, (double)total / COIN); free(utxos); - return(0); + return (0); } - if ( belowi < 0 || abovei >= 0 ) + if (belowi < 0 || abovei >= 0) ind = abovei; - else ind = belowi; - if ( ind < 0 ) - { - printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,n,(double)remains/COIN,(double)total/COIN,abovei,belowi,ind); + else + ind = belowi; + if (ind < 0) { + printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n", i, n, (double)remains / COIN, (double)total / COIN, abovei, belowi, ind); free(utxos); - return(0); + return (0); } up = &utxos[ind]; - mtx.vin.push_back(CTxIn(up->txid,up->vout,CScript())); + mtx.vin.push_back(CTxIn(up->txid, up->vout, CScript())); totalinputs += up->nValue; remains -= up->nValue; utxos[ind] = utxos[--n]; - memset(&utxos[n],0,sizeof(utxos[n])); + memset(&utxos[n], 0, sizeof(utxos[n])); //fprintf(stderr,"totalinputs %.8f vs total %.8f i.%d vs max.%d\n",(double)totalinputs/COIN,(double)total/COIN,i,maxinputs); - if ( totalinputs >= total || (i+1) >= maxinputs ) + if (totalinputs >= total || (i + 1) >= maxinputs) break; } free(utxos); - if ( totalinputs >= total ) - { + if (totalinputs >= total) { //fprintf(stderr,"return totalinputs %.8f\n",(double)totalinputs/COIN); - return(totalinputs); + return (totalinputs); } - return(0); + return (0); } -int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs,bool remote) +CAmount AddNormalinputs(CMutableTransaction& mtx, CPubKey mypk, CAmount total, int32_t maxinputs, bool remote) { - if (!remote) return (AddNormalinputsLocal(mtx,mypk,total,maxinputs)); - else return (AddNormalinputsRemote(mtx,mypk,total,maxinputs)); + if (!remote) + return (AddNormalinputsLocal(mtx, mypk, total, maxinputs)); + else + return (AddNormalinputsRemote(mtx, mypk, total, maxinputs)); } void AddSigData2UniValue(UniValue &sigdata, int32_t vini, UniValue& ccjson, std::string sscriptpubkey, int64_t amount) From aaf6b590cd613daba51559d0e75f10db51cde099 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 13 Jul 2021 16:46:53 +0500 Subject: [PATCH 059/348] added height to token[v2]info result added check if tokenid in active chain for token[v2]list --- src/cc/CCassetstx_impl.h | 19 -------------- src/cc/CCinclude.h | 9 +++++++ src/cc/CCtokens.cpp | 48 +++++++++++++++++++++++++----------- src/cc/CCtokens_impl.h | 12 +++++++++ src/cc/CCutils.cpp | 30 +++++++++++++++++++++- src/tui/tui_assets_orders.py | 4 +-- 6 files changed, 85 insertions(+), 37 deletions(-) diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index 9233411ae01..9bcc5efa9c6 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -20,25 +20,6 @@ #include "CCassets.h" #include "CCTokelData.h" - -static bool IsTxidInActiveChain(uint256 txid) -{ - CTransaction tx; - uint256 hashBlock; - AssertLockHeld(cs_main); - - if (myGetTransaction(txid, tx, hashBlock)) - { - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi != mapBlockIndex.end() && (*mi).second) { - CBlockIndex* pindex = (*mi).second; - if (chainActive.Contains(pindex)) - return true; - } - } - return false; -} - template UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) { diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index c5211d1537f..36ef836cb15 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -1102,6 +1102,15 @@ void AddSigData2UniValue(UniValue &result, int32_t vini, UniValue& ccjson, std:: /// @returns 0 if okay or -1 int32_t ensure_CCrequirements(uint8_t evalcode); +/// returns true if tx is in active chain +/// @param txid txid of tx to check +bool IsTxidInActiveChain(uint256 txid); + +/// returns true if block hash is in active chain +/// @param hashBlock hash of block to check +bool IsBlockHashInActiveChain(uint256 hashBlock); + + extern bool fUnspentCCIndex; // if unspent cc index enabled /// @private forward decl diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 4cf660b7042..0e75e09981b 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -871,13 +871,18 @@ UniValue TokenList() std::vector origpubkey; std::string name, description; - if (myGetTransaction(txid, vintx, hashBlock) != 0) { - std::vector oprets; - if (vintx.vout.size() > 0 && DecodeTokenCreateOpRetV1(vintx.vout.back().scriptPubKey, origpubkey, name, description, oprets) != 0) { - result.push_back(txid.GetHex()); - } - else { - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "DecodeTokenCreateOpRetV1 failed for txid=" << txid.GetHex() < oprets; + if (vintx.vout.size() > 0 && DecodeTokenCreateOpRetV1(vintx.vout.back().scriptPubKey, origpubkey, name, description, oprets) != 0) { + result.push_back(txid.GetHex()); + } + else { + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "DecodeTokenCreateOpRetV1 failed for txid=" << txid.GetHex() < oprets; - if (DecodeTokenCreateOpRetV2(opreturn, origpubkey, name, description, oprets) != 0) { - result.push_back(tokenid.GetHex()); - } - else { - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "DecodeTokenCreateOpRetV2 failed for tokenid=" << tokenid.GetHex() << " opreturn.size=" << opreturn.size() << std::endl); + if (IsTxidInActiveChain(tokenid)) + { + if (DecodeTokenCreateOpRetV2(opreturn, origpubkey, name, description, oprets) != 0) { + result.push_back(tokenid.GetHex()); + } + else { + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "DecodeTokenCreateOpRetV2 failed for tokenid=" << tokenid.GetHex() << " opreturn.size=" << opreturn.size() << std::endl); + } } }; @@ -940,7 +948,11 @@ UniValue TokenV2List(int32_t beginHeight, int32_t endHeight) uint256 hashBlock; if (!it.first.spending && myGetTransaction(it.first.txhash, creationtx, hashBlock) && creationtx.vout.size() > 0) - addTokenId(it.first.txhash, creationtx.vout.back().scriptPubKey); + { + LOCK(cs_main); + if (IsBlockHashInActiveChain(hashBlock)) + addTokenId(it.first.txhash, creationtx.vout.back().scriptPubKey); + } } } else @@ -952,7 +964,9 @@ UniValue TokenV2List(int32_t beginHeight, int32_t endHeight) SetCCunspentsCCIndex(unspentOutputs, cp->unspendableCCaddr, zeroid); // find by burnable validated cc addr marker LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetCCunspentsCCIndex unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (const auto &it : unspentOutputs) { - addTokenId(it.first.creationid, it.second.opreturn); + LOCK(cs_main); + if (IsTxidInActiveChain(it.first.creationid)) + addTokenId(it.first.creationid, it.second.opreturn); } } else @@ -965,7 +979,11 @@ UniValue TokenV2List(int32_t beginHeight, int32_t endHeight) CTransaction creationtx; uint256 hashBlock; if (myGetTransaction(it.first.txhash, creationtx, hashBlock) && creationtx.vout.size() > 0) - addTokenId(it.first.txhash, creationtx.vout.back().scriptPubKey); + { + LOCK(cs_main); + if (IsBlockHashInActiveChain(hashBlock)) + addTokenId(it.first.txhash, creationtx.vout.back().scriptPubKey); + } } } } diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 58e28ae4b7b..d25c503fd14 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -690,6 +690,18 @@ UniValue TokenInfo(uint256 tokenid, E parseExtraData) result.push_back(Pair("sourceTokenId", sourceTokenId)); } + LOCK(cs_main); + int32_t nHeight = -1; + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) { + CBlockIndex* pindex = (*mi).second; + if (chainActive.Contains(pindex)) { + nHeight = pindex->GetHeight(); + } else { + nHeight = -1; + } + } + result.push_back(Pair("height", nHeight)); return result; } diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 32a4804142f..5cfb59f23bb 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -1687,4 +1687,32 @@ bool CCDecodeTxVout(const CTransaction &tx, int32_t n, uint8_t &evalcode, uint8_ return true; } return false; -} \ No newline at end of file +} + +bool IsBlockHashInActiveChain(uint256 hashBlock) +{ + AssertLockHeld(cs_main); + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) { + CBlockIndex* pindex = (*mi).second; + if (chainActive.Contains(pindex)) + return true; + } + return false; +} + +/** + * IsTxidInActiveChain load a tx and checks if it is in active chain (not in orphaned blocks) + * cs_main section should be locked + */ +bool IsTxidInActiveChain(uint256 txid) +{ + CTransaction tx; + uint256 hashBlock; + + if (myGetTransaction(txid, tx, hashBlock)) + { + return IsBlockHashInActiveChain(hashBlock); + } + return false; +} diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 86950f9885c..0493e0fac66 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -53,8 +53,8 @@ def run_tokens_create(rpc): rpc3 = rpclib.rpc_connect("user972794450", "passe7eb16f5c015a53463cc5f27a004854cb76f4ec5c9aece177f01d8b3d13119e445", 16723) - for v in ["", "v2"] : - #for v in ["v2"] : + ## for v in ["", "v2"] : + for v in ["v2"] : print("creating fungible token 1...") result = call_rpc(rpc1, "token"+v+"create", "T1", str(0.000001)) # 100 assert(check_tx(result)) From 22dc83dedab43d2a45f36c66031b73fa9cc780e5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 19 Jul 2021 16:41:43 +0500 Subject: [PATCH 060/348] fixed change calc in FinalizeCCTx (as it is in wallet.cpp) --- src/cc/CCtx.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 81ccc2efdbe..82a83ef29f4 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -170,12 +170,13 @@ UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_inf // if (changeFlag != FINALIZECCTX_NO_CHANGE) { // no need change at all (already added by the caller itself) CAmount change = totalinputs - (totaloutputs + txfee); + CTxOut changeVout(change, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG); if (change >= 0) { if ((change != 0LL || changeFlag != FINALIZECCTX_NO_CHANGE_WHEN_ZERO) && // prevent adding zero change - (change > ASSETS_NORMAL_DUST || changeFlag != FINALIZECCTX_NO_CHANGE_WHEN_DUST)) // prevent adding dust change + (!changeVout.IsDust(::minRelayTxFee) || changeFlag != FINALIZECCTX_NO_CHANGE_WHEN_DUST)) // prevent adding dust change { - mtx.vout.push_back(CTxOut(change, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + mtx.vout.push_back(changeVout); } } } @@ -477,12 +478,13 @@ UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info } if (changeFlag != FINALIZECCTX_NO_CHANGE) { // no need change at all (already added by the caller itself) CAmount change = totalinputs - (totaloutputs + txfee); + CTxOut changeVout(change, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG); if (change >= 0) { if ((change != 0LL || changeFlag != FINALIZECCTX_NO_CHANGE_WHEN_ZERO) && // prevent adding zero change - (change > ASSETS_NORMAL_DUST || changeFlag != FINALIZECCTX_NO_CHANGE_WHEN_DUST)) // prevent adding dust change + (!changeVout.IsDust(::minRelayTxFee) || changeFlag != FINALIZECCTX_NO_CHANGE_WHEN_DUST)) // prevent adding dust change { - mtx.vout.push_back(CTxOut(change, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + mtx.vout.push_back(changeVout); } } } From 990c6c74f56e654233e7b1f74e0b75ec5d54cb32 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 20 Jul 2021 20:06:48 +0500 Subject: [PATCH 061/348] added expiryHeight to assets opreturn tokenask/bid has expiry-height param (default = maxint) order markers made 1of2, allowed to spend if chain height >= expiryHeight tokencancelask/bid uses global pk if mypk not origpk (to allow cancel expired orders) tokencancelask/bid takes fee from marker more int64_t to CAmount replacements test-assets-cc fixed for new opreturn, new test added for expiryHeight --- src/cc/CCassets.h | 42 +-- src/cc/CCassetsCore_impl.h | 72 ++--- src/cc/CCassetsUtils.cpp | 47 ++- src/cc/CCassetstx_impl.h | 150 +++++----- src/cc/CCinclude.h | 6 +- src/cc/CCtokens.h | 22 +- src/cc/CCtx.cpp | 6 +- src/cc/assets.cpp | 87 ++++-- src/rpc/tokensrpc.cpp | 94 +++--- src/test-komodo-cc/test-assets.cpp | 443 +++++++++++++++++++++-------- 10 files changed, 638 insertions(+), 331 deletions(-) diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index c0e574d3a38..f90159aa5b1 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -36,17 +36,17 @@ bool AssetsValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction & bool Assetsv2Validate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); // CCassetsCore -vscript_t EncodeAssetOpRetV1(uint8_t assetFuncId, uint256 assetid2, int64_t unit_price, std::vector origpubkey); -uint8_t DecodeAssetTokenOpRetV1(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &unit_price, std::vector &origpubkey); -vscript_t EncodeAssetOpRetV2(uint8_t assetFuncId, uint256 assetid2, int64_t unit_price, std::vector origpubkey); -uint8_t DecodeAssetTokenOpRetV2(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &unit_price, std::vector &origpubkey); - -bool ValidateBidRemainder(CAmount unit_price, int64_t remaining_nValue, int64_t orig_nValue, int64_t received_nValue, int64_t paid_units); -bool ValidateAskRemainder(CAmount unit_price, int64_t remaining_assetoshis, int64_t orig_assetoshis, int64_t received_assetoshis, int64_t paid_nValue); -bool ValidateSwapRemainder(int64_t remaining_units, int64_t remaining_nValue, int64_t orig_nValue, int64_t received_nValue, int64_t paidprice, int64_t totalprice); -bool SetBidFillamounts(CAmount unit_price, int64_t &received_nValue, int64_t orig_nValue, int64_t &paid_units, int64_t orig_units, CAmount paid_unit_price); -bool SetAskFillamounts(CAmount unit_price, int64_t fill_assetoshis, int64_t orig_assetoshis, int64_t paid_nValue); -bool SetSwapFillamounts(CAmount unit_price, int64_t &paid, int64_t orig_nValue, int64_t &received, int64_t totalprice); // not implemented +vscript_t EncodeAssetOpRetV1(uint8_t assetFuncId, CAmount unit_price, vscript_t origpubkey, int32_t expiryHeight); +uint8_t DecodeAssetTokenOpRetV1(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, CAmount &unit_price, vscript_t &origpubkey, int32_t &expiryHeight); +vscript_t EncodeAssetOpRetV2(uint8_t assetFuncId, CAmount unit_price, vscript_t origpubkey, int32_t expiryHeight); +uint8_t DecodeAssetTokenOpRetV2(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, CAmount &unit_price, vscript_t &origpubkey, int32_t &expiryHeight); + +bool ValidateBidRemainder(CAmount unit_price, CAmount remaining_nValue, CAmount orig_nValue, CAmount received_nValue, CAmount paid_units); +bool ValidateAskRemainder(CAmount unit_price, CAmount remaining_assetoshis, CAmount orig_assetoshis, CAmount received_assetoshis, CAmount paid_nValue); +bool ValidateSwapRemainder(CAmount remaining_units, CAmount remaining_nValue, CAmount orig_nValue, CAmount received_nValue, CAmount paidprice, CAmount totalprice); +bool SetBidFillamounts(CAmount unit_price, CAmount &received_nValue, CAmount orig_nValue, CAmount &paid_units, CAmount orig_units, CAmount paid_unit_price); +bool SetAskFillamounts(CAmount unit_price, CAmount fill_assetoshis, CAmount orig_assetoshis, CAmount paid_nValue); +bool SetSwapFillamounts(CAmount unit_price, CAmount &paid, CAmount orig_nValue, CAmount &received, CAmount totalprice); // not implemented CAmount AssetsGetCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx); const char ccassets_log[] = "ccassets"; @@ -58,17 +58,17 @@ class AssetsV1 { static uint8_t TokensEvalCode() { return EVAL_TOKENS; } static bool IsMixed() { return false; } - static vscript_t EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t unit_price, std::vector origpubkey) + static vscript_t EncodeAssetOpRet(uint8_t assetFuncId, CAmount unit_price, vscript_t origpubkey, int32_t expiryHeight) { - return ::EncodeAssetOpRetV1(assetFuncId, assetid2, unit_price, origpubkey); + return ::EncodeAssetOpRetV1(assetFuncId, unit_price, origpubkey, expiryHeight); } - static uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &unit_price, std::vector &origpubkey) + static uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, CAmount &unit_price, vscript_t &origpubkey, int32_t &expiryHeight) { - return ::DecodeAssetTokenOpRetV1(scriptPubKey, assetsEvalCode, tokenid, assetid2, unit_price, origpubkey); + return ::DecodeAssetTokenOpRetV1(scriptPubKey, assetsEvalCode, tokenid, unit_price, origpubkey, expiryHeight); } - static bool ConstrainVout(CTxOut vout, int32_t CCflag, char *cmpaddr, int64_t nValue, uint8_t evalCode) + static bool ConstrainVout(CTxOut vout, int32_t CCflag, char *cmpaddr, CAmount nValue, uint8_t evalCode) { return ::ConstrainVout(vout, CCflag, cmpaddr, nValue); } @@ -82,17 +82,17 @@ class AssetsV2 { static bool IsMixed() { return true; } - static vscript_t EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t unit_price, std::vector origpubkey) + static vscript_t EncodeAssetOpRet(uint8_t assetFuncId, CAmount unit_price, vscript_t origpubkey, int32_t expiryHeight) { - return ::EncodeAssetOpRetV2(assetFuncId, assetid2, unit_price, origpubkey); + return ::EncodeAssetOpRetV2(assetFuncId, unit_price, origpubkey, expiryHeight); } - static uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &unit_price, std::vector &origpubkey) + static uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, CAmount &unit_price, vscript_t &origpubkey, int32_t &expiryHeight) { - return ::DecodeAssetTokenOpRetV2(scriptPubKey, assetsEvalCode, tokenid, assetid2, unit_price, origpubkey); + return ::DecodeAssetTokenOpRetV2(scriptPubKey, assetsEvalCode, tokenid, unit_price, origpubkey, expiryHeight); } - static bool ConstrainVout(CTxOut vout, int32_t CCflag, char *cmpaddr, int64_t nValue, uint8_t evalCode) + static bool ConstrainVout(CTxOut vout, int32_t CCflag, char *cmpaddr, CAmount nValue, uint8_t evalCode) { return ::ConstrainVoutV2(vout, CCflag, cmpaddr, nValue, evalCode); } diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index 4245177ba42..1bd46478e83 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -45,15 +45,16 @@ // validates opret for asset tx: template -bool ValidateAssetOpret(CTransaction tx, int32_t v, uint256 assetid, int64_t &remaining_units_out, std::vector &origpubkey_out) +bool ValidateAssetOpret(CTransaction tx, int32_t v, uint256 assetid, CAmount &remaining_units_out, std::vector &origpubkey_out) { - uint256 assetidOpret, assetidOpret2; + uint256 assetidOpret; uint8_t funcid, evalCode; + int32_t expiryHeight; // this is just for log messages indentation fur debugging recursive calls: int32_t n = tx.vout.size(); - if ((funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCode, assetidOpret, assetidOpret2, remaining_units_out, origpubkey_out)) == 0) + if ((funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCode, assetidOpret, remaining_units_out, origpubkey_out, expiryHeight)) == 0) { LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "called DecodeAssetTokenOpRet returned funcId=0 for opret from txid=" << tx.GetHash().GetHex() << std::endl); return(false); @@ -66,19 +67,19 @@ bool ValidateAssetOpret(CTransaction tx, int32_t v, uint256 assetid, int64_t &re return(true); } } - else if (funcid == 'E') // NOTE: not implemented yet! + /*else if (funcid == 'E') // NOTE: not implemented yet! { if (v < 2 && assetid != zeroid && assetidOpret == assetid) return(true); else if (v == 2 && assetid != zeroid && assetidOpret2 == assetid) return(true); - } + }*/ return false; } // Checks if the vout is a really Asset CC vout template -int64_t IsAssetvout(struct CCcontract_info *cp, int64_t &remaining_units_out, std::vector &origpubkey_out, const CTransaction& tx, int32_t v, uint256 refassetid) +CAmount IsAssetvout(struct CCcontract_info *cp, CAmount &remaining_units_out, std::vector &origpubkey_out, const CTransaction& tx, int32_t v, uint256 refassetid) { // just check boundaries: int32_t n = tx.vout.size(); @@ -100,12 +101,12 @@ int64_t IsAssetvout(struct CCcontract_info *cp, int64_t &remaining_units_out, st // extract sell/buy owner's pubkey from the opret template -uint8_t GetOrderParams(std::vector &origpubkey_out, CAmount &unit_price, uint256 &assetid, const CTransaction &tx) +uint8_t GetOrderParams(std::vector &origpubkey_out, CAmount &unit_price, uint256 &assetid, int32_t &expiryHeightOut, const CTransaction &tx) { uint256 assetid2; uint8_t evalCode, funcid; - if (tx.vout.size() > 0 && (funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCode, assetid, assetid2, unit_price, origpubkey_out)) != 0) + if (tx.vout.size() > 0 && (funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCode, assetid, unit_price, origpubkey_out, expiryHeightOut)) != 0) return funcid; else return 0; @@ -115,16 +116,17 @@ uint8_t GetOrderParams(std::vector &origpubkey_out, CAmount &unit_price template bool GetAssetorigaddrs(struct CCcontract_info *cp, char *origCCaddr, char *origNormalAddr, const CTransaction& vintx) { - uint256 assetid, assetid2; - int64_t price,nValue=0; + uint256 assetid; + CAmount price, nValue=0; int32_t n; uint8_t vintxFuncId; std::vector origpubkey; CScript script; uint8_t evalCode; + int32_t expiryHeight; n = vintx.vout.size(); - if( n == 0 || (vintxFuncId = A::DecodeAssetTokenOpRet(vintx.vout[n-1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey)) == 0 ) { + if( n == 0 || (vintxFuncId = A::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, evalCode, assetid, price, origpubkey, expiryHeight)) == 0 ) { LOGSTREAMFN(ccassets_log, CCLOG_INFO, stream << "could not get vintx opreturn" << std::endl); return(false); } @@ -148,16 +150,17 @@ bool GetAssetorigaddrs(struct CCcontract_info *cp, char *origCCaddr, char *origN } template -CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, int32_t vini, CTransaction &vinTx) +CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *origCCaddr_out, char *origaddr_out, int32_t &vinExpiryHeightOut, const CTransaction &tx, int32_t vini, CTransaction &vinTx) { uint256 hashBlock; - uint256 assetid, assetid2; - uint256 vinAssetId, vinAssetId2; + uint256 assetid; + uint256 vinAssetId; CAmount tmpprice, vinPrice; std::vector tmporigpubkey; std::vector vinOrigpubkey; uint8_t evalCode; uint8_t vinEvalCode; + int32_t tmpExpiryHeight; char destaddr[KOMODO_ADDRESS_BUFSIZE], unspendableAddr[KOMODO_ADDRESS_BUFSIZE]; origaddr_out[0] = destaddr[0] = origCCaddr_out[0] = 0; @@ -165,9 +168,11 @@ CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *o uint8_t funcid = 0; uint8_t vinFuncId = 0; if (tx.vout.size() > 0) - funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCode, assetid, assetid2, tmpprice, tmporigpubkey); + funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCode, assetid, tmpprice, tmporigpubkey, tmpExpiryHeight); else return eval->Invalid("no vouts in tx"), 0LL; + if (funcid == 0) + return eval->Invalid("could not decode opreturn for tx"), 0LL; if (tx.vin.size() < 2) return eval->Invalid("not enough vins"), 0LL; @@ -178,7 +183,7 @@ CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *o LOGSTREAMFN(ccassets_log, CCLOG_ERROR, stream << "cannot load vintx for vin=" << vini << " vintx id=" << tx.vin[vini].prevout.hash.GetHex() << std::endl); return eval->Invalid("could not load previous tx or it has too few vouts"), 0LL; } - else if (vinTx.vout.size() < 1 || (vinFuncId = A::DecodeAssetTokenOpRet(vinTx.vout.back().scriptPubKey, vinEvalCode, vinAssetId, vinAssetId2, vinPrice, vinOrigpubkey)) == 0) { + else if (vinTx.vout.size() < 1 || (vinFuncId = A::DecodeAssetTokenOpRet(vinTx.vout.back().scriptPubKey, vinEvalCode, vinAssetId, vinPrice, vinOrigpubkey, vinExpiryHeightOut)) == 0) { return eval->Invalid("could not find assets opreturn in previous tx"), 0LL; } // if fillSell or cancelSell --> should spend tokens from dual-eval token-assets global addr: @@ -228,28 +233,29 @@ CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *o } template -CAmount AssetValidateBuyvin(struct CCcontract_info *cpAssets, Eval* eval, CAmount &unit_price, std::vector &origpubkey_out, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, uint256 refassetid) +CAmount AssetValidateBuyvin(struct CCcontract_info *cpAssets, Eval* eval, CAmount &unit_price, std::vector &origpubkey_out, char *origCCaddr_out, char *origaddr_out, int32_t &expiryHeightOut, const CTransaction &tx, uint256 refassetid) { - CTransaction vinTx; CAmount nValue; uint256 assetid, assetid2; uint8_t funcid, evalCode; + CTransaction vinTx; + CAmount nValue; + uint256 assetid; + uint8_t funcid, evalCode; + int32_t expiryHeight; origCCaddr_out[0] = origaddr_out[0] = 0; // get first ccvin: - int32_t ivincc; - for (ivincc = 0; ivincc < tx.vin.size(); ivincc ++) - if (cpAssets->ismyvin(tx.vin[ivincc].scriptSig)) - break; - if (ivincc == tx.vin.size()) + auto ccvin = std::find_if(tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin) { return cpAssets->ismyvin(vin.scriptSig); }); + if (ccvin == tx.vin.end()) return eval->Invalid("cc vin not found in tx"), 0LL; // validate locked coins on Assets vin[1] - if ((nValue = AssetValidateCCvin(cpAssets, eval, origCCaddr_out, origaddr_out, tx, /*ASSETS_GLOBALADDR_VIN*/ivincc, vinTx)) == 0) + if ((nValue = AssetValidateCCvin(cpAssets, eval, origCCaddr_out, origaddr_out, expiryHeightOut, tx, ccvin-tx.vin.begin(), vinTx)) == 0) return 0LL; // eval is set already in AssetValidateCCvin else if (vinTx.vout.size() < 2) return eval->Invalid("invalid previous tx, too few vouts"), 0LL; else if (vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == false) return eval->Invalid("invalid not cc vout0 for buyvin"), 0LL; - else if ((funcid = A::DecodeAssetTokenOpRet(vinTx.vout[vinTx.vout.size() - 1].scriptPubKey, evalCode, assetid, assetid2, unit_price, origpubkey_out)) == 'b' && + else if ((funcid = A::DecodeAssetTokenOpRet(vinTx.vout.back().scriptPubKey, evalCode, assetid, unit_price, origpubkey_out, expiryHeightOut)) == 'b' && vinTx.vout[1].scriptPubKey.IsPayToCryptoCondition() == false) // marker is only in 'b'? return eval->Invalid("invalid not cc vout1 for buyvin"), 0LL; else @@ -263,21 +269,19 @@ CAmount AssetValidateBuyvin(struct CCcontract_info *cpAssets, Eval* eval, CAmoun } template -CAmount AssetValidateSellvin(struct CCcontract_info *cpAssets, Eval* eval, CAmount &unit_price, std::vector &origpubkey_out, char *origCCaddr_out, char *origaddr_out, const CTransaction &tx, uint256 assetid) +CAmount AssetValidateSellvin(struct CCcontract_info *cpAssets, Eval* eval, CAmount &unit_price, std::vector &origpubkey_out, char *origCCaddr_out, char *origaddr_out, int32_t &expiryHeightOut, const CTransaction &tx, uint256 assetid) { - CTransaction vinTx; CAmount nValue, assetoshis; + CTransaction vinTxOut; + CAmount nValue, assetoshis; // get first ccvin: - int32_t ivincc; - for (ivincc = 0; ivincc < tx.vin.size(); ivincc ++) - if (cpAssets->ismyvin(tx.vin[ivincc].scriptSig)) - break; - if (ivincc == tx.vin.size()) + auto ccvin = std::find_if(tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin) { return cpAssets->ismyvin(vin.scriptSig); }); + if (ccvin == tx.vin.end()) return eval->Invalid("cc vin not found"), 0LL; - if ((nValue = AssetValidateCCvin(cpAssets, eval, origCCaddr_out, origaddr_out, tx, /*ASSETS_GLOBALADDR_VIN*/ivincc, vinTx)) == 0) + if ((nValue = AssetValidateCCvin(cpAssets, eval, origCCaddr_out, origaddr_out, expiryHeightOut, tx, ccvin-tx.vin.begin(), vinTxOut)) == 0) return 0LL; // eval is set already in AssetValidateCCvin - if ((assetoshis = IsAssetvout(cpAssets, unit_price, origpubkey_out, vinTx, ASSETS_GLOBALADDR_VOUT, assetid)) == 0) + if ((assetoshis = IsAssetvout(cpAssets, unit_price, origpubkey_out, vinTxOut, ASSETS_GLOBALADDR_VOUT, assetid)) == 0) return eval->Invalid("invalid missing CC vout0 for sellvin"), 0LL; else return assetoshis; diff --git a/src/cc/CCassetsUtils.cpp b/src/cc/CCassetsUtils.cpp index 1a370a34e3f..0e56a9e3b1f 100644 --- a/src/cc/CCassetsUtils.cpp +++ b/src/cc/CCassetsUtils.cpp @@ -17,7 +17,7 @@ #include "CCtokens.h" #include -vscript_t EncodeAssetOpRetV1(uint8_t assetFuncId, uint256 assetid2, int64_t unit_price, std::vector origpubkey) +vscript_t EncodeAssetOpRetV1(uint8_t assetFuncId, CAmount unit_price, vscript_t origpubkey, int32_t expiryHeight) { vscript_t vopret; uint8_t evalcode = EVAL_ASSETS; @@ -30,12 +30,12 @@ vscript_t EncodeAssetOpRetV1(uint8_t assetFuncId, uint256 assetid2, int64_t unit vopret = E_MARSHAL(ss << evalcode << assetFuncId << version); break; case 's': case 'b': case 'S': case 'B': - vopret = E_MARSHAL(ss << evalcode << assetFuncId << version << unit_price << origpubkey); + vopret = E_MARSHAL(ss << evalcode << assetFuncId << version << unit_price << origpubkey << expiryHeight); break; - case 'E': case 'e': + /*case 'E': case 'e': assetid2 = revuint256(assetid2); - vopret = E_MARSHAL(ss << evalcode << assetFuncId << version << assetid2 << unit_price << origpubkey); - break; + vopret = E_MARSHAL(ss << evalcode << assetFuncId << version << expiryHeight << unit_price << origpubkey); + break;*/ default: CCLogPrintF(ccassets_log, CCLOG_DEBUG1, "%s illegal funcid.%02x\n", __func__, assetFuncId); break; @@ -43,7 +43,7 @@ vscript_t EncodeAssetOpRetV1(uint8_t assetFuncId, uint256 assetid2, int64_t unit return(vopret); } -uint8_t DecodeAssetTokenOpRetV1(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &unit_price, std::vector &origpubkey) +uint8_t DecodeAssetTokenOpRetV1(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, CAmount &unit_price, vscript_t &origpubkey, int32_t &expiryHeight) { vscript_t vopretAssets; //, vopretAssetsStripped; uint8_t *script, funcId = 0, assetsFuncId = 0, dummyAssetFuncId, dummyEvalCode, version; @@ -52,7 +52,6 @@ uint8_t DecodeAssetTokenOpRetV1(const CScript &scriptPubKey, uint8_t &assetsEval std::vector oprets; tokenid = zeroid; - assetid2 = zeroid; unit_price = 0; assetsEvalCode = 0; assetsFuncId = 0; @@ -88,13 +87,13 @@ uint8_t DecodeAssetTokenOpRetV1(const CScript &scriptPubKey, uint8_t &assetsEval } break; case 's': case 'b': case 'S': case 'B': - if (E_UNMARSHAL(vopretAssets, ss >> dummyEvalCode; ss >> dummyAssetFuncId; ss >> version; ss >> unit_price; ss >> origpubkey) != 0) + if (E_UNMARSHAL(vopretAssets, ss >> dummyEvalCode; ss >> dummyAssetFuncId; ss >> version; ss >> unit_price; ss >> origpubkey; ss >> expiryHeight) != 0) { //fprintf(stderr,"DecodeAssetTokenOpRet() got price %lld\n",(long long)price); return(assetsFuncId); } break; - case 'E': case 'e': + /*case 'E': case 'e': // not implemented yet if (E_UNMARSHAL(vopretAssets, ss >> dummyEvalCode; ss >> dummyAssetFuncId; ss >> version; ss >> assetid2; ss >> unit_price; ss >> origpubkey) != 0) { @@ -102,7 +101,7 @@ uint8_t DecodeAssetTokenOpRetV1(const CScript &scriptPubKey, uint8_t &assetsEval assetid2 = revuint256(assetid2); return(assetsFuncId); } - break; + break;*/ default: break; } @@ -114,7 +113,7 @@ uint8_t DecodeAssetTokenOpRetV1(const CScript &scriptPubKey, uint8_t &assetsEval } -vscript_t EncodeAssetOpRetV2(uint8_t assetFuncId, uint256 assetid2, int64_t unit_price, std::vector origpubkey) +vscript_t EncodeAssetOpRetV2(uint8_t assetFuncId, CAmount unit_price, vscript_t origpubkey, int32_t expiryHeight) { vscript_t vopret; uint8_t evalcode = EVAL_ASSETSV2; @@ -127,12 +126,13 @@ vscript_t EncodeAssetOpRetV2(uint8_t assetFuncId, uint256 assetid2, int64_t unit vopret = E_MARSHAL(ss << evalcode << assetFuncId << version); break; case 's': case 'b': case 'S': case 'B': - vopret = E_MARSHAL(ss << evalcode << assetFuncId << version << unit_price << origpubkey); + vopret = E_MARSHAL(ss << evalcode << assetFuncId << version << unit_price << origpubkey << expiryHeight); break; + /* swaps not implemented case 'E': case 'e': assetid2 = revuint256(assetid2); vopret = E_MARSHAL(ss << evalcode << assetFuncId << version << assetid2 << unit_price << origpubkey); - break; + break;*/ default: CCLogPrintF(ccassets_log, CCLOG_DEBUG1, "%s illegal funcid.%02x\n", __func__, assetFuncId); break; @@ -140,7 +140,7 @@ vscript_t EncodeAssetOpRetV2(uint8_t assetFuncId, uint256 assetid2, int64_t unit return(vopret); } -uint8_t DecodeAssetTokenOpRetV2(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &unit_price, std::vector &origpubkey) +uint8_t DecodeAssetTokenOpRetV2(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, CAmount &unit_price, vscript_t &origpubkey, int32_t &expiryHeight) { vscript_t vopretAssets; //, vopretAssetsStripped; uint8_t *script, funcId = 0, assetsFuncId = 0, dummyAssetFuncId, dummyEvalCode, version; @@ -149,7 +149,6 @@ uint8_t DecodeAssetTokenOpRetV2(const CScript &scriptPubKey, uint8_t &assetsEval std::vector oprets; tokenid = zeroid; - assetid2 = zeroid; unit_price = 0; assetsEvalCode = 0; assetsFuncId = 0; @@ -185,13 +184,13 @@ uint8_t DecodeAssetTokenOpRetV2(const CScript &scriptPubKey, uint8_t &assetsEval } break; case 's': case 'b': case 'S': case 'B': - if (E_UNMARSHAL(vopretAssets, ss >> dummyEvalCode; ss >> dummyAssetFuncId; ss >> version; ss >> unit_price; ss >> origpubkey) != 0) + if (E_UNMARSHAL(vopretAssets, ss >> dummyEvalCode; ss >> dummyAssetFuncId; ss >> version; ss >> unit_price; ss >> origpubkey; ss >> expiryHeight) != 0) { //fprintf(stderr,"DecodeAssetTokenOpRet() got price %lld\n",(long long)price); return(assetsFuncId); } break; - case 'E': case 'e': + /* case 'E': case 'e': // not implemented yet if (E_UNMARSHAL(vopretAssets, ss >> dummyEvalCode; ss >> dummyAssetFuncId; ss >> version; ss >> assetid2; ss >> unit_price; ss >> origpubkey) != 0) { @@ -199,7 +198,7 @@ uint8_t DecodeAssetTokenOpRetV2(const CScript &scriptPubKey, uint8_t &assetsEval assetid2 = revuint256(assetid2); return(assetsFuncId); } - break; + break; */ default: break; } @@ -213,9 +212,9 @@ uint8_t DecodeAssetTokenOpRetV2(const CScript &scriptPubKey, uint8_t &assetsEval // validate: // unit_price received for a token >= seller's unit_price // remaining_nValue calculated correctly -bool ValidateBidRemainder(CAmount unit_price, int64_t remaining_nValue, int64_t orig_nValue, int64_t received_nValue, int64_t paid_units) +bool ValidateBidRemainder(CAmount unit_price, CAmount remaining_nValue, CAmount orig_nValue, CAmount received_nValue, CAmount paid_units) { - int64_t received_unit_price; + CAmount received_unit_price; // int64_t new_unit_price = 0; if (orig_nValue == 0 || received_nValue == 0 || paid_units == 0) { @@ -254,7 +253,7 @@ bool ValidateBidRemainder(CAmount unit_price, int64_t remaining_nValue, int64_t // paid_units is tokens paid to the bidder // orig_units it the tokens amount the bidder wants to buy // paid_unit_price is unit_price that token seller sells his tokens for -bool SetBidFillamounts(CAmount unit_price, int64_t &received_nValue, int64_t orig_nValue, int64_t &paid_units, int64_t orig_units, CAmount paid_unit_price) +bool SetBidFillamounts(CAmount unit_price, CAmount &received_nValue, CAmount orig_nValue, CAmount &paid_units, CAmount orig_units, CAmount paid_unit_price) { // int64_t remaining_nValue; @@ -299,7 +298,7 @@ bool SetBidFillamounts(CAmount unit_price, int64_t &received_nValue, int64_t ori // fill_assetoshis is tokens purchased // orig_assetoshis is available tokens to sell // paid_nValue is the paid coins calculated as fill_assetoshis * paid_unit_price -bool SetAskFillamounts(CAmount unit_price, int64_t fill_assetoshis, int64_t orig_assetoshis, int64_t paid_nValue) +bool SetAskFillamounts(CAmount unit_price, CAmount fill_assetoshis, CAmount orig_assetoshis, CAmount paid_nValue) { //int64_t remaining_assetoshis; //double dunit_price; @@ -351,9 +350,9 @@ bool SetAskFillamounts(CAmount unit_price, int64_t fill_assetoshis, int64_t orig // validate: // paid unit_price for a token <= the bidder's unit_price // remaining coins calculated correctly -bool ValidateAskRemainder(CAmount unit_price, int64_t remaining_assetoshis, int64_t orig_assetoshis, int64_t received_assetoshis, int64_t paid_nValue) +bool ValidateAskRemainder(CAmount unit_price, CAmount remaining_assetoshis, CAmount orig_assetoshis, CAmount received_assetoshis, CAmount paid_nValue) { - int64_t paid_unit_price; + CAmount paid_unit_price; //CAmount unit_price = AssetsGetUnitPrice(ordertxid); //int64_t new_unit_price = 0; diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index 9bcc5efa9c6..e9adbbfbdd8 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -34,12 +34,13 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) auto addOrders = [&](struct CCcontract_info *cp, std::vector >::const_iterator it) { - uint256 txid, hashBlock, assetid, assetid2; - int64_t unit_price; - std::vector origpubkey; + uint256 txid, hashBlock, assetid; + CAmount unit_price; + vscript_t origpubkey; CTransaction ordertx; uint8_t funcid, evalCode; char origaddr[KOMODO_ADDRESS_BUFSIZE], origtokenaddr[KOMODO_ADDRESS_BUFSIZE]; + int32_t expiryHeight; txid = it->first.txhash; LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " checking txid=" << txid.GetHex() << std::endl); @@ -48,7 +49,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) return; } - if (ordertx.vout.size() > 1 && (funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, assetid2, unit_price, origpubkey)) != 0) + if (ordertx.vout.size() > 1 && (funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, unit_price, origpubkey, expiryHeight)) != 0) { LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " checking ordertx.vout.size()=" << ordertx.vout.size() << " funcid=" << (char)(funcid ? funcid : ' ') << " assetid=" << assetid.GetHex() << std::endl); @@ -59,16 +60,18 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) uint256 init_txid = txid; int32_t spentvin; int32_t height; + // try to get unspent partially filled order (if it is a search by global assets address) while(CCgetspenttxid(spenttxid, spentvin, height, init_txid, ASSETS_GLOBALADDR_VOUT) == 0 && IsTxidInActiveChain(spenttxid)) { init_txid = spenttxid; } if (init_txid != txid) { + // if it is a filled order load it txid = init_txid; if (!myGetTransaction(txid, ordertx, hashBlock)) { LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " could not load order txid=" << txid.GetHex() << std::endl); return; } - if ((funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, assetid2, unit_price, origpubkey)) == 0) { + if ((funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, unit_price, origpubkey, expiryHeight)) == 0) { LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " could not decode order txid=" << txid.GetHex() << std::endl); return; } @@ -101,8 +104,6 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) } if (assetid != zeroid) item.push_back(Pair("tokenid", assetid.GetHex())); - if (assetid2 != zeroid) - item.push_back(Pair("otherid", assetid2.GetHex())); if (unit_price > 0) { if (funcid == 's' || funcid == 'S' /*|| funcid == 'e' || funcid == 'E' not supported */) @@ -116,14 +117,15 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) item.push_back(Pair("price", ValueFromAmount(unit_price))); } } + if (expiryHeight > 0) + item.push_back(Pair("ExpiryHeight", expiryHeight)); + result.push_back(item); LOGSTREAM(ccassets_log, CCLOG_DEBUG1, stream << funcname << " added order funcId=" << (char)(funcid ? funcid : ' ') << " it->first.index=" << it->first.index << " ordertx.vout[it->first.index].nValue=" << ordertx.vout[it->first.index].nValue << " tokenid=" << assetid.GetHex() << std::endl); } } }; - - if (!pk.IsValid()) { std::vector > unspentOutputsTokens, unspentOutputsNFTs, unspentOutputsCoins; @@ -173,7 +175,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) // use marker on my pk: std::vector > unspentsMyAddr; char assetsMyAddr[KOMODO_ADDRESS_BUFSIZE]; - GetCCaddress(cpAssets, assetsMyAddr, pk, A::IsMixed()); + GetCCaddress1of2(cpAssets, assetsMyAddr, pk, GetUnspendable(cpAssets, NULL), A::IsMixed()); SetCCunspents(unspentsMyAddr, assetsMyAddr, true); for (std::vector >::const_iterator itOrders = unspentsMyAddr.begin(); itOrders != unspentsMyAddr.end(); @@ -185,7 +187,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) // rpc tokenbid implementation, locks 'bidamount' coins for the 'pricetotal' of tokens template -UniValue CreateBuyOffer(const CPubKey &mypk, int64_t txfee, int64_t bidamount, uint256 assetid, int64_t numtokens) +UniValue CreateBuyOffer(const CPubKey &mypk, CAmount txfee, CAmount bidamount, uint256 assetid, CAmount numtokens, int32_t expiryHeight) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); struct CCcontract_info *cpAssets, C; @@ -193,7 +195,7 @@ UniValue CreateBuyOffer(const CPubKey &mypk, int64_t txfee, int64_t bidamount, u CTransaction vintx; std::vector origpubkey; std::string name,description; - int64_t inputs; + CAmount inputs; std::vector oprets; if (bidamount <= 0 || numtokens <= 0) { @@ -230,11 +232,11 @@ UniValue CreateBuyOffer(const CPubKey &mypk, int64_t txfee, int64_t bidamount, u } CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, unspendableAssetsPubkey)); - mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk)); // marker for my orders + mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); // 1of2 marker for my orders UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, {}, // TODO: actually this tx is not 'tokens', maybe it is better not to have token opret here but only asset opret. - { A::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(mypk.begin(), mypk.end())) } )); // But still such token opret should not make problems because no token eval in these vouts + { A::EncodeAssetOpRet('b', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) } )); // But still such token opret should not make problems because no token eval in these vouts if (!ResultHasTx(sigData)) return MakeResultError("Could not finalize tx"); return sigData; @@ -246,10 +248,9 @@ UniValue CreateBuyOffer(const CPubKey &mypk, int64_t txfee, int64_t bidamount, u // rpc tokenask implementation, locks 'numtokens' tokens for the 'askamount' template -UniValue CreateSell(const CPubKey &mypk, int64_t txfee, int64_t numtokens, uint256 assetid, int64_t askamount) +UniValue CreateSell(const CPubKey &mypk, CAmount txfee, CAmount numtokens, uint256 assetid, CAmount askamount, int32_t expiryHeight) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - uint64_t mask = 0LL; struct CCcontract_info *cpAssets, assetsC; struct CCcontract_info *cpTokens, tokensC; @@ -285,7 +286,7 @@ UniValue CreateSell(const CPubKey &mypk, int64_t txfee, int64_t numtokens, uint2 CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), evalcodeAdd, numtokens, unspendableAssetsPubkey)); - mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk)); //marker (seems, it is not for my tokenorders, not used yet) + mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); // 1of2 marker (it is for my tokenorders) CAmount CCchange = inputs - numtokens; if (CCchange != 0LL) { // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) @@ -298,7 +299,7 @@ UniValue CreateSell(const CPubKey &mypk, int64_t txfee, int64_t numtokens, uint2 UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpTokens, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { unspendableAssetsPubkey }, - { A::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(mypk.begin(), mypk.end()) ) } )); + { A::EncodeAssetOpRet('s', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) } )); if (!ResultHasTx(sigData)) return MakeResultError("Could not finalize tx"); return sigData; @@ -314,6 +315,7 @@ UniValue CreateSell(const CPubKey &mypk, int64_t txfee, int64_t numtokens, uint2 } ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// +/* template std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal) { @@ -340,7 +342,7 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a if (AddNormalinputs(mtx, mypk, txfee, 0x10000) > 0) { mask = ~((1LL << mtx.vin.size()) - 1); - /*if ((inputs = AddAssetInputs(cp, mtx, mypk, assetid, askamount, 60)) > 0) + if ((inputs = AddAssetInputs(cp, mtx, mypk, assetid, askamount, 60)) > 0) { ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// if (inputs < askamount) { @@ -374,18 +376,19 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a } else { fprintf(stderr, "need some assets to place ask\n"); - } */ + } } else { // dimxy added 'else', because it was misleading message before fprintf(stderr,"need some native coins to place ask\n"); } return(""); -} ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// +} */ +////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// // unlocks coins, ends bid order template -UniValue CancelBuyOffer(const CPubKey &mypk, int64_t txfee,uint256 assetid,uint256 bidtxid) +UniValue CancelBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 bidtxid) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction vintx; @@ -398,17 +401,23 @@ UniValue CancelBuyOffer(const CPubKey &mypk, int64_t txfee,uint256 assetid,uint2 txfee = 10000; // add normal inputs only from my mypk (not from any pk in the wallet) to validate the ownership of the canceller - if (AddNormalinputsRemote(mtx, mypk, txfee /*+ ASSETS_MARKER_AMOUNT*/, 0x10000) > 0) + if (txfee <= ASSETS_MARKER_AMOUNT || AddNormalinputsRemote(mtx, mypk, txfee /*+ ASSETS_MARKER_AMOUNT*/, 0x10000) > 0) { uint256 spendingtxid; int32_t spendingvin, h; - uint64_t mask = 0LL; LOCK(cs_main); if ((CCgetspenttxid(spendingtxid, spendingvin, h, bidtxid, ASSETS_GLOBALADDR_VOUT) != 0 || !IsTxidInActiveChain(spendingtxid)) && myGetTransaction(bidtxid, vintx, hashBlock) && vintx.vout.size() > ASSETS_GLOBALADDR_VOUT) { - uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; CAmount dummyPrice; std::vector dummyOrigpubkey; + uint8_t dummyEvalCode; uint256 dummyAssetid; + CAmount dummyPrice; + vscript_t origpubkey; + int32_t expiryHeight; + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk; + + unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); CAmount bidamount = vintx.vout[ASSETS_GLOBALADDR_VOUT].nValue; if (bidamount == 0) { @@ -417,7 +426,7 @@ UniValue CancelBuyOffer(const CPubKey &mypk, int64_t txfee,uint256 assetid,uint2 } mtx.vin.push_back(CTxIn(bidtxid, ASSETS_GLOBALADDR_VOUT, CScript())); // coins in Assets - uint8_t funcid = A::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey); + uint8_t funcid = A::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, origpubkey, expiryHeight); if (funcid == 'b' && vintx.vout.size() > 1) mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' else if (funcid == 'B' && vintx.vout.size() > 3) @@ -431,15 +440,22 @@ UniValue CancelBuyOffer(const CPubKey &mypk, int64_t txfee,uint256 assetid,uint2 mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); else { // send dust back to global addr - mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, GetUnspendable(cpAssets, NULL))); + mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, unspendableAssetsPk)); std::cerr << __func__ << " dust detected bidamount=" << bidamount << std::endl; } - // mtx.vout.push_back(CTxOut(ASSETS_MARKER_AMOUNT, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // we dont need a marker for cancelled orders + // probe to spend marker: + if (mypk == pubkey2pk(origpubkey)) { + CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk + } else { + CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk + } UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, {}, - { A::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(mypk.begin(), mypk.end())) })); + { A::EncodeAssetOpRet('o', 0, vuint8_t(), 0) })); if (!ResultHasTx(sigData)) return MakeResultError("Could not finalize tx"); return sigData; @@ -454,11 +470,11 @@ UniValue CancelBuyOffer(const CPubKey &mypk, int64_t txfee,uint256 assetid,uint2 //unlocks tokens, ends ask order template -UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 asktxid) +UniValue CancelSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 asktxid) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx; uint64_t mask; - uint256 hashBlock; int64_t askamount; + CTransaction vintx; + uint256 hashBlock; CAmount askamount; struct CCcontract_info *cpTokens, *cpAssets, tokensC, assetsC; cpAssets = CCinit(&assetsC, A::EvalCode()); @@ -467,19 +483,19 @@ UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 txfee = 10000; // add normal inputs only from my mypk (not from any pk in the wallet) to validate the ownership - if (AddNormalinputsRemote(mtx, mypk, txfee /* + ASSETS_MARKER_AMOUNT*/, 0x10000) > 0) + if (txfee <= ASSETS_MARKER_AMOUNT || AddNormalinputsRemote(mtx, mypk, txfee, 0x10000) > 0) { uint256 spendingtxid; int32_t spendingvin, h; - mask = ~((1LL << mtx.vin.size()) - 1); LOCK(cs_main); if ((CCgetspenttxid(spendingtxid, spendingvin, h, asktxid, ASSETS_GLOBALADDR_VOUT) != 0 || !IsTxidInActiveChain(spendingtxid)) && myGetTransaction(asktxid, vintx, hashBlock) != 0 && vintx.vout.size() > 0) { uint8_t dummyEvalCode; - uint256 dummyAssetid, dummyAssetid2; - int64_t dummyPrice; - std::vector dummyOrigpubkey; + uint256 dummyAssetid; + CAmount dummyPrice; + vscript_t origpubkey; + int32_t expiryHeight; askamount = vintx.vout[ASSETS_GLOBALADDR_VOUT].nValue; if (askamount == 0) { @@ -488,7 +504,7 @@ UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 } mtx.vin.push_back(CTxIn(asktxid, ASSETS_GLOBALADDR_VOUT, CScript())); - uint8_t funcid = A::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey); + uint8_t funcid = A::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, origpubkey, expiryHeight); if (funcid == 's' && vintx.vout.size() > 1) mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // spend marker if funcid='s' else if (funcid == 'S' && vintx.vout.size() > 3) @@ -512,12 +528,21 @@ UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); // add additional eval-tokens unspendable assets privkey: - CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), cpAssets->evalcodeAdd, unspendableAssetsPk)); + CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), cpAssets->evalcodeAdd, unspendableAssetsPk)); // probe to spend ask remainder CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); + // probe to spend marker + if (mypk == pubkey2pk(origpubkey)) { + CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk + } else { + CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk + } + UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { mypk }, - { A::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(mypk.begin(), mypk.end())) } )); + { A::EncodeAssetOpRet('x', 0, vuint8_t(), 0) } )); if (!ResultHasTx(sigData)) return MakeResultError("Could not finalize tx"); return sigData; @@ -532,14 +557,13 @@ UniValue CancelSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 //send tokens, receive coins: template -UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 bidtxid, int64_t fill_units, CAmount paid_unit_price) +UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 bidtxid, CAmount fill_units, CAmount paid_unit_price) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction vintx; uint256 hashBlock; std::vector origpubkey; const int32_t bidvout = ASSETS_GLOBALADDR_VOUT; - uint64_t mask = 0LL; CAmount orig_units, unit_price, bid_amount, paid_amount, remaining_units, inputs; struct CCcontract_info *cpTokens, tokensC; struct CCcontract_info *cpAssets, assetsC; @@ -575,9 +599,10 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 if ((CCgetspenttxid(spendingtxid, spendingvin, h, bidtxid, bidvout) != 0 || !IsTxidInActiveChain(spendingtxid)) && myGetTransaction(bidtxid, vintx, hashBlock) != 0 && vintx.vout.size() > bidvout) { uint256 assetidOpret; + int32_t expiryHeight; bid_amount = vintx.vout[bidvout].nValue; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, vintx); // get orig pk, orig units + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, vintx); // get orig pk, orig units if (funcid != 'b' && funcid != 'B') { CCerror = "not an bid order"; return ""; @@ -626,7 +651,7 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 } mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator if (orig_units - fill_units > 0) // order is not finished yet - mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey + mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey, unspendableAssetsPk)); // vout3(4 if royalty) marker to origpubkey if (tokensChange != 0LL) mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), tokensChange, mypk)); // change in single-eval tokens @@ -637,9 +662,13 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 CCwrapper wrCond2(T::MakeTokensCCcond1(evalcodeAdd, mypk)); // spend my tokens to fill buy CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey + // probe to spend marker + CCwrapper wrCond3(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond3, nullptr); // spend with mypk + UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpTokens, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { pubkey2pk(origpubkey) }, - { A::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) })); + { A::EncodeAssetOpRet('B', unit_price, origpubkey, expiryHeight) })); if (!ResultHasTx(sigData)) return MakeResultError("Could not finalize tx"); return sigData; @@ -660,13 +689,12 @@ UniValue FillBuyOffer(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint2 // send coins, receive tokens template -UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 assetid2, uint256 asktxid, int64_t fillunits, CAmount paid_unit_price) +UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 asktxid, CAmount fillunits, CAmount paid_unit_price) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction vintx; uint256 hashBlock; std::vector origpubkey; - uint64_t mask = 0; const int32_t askvout = ASSETS_GLOBALADDR_VOUT; CAmount unit_price, orig_assetoshis, paid_nValue; struct CCcontract_info *cpAssets, assetsC; @@ -676,11 +704,6 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a CCerror = strprintf("negative fillunits %lld\n",(long long)fillunits); return(""); } - if (assetid2 != zeroid) - { - CCerror = "asset swaps disabled"; - return(""); - } TokenDataTuple tokenData; vuint8_t vextraData; @@ -706,8 +729,9 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a if ((CCgetspenttxid(spendingtxid, spendingvin, h, asktxid, askvout) != 0 || !IsTxidInActiveChain(spendingtxid)) && myGetTransaction(asktxid, vintx, hashBlock) && vintx.vout.size() > askvout) { uint256 assetidOpret; + int32_t expiryHeight; orig_assetoshis = vintx.vout[askvout].nValue; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, vintx); // get orig pk, orig value + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, vintx); // get orig pk, orig value if (funcid != 's' && funcid != 'S') { CCerror = "not an ask order"; return ""; @@ -732,12 +756,6 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a if (royaltyFract > 0 && paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) // if value paid to seller less than when the royalty is minimum royaltyValue = 0LL; - if (assetid2 != zeroid) { - // inputs = AddAssetInputs(cpAssets, mtx, mypk, assetid2, paid_nValue, 60); // not implemented yet - CCerror = "swaps not implemented"; - return ""; - } - // Use only one AddNormalinputs() in each rpc call to allow payment if user has only single utxo with normal funds CAmount inputs = AddNormalinputs(mtx, mypk, txfee + ASSETS_MARKER_AMOUNT + paid_nValue, 0x10000, IsRemoteRPCCall()); if (inputs > 0) @@ -772,20 +790,22 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a } if (orig_assetoshis - fillunits > 0) // we dont need the marker if order is filled - mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) + mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey, GetUnspendable(cpAssets, NULL))); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) // init assets 'unspendable' privkey and pubkey uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), evalcodeAdd, unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); + CCwrapper wrCond1(T::MakeTokensCCcond1(A::EvalCode(), evalcodeAdd, unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond1, unspendableAssetsPrivkey); - //cpAssets->evalcodeAdd = evalcodeAdd; // set token eval for signing + // probe to spend marker + CCwrapper wrCond2(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond2, nullptr); // spend with mypk UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { mypk }, - { A::EncodeAssetOpRet('S', assetid2, unit_price, origpubkey) } )); + { A::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) } )); if (!ResultHasTx(sigData)) return MakeResultError("Could not finalize tx"); return sigData; @@ -795,7 +815,7 @@ UniValue FillSell(const CPubKey &mypk, int64_t txfee, uint256 assetid, uint256 a } } CCerror = "can't get ask tx"; - return(""); + return ""; } #endif // #ifndef CC_ASSETS_TX_IMPL_H diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 36ef836cb15..e7db68faa5f 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -883,7 +883,7 @@ extern std::vector NULL_pubkeys; //!< constant value for use in functio /// @param opret opreturn vout which function will add if it is not empty /// @param pubkeys array of pubkeys to make multiple probe 1of2 cc's with the call Make1of2cond(cp->evalcode, globalpk, pubkeys[i]) /// @returns signed transaction in hex encoding -std::string FinalizeCCTx(uint32_t changeFlag,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector pubkeys = NULL_pubkeys); +std::string FinalizeCCTx(uint32_t changeFlag, struct CCcontract_info* cp, CMutableTransaction& mtx, CPubKey mypk, CAmount txfee, CScript opret, std::vector pubkeys = NULL_pubkeys); /// FinalizeCCTx is a very useful function that will properly sign both CC and normal inputs, adds normal change and might add an opreturn output. /// This allows for Antara module transaction creation rpc functions to create an CMutableTransaction object, add the appropriate vins and vouts to it and use FinalizeCCTx to properly sign the transaction. @@ -903,11 +903,11 @@ std::string FinalizeCCTx(uint32_t changeFlag,struct CCcontract_info *cp,CMutable /// @param opret opreturn vout which function will add if it is not empty /// @param pubkeys array of pubkeys to make multiple probe 1of2 cc's with the call Make1of2cond(cp->evalcode, globalpk, pubkeys[i]) /// @returns signed transaction in hex encoding -UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector pubkeys = NULL_pubkeys); +UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, CAmount txfee, CScript opret, std::vector pubkeys = NULL_pubkeys); /// version FinalizeCCTx for CC v2, for params @see FinalizeCCTxExt /// @returns signed transaction in hex and optional PartiallySigned univalue object with vin indexes and partially signed conditions (if signature threshold not reached) -UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret); +UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, CAmount txfee, CScript opret); /// Add signature to multisig scriptSig /// @param mtx mutable tx with multisig cc vins diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index 63b92c2e313..95f3e275e80 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -329,23 +329,27 @@ class TokensV1 { } // vouts: - static CTxOut MakeCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector>* vData = NULL) + static CTxOut MakeCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector* vData = NULL) { return ::MakeCC1vout(evalcode, nValue, pk, vData); } - static CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector>* vData = NULL) + static CTxOut MakeCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector* vData = NULL) + { + return ::MakeCC1of2vout(evalcode, nValue, pk1, pk2, vData); + } + static CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector* vData = NULL) { return ::MakeTokensCC1vout(evalcode, nValue, pk, vData); } - static CTxOut MakeTokensCC1vout(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, CPubKey pk, std::vector>* vData = NULL) + static CTxOut MakeTokensCC1vout(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, CPubKey pk, std::vector* vData = NULL) { return ::MakeTokensCC1vout(evalcode1, evalcode2, nValue, pk, vData); } - static CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector>* vData = NULL) + static CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector* vData = NULL) { return ::MakeTokensCC1of2vout(evalcode, nValue, pk1, pk2, vData); } - static CTxOut MakeTokensCC1of2vout(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector>* vData = NULL) + static CTxOut MakeTokensCC1of2vout(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector* vData = NULL) { return ::MakeTokensCC1of2vout(evalcode1, evalcode2, nValue, pk1, pk2, vData); } @@ -360,7 +364,7 @@ class TokensV1 { return CTxOut(); } - static UniValue FinalizeCCTx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret) + static UniValue FinalizeCCTx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, CAmount txfee, CScript opret) { return ::FinalizeCCTxExt(remote, changeFlag, cp, mtx, mypk, txfee, opret); } @@ -416,6 +420,10 @@ class TokensV2 { { return ::MakeCC1voutMixed(evalcode, nValue, pk, (pvvData != nullptr ? &(*pvvData)[0] : nullptr)); } + static CTxOut MakeCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector* pvvData = NULL) + { + return ::MakeCC1of2voutMixed(evalcode, nValue, pk1, pk2, (pvvData != nullptr ? &(*pvvData)[0] : nullptr)); + } static CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector* pvvData = NULL) { return ::MakeTokensCC1voutMixed(evalcode, nValue, pk, (pvvData != nullptr ? &(*pvvData)[0] : nullptr)); @@ -437,7 +445,7 @@ class TokensV2 { { return ::MakeTokensCCMofNvoutMixed(evalcode1, evalcode2, nValue, M, pks, (pvvData != nullptr ? &(*pvvData)[0] : nullptr)); } - static UniValue FinalizeCCTx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret) + static UniValue FinalizeCCTx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, CAmount txfee, CScript opret) { return ::FinalizeCCV2Tx(remote, changeFlag, cp, mtx, mypk, txfee, opret); } diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 82a83ef29f4..742918d8312 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -42,7 +42,7 @@ This allows the contract transaction functions to create the appropriate vins an By using -addressindex=1, it allows tracking of all the CC addresses */ -std::string FinalizeCCTx(uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector pubkeys) +std::string FinalizeCCTx(uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, CAmount txfee, CScript opret, std::vector pubkeys) { UniValue sigData = FinalizeCCTxExt(false, changeFlag, cp, mtx, mypk, txfee, opret, pubkeys); return sigData[JSON_HEXTX].getValStr(); @@ -50,7 +50,7 @@ std::string FinalizeCCTx(uint32_t changeFlag, struct CCcontract_info *cp, CMutab // extended version that supports signInfo object with conds to vins map for remote cc calls -UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector pubkeys) +UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, CAmount 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; @@ -426,7 +426,7 @@ UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_inf } // extended version that supports signInfo object with conds to vins map for remote cc calls - for V2 mixed mode cc vins -UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info* cp, CMutableTransaction& mtx, CPubKey mypk, uint64_t txfee, CScript opret) +UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info* cp, CMutableTransaction& mtx, CPubKey mypk, CAmount txfee, CScript opret) { auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); CTransaction vintx; diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 50a4b722f3a..147711326d6 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -164,7 +164,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const static uint256 zero; CTxDestination address; CTransaction vinTx, createTx; - uint256 hashBlock, assetid, assetid2; + uint256 hashBlock, assetid; int32_t ccvins = -1, ccvouts = -1; int64_t unit_price, vin_unit_price; vuint8_t vorigpubkey, vin_origpubkey, vextraData; @@ -173,6 +173,9 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const char destaddr[KOMODO_ADDRESS_BUFSIZE], origNormalAddr[KOMODO_ADDRESS_BUFSIZE], ownerNormalAddr[KOMODO_ADDRESS_BUFSIZE]; char origTokensCCaddr[KOMODO_ADDRESS_BUFSIZE], origCCaddrDummy[KOMODO_ADDRESS_BUFSIZE]; char tokensDualEvalUnspendableCCaddr[KOMODO_ADDRESS_BUFSIZE], origAssetsCCaddr[KOMODO_ADDRESS_BUFSIZE], globalAssetsCCaddr[KOMODO_ADDRESS_BUFSIZE]; + char markerCCaddress[KOMODO_ADDRESS_BUFSIZE]; + int32_t expiryHeight, vin_expiryHeight; + std::vector::const_iterator ccvin, markervin; CAmount vin_tokens = 0; CAmount vin_coins = 0; @@ -182,7 +185,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (tx.vout.size() == 0) return eval->Invalid("AssetValidate: no vouts"); - if((funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCodeInOpret, assetid, assetid2, unit_price, vorigpubkey)) == 0 ) + if((funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCodeInOpret, assetid, unit_price, vorigpubkey, expiryHeight)) == 0 ) return eval->Invalid("AssetValidate: invalid opreturn payload"); // reinit cpAssets as we could set evalcodeAdd in it @@ -210,14 +213,19 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const GetTokensCCaddress(cpAssets, tokensDualEvalUnspendableCCaddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); // originator cc address, this is for marker validation: - GetCCaddress(cpAssets, origAssetsCCaddr, vorigpubkey, A::IsMixed()); + GetCCaddress(cpAssets, origAssetsCCaddr, pubkey2pk(vorigpubkey), A::IsMixed()); // global cc address: GetCCaddress(cpAssets, globalAssetsCCaddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); - if( IsCCInput(tx.vin[0].scriptSig) != false ) // vin0 should be normal vin - return eval->Invalid("illegal asset cc vin0"); - else if(tx.vout.size() < 2) + // marker cc address: + GetCCaddress1of2(cpAssets, markerCCaddress, pubkey2pk(vorigpubkey), GetUnspendable(cpAssets, NULL), A::IsMixed()); + + // cancelask/bid could have no normal vins (taking txfee from marker): + // if( IsCCInput(tx.vin[0].scriptSig) != false ) // vin0 should be normal vin + // return eval->Invalid("illegal asset cc vin0"); + + if(tx.vout.size() < 2) return eval->Invalid("too few vouts"); // it was if(numvouts < 1) but it refers at least to vout[1] below if (assetid == zeroid) @@ -252,7 +260,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("too few vouts"); else if(A::ConstrainVout(tx.vout[0], CCVOUT, globalAssetsCCaddr, 0LL, A::EvalCode()) == false) return eval->Invalid("invalid funding for bid"); - else if(A::ConstrainVout(tx.vout[1], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false) // marker to originator asset cc addr + else if(A::ConstrainVout(tx.vout[1], CCVOUT, markerCCaddress, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false) // marker to originator asset cc addr return eval->Invalid("invalid vout1 marker for original pubkey"); else if(TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vorigpubkey)) == 0) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for bid"); @@ -280,7 +288,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //vout.n-1: opreturn [EVAL_ASSETS] ['o'] ccvins = 2; // order and marker ccvouts = 0; - vin_coins = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origCCaddrDummy, origNormalAddr, tx, assetid); + + vin_coins = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origCCaddrDummy, origNormalAddr, vin_expiryHeight, tx, assetid); if (vin_coins == 0) return false; // eval already set @@ -293,8 +302,20 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("invalid dust refund for cancelbid"); ccvouts ++; } - if (TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vin_origpubkey)) == 0) // check tx is signed by originator pubkey - return eval->Invalid("not the originator pubkey signed for cancelbid"); + // get first ccvin: + ccvin = std::find_if(tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin) { return cpAssets->ismyvin(vin.scriptSig); }); + if (ccvin == tx.vin.end()) + return eval->Invalid("cc vin not found"), 0LL; + // get marker ccvin: + markervin = ccvin + 1; + if (markervin >= tx.vin.end()) + return eval->Invalid("marker vin not found"), 0LL; + + if (check_signing_pubkey(markervin->scriptSig) != pubkey2pk(vin_origpubkey)) { // check marker is signed by originator pubkey + if (eval->GetCurrentHeight() < vin_expiryHeight) + return eval->Invalid("not the originator pubkey signed for cancelbid for not yet expired orders"); + // allow to sign with globalpk to cancel the expired order + } break; case 'B': // fillbid: @@ -309,8 +330,11 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //vout.5: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['B'] [assetid] [remaining asset required] [origpubkey] ccvins = 1; - ccvouts = 0; // at least tokens output - vin_coins = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid); + ccvouts = 0; + if (tx.vout.size() < 2) + return eval->Invalid("too few vouts"), 0LL; + + vin_coins = AssetValidateBuyvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, vin_expiryHeight, tx, assetid); if (vin_coins == 0) return false; // eval already set else if(tx.vout.size() < 3) @@ -321,6 +345,9 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("mismatched unit price for fillbid"); else if (unit_price <= 0) return eval->Invalid("invalid unit price"); + else if (expiryHeight != vin_expiryHeight) { + return eval->Invalid("invalid expiry height"); + } else { if (royaltyFract < 0LL || royaltyFract >= TKLROYALTY_DIVISOR) @@ -382,7 +409,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (tx.vout[0].nValue / unit_price > 0) { // bid coins remainder sufficient for more tokens - marker should exist int32_t markerVout = 3 + r; - if (tx.vout.size() <= markerVout || !A::ConstrainVout(tx.vout[markerVout], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode())) // marker to originator asset cc addr + if (tx.vout.size() <= markerVout || !A::ConstrainVout(tx.vout[markerVout], CCVOUT, markerCCaddress, ASSETS_MARKER_AMOUNT, A::EvalCode())) // marker to originator asset cc addr return eval->Invalid("invalid vout" + std::to_string(markerVout) + " marker for originator pubkey for fillbid"); ccvouts ++; } @@ -425,7 +452,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("too few vouts"); else if (A::ConstrainVout(tx.vout[0], CCVOUT, tokensDualEvalUnspendableCCaddr, 0LL, T::EvalCode()) == false) // tokens sent to global addr return eval->Invalid("invalid vout0 global two eval address for sell"); - else if( A::ConstrainVout(tx.vout[1], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr + else if( A::ConstrainVout(tx.vout[1], CCVOUT, markerCCaddress, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr return eval->Invalid("invalid vout1 marker for originator pubkey"); else if (TotalPubkeyNormalInputs(eval, tx, origpk) == 0) // check tx is signed by originator pubkey return eval->Invalid("not the originator pubkey signed for ask"); @@ -452,13 +479,30 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //vout.1: vin.2 back to users pubkey //vout.2: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid] - vin_tokens = AssetValidateSellvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid); + if (tx.vout.size() < 2) + return eval->Invalid("too few vouts"), 0LL; + + vin_tokens = AssetValidateSellvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, vin_expiryHeight, tx, assetid); if (vin_tokens == 0) return false; // eval already set - else if (A::ConstrainVout(tx.vout[0], CCVOUT, origTokensCCaddr, vin_tokens, T::EvalCode()) == false) // tokens returning to originator cc addr + + if (A::ConstrainVout(tx.vout[0], CCVOUT, origTokensCCaddr, vin_tokens, T::EvalCode()) == false) // tokens returning to originator cc addr return eval->Invalid("invalid vout0 for cancelask"); - else if (TotalPubkeyNormalInputs(eval, tx, pubkey2pk(vin_origpubkey)) == 0) // check tx is signed by originator pubkey - return eval->Invalid("not the originator pubkey signed for cancelask"); + + // get first ccvin: + ccvin = std::find_if(tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin) { return cpAssets->ismyvin(vin.scriptSig); }); + if (ccvin == tx.vin.end()) + return eval->Invalid("cc vin not found"), 0LL; + // get marker ccvin: + markervin = ccvin + 1; + if (markervin >= tx.vin.end()) + return eval->Invalid("marker vin not found"), 0LL; + + if (check_signing_pubkey(markervin->scriptSig) != pubkey2pk(vin_origpubkey)) { // check marker is signed by originator pubkey + if (eval->GetCurrentHeight() < vin_expiryHeight) + return eval->Invalid("not the originator pubkey signed for cancelask for not yet expired orders"); + // allow to sign with globalpk to cancel the expired order + } ccvins = 2; // order and marker vins ccvouts = 1; // token back to the originator break; @@ -474,7 +518,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const //'S'.vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey] ccvins = 1; ccvouts = 2; - vin_tokens = AssetValidateSellvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, tx, assetid); + vin_tokens = AssetValidateSellvin(cpAssets, eval, vin_unit_price, vin_origpubkey, origTokensCCaddr, origNormalAddr, vin_expiryHeight, tx, assetid); if (vin_tokens == 0) return false; // eval is already set else if (tx.vout.size() < 3) @@ -483,6 +527,9 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("mismatched origpubkeys for fillask"); else if (unit_price != vin_unit_price) return eval->Invalid("mismatched unit price for fillask"); + else if (expiryHeight != vin_expiryHeight) { + return eval->Invalid("invalid expiry height"); + } else { if (vin_tokens != tx.vout[0].nValue + tx.vout[1].nValue) @@ -514,7 +561,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (tx.vout[0].nValue > 0) { int32_t markerVout = r > 0 ? 4 : 3; // marker should exist if remainder not empty - if (tx.vout.size() <= markerVout || A::ConstrainVout(tx.vout[markerVout], CCVOUT, origAssetsCCaddr, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false) // marker to originator asset cc addr + if (tx.vout.size() <= markerVout || A::ConstrainVout(tx.vout[markerVout], CCVOUT, markerCCaddress, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false) // marker to originator asset cc addr return eval->Invalid("invalid marker vout for original pubkey"); ccvouts ++; } diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 7430016b632..e14a8bff4f6 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -295,7 +295,7 @@ static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, if (ensure_CCrequirements(V::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - if (!EnsureWalletIsAvailable(false)) + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) throw runtime_error("wallet is required"); LOCK2(cs_main, pwalletMain->cs_wallet); // remote call not supported yet @@ -307,7 +307,6 @@ static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, if (supply <= 0) return MakeResultError("Token supply must be positive"); - if (params.size() >= 3) { description = params[2].get_str(); if (description.size() > TOKENS_MAX_DESC_LENGTH) @@ -413,7 +412,7 @@ UniValue tokenv2createtokel(const UniValue& params, bool fHelp, const CPubKey& r else if (params[3].getType() == UniValue::VSTR) // json in quoted string '{...}' jsonParams.read(params[3].get_str().c_str()); if (jsonParams.getType() != UniValue::VOBJ) - throw runtime_error("parameter 4 must be a json object\n"); + return MakeResultError("parameter 4 must be a json object\n"); tokenData = ParseTokelJson(jsonParams); if (tokenData.empty()) @@ -444,7 +443,7 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b if (ensure_CCrequirements(V::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - if (!EnsureWalletIsAvailable(false)) + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) throw runtime_error("wallet is required"); LOCK2(cs_main, pwalletMain->cs_wallet); // remote call not supported yet @@ -473,7 +472,7 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b else { if (V::EvalCode() != EVAL_TOKENSV2) - throw runtime_error("MofN transfer is supported only for tokens v2\n"); + return MakeResultError("MofN transfer is supported only for tokens v2\n"); UniValue jsonParams(UniValue::VOBJ); if (params[0].getType() == UniValue::VOBJ) @@ -481,7 +480,7 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b else if (params[0].getType() == UniValue::VSTR) // json in quoted string '{...}' jsonParams.read(params[0].get_str().c_str()); if (jsonParams.getType() != UniValue::VOBJ) - throw runtime_error("parameter 1 must be object\n"); + return MakeResultError("parameter 1 must be object\n"); uint256 tokenid = Parseuint256(jsonParams["tokenid"].get_str().c_str()); if( tokenid == zeroid ) @@ -491,16 +490,16 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b if (!jsonParams["ccaddressMofN"].isNull()) { ccaddressMofN = jsonParams["ccaddressMofN"].get_str(); if (!CBitcoinAddress(ccaddressMofN).IsValid()) - throw runtime_error("invalid ccaddressMofN\n"); + return MakeResultError("invalid ccaddressMofN\n"); } std::vector pks; UniValue udestpks = jsonParams["destpubkeys"]; if (!udestpks.isArray()) - throw runtime_error("destpubkeys must be an array\n"); + return MakeResultError("destpubkeys must be an array\n"); if (udestpks.size() > 128) - throw runtime_error("destpubkeys num is limited by 128\n"); + return MakeResultError("destpubkeys num is limited by 128\n"); for (int i = 0; i < udestpks.size(); i ++) { vuint8_t vpubkey(ParseHex(udestpks[i].get_str().c_str())); @@ -510,9 +509,9 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b } int M = jsonParams["M"].get_int(); if (M > 128) - throw runtime_error("M is limited by 128\n"); + return MakeResultError("M is limited by 128\n"); if (M > pks.size()) - throw runtime_error("M could not be more than dest pubkeys\n"); + return MakeResultError("M could not be more than dest pubkeys\n"); CAmount amount = jsonParams["amount"].get_int64(); if( amount <= 0 ) @@ -557,9 +556,9 @@ UniValue tokentransfermany(const std::string& name, const UniValue& params, bool CCerror.clear(); - if ( fHelp || params.size() < 3) + if (fHelp || params.size() < 3) throw runtime_error(name + " tokenid1 tokenid2 ... destpubkey amount \n"); - if ( ensure_CCrequirements(V::EvalCode()) < 0 ) + if (ensure_CCrequirements(V::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); std::vector tokenids; @@ -579,7 +578,7 @@ UniValue tokentransfermany(const std::string& name, const UniValue& params, bool if( amount <= 0 ) return MakeResultError("amount must be positive"); - if (!EnsureWalletIsAvailable(false)) + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) throw runtime_error("wallet is required"); LOCK2(cs_main, pwalletMain->cs_wallet); // remote call not supported yet @@ -638,9 +637,9 @@ UniValue tokenconvert(const UniValue& params, bool fHelp, const CPubKey& mypk) { UniValue result(UniValue::VOBJ); std::string hex; int32_t evalcode; int64_t amount; uint256 tokenid; CCerror.clear(); - if ( fHelp || params.size() != 4 ) + if (fHelp || params.size() != 4) throw runtime_error("tokenconvert evalcode tokenid pubkey amount\n"); - if ( ensure_CCrequirements(EVAL_ASSETS) < 0 ) + if (ensure_CCrequirements(EVAL_ASSETS) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); const CKeyStore& keystore = *pwalletMain; if (!EnsureWalletIsAvailable(false)) @@ -681,12 +680,12 @@ UniValue tokenbid(const std::string& name, const UniValue& params, bool fHelp, c uint256 tokenid; CCerror.clear(); - if ( fHelp || params.size() != 3 ) - throw runtime_error(name + " numtokens tokenid price\n"); + if (fHelp || params.size() < 3 || params.size() > 4) + throw runtime_error(name + " numtokens tokenid price [expiry-height]\n"); if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - if (!EnsureWalletIsAvailable(false)) + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) throw runtime_error("wallet is required"); CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !remotepk.IsValid()); @@ -696,17 +695,23 @@ UniValue tokenbid(const std::string& name, const UniValue& params, bool fHelp, c bidamount = (price * numtokens); if (price <= 0) return MakeResultError("price must be positive"); - if (tokenid == zeroid) return MakeResultError("invalid tokenid"); - if (bidamount <= 0) return MakeResultError("bid amount must be positive"); + int32_t expiryHeight = std::numeric_limits::max(); + if (params.size() == 4) { + expiryHeight = atol(params[3].get_str().c_str()); + if (!remotepk.IsValid() && expiryHeight < chainActive.LastTip()->GetHeight()) + return MakeResultError("expiry height invalid"); + + } + CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - result = CreateBuyOffer(mypk, 0, bidamount, tokenid, numtokens); + result = CreateBuyOffer(mypk, 0, bidamount, tokenid, numtokens, expiryHeight); else { hex = tokensv0::CreateBuyOffer(0, bidamount, tokenid, numtokens); if (!hex.empty()) @@ -738,7 +743,7 @@ UniValue tokencancelbid(const std::string& name, const UniValue& params, bool fH if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - if (!EnsureWalletIsAvailable(false)) + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) throw runtime_error("wallet is required"); CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !remotepk.IsValid()); @@ -786,7 +791,7 @@ UniValue tokenfillbid(const std::string& name, const UniValue& params, bool fHel if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - if (!EnsureWalletIsAvailable(false)) + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) throw runtime_error("wallet is required"); CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !remotepk.IsValid()); @@ -836,12 +841,12 @@ UniValue tokenask(const std::string& name, const UniValue& params, bool fHelp, c uint256 tokenid; CCerror.clear(); - if (fHelp || params.size() != 3) - throw runtime_error(name + " numtokens tokenid price\n"); + if (fHelp || params.size() < 3 || params.size() > 4) + throw runtime_error(name + " numtokens tokenid price [expiry-height]\n"); if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - if (!EnsureWalletIsAvailable(false)) + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) throw runtime_error("wallet is required"); CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !remotepk.IsValid()); @@ -849,14 +854,27 @@ UniValue tokenask(const std::string& name, const UniValue& params, bool fHelp, c tokenid = Parseuint256((char *)params[1].get_str().c_str()); CAmount price = AmountFromValue(params[2]); askamount = (price * numtokens); - if (tokenid == zeroid || numtokens <= 0 || price <= 0 || askamount <= 0) - return MakeResultError("invalid parameter"); + if (tokenid == zeroid) + return MakeResultError("tokenid invalid"); + if (numtokens <= 0) + return MakeResultError("numtokens invalid"); + if (price <= 0) + return MakeResultError("price invalid"); + if (askamount <= 0) + return MakeResultError("askamount invalid"); + + int32_t expiryHeight = std::numeric_limits::max(); + if (params.size() == 4) { + expiryHeight = atol(params[3].get_str().c_str()); + if (!remotepk.IsValid() && expiryHeight < chainActive.LastTip()->GetHeight()) + return MakeResultError("expiry height invalid"); + } CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - result = CreateSell(mypk, 0, numtokens, tokenid, askamount); + result = CreateSell(mypk, 0, numtokens, tokenid, askamount, expiryHeight); else { hex = tokensv0::CreateSell(0, numtokens, tokenid, askamount); if (!hex.empty()) @@ -895,6 +913,7 @@ UniValue tokenswapask(const UniValue& params, bool fHelp, const CPubKey& remotep throw runtime_error("tokenswapask not supported\n"); + /* numtokens = atoll(params[0].get_str().c_str()); tokenid = Parseuint256((char *)params[1].get_str().c_str()); otherid = Parseuint256((char *)params[2].get_str().c_str()); @@ -903,14 +922,15 @@ UniValue tokenswapask(const UniValue& params, bool fHelp, const CPubKey& remotep hex = CreateSwap(0,numtokens,tokenid,otherid,askamount); RETURN_IF_ERROR(CCerror); if (price > 0 && numtokens > 0) { - if ( hex.size() > 0 ) - { + if (hex.size() > 0) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else ERR_RESULT("couldnt create swap"); + } else + ERR_RESULT("couldnt create swap"); } else { ERR_RESULT("price and numtokens must be positive"); } + */ return result; } @@ -972,7 +992,7 @@ UniValue tokenfillask(const std::string& name, const UniValue& params, bool fHel if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - if (!EnsureWalletIsAvailable(false)) + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) throw runtime_error("wallet is required"); CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !remotepk.IsValid()); @@ -990,7 +1010,7 @@ UniValue tokenfillask(const std::string& name, const UniValue& params, bool fHel CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - result = FillSell(mypk, 0, tokenid, zeroid, asktxid, fillunits, unit_price); + result = FillSell(mypk, 0, tokenid, asktxid, fillunits, unit_price); else { hex = tokensv0::FillSell(0, tokenid, zeroid, asktxid, fillunits); if (!hex.empty()) @@ -1021,7 +1041,7 @@ UniValue tokenfillswap(const UniValue& params, bool fHelp, const CPubKey& remote CCerror.clear(); if (fHelp || params.size() != 4 && params.size() != 5) throw runtime_error("tokenfillswap tokenid otherid asktxid fillunits [unitprice]\n"); - if (ensure_CCrequirements(EVAL_ASSETS) < 0) + if (!remotepk.IsValid() && ensure_CCrequirements(EVAL_ASSETS) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!EnsureWalletIsAvailable(false)) @@ -1040,7 +1060,7 @@ UniValue tokenfillswap(const UniValue& params, bool fHelp, const CPubKey& remote unit_price = AmountFromValue(params[4].get_str().c_str()); CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); - result = FillSell(mypk,0,tokenid,otherid,asktxid,fillunits, unit_price); + result = FillSell(mypk, 0, tokenid, asktxid, fillunits, unit_price); RETURN_IF_ERROR(CCerror); if (fillunits > 0) { if ( hex.size() > 0 ) { diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index ff25b685bbb..7aee2b941bd 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -56,7 +56,12 @@ class EvalMock : public Eval } } const std::map & getTxs() { return txs; } - bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const + void SetCurrentHeight(int h) + { + currentHeight = h; + } + + virtual bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const { //std::cerr <<__func__ << " hash=" << hash.GetHex() << std::endl; auto r = txs.find(hash); @@ -69,6 +74,10 @@ class EvalMock : public Eval } return false; } + virtual unsigned int GetCurrentHeight() const + { + return currentHeight; + } }; static EvalMock eval; @@ -163,6 +172,7 @@ bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vin // in functions like cp->ismyvin() or TotalPubkeyNormalAmount() bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_t *myprivkey, CAmount txfee, CScript opret) { + std::cerr << __func__ << " enterred" << std::endl; auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); CAmount totaloutputs = 0LL; for (int i = 0; i < mtx.vout.size(); i ++) @@ -190,7 +200,7 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ } if (!myprivkey) { - std::cerr << __func__ << "myprivkey not set" << std::endl; + std::cerr << __func__ << " myprivkey not set" << std::endl; return false; } @@ -216,7 +226,7 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ GetTokensCCaddress(cp, mytokenaddr, mypk, true); // get token or nft probe PrecomputedTransactionData txdata(mtx); - for (int i = 0; i < mtx.vin.size(); i++) + for (int i = 0; i < mtx.vin.size(); i ++) { CTransaction vintx; uint256 hashBlock; @@ -249,24 +259,22 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ } else { char destaddr[KOMODO_ADDRESS_BUFSIZE]; if (!Getscriptaddress(destaddr, vintx.vout[mtx.vin[i].prevout.n].scriptPubKey)) { - std::cerr << __func__ << " could not Getscriptaddress for scriptPubKey=" << vintx.vout[mtx.vin[i].prevout.n].scriptPubKey.ToString() << std::endl; + std::cerr << __func__ << " vini." << i << " could not Getscriptaddress for scriptPubKey=" << vintx.vout[mtx.vin[i].prevout.n].scriptPubKey.ToString() << std::endl; return false; } if (strcmp(destaddr, globaladdr) == 0) { - std::cerr << __func__ << " found globaladdress=" << globaladdr << " destaddr=" << destaddr << " strlen=" << strlen(globaladdr) << " evalcode=" << (int)cp->evalcode << std::endl; - privkey = cp->CCpriv; cond.reset(MakeCCcond1(cp->evalcode, globalpk)); + std::cerr << __func__ << " vini." << i << " found globaladdress=" << globaladdr << " destaddr=" << destaddr << " strlen=" << strlen(globaladdr) << " evalcode=" << (int)cp->evalcode << std::endl; } else if (strcmp(destaddr, myccaddr) == 0) { privkey = myprivkey; cond.reset(MakeCCcond1(cp->evalcode, mypk)); - std::cerr << __func__ << " found myccaddr=" << myccaddr << std::endl; - + std::cerr << __func__ << " vini." << i << " found myccaddr=" << myccaddr << std::endl; } else if (strcmp(destaddr, mytokenaddr) == 0) { privkey = myprivkey; cond.reset(MakeTokensv2CCcond1(cp->evalcode, cp->evalcodeAdd, mypk)); - std::cerr << __func__ << " found mytokenaddr=" << mytokenaddr << " evalcode=" << (int)cp->evalcode << " evalcodeAdd=" << (int)cp->evalcodeAdd << std::endl; + std::cerr << __func__ << " vini." << i << " found mytokenaddr=" << mytokenaddr << " evalcode=" << (int)cp->evalcode << " evalcodeAdd=" << (int)cp->evalcodeAdd << std::endl; } else { const uint8_t nullpriv[32] = {'\0'}; // use vector of dest addresses and conds to probe vintxconds @@ -277,7 +285,7 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ CCtoAnon(anonCond.get()); Getscriptaddress(coinaddr, CCPubKey(anonCond.get(), true)); if (strcmp(destaddr, coinaddr) == 0) { - std::cerr << __func__ << " found vintxprobe=" << coinaddr << " privkey=" << (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) << std::endl; + std::cerr << __func__ << " vini." << i << " found vintxprobe=" << coinaddr << " privkey=" << (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) << std::endl; if (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) privkey = t.CCpriv; else @@ -418,30 +426,30 @@ class TestAssetsCC : public ::testing::Test { eval.AddTx(txtokencreateUnused); tokenidUnused = txtokencreateUnused.GetHash(); - txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1); + txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 0); eval.AddTx(txask1); - txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1); + txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 0); eval.AddTx(txask2); - txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1); + txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 0); eval.AddTx(txbid1); - //txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2); // test dust + //txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2, 0); // test dust } - static CTransaction MakeNormalTx(CPubKey pk, CAmount val) + static CTransaction MakeNormalTx(CPubKey mypk, CAmount val) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); mtx.vin.push_back(CTxIn(getRandomHash(), 0)); - mtx.vout.push_back(CTxOut(val, GetScriptForDestination(pk))); + mtx.vout.push_back(CTxOut(val, GetScriptForDestination(mypk))); //eval.txs[mtx.GetHash()] = mtx; return CTransaction(mtx); } - static CMutableTransaction MakeTokenV2CreateTx(CPubKey pk, CAmount amount, const UniValue &utokeldata = NullUniValue) + static CMutableTransaction MakeTokenV2CreateTx(CPubKey mypk, CAmount amount, const UniValue &utokeldata = NullUniValue) { struct CCcontract_info *cp, C; cp = CCinit(&C, TokensV2::EvalCode()); @@ -450,12 +458,12 @@ class TestAssetsCC : public ::testing::Test { CAmount txfee = 10000; CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { std::cerr << __func__ << " could not add normal inputs" << std::endl; return CTransaction(); } mtx.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, amount, pk)); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, amount, mypk)); std::vector vextras; vuint8_t vtokeldata; @@ -464,8 +472,8 @@ class TestAssetsCC : public ::testing::Test { if (!vtokeldata.empty()) vextras.push_back(vtokeldata); - if (!TestFinalizeTx(mtx, cp, testKeys[pk], txfee, - TokensV2::EncodeTokenCreateOpRet(vscript_t(pk.begin(), pk.end()), name, description, vextras))) { + if (!TestFinalizeTx(mtx, cp, testKeys[mypk], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(mypk.begin(), mypk.end()), name, description, vextras))) { std::cerr << __func__ << " could finalize tx" << std::endl; return CTransaction(); } @@ -474,7 +482,7 @@ class TestAssetsCC : public ::testing::Test { } - static CMutableTransaction MakeTokenV2AskTx(struct CCcontract_info *cpTokens, CPubKey pk, uint256 tokenid, CAmount numtokens, CAmount unit_price) + static CMutableTransaction MakeTokenV2AskTx(struct CCcontract_info *cpTokens, CPubKey mypk, uint256 tokenid, CAmount numtokens, CAmount unit_price, int32_t expiryHeight) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); @@ -484,7 +492,7 @@ class TestAssetsCC : public ::testing::Test { CAmount txfee = 10000; CAmount askamount = numtokens * unit_price; - if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { std::cerr << __func__ << " cant add normal inputs" << std::endl; return CTransaction(); } @@ -501,7 +509,7 @@ class TestAssetsCC : public ::testing::Test { evalcodeAdd = vextraData[0]; } - CAmount inputs = TestAddTokenInputs(mtx, pk, tokenid, numtokens); + CAmount inputs = TestAddTokenInputs(mtx, mypk, tokenid, numtokens); if (inputs == 0) { std::cerr << __func__ << " cant add token inputs" << std::endl; return CTransaction(); @@ -509,28 +517,28 @@ class TestAssetsCC : public ::testing::Test { CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens, unspendableAssetsPubkey)); - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk)); + mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); CAmount CCchange = inputs - numtokens; if (CCchange != 0LL) { // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), CCchange, pk)); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), CCchange, mypk)); } // cond to spend NFT from mypk - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(evalcodeAdd, pk)); + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(evalcodeAdd, mypk)); CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey // sign vins: - if(!TestFinalizeTx(mtx, cpTokens, testKeys[pk], txfee, + if(!TestFinalizeTx(mtx, cpTokens, testKeys[mypk], txfee, TokensV2::EncodeTokenOpRet(tokenid, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pk.begin(), pk.end())) }))) { + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))) { std::cerr << __func__ << " cant finalise tx" << std::endl; return CTransaction(); } return mtx; } - static CMutableTransaction MakeTokenV2BidTx(struct CCcontract_info *cpAssets, CPubKey pk, uint256 tokenid, CAmount numtokens, CAmount unit_price) + static CMutableTransaction MakeTokenV2BidTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, CAmount numtokens, CAmount unit_price, int32_t expiryHeight) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); //struct CCcontract_info *cpAssets, C; @@ -542,18 +550,18 @@ class TestAssetsCC : public ::testing::Test { //cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! //CAmount unit_price = bidamount / numtokens; - if (TestAddNormalInputs(mtx, pk, txfee) == 0LL) { + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { std::cerr << __func__ << " cant add normal inputs" << std::endl; return CTransaction(); } - CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, nullptr); mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, unspendableAssetsPubkey)); - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pk)); // marker for my orders + mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); // marker for my orders // sign vins: - if (!TestFinalizeTx(mtx, cpAssets, testKeys[pk], txfee, + if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, TokensV2::EncodeTokenOpRet(tokenid, {}, - { AssetsV2::EncodeAssetOpRet('b', zeroid, unit_price, vuint8_t(pk.begin(), pk.end())) }))) { + { AssetsV2::EncodeAssetOpRet('b', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))) { std::cerr << __func__ << " cant finalise tx" << std::endl; return CTransaction(); } @@ -599,7 +607,8 @@ class TestAssetsCC : public ::testing::Test { vuint8_t ownerpubkey = std::get<0>(tokenData); vuint8_t origpubkey; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, asktx); // get orig pk, orig value + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, asktx); // get orig pk, orig value if (paid_unit_price <= 0LL) paid_unit_price = unit_price; @@ -625,17 +634,21 @@ class TestAssetsCC : public ::testing::Test { mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner if (orig_assetoshis - fill_units > 0) // we dont need the marker if order is filled - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) + mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(origpubkey), GetUnspendable(cpAssets, NULL))); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeAdd, unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); + CCwrapper wrCond1(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeAdd, unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond1, unspendableAssetsPrivkey); + + // probe to spend marker + CCwrapper wrCond2(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(ownerpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond2, nullptr); // spend with mypk if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, TokensV2::EncodeTokenOpRet(tokenid, { mypk }, - { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))) { + { AssetsV2::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) } ))) { std::cerr << __func__ << " cant finalise tx" << std::endl; return CTransaction(); } @@ -690,11 +703,12 @@ class TestAssetsCC : public ::testing::Test { } vuint8_t ownerpubkey = std::get<0>(tokenData); - vuint8_t origpubkey; std::cerr << __func__ << " bidtx=" << bidtx.GetHash().GetHex() << " " << HexStr(E_MARSHAL(ss << bidtx)) << " vouts=" << bidtx.vout.size() << std::endl; CAmount bid_amount = bidtx.vout[bidvout].nValue; - if (GetOrderParams(origpubkey, unit_price, assetidOpret, bidtx) == 0) { // get orig pk, orig value + vuint8_t origpubkey; + int32_t expiryHeight; + if (GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, bidtx) == 0) { // get orig pk, orig value std::cerr << __func__ << " cant get order data" << std::endl; return CTransaction(); } @@ -746,7 +760,7 @@ class TestAssetsCC : public ::testing::Test { mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator if (orig_units - fill_units > 0) // order is not finished yet - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey)); // vout3(4 if royalty) marker to origpubkey + mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(origpubkey), unspendableAssetsPk)); // vout3(4 if royalty) marker to origpubkey if (tokensChange != 0LL) mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), tokensChange, mypk)); // change in single-eval tokens @@ -759,21 +773,25 @@ class TestAssetsCC : public ::testing::Test { CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(evalcodeAdd, mypk)); // spend my tokens to fill buy CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey + // probe to spend marker + CCwrapper wrCond3(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(ownerpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond3, nullptr); // spend with mypk + if (!TestFinalizeTx(mtx, cpTokens, testKeys[mypk], txfee, TokensV2::EncodeTokenOpRet(tokenid, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))) { + { AssetsV2::EncodeAssetOpRet('B', unit_price, origpubkey, expiryHeight) }))) { std::cerr << __func__ << " could not finalize tx" << std::endl; return CTransaction(); } data.pushKV("ownerpubkey", HexStr(ownerpubkey)); data.pushKV("origpubkey", HexStr(origpubkey)); data.pushKV("unit_price", unit_price); - + data.pushKV("expiryHeight", expiryHeight); return mtx; } - static CMutableTransaction MakeTokenV2CancelAskTx(struct CCcontract_info *cpAssets, uint256 tokenid, uint256 asktxid, UniValue &data) + static CMutableTransaction MakeTokenV2CancelAskTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, uint256 asktxid, UniValue &data) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); @@ -797,7 +815,7 @@ class TestAssetsCC : public ::testing::Test { evalcodeAdd = vextraData[0]; vuint8_t ownerpubkey = std::get<0>(tokenData); - if (TestAddNormalInputs(mtx, ownerpubkey, txfee) == 0LL) { + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { std::cerr << __func__ << " could not add normal inputs" << std::endl; return CTransaction(); } @@ -806,8 +824,9 @@ class TestAssetsCC : public ::testing::Test { uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; - std::vector dummyOrigpubkey; - uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(asktx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey); + vuint8_t origpubkey; + int32_t expiryHeight; + uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(asktx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, origpubkey, expiryHeight); if (funcid == 's' && asktx.vout.size() > 1) mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // spend marker if funcid='s' else if (funcid == 'S' && asktx.vout.size() > 3) @@ -817,7 +836,7 @@ class TestAssetsCC : public ::testing::Test { return CTransaction(); } - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(cpAssets->evalcodeAdd ? cpAssets->evalcodeAdd : TokensV2::EvalCode(), askamount, ownerpubkey)); // one-eval token vout + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(cpAssets->evalcodeAdd ? cpAssets->evalcodeAdd : TokensV2::EvalCode(), askamount, origpubkey)); // one-eval token vout // init assets 'unspendable' privkey and pubkey uint8_t unspendableAssetsPrivkey[32]; @@ -826,20 +845,33 @@ class TestAssetsCC : public ::testing::Test { CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), cpAssets->evalcodeAdd, unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); - if (!TestFinalizeTx(mtx, cpAssets, testKeys[ownerpubkey], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))) { + // probe to spend marker + std::cerr << __func__ << " mypk=" << HexStr(mypk) << " origpubkey=" << HexStr(pubkey2pk(origpubkey)) << std::endl; + if (mypk == pubkey2pk(origpubkey)) { + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk + std::cerr << __func__ << " use mypk" << std::endl; + } else { + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk + std::cerr << __func__ << " use unspendableAssetsPrivkey=" << HexStr(unspendableAssetsPrivkey, unspendableAssetsPrivkey+32) << std::endl; + } + + if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { origpubkey }, + { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(), 0) } ))) { std::cerr << __func__ << " could not finalize tx" << std::endl; return CTransaction(); } - data.pushKV("ownerpubkey", HexStr(ownerpubkey)); + data.pushKV("ownerpubkey", HexStr(ownerpubkey)); + data.pushKV("origpubkey", HexStr(origpubkey)); data.pushKV("askamount", askamount); return mtx; } - static CMutableTransaction MakeTokenV2CancelBidTx(struct CCcontract_info *cpAssets, uint256 tokenid, uint256 bidtxid, UniValue &data) + static CMutableTransaction MakeTokenV2CancelBidTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, uint256 bidtxid, UniValue &data) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); @@ -858,14 +890,12 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " could not load token data" << std::endl; return CTransaction(); } - - uint8_t evalcodeAdd = 0; if (vextraData.size() > 0) evalcodeAdd = vextraData[0]; vuint8_t ownerpubkey = std::get<0>(tokenData); - if (TestAddNormalInputs(mtx, ownerpubkey, txfee) == 0LL) { + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { std::cerr << __func__ << " could not add normal inputs" << std::endl; return CTransaction(); } @@ -874,8 +904,9 @@ class TestAssetsCC : public ::testing::Test { uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; - std::vector dummyOrigpubkey; - uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(bidtx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey); + vuint8_t origpubkey; + int32_t expiryHeight; + uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(bidtx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, origpubkey, expiryHeight); if (funcid == 'b' && bidtx.vout.size() > 1) mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' else if (funcid == 'B' && bidtx.vout.size() > 3) @@ -885,7 +916,7 @@ class TestAssetsCC : public ::testing::Test { return CTransaction(); } if (bidamount > ASSETS_NORMAL_DUST) - mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); + mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); else { // send dust back to global addr mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, GetUnspendable(cpAssets, NULL))); @@ -896,15 +927,24 @@ class TestAssetsCC : public ::testing::Test { uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + // probe to spend marker + if (mypk == pubkey2pk(origpubkey)) { + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk + } else { + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk + } + // sign, add change, add opreturn - if (!TestFinalizeTx(mtx, cpAssets, testKeys[ownerpubkey], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))) { + if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { origpubkey }, + { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(), 0) } ))) { std::cerr << __func__ << " could not finalise tx" << std::endl; return CTransaction(); } - - data.pushKV("ownerpubkey", HexStr(ownerpubkey)); + data.pushKV("ownerpubkey", HexStr(ownerpubkey)); + data.pushKV("origpubkey", HexStr(origpubkey)); data.pushKV("bidamount", bidamount); return mtx; } @@ -929,13 +969,14 @@ TEST_F(TestAssetsCC, tokenv2ask) cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, mypk, mytokenid, numtokens, 501); // price more than dust + CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, mypk, mytokenid, numtokens, 501, 0); // price more than dust ASSERT_FALSE(CTransaction(mtx).IsNull()); vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, mtx); + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, mtx); // test: valid tokenv2ask EXPECT_TRUE(TestRunCCEval(mtx)); @@ -946,7 +987,7 @@ TEST_F(TestAssetsCC, tokenv2ask) mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', zeroid, 0, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + { AssetsV2::EncodeAssetOpRet('s', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); } { @@ -955,7 +996,7 @@ TEST_F(TestAssetsCC, tokenv2ask) mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pkunused }, // bad pk instead of global - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); EXPECT_TRUE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { @@ -964,7 +1005,7 @@ TEST_F(TestAssetsCC, tokenv2ask) mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(pkunused.begin(), pkunused.end())) }))); // not matched origpk (should be pk1) + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(pkunused.begin(), pkunused.end()), expiryHeight) }))); // not matched origpk (should be pk1) EXPECT_FALSE(TestRunCCEval(mtx1)); } { @@ -973,7 +1014,7 @@ TEST_F(TestAssetsCC, tokenv2ask) // mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); } { @@ -983,7 +1024,7 @@ TEST_F(TestAssetsCC, tokenv2ask) mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { @@ -995,7 +1036,7 @@ TEST_F(TestAssetsCC, tokenv2ask) mtx1.vout.pop_back(); // remove old opreturn ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { @@ -1007,7 +1048,7 @@ TEST_F(TestAssetsCC, tokenv2ask) mtx1.vout.pop_back(); // remove old opreturn ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { @@ -1018,7 +1059,7 @@ TEST_F(TestAssetsCC, tokenv2ask) mtx1.vout.pop_back(); // remove old opreturn ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', zeroid, unit_price, vuint8_t(origpubkey.begin(), origpubkey.end())) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } } @@ -1030,7 +1071,7 @@ TEST_F(TestAssetsCC, tokenv2bid) cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - CMutableTransaction mtx = MakeTokenV2BidTx(cpAssets, pk2, tokenid1, 2, 501); // price more than dust + CMutableTransaction mtx = MakeTokenV2BidTx(cpAssets, pk2, tokenid1, 2, 501, 0); // price more than dust ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2bid @@ -1045,7 +1086,7 @@ TEST_F(TestAssetsCC, tokenv2bid) ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], txfee, TokensV2::EncodeTokenOpRet(tokenid1, {}, - { AssetsV2::EncodeAssetOpRet('b', zeroid, 10000, vuint8_t(pk2.begin(), pk2.end())) }))); + { AssetsV2::EncodeAssetOpRet('b', 10000, vuint8_t(pk2.begin(), pk2.end()), 0) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail } } @@ -1071,12 +1112,13 @@ TEST_F(TestAssetsCC, tokenv2fillask) vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txask1); + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); ASSERT_TRUE(funcid != 0); mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(tokenidUnused, { pk2 }, - { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))); + { AssetsV2::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) } ))); EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail } @@ -1088,12 +1130,13 @@ TEST_F(TestAssetsCC, tokenv2fillask) vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txbid1); + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], txfee, TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); // 'S' -> 'B' + { AssetsV2::EncodeAssetOpRet('B', unit_price, origpubkey, expiryHeight) }))); // 'S' -> 'B' EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid } @@ -1104,12 +1147,13 @@ TEST_F(TestAssetsCC, tokenv2fillask) vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txask2); + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask2); ASSERT_TRUE(funcid != 0); mtx2.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx2, cpAssets, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, - { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) } ))); + { AssetsV2::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) } ))); EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail } @@ -1119,12 +1163,13 @@ TEST_F(TestAssetsCC, tokenv2fillask) vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txask1); // get orig pk, orig value + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); // get orig pk, orig value ASSERT_TRUE(funcid != 0); mtx2.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx2, cpAssets, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, - { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price+1, origpubkey) } ))); + { AssetsV2::EncodeAssetOpRet('S', unit_price+1, origpubkey, expiryHeight) } ))); EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail } @@ -1134,11 +1179,12 @@ TEST_F(TestAssetsCC, tokenv2fillask) vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txask1); // get orig pk, orig value + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); // get orig pk, orig value mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(tokenid1, { pk2 }, - { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, vuint8_t(pkunused.begin(), pkunused.end())) }))); // not matched origpk (should be pk1) + { AssetsV2::EncodeAssetOpRet('S', unit_price, vuint8_t(pkunused.begin(), pkunused.end()), expiryHeight) }))); // not matched origpk (should be pk1) EXPECT_FALSE(TestRunCCEval(mtx1)); } } @@ -1163,12 +1209,13 @@ TEST_F(TestAssetsCC, tokenv2fillbid) vuint8_t ownerpubkey = ParseHex(data["ownerpubkey"].getValStr()); vuint8_t origpubkey = ParseHex(data["origpubkey"].getValStr()); CAmount unit_price = data["unit_price"].get_int64(); + int32_t expiryHeight = data["expiryHeight"].get_int(); mtx1.vin[1] = CTxIn(txtokencreate3.GetHash(), 1, CScript()); // spend other tokenid3 mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, origpubkey) }))); + { AssetsV2::EncodeAssetOpRet('B', unit_price, origpubkey, expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: can't fill with another tokenid3 } @@ -1180,12 +1227,13 @@ TEST_F(TestAssetsCC, tokenv2fillbid) vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txbid1); // get orig pk, orig value + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('S', zeroid, unit_price, origpubkey) }))); // 'B' -> 'S' + { AssetsV2::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) }))); // 'B' -> 'S' EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid } @@ -1195,11 +1243,12 @@ TEST_F(TestAssetsCC, tokenv2fillbid) vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, txbid1); // get orig pk, orig value + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, - { AssetsV2::EncodeAssetOpRet('B', zeroid, unit_price, vuint8_t(pkunused.begin(), pkunused.end())) }))); // not matched origpk (should be pk1) + { AssetsV2::EncodeAssetOpRet('B', unit_price, vuint8_t(pkunused.begin(), pkunused.end()), expiryHeight) }))); // not matched origpk (should be pk1) EXPECT_FALSE(TestRunCCEval(mtx1)); } } @@ -1216,11 +1265,12 @@ TEST_F(TestAssetsCC, tokenv2fillbid_royalty) cpAssets = CCinit(&assetsC, AssetsV2::EvalCode()); tokeldata.pushKV("royalty", r); - CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); + // use static mtx as it is added to static eval + static CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); uint256 mytokenid = mytxtokencreate.GetHash(); eval.AddTx(mytxtokencreate); - CTransaction mytxbid = MakeTokenV2BidTx(cpAssets, pk2, mytokenid, 1, ASSETS_NORMAL_DUST*2+1); + static CTransaction mytxbid = MakeTokenV2BidTx(cpAssets, pk2, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 0); eval.AddTx(mytxbid); CMutableTransaction mytxfill = MakeTokenV2FillBidTx(cpTokens, pk1, mytokenid, mytxbid.GetHash(), 1, 0, data); @@ -1243,11 +1293,11 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty) cpAssets = CCinit(&assetsC, AssetsV2::EvalCode()); tokeldata.pushKV("royalty", r); - CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); + static CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); uint256 mytokenid = mytxtokencreate.GetHash(); eval.AddTx(mytxtokencreate); - CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, 1, ASSETS_NORMAL_DUST*2+1); + static CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 0); eval.AddTx(mytxask); CMutableTransaction mytxfill = MakeTokenV2FillAskTx(cpAssets, pk2, mytokenid, mytxask.GetHash(), 1, 0, data); @@ -1274,31 +1324,36 @@ TEST_F(TestAssetsCC, tokenv2cancelask) UniValue data(UniValue::VOBJ); uint256 asktxid = vintx.GetHash(); + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, vintx); + struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); - CMutableTransaction mtx = MakeTokenV2CancelAskTx(cpAssets, tokenid1, asktxid, data); + CMutableTransaction mtx = MakeTokenV2CancelAskTx(cpAssets, pubkey2pk(origpubkey), tokenid1, asktxid, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); - vuint8_t ownerpubkey = ParseHex(data["ownerpubkey"].getValStr()); CAmount askamount = data["askamount"].get_int64(); // test: valid tokenv2cancelask EXPECT_TRUE(TestRunCCEval(mtx)); { - // test: invalid pk in assets opreturn + // test: invalid pk2 in assets opreturn CMutableTransaction mtx2(mtx); mtx2.vout.pop_back(); - mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(pk2.begin(), pk2.end())) } ))); + mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { origpubkey }, + { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(pk2.begin(), pk2.end()), 0) } ))); EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret not checked } { - // test: another pk in token opret + // test: some unused pk in token opret CMutableTransaction mtx3(mtx); mtx3.vout.pop_back(); mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { pkunused }, - { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); - EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked + { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); + EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked for token v2, it is only for a hint } { // test: invalid pk where to funds sent @@ -1310,21 +1365,96 @@ TEST_F(TestAssetsCC, tokenv2cancelask) // test: invalid tokenid in token opret CMutableTransaction mtx5(mtx); mtx5.vout.pop_back(); - mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { origpubkey }, + { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); EXPECT_FALSE(TestRunCCEval(mtx5)); // must fail: cant send to another tokenid } { // test: invalid funcid in token opret CMutableTransaction mtx6(mtx); mtx6.vout.pop_back(); - mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { origpubkey }, + { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); EXPECT_FALSE(TestRunCCEval(mtx6)); // must fail } } } +TEST_F(TestAssetsCC, tokenv2cancelask_expired) +{ + CAmount txfee = 10000; + + { + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + // use static mtx as it is added to static eval + static CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + ASSERT_FALSE(CTransaction(txaskexp).IsNull()); + eval.AddTx(txaskexp); + EXPECT_TRUE(TestRunCCEval(txaskexp)); + + + UniValue data(UniValue::VOBJ); + uint256 asktxid = txaskexp.GetHash(); + + eval.SetCurrentHeight(111); + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + + CMutableTransaction mtx = MakeTokenV2CancelAskTx(cpAssets, pk1, tokenid1, asktxid, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: valid tokenv2cancelask with mypk + EXPECT_TRUE(TestRunCCEval(mtx)); + } + { + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + static CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + ASSERT_FALSE(CTransaction(txaskexp).IsNull()); + eval.AddTx(txaskexp); + EXPECT_TRUE(TestRunCCEval(txaskexp)); + + UniValue data(UniValue::VOBJ); + uint256 asktxid = txaskexp.GetHash(); + + eval.SetCurrentHeight(111); //set height not expired + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + + CMutableTransaction mtx = MakeTokenV2CancelAskTx(cpAssets, pk2, tokenid1, asktxid, data); // use another pk (global pk will be used actually) + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: try tokenv2cancelask not yet expired with globalpk + EXPECT_FALSE(TestRunCCEval(mtx)); // should fail + } + { + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + // use static mtx as it is added to static eval + static CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + ASSERT_FALSE(CTransaction(txaskexp).IsNull()); + eval.AddTx(txaskexp); + EXPECT_TRUE(TestRunCCEval(txaskexp)); + + UniValue data(UniValue::VOBJ); + uint256 asktxid = txaskexp.GetHash(); + + eval.SetCurrentHeight(223); + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + + CMutableTransaction mtx = MakeTokenV2CancelAskTx(cpAssets, pk2, tokenid1, asktxid, data); // use another pk (global pk will be used actually) + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: try tokenv2cancelask already expired with globalpk + EXPECT_TRUE(TestRunCCEval(mtx)); // should not fail + } +} + TEST_F(TestAssetsCC, tokenv2cancelbid) { struct CCcontract_info *cpAssets, C; @@ -1339,12 +1469,17 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) UniValue data(UniValue::VOBJ); uint256 bidtxid = vintx.GetHash(); + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, vintx); + struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); - CMutableTransaction mtx = MakeTokenV2CancelBidTx(cpAssets, tokenid2, bidtxid, data); + CMutableTransaction mtx = MakeTokenV2CancelBidTx(cpAssets, pubkey2pk(origpubkey), tokenid2, bidtxid, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); - vuint8_t ownerpubkey = ParseHex(data["ownerpubkey"].getValStr()); CAmount bidamount = data["bidamount"].get_int64(); // test: valid tokenv2cancelbid @@ -1353,8 +1488,8 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) // test: invalid pk in assets opreturn CMutableTransaction mtx2(mtx); mtx2.vout.pop_back(); - mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(pk1.begin(), pk1.end())) } ))); + mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { origpubkey }, + { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(pk1.begin(), pk1.end()), 0) } ))); EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret is not checked } { @@ -1362,7 +1497,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) CMutableTransaction mtx3(mtx); mtx3.vout.pop_back(); mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pkunused }, - { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked } { @@ -1375,8 +1510,8 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) // test: invalid tokenid in token opret CMutableTransaction mtx5(mtx); mtx5.vout.pop_back(); - mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { ownerpubkey }, - { AssetsV2::EncodeAssetOpRet('o', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { origpubkey }, + { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); EXPECT_FALSE(TestRunCCEval(mtx5)); } { @@ -1384,7 +1519,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) CMutableTransaction mtx6(mtx); mtx6.vout.pop_back(); mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pk2 }, - { AssetsV2::EncodeAssetOpRet('x', zeroid, 0, vuint8_t(ownerpubkey.begin(), ownerpubkey.end())) } ))); + { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); EXPECT_FALSE(TestRunCCEval(mtx6)); } { @@ -1396,6 +1531,80 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) } } +TEST_F(TestAssetsCC, tokenv2cancelbid_expired) +{ + CAmount txfee = 10000; + + { + struct CCcontract_info *cpAssets0, C0; + cpAssets0 = CCinit(&C0, AssetsV2::EvalCode()); + + // use static mtx as it is added to static eval + static CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + ASSERT_FALSE(CTransaction(txbidexp).IsNull()); + eval.AddTx(txbidexp); + EXPECT_TRUE(TestRunCCEval(txbidexp)); + + + UniValue data(UniValue::VOBJ); + uint256 bidtxid = txbidexp.GetHash(); + + eval.SetCurrentHeight(111); + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + + CMutableTransaction mtx = MakeTokenV2CancelBidTx(cpAssets, pk1, tokenid1, bidtxid, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: valid tokenv2cancelbid with mypk + EXPECT_TRUE(TestRunCCEval(mtx)); + } + { + struct CCcontract_info *cpAssets0, C0; + cpAssets0 = CCinit(&C0, AssetsV2::EvalCode()); + + static CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + ASSERT_FALSE(CTransaction(txbidexp).IsNull()); + eval.AddTx(txbidexp); + EXPECT_TRUE(TestRunCCEval(txbidexp)); + + UniValue data(UniValue::VOBJ); + uint256 bidtxid = txbidexp.GetHash(); + + eval.SetCurrentHeight(111); //set height not expired + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + + CMutableTransaction mtx = MakeTokenV2CancelBidTx(cpAssets, pk2, tokenid1, bidtxid, data); // use another pk (global pk will be used actually) + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: try tokenv2cancelbid not yet expired with globalpk + EXPECT_FALSE(TestRunCCEval(mtx)); // should fail + } + { + struct CCcontract_info *cpAssets0, C0; + cpAssets0 = CCinit(&C0, AssetsV2::EvalCode()); + + // use static mtx as it is added to static eval + static CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + ASSERT_FALSE(CTransaction(txbidexp).IsNull()); + eval.AddTx(txbidexp); + EXPECT_TRUE(TestRunCCEval(txbidexp)); + + UniValue data(UniValue::VOBJ); + uint256 bidtxid = txbidexp.GetHash(); + + eval.SetCurrentHeight(223); + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + + CMutableTransaction mtx = MakeTokenV2CancelBidTx(cpAssets, pk2, tokenid1, bidtxid, data); // use another pk (global pk will be used actually) + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: try tokenv2cancelbid already expired with globalpk + EXPECT_TRUE(TestRunCCEval(mtx)); // should not fail + } +} /* ---------------------------------------------------------------------------------------------------------------------------------- */ // tokens tests: From d78e0dc4677590c1ae71139155196c2f1b600daf Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 20 Jul 2021 20:37:24 +0500 Subject: [PATCH 062/348] removed unused evalcode param from mytokenorders rpc --- src/cc/CCassetstx_impl.h | 35 +++++++++++------------------------ src/rpc/tokensrpc.cpp | 19 ++++++++++--------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index e9adbbfbdd8..1a626ff701b 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -126,14 +126,8 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) } }; - if (!pk.IsValid()) + if (!pk.IsValid()) // get tokenorders (all orders) { - std::vector > unspentOutputsTokens, unspentOutputsNFTs, unspentOutputsCoins; - char assetsUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; - GetCCaddress(cpAssets, assetsUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); - SetCCunspents(unspentOutputsCoins, assetsUnspendableAddr, true); - - char assetsTokensUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; TokenDataTuple tokenData; vuint8_t vextraData; if (refassetid != zeroid) { @@ -141,38 +135,31 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) if (vextraData.size() > 0) cpAssets->evalcodeAdd = vextraData[0]; } - GetTokensCCaddress(cpAssets, assetsTokensUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); - SetCCunspents(unspentOutputsTokens, assetsTokensUnspendableAddr, true); // tokenbids: + std::vector > unspentOutputsCoins; + char assetsGlobalAddr[KOMODO_ADDRESS_BUFSIZE]; + GetCCaddress(cpAssets, assetsGlobalAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); + SetCCunspents(unspentOutputsCoins, assetsGlobalAddr, true); for (std::vector >::const_iterator itCoins = unspentOutputsCoins.begin(); itCoins != unspentOutputsCoins.end(); itCoins++) addOrders(cpAssets, itCoins); // tokenasks: + std::vector > unspentOutputsTokens; + char tokensAssetsGlobalAddr[KOMODO_ADDRESS_BUFSIZE]; + cpAssets->evalcodeAdd = evalcodeAdd; + GetTokensCCaddress(cpAssets, tokensAssetsGlobalAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); + SetCCunspents(unspentOutputsTokens, tokensAssetsGlobalAddr, true); for (std::vector >::const_iterator itTokens = unspentOutputsTokens.begin(); itTokens != unspentOutputsTokens.end(); itTokens++) addOrders(cpAssets, itTokens); - - if (evalcodeAdd != 0) { //this would be mytokenorders - char assetsNFTUnspendableAddr[KOMODO_ADDRESS_BUFSIZE]; - - // try also dual eval tokenasks (and we do not need bids (why? bids are on assets global addr anyway.)): - cpAssets->evalcodeAdd = evalcodeAdd; - GetTokensCCaddress(cpAssets, assetsNFTUnspendableAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); - SetCCunspents(unspentOutputsNFTs, assetsNFTUnspendableAddr,true); - - for (std::vector >::const_iterator itNFTs = unspentOutputsNFTs.begin(); - itNFTs != unspentOutputsNFTs.end(); - itNFTs++) - addOrders(cpAssets, itNFTs); - } } else { - // use marker on my pk: + // mytokenorders, use marker on my pk : std::vector > unspentsMyAddr; char assetsMyAddr[KOMODO_ADDRESS_BUFSIZE]; GetCCaddress1of2(cpAssets, assetsMyAddr, pk, GetUnspendable(cpAssets, NULL), A::IsMixed()); diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index e14a8bff4f6..1a8596270b6 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -206,22 +206,23 @@ template UniValue mytokenorders(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) { uint256 tokenid; - if (fHelp || params.size() > 1) - throw runtime_error(name + " [evalcode]\n" - "returns all the token orders for mypubkey\n" - "if evalcode is set then returns mypubkey's token orders for non-fungible tokens with this evalcode\n" "\n"); + if (fHelp || params.size() > 0) + throw runtime_error(name + "\n" + "returns all tokens orders for mypubkey\n" + // no additional evalcode for mytokenorders - it will return all orders for on mypk: + /*"if evalcode is set then returns mypubkey's token orders for non-fungible tokens with this evalcode\n"*/ "\n"); if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - uint8_t evalcodeAdd = 0; - if (params.size() == 1) - evalcodeAdd = strtol(params[0].get_str().c_str(), NULL, 0); // supports also 0xEE-like values + //uint8_t evalcodeAdd = 0; + //if (params.size() == 1) + // evalcodeAdd = strtol(params[0].get_str().c_str(), NULL, 0); // supports also 0xEE-like values CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - return AssetOrders(zeroid, mypk, evalcodeAdd); + return AssetOrders(zeroid, mypk, 0); else - return tokensv0::AssetOrders(zeroid, Mypubkey(), evalcodeAdd); + return tokensv0::AssetOrders(zeroid, Mypubkey(), 0); } UniValue mytokenorders(const UniValue& params, bool fHelp, const CPubKey& remotepk) From 6b460ad28c690c8761e56d4c4beb77a739a2ddd3 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 21 Jul 2021 20:37:44 +0500 Subject: [PATCH 063/348] big change: removed evalcodeAdd from cp what means tokencreate extradata evalcode will not be auto-added to token vouts instead when tokencreate tx is checked it will subcall tokendata evalcode validate function Removed v0 code in old dir Added error return from tokel data crosschain, komodo-tests-cc updated for new cp struct --- src/Makefile.am | 6 - src/cc/CCTokelData.cpp | 39 +- src/cc/CCTokelData.h | 2 +- src/cc/CCassets.h | 2 - src/cc/CCassetsCore_impl.h | 1 - src/cc/CCassetstx_impl.h | 46 +- src/cc/CCinclude.h | 7 +- src/cc/CCtokens.cpp | 95 +-- src/cc/CCtokens.h | 6 +- src/cc/CCtokens_impl.h | 77 +- src/cc/CCtokenutils.cpp | 120 ---- src/cc/CCtx.cpp | 8 +- src/cc/CCutils.cpp | 53 +- src/cc/assets.cpp | 12 +- src/cc/heir.cpp | 21 +- src/cc/heir_validate.h | 34 +- src/cc/old/CCassetsCore_v0.cpp | 655 ----------------- src/cc/old/CCassets_v0.h | 69 -- src/cc/old/CCassetstx_v0.cpp | 802 --------------------- src/cc/old/CCtokens_v0.cpp | 1059 ---------------------------- src/cc/old/CCtokens_v0.h | 99 --- src/cc/old/CCtokenutils_v0.cpp | 354 ---------- src/cc/old/assets_v0.cpp | 478 ------------- src/cc/old/heir_v0.cpp | 231 ------ src/cc/old/heir_validate_v0.h | 27 - src/rpc/crosschain.cpp | 18 +- src/rpc/tokensrpc.cpp | 98 +-- src/test-komodo-cc/test-assets.cpp | 54 +- 28 files changed, 161 insertions(+), 4312 deletions(-) delete mode 100644 src/cc/old/CCassetsCore_v0.cpp delete mode 100644 src/cc/old/CCassets_v0.h delete mode 100644 src/cc/old/CCassetstx_v0.cpp delete mode 100644 src/cc/old/CCtokens_v0.cpp delete mode 100644 src/cc/old/CCtokens_v0.h delete mode 100644 src/cc/old/CCtokenutils_v0.cpp delete mode 100644 src/cc/old/assets_v0.cpp delete mode 100644 src/cc/old/heir_v0.cpp delete mode 100644 src/cc/old/heir_validate_v0.h diff --git a/src/Makefile.am b/src/Makefile.am index de18ebf2ebe..8abfd389430 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -296,23 +296,18 @@ libbitcoin_server_a_SOURCES = \ cc/import.cpp \ cc/importgateway.cpp \ cc/CCassetsUtils.cpp \ - cc/old/CCassetsCore_v0.cpp \ - cc/old/CCassetstx_v0.cpp \ cc/CCcustom.cpp \ cc/CCtx.cpp \ cc/CCutils.cpp \ cc/CCvalidation.cpp \ cc/CCtokens.cpp \ - cc/old/CCtokens_v0.cpp \ cc/assets.cpp \ - cc/old/assets_v0.cpp \ cc/faucet.cpp \ cc/rewards.cpp \ cc/dice.cpp \ cc/lotto.cpp \ cc/fsm.cpp \ cc/heir.cpp \ - cc/old/heir_v0.cpp \ cc/oracles.cpp \ cc/prices.cpp \ cc/pegs.cpp \ @@ -511,7 +506,6 @@ libbitcoin_common_a_SOURCES = \ script/standard.cpp \ transaction_builder.cpp \ cc/CCtokenutils.cpp \ - cc/old/CCtokenutils_v0.cpp \ cc/CCutilbits.cpp \ gmp_i64.c \ $(BITCOIN_CORE_H) \ diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index 2c8236399c6..e48b152cd5d 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -17,7 +17,6 @@ #include "CCtokens.h" #include "CCTokelData.h" - static UniValue tklReadString(CDataStream &ss) { std::string sval; @@ -43,24 +42,31 @@ static UniValue tklReadVuint8(CDataStream &ss) return ret; } -static void tklWriteString(CDataStream &ss, const UniValue &val) +static bool tklWriteString(CDataStream &ss, const UniValue &val) { std::string sval = val.getValStr(); ::Serialize(ss, sval); + return true; } -static void tklWriteInt64(CDataStream &ss, const UniValue &val) +static bool tklWriteInt64(CDataStream &ss, const UniValue &val) { int64_t i64val = 0; + if (!val.isNum()) + return false; ParseInt64(val.getValStr(), &i64val); //::Serialize(ss, i64val); ss << COMPACTSIZE((uint64_t)i64val); + return true; } -static void tklWriteVuint8(CDataStream &ss, const UniValue &val) +static bool tklWriteVuint8(CDataStream &ss, const UniValue &val) { vuint8_t vuint8val = ParseHex(val.getValStr()); + if (vuint8val.empty() && !val.getValStr().empty()) // can't decode hex string + return false; ::Serialize(ss, vuint8val); + return true; } typedef std::map tklPropDesc_map; @@ -71,16 +77,6 @@ static const tklPropDesc_map tklPropDesc = { { TKLPROP_ARBITRARY, std::make_tuple(TKLTYP_VUINT8, std::string("arbitrary"), &tklReadVuint8, &tklWriteVuint8) } }; -/*typedef struct { - tklPropType type; - struct - { - uint64_t uint64; - vuint8_t vuint8; - } v; -} tklPropValue; -*/ - static tklPropId FindTokelDataIdByName(const std::string &name) { auto found = std::find_if(tklPropDesc.begin(), tklPropDesc.end(), [&](const std::pair &e){ return std::get<1>(e.second) == name; }); @@ -109,13 +105,12 @@ vuint8_t ParseTokelJson(const UniValue &jsonParams) { std::string key = jsonParams.getKeys()[i]; tklPropId id; - //CAmount valAmount; - //vuint8_t valVuint8; if ((id = FindTokelDataIdByName(key)) == (tklPropId)0) - throw std::runtime_error("invalid token data id=" + key); + throw std::runtime_error("invalid token data id: " + key); tklPropDesc_t entry = GetTokelDataDesc(id); ss << (uint8_t)id; - (*std::get<3>(entry))(ss, jsonParams[key]); + if (!(*std::get<3>(entry))(ss, jsonParams[key])) + throw std::runtime_error(std::string("tokel data invalid: ") + key); } return vuint8_t(ss.begin(), ss.end()); @@ -129,7 +124,6 @@ static bool UnmarshalTokelVData(const vuint8_t &vdata, std::map propMap; if (vdata[1] != TKLDATA_VERSION) @@ -252,7 +246,7 @@ bool ValidatePrevTxTokelOpretV1(struct CCcontract_info *cp, Eval* eval, const CT std::vector vcroprets; std::string sError; - if (!myGetTransaction(vin.prevout.hash, vintx, hashBlock)) + if (!eval->GetTxUnconfirmed(vin.prevout.hash, vintx, hashBlock)) return eval->Error("could load vintx"); if (DecodeTokenCreateOpRetV1(vintx.vout.back().scriptPubKey, vorigpk, name, desc, vcroprets) == 0) return eval->Error("could not decode token create tx opreturn"); @@ -286,11 +280,6 @@ bool ValidateTokelOpretV2(struct CCcontract_info *cp, Eval* eval, const CTransac bool TokelDataValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) { - //if (strcmp(ASSETCHAINS_SYMBOL, "TKLTEST") == 0 && chainActive.Height() <= 33711) - // return true; - //if (strcmp(ASSETCHAINS_SYMBOL, "DIMXY20") == 0 && chainActive.Height() <= 1704) - // return true; - if (tx.vout.size() < 1) return eval->Error("no vouts"); diff --git a/src/cc/CCTokelData.h b/src/cc/CCTokelData.h index d2199aa1c60..89dbd8f0b80 100644 --- a/src/cc/CCTokelData.h +++ b/src/cc/CCTokelData.h @@ -23,7 +23,7 @@ enum tklPropType : uint8_t { TKLTYP_VUINT8 = 0x2 }; -typedef void tklWriteSS(CDataStream &ss, const UniValue &val); +typedef bool tklWriteSS(CDataStream &ss, const UniValue &val); typedef UniValue tklReadSS(CDataStream &ss); diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index f90159aa5b1..285d6a17303 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -25,8 +25,6 @@ #include "CCinclude.h" -#include "old/CCassets_v0.h" - #define ASSETS_GLOBALADDR_VIN 1 #define ASSETS_GLOBALADDR_VOUT 0 #define ASSETS_MARKER_AMOUNT 10000 diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index 1bd46478e83..50c0d6d75f0 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -135,7 +135,6 @@ bool GetAssetorigaddrs(struct CCcontract_info *cp, char *origCCaddr, char *origN cpTokens = CCinit(&tokensC, A::TokensEvalCode()); if (vintxFuncId == 's' || vintxFuncId == 'S' || vintxFuncId == 'b' || vintxFuncId == 'B') { - cpTokens->evalcodeAdd = cp->evalcodeAdd; // add non-fungible evalcode if present if (!GetTokensCCaddress(cpTokens, origCCaddr, pubkey2pk(origpubkey), A::IsMixed())) // tokens to single-eval token or token+nonfungible return false; } diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index 1a626ff701b..771f918d86d 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -21,7 +21,7 @@ #include "CCTokelData.h" template -UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) +UniValue AssetOrders(uint256 refassetid, CPubKey pk) { UniValue result(UniValue::VARR); const char *funcname = __func__; @@ -128,14 +128,6 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) if (!pk.IsValid()) // get tokenorders (all orders) { - TokenDataTuple tokenData; - vuint8_t vextraData; - if (refassetid != zeroid) { - GetTokenData(NULL, refassetid, tokenData, vextraData); - if (vextraData.size() > 0) - cpAssets->evalcodeAdd = vextraData[0]; - } - // tokenbids: std::vector > unspentOutputsCoins; char assetsGlobalAddr[KOMODO_ADDRESS_BUFSIZE]; @@ -149,7 +141,6 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t evalcodeAdd) // tokenasks: std::vector > unspentOutputsTokens; char tokensAssetsGlobalAddr[KOMODO_ADDRESS_BUFSIZE]; - cpAssets->evalcodeAdd = evalcodeAdd; GetTokensCCaddress(cpAssets, tokensAssetsGlobalAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); SetCCunspents(unspentOutputsTokens, tokensAssetsGlobalAddr, true); for (std::vector >::const_iterator itTokens = unspentOutputsTokens.begin(); @@ -269,19 +260,17 @@ UniValue CreateSell(const CPubKey &mypk, CAmount txfee, CAmount numtokens, uint2 return (""); } - uint8_t evalcodeAdd = cpTokens->evalcodeAdd ? cpTokens->evalcodeAdd : 0; - CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); - mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), evalcodeAdd, numtokens, unspendableAssetsPubkey)); + mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), numtokens, unspendableAssetsPubkey)); mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); // 1of2 marker (it is for my tokenorders) CAmount CCchange = inputs - numtokens; if (CCchange != 0LL) { // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) - mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), CCchange, mypk)); + mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), CCchange, mypk)); } // cond to spend NFT from mypk - CCwrapper wrCond(T::MakeTokensCCcond1(evalcodeAdd, mypk)); + CCwrapper wrCond(T::MakeTokensCCcond1(T::EvalCode(), mypk)); CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpTokens, mtx, mypk, txfee, @@ -500,14 +489,7 @@ UniValue CancelSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 CCerror = "invalid ask tx or not enough vouts"; return ""; } - - TokenDataTuple tokenData; - vuint8_t vextraData; - GetTokenData(NULL, assetid, tokenData, vextraData); - if (vextraData.size() > 0) - cpAssets->evalcodeAdd = vextraData.begin()[0]; - - mtx.vout.push_back(T::MakeTokensCC1vout(cpAssets->evalcodeAdd ? cpAssets->evalcodeAdd : T::EvalCode(), askamount, mypk)); // one-eval token vout + mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), askamount, mypk)); // one-eval token vout // mtx.vout.push_back(CTxOut(ASSETS_MARKER_AMOUNT, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // we dont need marker for cancelled orders // init assets 'unspendable' privkey and pubkey @@ -515,7 +497,7 @@ UniValue CancelSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); // add additional eval-tokens unspendable assets privkey: - CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), cpAssets->evalcodeAdd, unspendableAssetsPk)); // probe to spend ask remainder + CCwrapper wrCond(T::MakeTokensCCcond1(A::EvalCode(), unspendableAssetsPk)); // probe to spend ask remainder CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // probe to spend marker @@ -563,11 +545,9 @@ UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint2 TokenDataTuple tokenData; vuint8_t vextraData; - uint8_t evalcodeAdd = 0; int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction GetTokenData(NULL, assetid, tokenData, vextraData); if (vextraData.size() > 0) { - evalcodeAdd = vextraData.begin()[0]; GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); if (royaltyFract > TKLROYALTY_DIVISOR-1) royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit @@ -636,17 +616,17 @@ UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint2 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_amount - royaltyValue=" << paid_amount - royaltyValue << std::endl; } - mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator + mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator if (orig_units - fill_units > 0) // order is not finished yet mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey, unspendableAssetsPk)); // vout3(4 if royalty) marker to origpubkey if (tokensChange != 0LL) - mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), tokensChange, mypk)); // change in single-eval tokens + mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), tokensChange, mypk)); // change in single-eval tokens CCwrapper wrCond1(MakeCCcond1(A::EvalCode(), unspendableAssetsPk)); // spend coins CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); - CCwrapper wrCond2(T::MakeTokensCCcond1(evalcodeAdd, mypk)); // spend my tokens to fill buy + CCwrapper wrCond2(T::MakeTokensCCcond1(T::EvalCode(), mypk)); // spend my tokens to fill buy CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey // probe to spend marker @@ -694,11 +674,9 @@ UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 a TokenDataTuple tokenData; vuint8_t vextraData; - uint8_t evalcodeAdd = 0; int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction GetTokenData(NULL, assetid, tokenData, vextraData); if (vextraData.size() > 0) { - evalcodeAdd = vextraData.begin()[0]; GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); if (royaltyFract > TKLROYALTY_DIVISOR-1) royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit @@ -766,10 +744,10 @@ UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 a } // vout.0 tokens remainder to unspendable cc addr: - mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), evalcodeAdd, orig_assetoshis - fillunits, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr + mtx.vout.push_back(T::MakeTokensCC1vout(A::EvalCode(), orig_assetoshis - fillunits, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: - mtx.vout.push_back(T::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : T::EvalCode(), fillunits, mypk)); + mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), fillunits, mypk)); mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr if (royaltyValue > 0) { // note it makes the vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner @@ -783,7 +761,7 @@ UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 a uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - CCwrapper wrCond1(T::MakeTokensCCcond1(A::EvalCode(), evalcodeAdd, unspendableAssetsPk)); + CCwrapper wrCond1(T::MakeTokensCCcond1(A::EvalCode(), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond1, unspendableAssetsPrivkey); // probe to spend marker diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index e7db68faa5f..dff7522e2e1 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -232,7 +232,8 @@ struct CCVintxProbe { struct CCcontract_info { uint8_t evalcode; //!< cc contract eval code, set by CCinit function - uint8_t evalcodeAdd; //!< additional eval code for spending from three-eval-code vouts with EVAL_TOKENS, cc evalcode, cc evalcode NFT + // unused: + // uint8_t evalcodeAdd; //!< additional eval code for spending from three-eval-code vouts with EVAL_TOKENS, cc evalcode, cc evalcode NFT //!< or vouts with two evalcodes: EVAL_TOKENS, evalcodeAdd. //!< Set by AddTokenCCInputs function @@ -293,7 +294,7 @@ struct CCcontract_info void init_to_zeros() { // init to zeros: evalcode = 0; - evalcodeAdd = 0; + // evalcodeAdd = 0; memset(CCpriv, '\0', sizeof(CCpriv) / sizeof(CCpriv[0])); @@ -1110,6 +1111,8 @@ bool IsTxidInActiveChain(uint256 txid); /// @param hashBlock hash of block to check bool IsBlockHashInActiveChain(uint256 hashBlock); +/// subcalls an additional evalcode validator +bool SubcallCCValidate(Eval* eval, uint8_t evalcode, const CTransaction& ctx, int32_t nIn); extern bool fUnspentCCIndex; // if unspent cc index enabled diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 0e75e09981b..7ced57f5c27 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -14,7 +14,6 @@ ******************************************************************************/ #include "CCtokens.h" -#include "old/CCtokens_v0.h" ///#include "importcoin.h" /* TODO: correct this: @@ -148,6 +147,13 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const errorStr = "tokenbase tx cannot have cc vins"; return -1; } + + // call extra data validators + for (auto const &vd : vdatas) + if (vd.size() > 0 && vd[0] != 0) + if (!SubcallCCValidate(eval, vd[0], tx, 0)) + return -1; + // set returned tokend to tokenbase txid: reftokenid = tx.GetHash(); } @@ -174,17 +180,6 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const evalCode2 = vdatas[1].size() > 0 ? vdatas[1][0] : 0; } - // get optional nft eval code: - TokenDataTuple tokenData; - vscript_t vopretNonfungible; - GetTokenData(eval, reftokenid, tokenData, vopretNonfungible); - - if (vopretNonfungible.size() > 0) { - // shift evalcodes so the first is NFT evalcode - evalCode2 = evalCode1; - evalCode1 = vopretNonfungible[0]; - } - LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " for txid=" << tx.GetHash().GetHex() << " checking evalCode1=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " voutPubkeysInOpret.size()=" << voutPubkeysInOpret.size() << std::endl); if (IsTokenTransferFuncid(funcId)) @@ -308,13 +303,11 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " function ValidateTokenOpret returned not-null funcId=" << (char)(funcId ? funcId : ' ') << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); - TokenDataTuple tokenData; - vscript_t vopretExtra, vopretNonfungible; + vscript_t vopretExtra; // MakeTokenCCVout functions support up to two evalcodes in vouts // We assume one of them could be a cc module working with tokens like assets, gateways or heir // another eval code could be for a cc module responsible to non-fungible token data - uint8_t evalCodeNonfungible = 0; uint8_t evalCode1 = EVAL_TOKENS; // if both payloads are empty maybe it is a transfer to non-payload-one-eval-token vout like GatewaysClaim uint8_t evalCode2 = 0; // will be checked if zero or not @@ -333,18 +326,13 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const vopretExtra = vdatas[0]; LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << funcname << "()" << " vopretExtra=" << HexStr(vopretExtra) << std::endl); - // get non-fungible data - GetTokenData(eval, reftokenid, tokenData, vopretNonfungible); std::vector voutPubkeys; FilterOutTokensUnspendablePk(voutPubkeysInOpret, voutPubkeys); // cannot send tokens to token unspendable cc addr (only marker is allowed there) // NOTE: evalcode order in vouts is important: // non-fungible-eval -> EVAL_TOKENS -> assets-eval - - if (vopretNonfungible.size() > 0) - evalCodeNonfungible = evalCode1 = vopretNonfungible.begin()[0]; if (vopretExtra.size() > 0) - evalCode2 = vopretExtra.begin()[0]; + evalCode2 = vopretExtra[0]; if (evalCode1 == EVAL_TOKENS && evalCode2 != 0) { evalCode1 = evalCode2; // for using MakeTokensCC1vout(evalcode,...) instead of MakeCC1vout(EVAL_TOKENS, evalcode...) @@ -378,8 +366,7 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const } // maybe this is like gatewayclaim to single-eval token? - if( evalCodeNonfungible == 0 ) // do not allow to convert non-fungible to fungible token - testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[0]), std::string("single-eval cc1 pk[0]"))); + testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[0]), std::string("single-eval cc1 pk[0]"))); // maybe this is like FillSell for non-fungible token? if( evalCode1 != 0 ) @@ -389,8 +376,7 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const // the same for pk[1]: if (voutPubkeys.size() == 2) { - if (evalCodeNonfungible == 0) // do not allow to convert non-fungible to fungible token - testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[1]), std::string("single-eval cc1 pk[1]"))); + testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[1]), std::string("single-eval cc1 pk[1]"))); if (evalCode1 != 0) testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, tx.vout[v].nValue, voutPubkeys[1]), std::string("dual-eval-token cc1 pk[1]"))); if (evalCode2 != 0) @@ -422,8 +408,7 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const FilterOutTokensUnspendablePk(vinPubkeysUnfiltered, vinPubkeys); // cannot send tokens to token unspendable cc addr (only marker is allowed there) for(std::vector::iterator it = vinPubkeys.begin(); it != vinPubkeys.end(); it++) { - if (evalCodeNonfungible == 0) // do not allow to convert non-fungible to fungible token - testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, *it), std::string("single-eval cc1 self vin pk"))); + testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, *it), std::string("single-eval cc1 self vin pk"))); testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, evalCode2, tx.vout[v].nValue, *it), std::string("three-eval cc1 self vin pk"))); if (evalCode2 != 0) @@ -433,7 +418,7 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const // try all test vouts: for (const auto &t : testVouts) { - if (t.first == tx.vout[v]) { // test vout matches + if (IsEqualDestinations(t.first.scriptPubKey, tx.vout[v].scriptPubKey)) { // test vout matches LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << funcname << "()" << " valid amount=" << tx.vout[v].nValue << " msg=" << t.second << " evalCode=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " txid=" << tx.GetHash().GetHex() << " tokenid=" << reftokenid.GetHex() << std::endl); return tx.vout[v].nValue; } @@ -495,7 +480,7 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const CAmount ccOutputs = 0; for (const auto &vout : tx.vout) if (vout.scriptPubKey.IsPayToCryptoCondition()) { - CTxOut testvout = vopretNFT.size() == 0 ? MakeCC1vout(EVAL_TOKENS, vout.nValue, origPubkey) : MakeTokensCC1vout(vopretNFT[0], vout.nValue, origPubkey); + CTxOut testvout = MakeCC1vout(EVAL_TOKENS, vout.nValue, origPubkey); if (IsEqualDestinations(vout.scriptPubKey, testvout.scriptPubKey)) ccOutputs += vout.nValue; } @@ -507,7 +492,7 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << indentStr << funcname << "()" << " assured origInputs >= ccOutputs" << " for tokenbase=" << reftokenid.GetHex() << std::endl); // make test vout for origpubkey (either for fungible or NFT): - CTxOut testvout = vopretNFT.size() == 0 ? MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, origPubkey) : MakeTokensCC1vout(vopretNFT[0], tx.vout[v].nValue, origPubkey); + CTxOut testvout = MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, origPubkey); if (IsEqualDestinations(tx.vout[v].scriptPubKey, testvout.scriptPubKey)) // check vout sent to orig pubkey return tx.vout[v].nValue; @@ -592,6 +577,11 @@ CAmount TokensV2::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const return -1; // invalid tokendata } */ + // call extra data validators + for (auto const &vd : vdatas) + if (vd.size() > 0 && vd[0] != 0) + if (!SubcallCCValidate(eval, vd[0], tx, 0)) + return -1; // set returned tokend to tokenbase txid: reftokenid = tx.GetHash(); @@ -680,12 +670,6 @@ CAmount TokensV2::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const // NOTE: opreturn decode v1 functions (DecodeTokenCreateOpRetV1 DecodeTokenOpRetV1) understands both old and new opreturn versions bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) { - if (!TokensIsVer1Active(eval)) - return tokensv0::TokensValidate(cp, eval, tx, nIn); - - if (strcmp(ASSETCHAINS_SYMBOL, "ROGUE") == 0 && chainActive.Height() <= 12500) - return true; - // check boundaries: if (tx.vout.size() < 1) return eval->Invalid("no vouts"); @@ -792,9 +776,6 @@ static bool CheckTokensV2CreateTx(struct CCcontract_info *cp, Eval* eval, const // token 2 cc validation entry point bool Tokensv2Validate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) { - if (!TokensIsVer1Active(eval)) - return eval->Invalid("tokens v2 not active yet"); - // check boundaries: if (tx.vout.size() < 1) return report_validation_error(__func__, eval, tx, "no vouts"); @@ -820,42 +801,6 @@ bool Tokensv2Validate(struct CCcontract_info *cp, Eval* eval, const CTransaction } -// default old version functions: - -/*void GetNonfungibleData(uint256 tokenid, vscript_t &vopretNonfungible) -{ - GetNonfungibleData(tokenid, vopretNonfungible); -} - -std::string CreateTokenLocal(CAmount txfee, CAmount tokensupply, std::string name, std::string description, vscript_t nonfungibleData) -{ - return CreateTokenLocal(txfee, tokensupply, name, description, nonfungibleData); -}*/ - -/*bool IsTokenMarkerVout(CTxOut vout) { - return IsTokenMarkerVout(vout); // TODO: fix CheckMigration for tokens V2 -}*/ - -//CAmount IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid) -//{ -// return IsTokensvout(goDeeper, checkPubkeys, cp, eval, tx, v, reftokenid); -//} - -//CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, const char *tokenaddr, uint256 tokenid, CAmount total, int32_t maxinputs, bool useMempool) -//{ -// return AddTokenCCInputs(cp, mtx, tokenaddr, tokenid, total, maxinputs, useMempool); -//} -//CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, const CPubKey &pk, uint256 tokenid, CAmount total, int32_t maxinputs, bool useMempool) -//{ -// return AddTokenCCInputs(cp, mtx, pk, tokenid, total, maxinputs, useMempool); -//} - -//CAmount GetTokenBalance(CPubKey pk, uint256 tokenid, bool usemempool) -//{ -// return GetTokenBalance(pk, tokenid, usemempool); -//} -//UniValue TokenInfo(uint256 tokenid) { return TokenInfo(tokenid); } - UniValue TokenList() { UniValue result(UniValue::VARR); diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index 95f3e275e80..56400852c64 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -45,7 +45,7 @@ bool Tokensv2Validate(struct CCcontract_info *cp,Eval* eval,const CTransaction & /// @param maxinputs maximum number of inputs to add. If 0 then CC_MAXVINS define is used //CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, const CPubKey &pk, uint256 tokenid, CAmount total, int32_t maxinputs, bool useMempool = false); -/// Adds token inputs to transaction object. If tokenid is a non-fungible token then the function will set evalcodeAdd variable in the cp object to the eval code from tokencreate tx NFT data to spend NFT outputs properly +/// Adds token inputs to transaction object. /// @param cp CCcontract_info structure /// @param mtx mutable transaction object /// @param tokenaddr address where token inputs to add @@ -55,7 +55,7 @@ bool Tokensv2Validate(struct CCcontract_info *cp,Eval* eval,const CTransaction & /// @see AddTokenCCInputs //CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, const char *tokenaddr, uint256 tokenid, CAmount total, int32_t maxinputs, bool useMempool = false); -/// Adds token inputs to transaction object. If tokenid is a non-fungible token then the function will set evalcodeAdd variable in the cp object to the eval code from tokencreate tx NFT data to spend NFT outputs properly +/// Adds token inputs to transaction object. /// @param cp CCcontract_info structure /// @param mtx mutable transaction object /// @param pk pubkey from which the token cc address will be created and token inputs are added @@ -280,8 +280,6 @@ inline bool IsTokenTransferFuncid(uint8_t funcid) { return funcid == 't'; } bool IsEqualDestinations(const CScript &spk1, const CScript &spk2); -bool TokensIsVer1Active(const Eval *eval); - const char cctokens_log[] = "cctokens"; // old tokens specific functions diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index d25c503fd14..7ee1dbc9481 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -83,17 +83,7 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c const char *funcname = __func__; if (cp->evalcode != V::EvalCode()) - LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << funcname << "()" << " warning: EVAL_TOKENS *cp is needed but used evalcode=" << (int)cp->evalcode << std::endl); - - if (cp->evalcodeAdd == 0) // if not set yet (in TransferToken or this func overload) - { - // check if this is a NFT - TokenDataTuple tokenData; - vscript_t vextraData; - GetTokenData(NULL, tokenid, tokenData, vextraData); - if (vextraData.size() > 0) - cp->evalcodeAdd = vextraData.begin()[0]; // set evalcode of NFT, for signing - } + LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << funcname << "()" << " warning: EVAL_TOKENS *cp is needed but used evalcode=" << (int)cp->evalcode << std::endl); // make lambda to use it for either index kind: auto add_token_vin = [&](uint256 txhash, int32_t index, CAmount satoshis) -> void @@ -176,14 +166,7 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c { char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; - // check if this is a NFT - TokenDataTuple tokenData; - vscript_t vextraData; - GetTokenData(NULL, tokenid, tokenData, vextraData); - if (vextraData.size() > 0) - cp->evalcodeAdd = vextraData.begin()[0]; // set evalcode of NFT - - GetTokensCCaddress(cp, tokenaddr, pk, V::IsMixed()); // GetTokensCCaddress will use 'evalcodeAdd' + GetTokensCCaddress(cp, tokenaddr, pk, V::IsMixed()); return AddTokenCCInputs(cp, mtx, tokenaddr, tokenid, total, maxinputs, useMempool); } @@ -196,11 +179,6 @@ UniValue TokenBeginTransferTx(CMutableTransaction &mtx, struct CCcontract_info * return MakeResultError("my pubkey not set"); } - if (V::EvalCode() == EVAL_TOKENS) { - if (!TokensIsVer1Active(NULL)) - return MakeResultError("tokens version 1 not active yet"); - } - if (txfee == 0) txfee = 10000; @@ -216,11 +194,6 @@ UniValue TokenBeginTransferTx(CMutableTransaction &mtx, struct CCcontract_info * template UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info *cp, const CPubKey &remotepk, uint256 tokenid, const char *tokenaddr, std::vector destpubkeys, const std::pair &probecond, CAmount amount, bool useMempool) { - if (V::EvalCode() == EVAL_TOKENS) { - if (!TokensIsVer1Active(NULL)) - return MakeResultError("tokens version 1 not active yet"); - } - if (amount < 0) { CCerror = strprintf("negative amount"); LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << CCerror << "=" << amount << std::endl); @@ -243,12 +216,6 @@ UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info * return MakeResultError("insufficient token inputs"); } - uint8_t destEvalCode = V::EvalCode(); - if (cp->evalcodeAdd != 0) // if set in AddTokenCCInputs - { - destEvalCode = cp->evalcodeAdd; - } - if (probecond.first != nullptr) { // add probe cc and kogs priv to spend from kogs global pk @@ -260,9 +227,9 @@ UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info * GetOpReturnData(opret, vopret); std::vector vData { vopret }; if (destpubkeys.size() == 1) - mtx.vout.push_back(V::MakeTokensCC1vout(destEvalCode, amount, destpubkeys[0], &vData)); // if destEvalCode == EVAL_TOKENS then it is actually equal to MakeCC1vout(EVAL_TOKENS,...) + mtx.vout.push_back(V::MakeTokensCC1vout(V::EvalCode(), amount, destpubkeys[0], &vData)); else if (destpubkeys.size() == 2) - mtx.vout.push_back(V::MakeTokensCC1of2vout(destEvalCode, amount, destpubkeys[0], destpubkeys[1], &vData)); + mtx.vout.push_back(V::MakeTokensCC1of2vout(V::EvalCode(), amount, destpubkeys[0], destpubkeys[1], &vData)); else { CCerror = "zero or unsupported destination pk count"; @@ -277,7 +244,7 @@ UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info * vscript_t vopret; GetOpReturnData(opret, vopret); std::vector vData { vopret }; - mtx.vout.push_back(V::MakeTokensCC1vout(destEvalCode, CCchange, mypk, &vData)); + mtx.vout.push_back(V::MakeTokensCC1vout(V::EvalCode(), CCchange, mypk, &vData)); } return MakeResultSuccess(""); @@ -289,12 +256,6 @@ UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info * template UniValue TokenFinalizeTransferTx(CMutableTransaction &mtx, struct CCcontract_info *cp, const CPubKey &remotepk, CAmount txfee, const CScript &opret) { - if (V::EvalCode() == EVAL_TOKENS) { - if (!TokensIsVer1Active(NULL)) - return MakeResultError("tokens version 1 not active yet"); - } - - //uint64_t mask = ~((1LL << mtx.vin.size()) - 1); // seems, mask is not used anymore bool isRemote = IS_REMOTE(remotepk); CPubKey mypk = isRemote ? remotepk : pubkey2pk(Mypubkey()); if (!mypk.IsFullyValid()) { @@ -357,13 +318,7 @@ UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokeni if (normalInputs > 0) { if ((inputs = AddTokenCCInputs(cp, mtx, tokenaddr, tokenid, total, CC_MAXVINS, useMempool)) >= total) // NOTE: AddTokenCCInputs might set cp->additionalEvalCode which is used in FinalizeCCtx! - { - uint8_t destEvalCode = V::EvalCode(); - if (cp->evalcodeAdd != 0) // if set in AddTokenCCInputs - { - destEvalCode = cp->evalcodeAdd; - } - + { if (inputs > total) CCchange = (inputs - total); @@ -385,7 +340,7 @@ UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokeni } } - mtx.vout.push_back(V::MakeTokensCCMofNvout(destEvalCode, 0, total, M, destpubkeys)); + mtx.vout.push_back(V::MakeTokensCCMofNvout(V::EvalCode(), 0, total, M, destpubkeys)); // add optional custom probe conds to non-usual sign vins for (const auto &p : probeconds) @@ -407,10 +362,10 @@ UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokeni COptCCParams ccparams(vParams[0]); if (ccparams.version != 0 && ccparams.vKeys.size() > 1) { if (CCchange != 0) { - mtx.vout.push_back(V::MakeTokensCCMofNvout(destEvalCode, 0, CCchange, ccparams.m, ccparams.vKeys)); + mtx.vout.push_back(V::MakeTokensCCMofNvout(V::EvalCode(), 0, CCchange, ccparams.m, ccparams.vKeys)); CCchange = 0; } - CCwrapper ccprobeMofN( MakeTokensv2CCcondMofN(destEvalCode, 0, ccparams.m, ccparams.vKeys) ); + CCwrapper ccprobeMofN( MakeTokensv2CCcondMofN(V::EvalCode(), 0, ccparams.m, ccparams.vKeys) ); CCAddVintxCond(cp, ccprobeMofN, nullptr); //add MofN probe to find vins and sign break; } @@ -419,11 +374,7 @@ UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokeni } if (CCchange != 0) - mtx.vout.push_back(V::MakeTokensCC1vout(destEvalCode, CCchange, mypk)); - - // no need this: this prbe added in FinalizeCCV2Tx - //CCwrapper ccprobeNFT( MakeTokensv2CCcond1(destEvalCode, mypk) ); - //CCAddVintxCond(cp, ccprobeNFT, nullptr); //add NFT probe to find vins and sign + mtx.vout.push_back(V::MakeTokensCC1vout(V::EvalCode(), CCchange, mypk)); // TODO maybe add also opret blobs form vintx // as now this TokenTransfer() allows to transfer only tokens (including NFTs) that are unbound to other cc @@ -462,8 +413,6 @@ std::string TokenTransfer(CAmount txfee, uint256 tokenid, uint8_t M, const std:: TokenDataTuple tokenData; vscript_t vextraData; GetTokenData(NULL, tokenid, tokenData, vextraData); - if (vextraData.size() > 0) - cp->evalcodeAdd = vextraData.begin()[0]; // set evalcode of NFT GetTokensCCaddress(cp, tokenaddr, mypk, V::IsMixed()); UniValue sigData = TokenTransferExt(CPubKey(), txfee, tokenid, tokenaddr, {}, M, destpubkeys, total, true); @@ -522,13 +471,9 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup return NullUniValue; } - uint8_t destEvalCode = V::EvalCode(); - if( nonfungibleData.size() > 0 && nonfungibleData[0] != 0 ) - destEvalCode = nonfungibleData[0]; - // NOTE: we should prevent spending fake-tokens from this marker in IsTokenvout(): mtx.vout.push_back(V::MakeCC1vout(V::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); // new marker to token cc addr, burnable and validated, vout pos now changed to 0 (from 1) - mtx.vout.push_back(V::MakeTokensCC1vout(destEvalCode, tokensupply, mypk)); + mtx.vout.push_back(V::MakeTokensCC1vout(V::EvalCode(), tokensupply, mypk)); if (additionalMarkerEvalCode > 0) { diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index d3bc0d6e9b2..d1521c618f1 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -18,94 +18,9 @@ // This code was moved to a separate source file to enable linking libcommon.so (with importcoin.cpp which depends on some token functions) #include "CCtokens.h" -#include "old/CCtokens_v0.h" - - -#ifndef IS_CHARINSTR -#define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos) -#endif - - -// return true if new v1 version activation time is passed or chain is always works v1 -// return false if v0 is still active -bool TokensIsVer1Active(const Eval *eval) -{ - return true; // aleays true for tokel chains -} - -// compatibility code -// adds old-style opretid -// for create oprets treat EVAL_IMPORTCOIN as import tx -static std::vector> CreationOpretsToOpretsWithId(const std::vector &oprets) { - std::vector> opretswithid; - - for (auto const &o : oprets) { - if (o.size() > 0) { - uint8_t opretid = 0; - switch(o[0]) { - case EVAL_IMPORTCOIN: - opretid = tokensv0::OPRETID_IMPORTDATA; - break; - default: - opretid = tokensv0::OPRETID_NONFUNGIBLEDATA; - break; - } - if (opretid != 0) - opretswithid.push_back(std::make_pair(opretid, o)); - } - } - return opretswithid; -} - -// compatibility code -// adds old-style opretid for eval code -// for non create oprets treat EVAL_IMPORTCOIN as burn tx -static std::vector> NonCreationOpretsToOpretsWithId(const std::vector &oprets) { - std::vector> opretswithid; - - for (auto const &o : oprets) - { - if (o.size() > 0) { - uint8_t opretid = 0; - switch(o[0]) { - case EVAL_CHANNELS: - opretid = tokensv0::OPRETID_CHANNELSDATA; - break; - case EVAL_HEIR: - opretid = tokensv0::OPRETID_HEIRDATA; - break; - case 17: - opretid = tokensv0::OPRETID_ROGUEGAMEDATA; - break; - case EVAL_ASSETS: - opretid = tokensv0::OPRETID_ASSETSDATA; - break; - case EVAL_PEGS: - opretid = tokensv0::OPRETID_PEGSDATA; - break; - case EVAL_GATEWAYS: - opretid = tokensv0::OPRETID_GATEWAYSDATA; - break; - case EVAL_IMPORTCOIN: - opretid = tokensv0::OPRETID_BURNDATA; - break; - } - if (opretid != 0) - opretswithid.push_back(std::make_pair(opretid, o)); - } - } - return opretswithid; -} CScript EncodeTokenCreateOpRetV1(const std::vector &origpubkey, const std::string &name, const std::string &description, const std::vector &oprets) { - /* no tokens v0 for tokel - // call compatibility code: - if (!TokensIsVer1Active(NULL)) { - return tokensv0::EncodeTokenCreateOpRet('c', origpubkey, name, description, CreationOpretsToOpretsWithId(oprets)); // route to the previous version - } - */ - CScript opret; uint8_t evalcode = EVAL_TOKENS; uint8_t funcid = 'C'; // 'C' indicates opreturn version 1 (with the version field) @@ -135,13 +50,6 @@ CScript EncodeTokenCreateOpRetV2(const std::vector &origpubkey, const s // v1 format with no opretid (evalcode is used instead) CScript EncodeTokenOpRetV1(uint256 tokenid, const std::vector &voutPubkeys, const std::vector &oprets) { - /* no tokens v0 for tokel - // call compatibility code: - if (!TokensIsVer1Active(NULL)) { - return tokensv0::EncodeTokenOpRet(tokenid, voutPubkeys, NonCreationOpretsToOpretsWithId(oprets)); // route to the previous version - } - */ - CScript opret; uint8_t tokenFuncId = 'T'; // 'T' indicates opreturn version 1 (with the version field) uint8_t evalCodeInOpret = EVAL_TOKENS; @@ -156,9 +64,6 @@ CScript EncodeTokenOpRetV1(uint256 tokenid, const std::vector &voutPubk LOGSTREAM(cctokens_log, 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 << version << tokenid << pkCount; if (pkCount >= 1) ss << voutPubkeys[0]; if (pkCount == 2) ss << voutPubkeys[1]; @@ -202,19 +107,6 @@ uint8_t DecodeTokenCreateOpRetV1(const CScript &scriptPubKey, std::vector> opretswithid; - if ((funcid = tokensv0::DecodeTokenCreateOpRet(scriptPubKey, origpubkey, name, description, opretswithid)) != 0) // check pubkey is parsed okay - { - for (auto const & oi : opretswithid) - oprets.push_back(oi.second); - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "decoded v0 opret funcid=" << (char)funcid << " name=" << name << std::endl); - return funcid; - } - */ - - GetOpReturnData(scriptPubKey, vopret); if (vopret.size() > 2 && vopret[0] == EVAL_TOKENS && vopret[1] == 'C') { @@ -269,18 +161,6 @@ uint8_t DecodeTokenOpRetV1(const CScript scriptPubKey, uint256 &tokenid, std::ve oprets.clear(); - /* no tokens v0 for tokel - // try to decode old opreturn version (check tokenid is not null): - std::vector> opretswithid; - if ((funcId = tokensv0::DecodeTokenOpRet(scriptPubKey, evalCodeOld, tokenid, voutPubkeys, opretswithid)) != 0) - { - for (auto const & oi : opretswithid) - oprets.push_back(oi.second); - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "decoded v0 opret funcid=" << (char)funcId << " tokenid=" << tokenid.GetHex() << std::endl); - return funcId; - } - */ - GetOpReturnData(scriptPubKey, vopret); // tokenid = zeroid; this was incorrect: cleared the passed tokenid if creation tx diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 742918d8312..6851c0ba614 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -104,7 +104,7 @@ UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_inf // 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->evalcodeAdd, mypk); + mytokenscond = MakeTokensCCcond1(cp->evalcode, mypk); // to spend from single-eval EVAL_TOKENS mypk cpTokens = CCinit(&tokensC, EVAL_TOKENS); @@ -113,7 +113,7 @@ UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_inf // 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->evalcodeAdd, unspendablepk); + othertokenscond = MakeTokensCCcond1(cp->evalcode, 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. @@ -297,7 +297,7 @@ UniValue FinalizeCCTxExt(bool remote, uint32_t changeFlag, struct CCcontract_inf 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->evalcodeAdd, cp->tokens1of2pk[0], cp->tokens1of2pk[1]); + othercond1of2tokens = MakeTokensCCcond1of2(cp->evalcode, cp->tokens1of2pk[0], cp->tokens1of2pk[1]); cond = othercond1of2tokens; } else @@ -530,7 +530,7 @@ UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info cond.reset(MakeCCcond1(cp->evalcode, mypk)); } else if (strcmp(destaddr, mynftaddr) == 0) { privkey = myprivkey; - cond.reset(MakeTokensv2CCcond1(cp->evalcode, cp->evalcodeAdd, mypk)); + cond.reset(MakeTokensv2CCcond1(cp->evalcode, mypk)); } else { const uint8_t nullpriv[32] = {'\0'}; // use vector of dest addresses and conds to probe vintxconds diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 5cfb59f23bb..9b651089516 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -440,7 +440,7 @@ 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->evalcodeAdd, pk, mixed)); + return(_GetTokensCCaddress(destaddr, cp->evalcode, 0, pk, mixed)); } bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2, bool mixed) @@ -459,12 +459,12 @@ bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey { CCwrapper payoutCond; if (!mixed) - payoutCond.reset(MakeTokensCCcond1of2(cp->evalcode, cp->evalcodeAdd, pk1, pk2)); + payoutCond.reset(MakeTokensCCcond1of2(cp->evalcode, pk1, pk2)); else - payoutCond.reset(MakeTokensv2CCcond1of2(cp->evalcode, cp->evalcodeAdd, pk1, pk2)); + payoutCond.reset(MakeTokensv2CCcond1of2(cp->evalcode, pk1, pk2)); destaddr[0] = 0; - if (payoutCond != nullptr) // if evalcodeAdd not set then it is dual-eval cc else three-eval cc + if (payoutCond != nullptr) { if (mixed) CCtoAnon(payoutCond.get()); @@ -1017,11 +1017,11 @@ CAmount TotalPubkeyCCInputs(Eval *eval, const CTransaction &tx, const CPubKey &p bool ProcessCC(struct CCcontract_info* cp, Eval* eval, std::vector paramsNull, const CTransaction& ctx, unsigned int nIn, std::shared_ptr evalcodeChecker) { - CTransaction createTx; - uint256 assetid, assetid2, hashBlock; - uint8_t funcid; - int32_t height, i, n, from_mempool = 0; - int64_t amount; + //CTransaction createTx; + //uint256 assetid, assetid2, hashBlock; + //uint8_t funcid; + int32_t height, from_mempool = 0; + //int64_t amount; std::vector origpubkey; height = KOMODO_CONNECTING; if (KOMODO_CONNECTING < 0) // always comes back with > 0 for final confirmation @@ -1057,6 +1057,41 @@ bool ProcessCC(struct CCcontract_info* cp, Eval* eval, std::vector para return (false); } +bool SubcallCCValidate(Eval* eval, uint8_t evalcode, const CTransaction& ctx, int32_t nIn) +{ + if (ASSETCHAINS_CC == 0) + return eval->Invalid("CC are disabled"); + + + if ( ASSETCHAINS_CCDISABLES[evalcode] != 0 ) + { + // check if a height activation has been set. + if ( mapHeightEvalActivate[evalcode] == 0 || eval->GetCurrentHeight() == 0 || mapHeightEvalActivate[evalcode] > eval->GetCurrentHeight() ) + { + return eval->Invalid("disabled-code, -ac_ccenables didnt include this ecode"); + } + } + + struct CCcontract_info *cp; + cp = &CCinfos[(int32_t)evalcode]; + if ( cp->didinit == 0 ) + { + CCinit(cp, evalcode); + cp->didinit = 1; + } + + if (cp->validate == NULL) + return eval->Invalid("validation not supported for eval code"); + + CCclearvars(cp); + if ((*cp->validate)(cp, eval, ctx, nIn) != false) { + return true; + } + else { + return false; + } +} + bool CClib_Dispatch(const CC* cond, Eval* eval, std::vector paramsNull, const CTransaction& txTo, unsigned int nIn, std::shared_ptr evalcodeChecker) { uint8_t evalcode; diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 147711326d6..0492b924d9f 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -166,7 +166,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const CTransaction vinTx, createTx; uint256 hashBlock, assetid; int32_t ccvins = -1, ccvouts = -1; - int64_t unit_price, vin_unit_price; + CAmount unit_price, vin_unit_price; vuint8_t vorigpubkey, vin_origpubkey, vextraData; TokenDataTuple tokenData; uint8_t funcid, evalCodeInOpret; @@ -188,7 +188,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if((funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCodeInOpret, assetid, unit_price, vorigpubkey, expiryHeight)) == 0 ) return eval->Invalid("AssetValidate: invalid opreturn payload"); - // reinit cpAssets as we could set evalcodeAdd in it + // reinit cpAssets for a chance anything is set there struct CCcontract_info *cpAssets, assetsC; cpAssets = CCinit(&assetsC, A::EvalCode()); @@ -200,7 +200,6 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const GetTokenData(eval, assetid, tokenData, vextraData); int64_t royaltyFract = 0; // royalty is N in N/1000 fraction if (vextraData.size() > 0) { - cpAssets->evalcodeAdd = vextraData.begin()[0]; GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); if (royaltyFract > TKLROYALTY_DIVISOR-1) royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit @@ -650,13 +649,6 @@ bool AssetsValidate(struct CCcontract_info *cpAssets, Eval* eval,const CTransact if (strcmp(ASSETCHAINS_SYMBOL, "MGNX") == 0 && chainActive.Height() <= 210190) return true; - if (!TokensIsVer1Active(NULL)) { - bool valid = tokensv0::AssetsValidate(cpAssets, eval, tx, nIn); // call assets validation version 0 - if (!valid) - LOGSTREAMFN(ccassets_log, CCLOG_ERROR, stream << "v0 validation error: " << eval->state.GetRejectReason() << ", code: " << eval->state.GetRejectCode() << ", tx: " << HexStr(E_MARSHAL(ss << tx)) << std::endl); - return valid; - } - if (!AssetsValidateInternal(cpAssets, eval, tx, nIn)) { LOGSTREAMFN(ccassets_log, CCLOG_ERROR, stream << "validation error: " << eval->state.GetRejectReason() << ", code: " << eval->state.GetRejectCode() << ", tx: " << HexStr(E_MARSHAL(ss << tx)) << std::endl); return false; diff --git a/src/cc/heir.cpp b/src/cc/heir.cpp index db565af5c97..3129e636aaa 100644 --- a/src/cc/heir.cpp +++ b/src/cc/heir.cpp @@ -15,22 +15,11 @@ #include "CCHeir.h" #include "heir_validate.h" -#include "old/heir_validate_v0.h" #include class CoinHelper; class TokenHelper; -//#ifndef MAY2020_NNELECTION_HARDFORK -//#define MAY2020_NNELECTION_HARDFORK 1590926400 -//#endif - -// return true if new v1 version activation time is passed or chain is always works v1 -// return false if v0 is still active -bool HeirIsVer1Active(const Eval *eval) -{ - return true; // aleays true for tokel chains -} /* The idea of Heir CC is to allow crypto inheritance. @@ -336,11 +325,6 @@ uint8_t _DecodeHeirEitherOpRetV1(CScript scriptPubKey, uint256 &tokenid, CPubKey std::vector oprets; vscript_t vopretExtra /*, vopretStripped*/; - // try to parse - uint8_t oldfuncid; - if ((oldfuncid = heirv0::_DecodeHeirEitherOpRet(scriptPubKey, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, memo, fundingTxidInOpret, hasHeirSpendingBegun, noLogging)) != 0) - return oldfuncid; - if (DecodeTokenOpRetV1(scriptPubKey, tokenid, voutPubkeysDummy, oprets) != 0 && GetOpReturnCCBlob(oprets, vopretExtra)) { if (vopretExtra.size() < 1) { @@ -381,10 +365,7 @@ uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &toke CTransaction fundingtx; uint256 hashBlock; const bool allowSlow = false; - - if (!HeirIsVer1Active(NULL)) - return heirv0::_FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, memo, fundingOpretScript, hasHeirSpendingBegun); - + hasHeirSpendingBegun = 0; funcId = 0; diff --git a/src/cc/heir_validate.h b/src/cc/heir_validate.h index cd97bbb69f7..1fd955b810e 100644 --- a/src/cc/heir_validate.h +++ b/src/cc/heir_validate.h @@ -5,13 +5,10 @@ #include "CCtokens.h" #include "CCtokens_impl.h" #include "CCHeir.h" -#include "old/heir_validate_v0.h" #define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos) -bool HeirIsVer1Active(const Eval *eval); - // makes coin initial tx opret vscript_t EncodeHeirCreateOpRetV1(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo); vscript_t EncodeHeirOpRetV1(uint8_t funcid, uint256 fundingtxid, uint8_t isHeirSpendingBegan); @@ -33,23 +30,13 @@ class CoinHelper { } static CScript makeCreateOpRet(uint256 dummyid, std::vector dummyPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo) { - if (HeirIsVer1Active(NULL)) - return CScript() << OP_RETURN << EncodeHeirCreateOpRetV1((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo); - else - return CScript() << OP_RETURN << heirv0::EncodeHeirCreateOpRet((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo); + return CScript() << OP_RETURN << EncodeHeirCreateOpRetV1((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo); } static CScript makeAddOpRet(uint256 dummyid, std::vector dummyPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) { - if (HeirIsVer1Active(NULL)) - return CScript() << OP_RETURN << EncodeHeirOpRetV1((uint8_t)'A', fundingtxid, isHeirSpendingBegan); - else - return CScript() << OP_RETURN << heirv0::EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan); - + return CScript() << OP_RETURN << EncodeHeirOpRetV1((uint8_t)'A', fundingtxid, isHeirSpendingBegan); } static CScript makeClaimOpRet(uint256 dummyid, std::vector dummyPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) { - if (HeirIsVer1Active(NULL)) - return CScript() << OP_RETURN << EncodeHeirOpRetV1((uint8_t)'C', fundingtxid, isHeirSpendingBegan); - else - return CScript() << OP_RETURN << heirv0::EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan); + return CScript() << OP_RETURN << EncodeHeirOpRetV1((uint8_t)'C', fundingtxid, isHeirSpendingBegan); } static CTxOut make1of2Vout(int64_t amount, CPubKey ownerPubkey, CPubKey heirPubkey) { return MakeCC1of2vout(EVAL_HEIR, amount, ownerPubkey, heirPubkey); @@ -85,22 +72,13 @@ class TokenHelper { } static CScript makeCreateOpRet(uint256 tokenid, std::vector voutTokenPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo) { - if (HeirIsVer1Active(NULL)) - return EncodeTokenOpRetV1(tokenid, voutTokenPubkeys, { EncodeHeirCreateOpRetV1((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo) }); - else - return EncodeTokenOpRetV1(tokenid, voutTokenPubkeys, { heirv0::EncodeHeirCreateOpRet((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo) }); + return EncodeTokenOpRetV1(tokenid, voutTokenPubkeys, { EncodeHeirCreateOpRetV1((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo) }); } static CScript makeAddOpRet(uint256 tokenid, std::vector voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) { - if (HeirIsVer1Active(NULL)) - return EncodeTokenOpRetV1(tokenid, voutTokenPubkeys, { EncodeHeirOpRetV1((uint8_t)'A', fundingtxid, isHeirSpendingBegan) }); - else - return EncodeTokenOpRetV1(tokenid, voutTokenPubkeys, { heirv0::EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan) }); + return EncodeTokenOpRetV1(tokenid, voutTokenPubkeys, { EncodeHeirOpRetV1((uint8_t)'A', fundingtxid, isHeirSpendingBegan) }); } static CScript makeClaimOpRet(uint256 tokenid, std::vector voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) { - if (HeirIsVer1Active(NULL)) - return EncodeTokenOpRetV1(tokenid, voutTokenPubkeys, { EncodeHeirOpRetV1((uint8_t)'C', fundingtxid, isHeirSpendingBegan) }); - else - return EncodeTokenOpRetV1(tokenid, voutTokenPubkeys, { heirv0::EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan) }); + return EncodeTokenOpRetV1(tokenid, voutTokenPubkeys, { EncodeHeirOpRetV1((uint8_t)'C', fundingtxid, isHeirSpendingBegan) }); } static CTxOut make1of2Vout(int64_t amount, CPubKey ownerPubkey, CPubKey heirPubkey) { diff --git a/src/cc/old/CCassetsCore_v0.cpp b/src/cc/old/CCassetsCore_v0.cpp deleted file mode 100644 index a313f832e03..00000000000 --- a/src/cc/old/CCassetsCore_v0.cpp +++ /dev/null @@ -1,655 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2018 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. * - * * - ******************************************************************************/ - -#include "CCtokens_v0.h" -#include "CCassets_v0.h" - -namespace tokensv0 { - -/* - The SetAssetFillamounts() and ValidateAssetRemainder() work in tandem to calculate the vouts for a fill and to validate the vouts, respectively. - - This pair of functions are critical to make sure the trading is correct and is the trickiest part of the assets contract. - - //vin.0: normal input - //vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] - //vin.2+: valid CC output satisfies buyoffer (*tx.vin[2])->nValue - //vout.0: remaining amount of bid to unspendable - //vout.1: vin.1 value to signer of vin.2 - //vout.2: vin.2 assetoshis to original pubkey - //vout.3: CC output for assetoshis change (if any) - //vout.4: normal output for change (if any) - //vout.n-1: opreturn [EVAL_ASSETS] ['B'] [assetid] [remaining asset required] [origpubkey] - ValidateAssetRemainder(remaining_price,tx.vout[0].nValue,nValue,tx.vout[1].nValue,tx.vout[2].nValue,totalunits); - - Yes, this is quite confusing... - - In ValidateAssetRemainder the naming convention is nValue is the coin/asset with the offer on the books and "units" is what it is being paid in. The high level check is to make sure we didnt lose any coins or assets, the harder to validate is the actual price paid as the "orderbook" is in terms of the combined nValue for the combined totalunits. - - We assume that the effective unit cost in the orderbook is valid and that that amount was paid and also that any remainder will be close enough in effective unit cost to not matter. At the edge cases, this will probably be not true and maybe some orders wont be practically fillable when reduced to fractional state. However, the original pubkey that created the offer can always reclaim it. -*/ - -bool ValidateBidRemainder(int64_t remaining_units,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidunits,int64_t totalunits) -{ - int64_t unitprice,recvunitprice,newunitprice=0; - if ( orig_nValue == 0 || received_nValue == 0 || paidunits == 0 || totalunits == 0 ) - { - fprintf(stderr,"ValidateAssetRemainder() orig_nValue == %llu || received_nValue == %llu || paidunits == %llu || totalunits == %llu\n",(long long)orig_nValue,(long long)received_nValue,(long long)paidunits,(long long)totalunits); - return(false); - } - else if ( totalunits != (remaining_units + paidunits) ) - { - fprintf(stderr,"ValidateAssetRemainder() totalunits %llu != %llu (remaining_units %llu + %llu paidunits)\n",(long long)totalunits,(long long)(remaining_units + paidunits),(long long)remaining_units,(long long)paidunits); - return(false); - } - else if ( orig_nValue != (remaining_nValue + received_nValue) ) - { - fprintf(stderr,"ValidateAssetRemainder() orig_nValue %llu != %llu (remaining_nValue %llu + %llu received_nValue)\n",(long long)orig_nValue,(long long)(remaining_nValue - received_nValue),(long long)remaining_nValue,(long long)received_nValue); - return(false); - } - else - { - //unitprice = (orig_nValue * COIN) / totalunits; - //recvunitprice = (received_nValue * COIN) / paidunits; - //if ( remaining_units != 0 ) - // newunitprice = (remaining_nValue * COIN) / remaining_units; - unitprice = (orig_nValue / totalunits); - recvunitprice = (received_nValue / paidunits); - if ( remaining_units != 0 ) - newunitprice = (remaining_nValue / remaining_units); - if ( recvunitprice < unitprice ) - { - fprintf(stderr,"ValidateAssetRemainder() error recvunitprice %.8f < %.8f unitprice, new unitprice %.8f\n",(double)recvunitprice/(COIN),(double)unitprice/(COIN),(double)newunitprice/(COIN)); - return(false); - } - fprintf(stderr,"ValidateAssetRemainder() orig %llu total %llu, recv %llu paid %llu,recvunitprice %.8f >= %.8f unitprice, new unitprice %.8f\n",(long long)orig_nValue,(long long)totalunits,(long long)received_nValue,(long long)paidunits,(double)recvunitprice/(COIN),(double)unitprice/(COIN),(double)newunitprice/(COIN)); - } - return(true); -} - -bool SetBidFillamounts(int64_t &received_nValue,int64_t &remaining_units,int64_t orig_nValue,int64_t &paidunits,int64_t totalunits) -{ - int64_t remaining_nValue,unitprice; double dprice; - if ( totalunits == 0 ) - { - received_nValue = remaining_units = paidunits = 0; - return(false); - } - if ( paidunits >= totalunits ) - { - paidunits = totalunits; - received_nValue = orig_nValue; - remaining_units = 0; - fprintf(stderr,"SetBidFillamounts() bid order totally filled!\n"); - return(true); - } - remaining_units = (totalunits - paidunits); - //unitprice = (orig_nValue * COIN) / totalunits; - //received_nValue = (paidunits * unitprice) / COIN; - unitprice = (orig_nValue / totalunits); - received_nValue = (paidunits * unitprice); - if ( unitprice > 0 && received_nValue > 0 && received_nValue <= orig_nValue ) - { - remaining_nValue = (orig_nValue - received_nValue); - printf("SetBidFillamounts() total.%llu - paid.%llu, remaining %llu <- %llu (%llu - %llu)\n",(long long)totalunits,(long long)paidunits,(long long)remaining_nValue,(long long)(orig_nValue - received_nValue),(long long)orig_nValue,(long long)received_nValue); - return(ValidateBidRemainder(remaining_units,remaining_nValue,orig_nValue,received_nValue,paidunits,totalunits)); - } else return(false); -} - -bool SetAskFillamounts(int64_t &received_assetoshis,int64_t &remaining_nValue,int64_t orig_assetoshis,int64_t &paid_nValue,int64_t total_nValue) -{ - int64_t remaining_assetoshis; double dunitprice; - if ( total_nValue == 0 ) - { - received_assetoshis = remaining_nValue = paid_nValue = 0; - return(false); - } - if ( paid_nValue >= total_nValue ) - { - paid_nValue = total_nValue; - received_assetoshis = orig_assetoshis; - remaining_nValue = 0; - fprintf(stderr,"SetAskFillamounts() ask order totally filled!\n"); - return(true); - } - remaining_nValue = (total_nValue - paid_nValue); - dunitprice = ((double)total_nValue / orig_assetoshis); - received_assetoshis = (paid_nValue / dunitprice); - fprintf(stderr,"SetAskFillamounts() remaining_nValue %.8f (%.8f - %.8f)\n",(double)remaining_nValue/COIN,(double)total_nValue/COIN,(double)paid_nValue/COIN); - fprintf(stderr,"SetAskFillamounts() unitprice %.8f received_assetoshis %llu orig %llu\n",dunitprice/COIN,(long long)received_assetoshis,(long long)orig_assetoshis); - if ( fabs(dunitprice) > SMALLVAL && received_assetoshis > 0 && received_assetoshis <= orig_assetoshis ) - { - remaining_assetoshis = (orig_assetoshis - received_assetoshis); - return(ValidateAskRemainder(remaining_nValue,remaining_assetoshis,orig_assetoshis,received_assetoshis,paid_nValue,total_nValue)); - } else return(false); -} - -bool ValidateAskRemainder(int64_t remaining_nValue,int64_t remaining_assetoshis,int64_t orig_assetoshis,int64_t received_assetoshis,int64_t paid_nValue,int64_t total_nValue) -{ - int64_t unitprice,recvunitprice,newunitprice=0; - if ( orig_assetoshis == 0 || received_assetoshis == 0 || paid_nValue == 0 || total_nValue == 0 ) - { - fprintf(stderr,"ValidateAssetRemainder() orig_assetoshis == %llu || received_assetoshis == %llu || paid_nValue == %llu || total_nValue == %llu\n",(long long)orig_assetoshis,(long long)received_assetoshis,(long long)paid_nValue,(long long)total_nValue); - return(false); - } - else if ( total_nValue != (remaining_nValue + paid_nValue) ) - { - fprintf(stderr,"ValidateAssetRemainder() total_nValue %llu != %llu (remaining_nValue %llu + %llu paid_nValue)\n",(long long)total_nValue,(long long)(remaining_nValue + paid_nValue),(long long)remaining_nValue,(long long)paid_nValue); - return(false); - } - else if ( orig_assetoshis != (remaining_assetoshis + received_assetoshis) ) - { - fprintf(stderr,"ValidateAssetRemainder() orig_assetoshis %llu != %llu (remaining_nValue %llu + %llu received_nValue)\n",(long long)orig_assetoshis,(long long)(remaining_assetoshis - received_assetoshis),(long long)remaining_assetoshis,(long long)received_assetoshis); - return(false); - } - else - { - unitprice = (total_nValue / orig_assetoshis); - recvunitprice = (paid_nValue / received_assetoshis); - if ( remaining_nValue != 0 ) - newunitprice = (remaining_nValue / remaining_assetoshis); - if ( recvunitprice < unitprice ) - { - fprintf(stderr,"ValidateAskRemainder() error recvunitprice %.8f < %.8f unitprice, new unitprice %.8f\n",(double)recvunitprice/COIN,(double)unitprice/COIN,(double)newunitprice/COIN); - return(false); - } - fprintf(stderr,"ValidateAskRemainder() got recvunitprice %.8f >= %.8f unitprice, new unitprice %.8f\n",(double)recvunitprice/COIN,(double)unitprice/COIN,(double)newunitprice/COIN); - } - return(true); -} - -bool SetSwapFillamounts(int64_t &received_assetoshis,int64_t &remaining_assetoshis2,int64_t orig_assetoshis,int64_t &paid_assetoshis2,int64_t total_assetoshis2) -{ - int64_t remaining_assetoshis; double dunitprice; - if ( total_assetoshis2 == 0 ) - { - fprintf(stderr,"SetSwapFillamounts() total_assetoshis2.0 origsatoshis.%llu paid_assetoshis2.%llu\n",(long long)orig_assetoshis,(long long)paid_assetoshis2); - received_assetoshis = remaining_assetoshis2 = paid_assetoshis2 = 0; - return(false); - } - if ( paid_assetoshis2 >= total_assetoshis2 ) - { - paid_assetoshis2 = total_assetoshis2; - received_assetoshis = orig_assetoshis; - remaining_assetoshis2 = 0; - fprintf(stderr,"SetSwapFillamounts() swap order totally filled!\n"); - return(true); - } - remaining_assetoshis2 = (total_assetoshis2 - paid_assetoshis2); - dunitprice = ((double)total_assetoshis2 / orig_assetoshis); - received_assetoshis = (paid_assetoshis2 / dunitprice); - fprintf(stderr,"SetSwapFillamounts() remaining_assetoshis2 %llu (%llu - %llu)\n",(long long)remaining_assetoshis2/COIN,(long long)total_assetoshis2/COIN,(long long)paid_assetoshis2/COIN); - fprintf(stderr,"SetSwapFillamounts() unitprice %.8f received_assetoshis %llu orig %llu\n",dunitprice/COIN,(long long)received_assetoshis,(long long)orig_assetoshis); - if ( fabs(dunitprice) > SMALLVAL && received_assetoshis > 0 && received_assetoshis <= orig_assetoshis ) - { - remaining_assetoshis = (orig_assetoshis - received_assetoshis); - return(ValidateAskRemainder(remaining_assetoshis2,remaining_assetoshis,orig_assetoshis,received_assetoshis,paid_assetoshis2,total_assetoshis2)); - } else return(false); -} - -bool ValidateSwapRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidunits,int64_t totalunits) -{ - int64_t unitprice,recvunitprice,newunitprice=0; - if ( orig_nValue == 0 || received_nValue == 0 || paidunits == 0 || totalunits == 0 ) - { - fprintf(stderr,"ValidateAssetRemainder() orig_nValue == %llu || received_nValue == %llu || paidunits == %llu || totalunits == %llu\n",(long long)orig_nValue,(long long)received_nValue,(long long)paidunits,(long long)totalunits); - return(false); - } - else if ( totalunits != (remaining_price + paidunits) ) - { - fprintf(stderr,"ValidateAssetRemainder() totalunits %llu != %llu (remaining_price %llu + %llu paidunits)\n",(long long)totalunits,(long long)(remaining_price + paidunits),(long long)remaining_price,(long long)paidunits); - return(false); - } - else if ( orig_nValue != (remaining_nValue + received_nValue) ) - { - fprintf(stderr,"ValidateAssetRemainder() orig_nValue %llu != %llu (remaining_nValue %llu + %llu received_nValue)\n",(long long)orig_nValue,(long long)(remaining_nValue - received_nValue),(long long)remaining_nValue,(long long)received_nValue); - return(false); - } - else - { - unitprice = (orig_nValue * COIN) / totalunits; - recvunitprice = (received_nValue * COIN) / paidunits; - if ( remaining_price != 0 ) - newunitprice = (remaining_nValue * COIN) / remaining_price; - if ( recvunitprice < unitprice ) - { - fprintf(stderr,"ValidateAssetRemainder() error recvunitprice %.8f < %.8f unitprice, new unitprice %.8f\n",(double)recvunitprice/(COIN*COIN),(double)unitprice/(COIN*COIN),(double)newunitprice/(COIN*COIN)); - return(false); - } - fprintf(stderr,"ValidateAssetRemainder() recvunitprice %.8f >= %.8f unitprice, new unitprice %.8f\n",(double)recvunitprice/(COIN*COIN),(double)unitprice/(COIN*COIN),(double)newunitprice/(COIN*COIN)); - } - return(true); -} - -/* use EncodeTokenCreateOpRet instead: -CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector origpubkey,std::string name,std::string description) -{ - CScript opret; uint8_t evalcode = EVAL_ASSETS; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << origpubkey << name << description); - return(opret); -} -*/ - -vscript_t EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t price, std::vector origpubkey) -{ - vscript_t vopret; - uint8_t evalcode = EVAL_ASSETS; - - switch ( assetFuncId ) - { - //case 't': this cannot be here - case 'x': case 'o': - vopret = /*<< OP_RETURN <<*/ E_MARSHAL(ss << evalcode << assetFuncId); - break; - case 's': case 'b': case 'S': case 'B': - vopret = /*<< OP_RETURN <<*/ E_MARSHAL(ss << evalcode << assetFuncId << price << origpubkey); - break; - case 'E': case 'e': - assetid2 = revuint256(assetid2); - vopret = /*<< OP_RETURN <<*/ E_MARSHAL(ss << evalcode << assetFuncId << assetid2 << price << origpubkey); - break; - default: - fprintf(stderr,"EncodeAssetOpRet: illegal funcid.%02x\n", assetFuncId); - //opret << OP_RETURN; - break; - } - return(vopret); -} - -/* it is for compatibility, do not use this for new contracts (use DecodeTokenCreateOpRet) -bool DecodeAssetCreateOpRet(const CScript &scriptPubKey, std::vector &origpubkey, std::string &name, std::string &description) -{ - std::vector vopret; uint8_t evalcode,funcid,*script; - GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( script != 0 && vopret.size() > 2 && script[0] == EVAL_ASSETS && script[1] == 'c' ) - { - if ( E_UNMARSHAL(vopret,ss >> evalcode; ss >> funcid; ss >> origpubkey; ss >> name; ss >> description) != 0 ) - return(true); - } - return(0); -} */ - -uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &price, std::vector &origpubkey) -{ - vscript_t vopretAssets; //, vopretAssetsStripped; - uint8_t *script, funcId = 0, assetsFuncId = 0, dummyEvalCode, dummyAssetFuncId; - uint256 dummyTokenid; - std::vector voutPubkeysDummy; - std::vector> oprets; - - tokenid = zeroid; - assetid2 = zeroid; - price = 0; - assetsEvalCode = 0; - assetsFuncId = 0; - - // First - decode token opret: - funcId = DecodeTokenOpRet(scriptPubKey, dummyEvalCode, tokenid, voutPubkeysDummy, oprets); - GetOpretBlob(oprets, OPRETID_ASSETSDATA, vopretAssets); - - LOGSTREAM((char *)"ccassets", CCLOG_DEBUG2, stream << "DecodeAssetTokenOpRet() from DecodeTokenOpRet returned funcId=" << (int)funcId << std::endl); - - if (funcId == 0 || vopretAssets.size() < 2) { - LOGSTREAM((char *)"ccassets", CCLOG_INFO, stream << "DecodeAssetTokenOpRet() incorrect opret or no asset's payload" << " funcId=" << (int)funcId << " vopretAssets.size()=" << vopretAssets.size() << std::endl); - return (uint8_t)0; - } - - //if (!E_UNMARSHAL(vopretAssets, { ss >> vopretAssetsStripped; })) { //strip string size - // std::cerr << "DecodeAssetTokenOpRet() could not unmarshal vopretAssetsStripped" << std::endl; - // return (uint8_t)0; - //} - - // additional check to prevent crash - if (vopretAssets.size() >= 2) { - - assetsEvalCode = vopretAssets.begin()[0]; - assetsFuncId = vopretAssets.begin()[1]; - - LOGSTREAM((char *)"ccassets", CCLOG_DEBUG2, stream << "DecodeAssetTokenOpRet() assetsEvalCode=" << (int)assetsEvalCode << " funcId=" << (char)(funcId ? funcId : ' ') << " assetsFuncId=" << (char)(assetsFuncId ? assetsFuncId : ' ') << std::endl); - - if (assetsEvalCode == EVAL_ASSETS) - { - //fprintf(stderr,"DecodeAssetTokenOpRet() decode.[%c] assetFuncId.[%c]\n", funcId, assetFuncId); - switch (assetsFuncId) - { - case 'x': case 'o': - if (vopretAssets.size() == 2) // no data after 'evalcode assetFuncId' allowed - { - return(assetsFuncId); - } - break; - case 's': case 'b': case 'S': case 'B': - if (E_UNMARSHAL(vopretAssets, ss >> dummyEvalCode; ss >> dummyAssetFuncId; ss >> price; ss >> origpubkey) != 0) - { - //fprintf(stderr,"DecodeAssetTokenOpRet() got price %llu\n",(long long)price); - return(assetsFuncId); - } - break; - case 'E': case 'e': - if (E_UNMARSHAL(vopretAssets, ss >> dummyEvalCode; ss >> dummyAssetFuncId; ss >> assetid2; ss >> price; ss >> origpubkey) != 0) - { - //fprintf(stderr,"DecodeAssetTokenOpRet() got price %llu\n",(long long)price); - assetid2 = revuint256(assetid2); - return(assetsFuncId); - } - break; - default: - break; - } - } - } - - LOGSTREAM((char *)"ccassets", CCLOG_INFO, stream << "DecodeAssetTokenOpRet() no asset's payload or incorrect assets funcId or evalcode" << " funcId=" << (int)funcId << " vopretAssets.size()=" << vopretAssets.size() << " assetsEvalCode=" << assetsEvalCode << " assetsFuncId=" << assetsFuncId << std::endl); - return (uint8_t)0; -} - -// extract sell/buy owner's pubkey from the opret -bool SetAssetOrigpubkey(std::vector &origpubkey,int64_t &price,const CTransaction &tx) -{ - uint256 assetid,assetid2; - uint8_t evalCode; - - if ( tx.vout.size() > 0 && DecodeAssetTokenOpRet(tx.vout[tx.vout.size()-1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey) != 0 ) - return(true); - else - return(false); -} - -// Calculate seller/buyer's dest cc address from ask/bid tx funcid -bool GetAssetorigaddrs(struct CCcontract_info *cp, char *origCCaddr, char *origNormalAddr, const CTransaction& vintx) -{ - uint256 assetid, assetid2; - int64_t price,nValue=0; - int32_t n; - uint8_t vintxFuncId; - std::vector origpubkey; - CScript script; - uint8_t evalCode; - - n = vintx.vout.size(); - if( n == 0 || (vintxFuncId = DecodeAssetTokenOpRet(vintx.vout[n-1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey)) == 0 ) - return(false); - - bool bGetCCaddr = false; - struct CCcontract_info *cpTokens, tokensC; - cpTokens = CCinit(&tokensC, EVAL_TOKENS); - - if (vintxFuncId == 's' || vintxFuncId == 'S') { - // bGetCCaddr = GetCCaddress(cpTokens, origCCaddr, pubkey2pk(origpubkey)); - cpTokens->evalcodeAdd = cp->evalcodeAdd; // add non-fungible if present - bGetCCaddr = GetTokensCCaddress(cpTokens, origCCaddr, pubkey2pk(origpubkey)); // tokens to single-eval token or token+nonfungible - } - else if (vintxFuncId == 'b' || vintxFuncId == 'B') { - cpTokens->evalcodeAdd = cp->evalcodeAdd; // add non-fungible if present - bGetCCaddr = GetTokensCCaddress(cpTokens, origCCaddr, pubkey2pk(origpubkey)); // tokens to single-eval token or token+nonfungible - } - else { - std::cerr << "GetAssetorigaddrs incorrect vintx funcid=" << (char)(vintxFuncId?vintxFuncId:' ') << std::endl; - return false; - } - if( bGetCCaddr && Getscriptaddress(origNormalAddr, CScript() << origpubkey << OP_CHECKSIG)) - return(true); - else - return(false); -} - - -int64_t AssetValidateCCvin(struct CCcontract_info *cp,Eval* eval,char *origCCaddr,char *origaddr,const CTransaction &tx,int32_t vini,CTransaction &vinTx) -{ - uint256 hashBlock; - uint256 assetid, assetid2; - int64_t tmpprice; - std::vector tmporigpubkey; - uint8_t evalCode; - - char destaddr[64], unspendableAddr[64]; - - origaddr[0] = destaddr[0] = origCCaddr[0] = 0; - - uint8_t funcid = 0; - if (tx.vout.size() > 0) { - uint256 assetid, assetid2; - int64_t tmpprice; - std::vector tmporigpubkey; - uint8_t evalCode; - - funcid = DecodeAssetTokenOpRet(tx.vout[tx.vout.size() - 1].scriptPubKey, evalCode, assetid, assetid2, tmpprice, tmporigpubkey); - } - - if( tx.vin.size() < 2 ) - return eval->Invalid("not enough for CC vins"); - else if( tx.vin[vini].prevout.n != 0 ) - return eval->Invalid("vin1 needs to be buyvin.vout[0]"); - else if( eval->GetTxUnconfirmed(tx.vin[vini].prevout.hash, vinTx,hashBlock) == 0 ) - { - std::cerr << "AssetValidateCCvin() cannot load vintx for vin=" << vini << " vintx id=" << tx.vin[vini].prevout.hash.GetHex() << std::endl; - return eval->Invalid("always should find CCvin, but didnt"); - } - // check source cc unspendable cc address: - // if fillSell or cancelSell --> should spend tokens from dual-eval token-assets unspendable addr - else if( (funcid == 'S' || funcid == 'x') && - (Getscriptaddress(destaddr, vinTx.vout[tx.vin[vini].prevout.n].scriptPubKey) == 0 || - !GetTokensCCaddress(cp, unspendableAddr, GetUnspendable(cp, NULL)) || - strcmp(destaddr, unspendableAddr) != 0)) - { - fprintf(stderr,"AssetValidateCCvin() cc addr %s is not dual token-evalcode=0x%02x asset unspendable addr %s\n", destaddr, (int)cp->evalcode, unspendableAddr); - return eval->Invalid("invalid vin assets CCaddr"); - } - // if fillBuy or cancelBuy --> should spend coins from asset unspendable addr - else if ((funcid == 'B' || funcid == 'o') && - (Getscriptaddress(destaddr, vinTx.vout[tx.vin[vini].prevout.n].scriptPubKey) == 0 || - !GetCCaddress(cp, unspendableAddr, GetUnspendable(cp, NULL)) || - strcmp(destaddr, unspendableAddr) != 0)) - { - fprintf(stderr, "AssetValidateCCvin() cc addr %s is not evalcode=0x%02x asset unspendable addr %s\n", destaddr, (int)cp->evalcode, unspendableAddr); - return eval->Invalid("invalid vin assets CCaddr"); - } - // end of check source unspendable cc address - //else if ( vinTx.vout[0].nValue < 10000 ) - // return eval->Invalid("invalid dust for buyvin"); - // get user dest cc and normal addresses: - else if( GetAssetorigaddrs(cp, origCCaddr, origaddr, vinTx) == 0 ) - return eval->Invalid("couldnt get origaddr for buyvin"); - - //fprintf(stderr,"AssetValidateCCvin() got %.8f to origaddr.(%s)\n", (double)vinTx.vout[tx.vin[vini].prevout.n].nValue/COIN,origaddr); - - if ( vinTx.vout[0].nValue == 0 ) - return eval->Invalid("null value CCvin"); - - return(vinTx.vout[0].nValue); -} - -int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid) -{ - CTransaction vinTx; int64_t nValue; uint256 assetid,assetid2; uint8_t funcid, evalCode; - - CCaddr[0] = origaddr[0] = 0; - - // validate locked coins on Assets vin[1] - if ( (nValue= AssetValidateCCvin(cp, eval, CCaddr, origaddr, tx, 1, vinTx)) == 0 ) - return(0); - else if ( vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("invalid normal vout0 for buyvin"); - else if ((funcid = DecodeAssetTokenOpRet(vinTx.vout[vinTx.vout.size() - 1].scriptPubKey, evalCode, assetid, assetid2, tmpprice, tmporigpubkey)) == 'b' && - vinTx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) // marker is only in 'b'? - return eval->Invalid("invalid normal vout1 for buyvin"); - else - { - //fprintf(stderr,"have %.8f checking assetid origaddr.(%s)\n",(double)nValue/COIN,origaddr); - if ( vinTx.vout.size() > 0 && funcid != 'b' && funcid != 'B' ) - return eval->Invalid("invalid opreturn for buyvin"); - else if ( refassetid != assetid ) - return eval->Invalid("invalid assetid for buyvin"); - //int32_t i; for (i=31; i>=0; i--) - // fprintf(stderr,"%02x",((uint8_t *)&assetid)[i]); - //fprintf(stderr," AssetValidateBuyvin assetid for %s\n",origaddr); - } - return(nValue); -} - -int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid) -{ - CTransaction vinTx; int64_t nValue,assetoshis; - //fprintf(stderr,"AssetValidateSellvin()\n"); - if ( (nValue = AssetValidateCCvin(cp, eval, CCaddr, origaddr, tx, 1, vinTx)) == 0 ) - return(0); - if ( (assetoshis= IsAssetvout(cp, tmpprice, tmporigpubkey, vinTx, 0, assetid)) == 0 ) - return eval->Invalid("invalid missing CC vout0 for sellvin"); - else - return(assetoshis); -} - - -// validates opret for asset tx: -bool ValidateAssetOpret(CTransaction tx, int32_t v, uint256 assetid, int64_t &price, std::vector &origpubkey) { - - uint256 assetidOpret, assetidOpret2; - uint8_t funcid, evalCode; - - // this is just for log messages indentation fur debugging recursive calls: - int32_t n = tx.vout.size(); - - if ((funcid = DecodeAssetTokenOpRet(tx.vout[n - 1].scriptPubKey, evalCode, assetidOpret, assetidOpret2, price, origpubkey)) == 0) - { - std::cerr << "ValidateAssetOpret() DecodeAssetTokenOpRet returned funcId=0 for opret from txid=" << tx.GetHash().GetHex() << std::endl; - return(false); - } -/* it is now on token level: - else if (funcid == 'c') - { - if (assetid != zeroid && assetid == tx.GetHash() && v == 0) { - //std::cerr << "ValidateAssetOpret() this is the tokenbase 'c' tx, txid=" << tx.GetHash().GetHex() << " vout=" << v << " returning true" << std::endl; - return(true); - } - } - else if (funcid == 't') // TODO: check if this new block does not influence IsAssetVout - { - //std::cerr << "ValidateAssetOpret() assetid=" << assetid.GetHex() << " assetIdOpret=" << assetidOpret.GetHex() << " txid=" << tx.GetHash().GetHex() << std::endl; - if (assetid != zeroid && assetid == assetidOpret) { - //std::cerr << "ValidateAssetOpret() this is a transfer 't' tx, txid=" << tx.GetHash().GetHex() << " vout=" << v << " returning true" << std::endl; - return(true); - } - } */ - //else if ((funcid == 'b' || funcid == 'B') && v == 0) // critical! 'b'/'B' vout0 is NOT asset - // return(false); - else if (funcid != 'E') - { - if (assetid != zeroid && assetidOpret == assetid) - { - //std::cerr << "ValidateAssetOpret() returns true for not 'E', funcid=" << (char)funcid << std::endl; - return(true); - } - } - else if (funcid == 'E') // NOTE: not implemented yet! - { - if (v < 2 && assetid != zeroid && assetidOpret == assetid) - return(true); - else if (v == 2 && assetid != zeroid && assetidOpret2 == assetid) - return(true); - } - - //std::cerr << "ValidateAssetOpret() return false funcid=" << (char)funcid << " assetid=" << assetid.GetHex() << " assetIdOpret=" << assetidOpret.GetHex() << " txid=" << tx.GetHash().GetHex() << std::endl; - return false; -} - -// Checks if the vout is a really Asset CC vout -int64_t IsAssetvout(struct CCcontract_info *cp, int64_t &price, std::vector &origpubkey, const CTransaction& tx, int32_t v, uint256 refassetid) -{ - - //std::cerr << "IsAssetvout() entered for txid=" << tx.GetHash().GetHex() << " v=" << v << " for assetid=" << refassetid.GetHex() << std::endl; - - int32_t n = tx.vout.size(); - // just check boundaries: - if (v >= n - 1) { // just moved this up (dimxy) - std::cerr << "isAssetVout() internal err: (v >= n - 1), returning 0" << std::endl; - return(0); - } - - if (tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0) // maybe check address too? dimxy: possibly no, because there are too many cases with different addresses here - { - // moved opret checking to this new reusable func (dimxy): - const bool valOpret = ValidateAssetOpret(tx, v, refassetid, price, origpubkey); - //std::cerr << "IsAssetvout() ValidateAssetOpret returned=" << std::boolalpha << valOpret << " for txid=" << tx.GetHash().GetHex() << " for assetid=" << refassetid.GetHex() << std::endl; - if (valOpret) { - //std::cerr << "IsAssetvout() ValidateAssetOpret returned true, returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for assetid=" << refassetid.GetHex() << std::endl; - return tx.vout[v].nValue; - } - - //fprintf(stderr,"IsAssetvout() CC vout v.%d of n=%d amount=%.8f txid=%s\n",v,n,(double)0/COIN, tx.GetHash().GetHex().c_str()); - } - //fprintf(stderr,"IsAssetvout() normal output v.%d %.8f\n",v,(double)tx.vout[v].nValue/COIN); - return(0); -} - -// sets cc inputs vs cc outputs and ensures they are equal: -bool AssetCalcAmounts(struct CCcontract_info *cpAssets, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid) -{ - CTransaction vinTx; uint256 hashBlock, id, id2; int32_t flag; int64_t assetoshis; std::vector tmporigpubkey; int64_t tmpprice; - int32_t numvins = tx.vin.size(); - int32_t numvouts = tx.vout.size(); - inputs = outputs = 0; - - struct CCcontract_info *cpTokens, C; - - cpTokens = CCinit(&C, EVAL_TOKENS); - - for (int32_t i = 0; iismyvin)(tx.vin[i].scriptSig)*/ (*cpTokens->ismyvin)(tx.vin[i].scriptSig) ) // || IsVinAllowed(tx.vin[i].scriptSig) != 0) - { - //std::cerr << indentStr << "AssetExactAmounts() eval is true=" << (eval != NULL) << " ismyvin=ok for_i=" << i << std::endl; - // we are not inside the validation code -- dimxy - if ((eval && eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock) == 0) || (!eval && !myGetTransaction(tx.vin[i].prevout.hash, vinTx, hashBlock))) - { - std::cerr << "AssetCalcAmounts() cannot read vintx for i." << i << " numvins." << numvins << std::endl; - return (!eval) ? false : eval->Invalid("always should find vin tx, but didnt"); - } - else { - // validate vouts of vintx - //std::cerr << indentStr << "AssetExactAmounts() check vin i=" << i << " nValue=" << vinTx.vout[tx.vin[i].prevout.n].nValue << std::endl; - //assetoshis = IsAssetvout(cpAssets, tmpprice, tmporigpubkey, vinTx, tx.vin[i].prevout.n, assetid); - std::vector vopretExtra; - std::vector vinPubkeysEmpty; - - // TODO: maybe we do not need call to IsTokensVout here, cause we've already selected token vins - assetoshis = IsTokensvout(false, false, cpTokens, eval, vinTx, tx.vin[i].prevout.n, assetid); - if (assetoshis != 0) - { - //std::cerr << "AssetCalcAmounts() vin i=" << i << " assetoshis=" << assetoshis << std::endl; - inputs += assetoshis; - } - } - } - } - - for (int32_t i = 0; i < numvouts-1; i++) - { - assetoshis = IsAssetvout(cpAssets, tmpprice, tmporigpubkey, tx, i, assetid); - if (assetoshis != 0) - { - //std::cerr << "AssetCalcAmounts() vout i=" << i << " assetoshis=" << assetoshis << std::endl; - outputs += assetoshis; - } - } - - //std::cerr << "AssetCalcAmounts() inputs=" << inputs << " outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << std::endl; - - /* we do not verify inputs == outputs here, - it's now done in Tokens */ - return(true); -} - -}; \ No newline at end of file diff --git a/src/cc/old/CCassets_v0.h b/src/cc/old/CCassets_v0.h deleted file mode 100644 index e0163dccc37..00000000000 --- a/src/cc/old/CCassets_v0.h +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - - -/* - CCassetstx has the functions that create the EVAL_ASSETS transactions. It is expected that rpc calls would call these functions. For EVAL_ASSETS, the rpc functions are in rpcwallet.cpp - - CCassetsCore has functions that are used in two contexts, both during rpc transaction create time and also during the blockchain validation. Using the identical functions is a good way to prevent them from being mismatched. The must match or the transaction will get rejected. - */ - -#ifndef CC_ASSETS_V0_H -#define CC_ASSETS_V0_H - -#include "../CCinclude.h" - -namespace tokensv0 { - -// CCcustom -bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); - -// CCassetsCore -vscript_t EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t price, std::vector origpubkey); -uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &price, std::vector &origpubkey); -bool SetAssetOrigpubkey(std::vector &origpubkey,int64_t &price,const CTransaction &tx); -int64_t IsAssetvout(struct CCcontract_info *cp, int64_t &price, std::vector &origpubkey, const CTransaction& tx, int32_t v, uint256 refassetid); -bool ValidateBidRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice); -bool ValidateAskRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice); -bool ValidateSwapRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice); -bool SetBidFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValue,int64_t &received,int64_t totalprice); -bool SetAskFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValue,int64_t &received,int64_t totalprice); -bool SetSwapFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValue,int64_t &received,int64_t totalprice); -int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid); -int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid); -bool AssetCalcAmounts(struct CCcontract_info *cpAssets, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid); - -// CCassetstx -//int64_t GetAssetBalance(CPubKey pk,uint256 tokenid); // --> GetTokenBalance() -int64_t AddAssetInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 assetid, int64_t total, int32_t maxinputs); - -UniValue AssetOrders(uint256 tokenid, CPubKey pubkey, uint8_t additionalEvalCode); -//UniValue AssetInfo(uint256 tokenid); -//UniValue AssetList(); -//std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description); -//std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total); -//std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total,int32_t evalcode); - -std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64_t pricetotal); -std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid); -std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t fillamount); -std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t pricetotal); -std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal); -std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid); -std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 asktxid,int64_t fillamount); - -}; - -#endif diff --git a/src/cc/old/CCassetstx_v0.cpp b/src/cc/old/CCassetstx_v0.cpp deleted file mode 100644 index 588e29bb3e1..00000000000 --- a/src/cc/old/CCassetstx_v0.cpp +++ /dev/null @@ -1,802 +0,0 @@ -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - -#include "CCassets_v0.h" -#include "CCtokens_v0.h" - -namespace tokensv0 { - - -UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t additionalEvalCode) -{ - UniValue result(UniValue::VARR); - - struct CCcontract_info *cpAssets, assetsC; - struct CCcontract_info *cpTokens, tokensC; - - cpAssets = CCinit(&assetsC, EVAL_ASSETS); - cpTokens = CCinit(&tokensC, EVAL_TOKENS); - - auto addOrders = [&](struct CCcontract_info *cp, std::vector >::const_iterator it) - { - uint256 txid, hashBlock, assetid, assetid2; - int64_t price; - std::vector origpubkey; - CTransaction ordertx; - uint8_t funcid, evalCode; - char numstr[32], funcidstr[16], origaddr[64], origtokenaddr[64]; - - txid = it->first.txhash; - LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() checking txid=" << txid.GetHex() << std::endl); - if ( myGetTransaction(txid, ordertx, hashBlock) != 0 ) - { - // for logging: funcid = DecodeAssetOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey); - if (ordertx.vout.size() > 0 && (funcid = DecodeAssetTokenOpRet(ordertx.vout[ordertx.vout.size()-1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey)) != 0) - { - LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() checking ordertx.vout.size()=" << ordertx.vout.size() << " funcid=" << (char)(funcid ? funcid : ' ') << " assetid=" << assetid.GetHex() << std::endl); - - if (pk == CPubKey() && (refassetid == zeroid || assetid == refassetid) // tokenorders - || pk != CPubKey() && pk == pubkey2pk(origpubkey) && (funcid == 'S' || funcid == 's')) // mytokenorders, returns only asks (is this correct?) - { - - LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() it->first.index=" << it->first.index << " ordertx.vout[it->first.index].nValue=" << ordertx.vout[it->first.index].nValue << std::endl); - if (ordertx.vout[it->first.index].nValue == 0) { - LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() order with value=0 skipped" << std::endl); - return; - } - - UniValue item(UniValue::VOBJ); - - funcidstr[0] = funcid; - funcidstr[1] = 0; - item.push_back(Pair("funcid", funcidstr)); - item.push_back(Pair("txid", txid.GetHex())); - item.push_back(Pair("vout", (int64_t)it->first.index)); - if (funcid == 'b' || funcid == 'B') - { - sprintf(numstr, "%.8f", (double)ordertx.vout[it->first.index].nValue / COIN); - item.push_back(Pair("amount", numstr)); - sprintf(numstr, "%.8f", (double)ordertx.vout[0].nValue / COIN); - item.push_back(Pair("bidamount", numstr)); - } - else - { - sprintf(numstr, "%llu", (long long)ordertx.vout[it->first.index].nValue); - item.push_back(Pair("amount", numstr)); - sprintf(numstr, "%llu", (long long)ordertx.vout[0].nValue); - item.push_back(Pair("askamount", numstr)); - } - if (origpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) - { - GetCCaddress(cp, origaddr, pubkey2pk(origpubkey)); - item.push_back(Pair("origaddress", origaddr)); - GetTokensCCaddress(cpTokens, origtokenaddr, pubkey2pk(origpubkey)); - item.push_back(Pair("origtokenaddress", origtokenaddr)); - } - if (assetid != zeroid) - item.push_back(Pair("tokenid", assetid.GetHex())); - if (assetid2 != zeroid) - item.push_back(Pair("otherid", assetid2.GetHex())); - if (price > 0) - { - if (funcid == 's' || funcid == 'S' || funcid == 'e' || funcid == 'e') - { - sprintf(numstr, "%.8f", (double)price / COIN); - item.push_back(Pair("totalrequired", numstr)); - sprintf(numstr, "%.8f", (double)price / (COIN * ordertx.vout[0].nValue)); - item.push_back(Pair("price", numstr)); - } - else - { - item.push_back(Pair("totalrequired", (int64_t)price)); - sprintf(numstr, "%.8f", (double)ordertx.vout[0].nValue / (price * COIN)); - item.push_back(Pair("price", numstr)); - } - } - result.push_back(item); - LOGSTREAM("ccassets", CCLOG_DEBUG1, stream << "addOrders() added order funcId=" << (char)(funcid ? funcid : ' ') << " it->first.index=" << it->first.index << " ordertx.vout[it->first.index].nValue=" << ordertx.vout[it->first.index].nValue << " tokenid=" << assetid.GetHex() << std::endl); - } - } - } - }; - - std::vector > unspentOutputsTokens, unspentOutputsDualEvalTokens, unspentOutputsCoins; - - char assetsUnspendableAddr[64]; - GetCCaddress(cpAssets, assetsUnspendableAddr, GetUnspendable(cpAssets, NULL)); - SetCCunspents(unspentOutputsCoins, assetsUnspendableAddr,true); - - char assetsTokensUnspendableAddr[64]; - std::vector vopretNonfungible; - if (refassetid != zeroid) { - GetNonfungibleData(refassetid, vopretNonfungible); - if (vopretNonfungible.size() > 0) - cpAssets->evalcodeAdd = vopretNonfungible.begin()[0]; - } - GetTokensCCaddress(cpAssets, assetsTokensUnspendableAddr, GetUnspendable(cpAssets, NULL)); - SetCCunspents(unspentOutputsTokens, assetsTokensUnspendableAddr,true); - - // tokenbids: - for (std::vector >::const_iterator itCoins = unspentOutputsCoins.begin(); - itCoins != unspentOutputsCoins.end(); - itCoins++) - addOrders(cpAssets, itCoins); - - // tokenasks: - for (std::vector >::const_iterator itTokens = unspentOutputsTokens.begin(); - itTokens != unspentOutputsTokens.end(); - itTokens++) - addOrders(cpAssets, itTokens); - - if (additionalEvalCode != 0) { //this would be mytokenorders - char assetsDualEvalTokensUnspendableAddr[64]; - - // try also dual eval tokenasks (and we do not need bids): - cpAssets->evalcodeAdd = additionalEvalCode; - GetTokensCCaddress(cpAssets, assetsDualEvalTokensUnspendableAddr, GetUnspendable(cpAssets, NULL)); - SetCCunspents(unspentOutputsDualEvalTokens, assetsDualEvalTokensUnspendableAddr,true); - - for (std::vector >::const_iterator itDualEvalTokens = unspentOutputsDualEvalTokens.begin(); - itDualEvalTokens != unspentOutputsDualEvalTokens.end(); - itDualEvalTokens++) - addOrders(cpAssets, itDualEvalTokens); - } - return(result); -} - -// not used (use TokenCreate instead) -/* std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; struct CCcontract_info *cp,C; - if ( assetsupply < 0 ) - { - fprintf(stderr,"negative assetsupply %lld\n",(long long)assetsupply); - return(""); - } - cp = CCinit(&C,EVAL_ASSETS); - if ( name.size() > 32 || description.size() > 4096 ) - { - fprintf(stderr,"name.%d or description.%d is too big\n",(int32_t)name.size(),(int32_t)description.size()); - return(""); - } - if ( txfee == 0 ) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,assetsupply+2*txfee,64) > 0 ) - { - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,assetsupply,mypk)); - mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(cp->CChexstr) << OP_CHECKSIG)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetCreateOpRet('c',Mypubkey(),name,description))); - } - return(""); -} */ - -// not used (use TokenTransfer instead) -/* std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; uint64_t mask; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C; - if ( total < 0 ) - { - fprintf(stderr,"negative total %lld\n",(long long)total); - return(""); - } - cp = CCinit(&C,EVAL_ASSETS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) - { - //n = outputs.size(); - //if ( n == amounts.size() ) - //{ - // for (i=0; i 0 ) - { - - if (inputs < total) { //added dimxy - std::cerr << "AssetTransfer(): insufficient funds" << std::endl; - return (""); - } - if ( inputs > total ) - CCchange = (inputs - total); - //for (i=0; i destpubkey,int64_t total,int32_t evalcode) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C; - if ( total < 0 ) - { - fprintf(stderr,"negative total %lld\n",(long long)total); - return(""); - } - cp = CCinit(&C,EVAL_ASSETS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) - { - if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 ) - { - if ( inputs > total ) - CCchange = (inputs - total); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); - mtx.vout.push_back(MakeCC1vout(evalcode,total,pubkey2pk(destpubkey))); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey()))); - } else fprintf(stderr,"not enough CC asset inputs for %.8f\n",(double)total/COIN); - } - return(""); -} */ - -// rpc tokenbid implementation, locks 'bidamount' coins for the 'pricetotal' of tokens -std::string CreateBuyOffer(int64_t txfee, int64_t bidamount, uint256 assetid, int64_t pricetotal) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; - struct CCcontract_info *cpAssets, C; - uint256 hashBlock; - CTransaction vintx; - std::vector origpubkey; - std::string name,description; - int64_t inputs; - - std::cerr << "CreateBuyOffer() bidamount=" << bidamount << " numtokens(pricetotal)=" << pricetotal << std::endl; - - if (bidamount < 0 || pricetotal < 0) - { - fprintf(stderr,"negative bidamount %lld, pricetotal %lld\n", (long long)bidamount, (long long)pricetotal); - return(""); - } - if (myGetTransaction(assetid, vintx, hashBlock) == 0) - { - fprintf(stderr,"cant find assetid\n"); - return(""); - } - if (vintx.vout.size() > 0 && DecodeTokenCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey, origpubkey, name, description) == 0) - { - fprintf(stderr,"assetid isnt assetcreation txid\n"); - return(""); - } - - cpAssets = CCinit(&C,EVAL_ASSETS); // NOTE: assets here! - if (txfee == 0) - txfee = 10000; - - mypk = pubkey2pk(Mypubkey()); - - if ((inputs = AddNormalinputs(mtx, mypk, bidamount+(2*txfee), 64)) > 0) - { - std::cerr << "CreateBuyOffer() inputs=" << inputs << std::endl; - if (inputs < bidamount+txfee) { - std::cerr << "CreateBuyOffer(): insufficient coins to make buy offer" << std::endl; - CCerror = strprintf("insufficient coins to make buy offer"); - return (""); - } - - CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount, unspendableAssetsPubkey)); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk)); - std::vector voutTokenPubkeys; // should be empty - no token vouts - - return FinalizeCCTx(0, cpAssets, mtx, mypk, txfee, - EncodeTokenOpRet(assetid, voutTokenPubkeys, // TODO: actually this tx is not 'tokens', maybe it is better not to have token opret here but only asset opret. - std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('b', zeroid, pricetotal, Mypubkey())))); // But still such token opret should not make problems because no token eval in these vouts - } - CCerror = strprintf("no coins found to make buy offer"); - return(""); -} - -// rpc tokenask implementation, locks 'askamount' tokens for the 'pricetotal' -std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t pricetotal) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; - uint64_t mask; - int64_t inputs, CCchange; - struct CCcontract_info *cpAssets, assetsC; - struct CCcontract_info *cpTokens, tokensC; - - //std::cerr << "CreateSell() askamount=" << askamount << " pricetotal=" << pricetotal << std::endl; - - if (askamount < 0 || pricetotal < 0) { - fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount); - return(""); - } - - cpAssets = CCinit(&assetsC, EVAL_ASSETS); // NOTE: for signing - - - if (txfee == 0) - txfee = 10000; - - mypk = pubkey2pk(Mypubkey()); - if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0) - { - std::vector vopretNonfungible; - mask = ~((1LL << mtx.vin.size()) - 1); - // add single-eval tokens (or non-fungible tokens): - cpTokens = CCinit(&tokensC, EVAL_TOKENS); // NOTE: adding inputs only from EVAL_TOKENS cc - if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, askamount, 60, vopretNonfungible)) > 0) - { - if (inputs < askamount) { - //was: askamount = inputs; - std::cerr << "CreateSell(): insufficient tokens for ask" << std::endl; - CCerror = strprintf("insufficient tokens for ask"); - return (""); - } - - // if this is non-fungible tokens: - if( !vopretNonfungible.empty() ) - // set its evalcode - cpAssets->evalcodeAdd = vopretNonfungible.begin()[0]; - - CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); - mtx.vout.push_back(MakeTokensCC1vout(EVAL_ASSETS, cpAssets->evalcodeAdd, askamount, unspendableAssetsPubkey)); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk)); //marker (seems, it is not for tokenorders) - if (inputs > askamount) - CCchange = (inputs - askamount); - if (CCchange != 0) - // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) - mtx.vout.push_back(MakeTokensCC1vout((cpAssets->evalcodeAdd) ? cpAssets->evalcodeAdd : EVAL_TOKENS, CCchange, mypk)); - - std::vector voutTokenPubkeys; - voutTokenPubkeys.push_back(unspendableAssetsPubkey); - - return FinalizeCCTx(0, cpTokens, mtx, mypk, txfee, - EncodeTokenOpRet(assetid, voutTokenPubkeys, - std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('s', zeroid, pricetotal, Mypubkey())))); - } - else { - fprintf(stderr, "need some tokens to place ask\n"); - } - } - else { // dimxy added 'else', because it was misleading message before - fprintf(stderr, "need some native coins to place ask\n"); - } - return(""); -} - -////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// -std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C; - - ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// - fprintf(stderr,"asset swaps disabled\n"); - return(""); - ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// - - if ( askamount < 0 || pricetotal < 0 ) - { - fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount); - return(""); - } - cp = CCinit(&C, EVAL_ASSETS); - - if ( txfee == 0 ) - txfee = 10000; - ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// - mypk = pubkey2pk(Mypubkey()); - - if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) - { - mask = ~((1LL << mtx.vin.size()) - 1); - /*if ((inputs = AddAssetInputs(cp, mtx, mypk, assetid, askamount, 60)) > 0) - { - ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// - if (inputs < askamount) { - //was: askamount = inputs; - std::cerr << "CreateSwap(): insufficient tokens for ask" << std::endl; - CCerror = strprintf("insufficient tokens for ask"); - return (""); - } - ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// - CPubKey unspendablePubkey = GetUnspendable(cp, 0); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, askamount, unspendablePubkey)); - - if (inputs > askamount) - CCchange = (inputs - askamount); - if (CCchange != 0) - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk)); - - ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// - std::vector voutTokenPubkeys; // should be empty - no token vouts - - if (assetid2 == zeroid) { - opret = EncodeTokenOpRet(assetid, voutTokenPubkeys, - EncodeAssetOpRet('s', zeroid, pricetotal, Mypubkey())); - } - else { - opret = EncodeTokenOpRet(assetid, voutTokenPubkeys, - EncodeAssetOpRet('e', assetid2, pricetotal, Mypubkey())); - } - ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// - return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret)); - } - else { - fprintf(stderr, "need some assets to place ask\n"); - } */ - } - else { // dimxy added 'else', because it was misleading message before - fprintf(stderr,"need some native coins to place ask\n"); - } - - return(""); -} ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// - -// unlocks coins -std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx; uint64_t mask; - uint256 hashBlock; int64_t bidamount; - CPubKey mypk; struct CCcontract_info *cpAssets, C; - uint8_t funcid,dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector dummyOrigpubkey; - - cpAssets = CCinit(&C, EVAL_ASSETS); - - if (txfee == 0) - txfee = 10000; - - mypk = pubkey2pk(Mypubkey()); - - if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) - { - mask = ~((1LL << mtx.vin.size()) - 1); - if (myGetTransaction(bidtxid, vintx, hashBlock) != 0) - { - std::vector vopretNonfungible; - GetNonfungibleData(assetid, vopretNonfungible); - - bidamount = vintx.vout[0].nValue; - if (bidamount == 0) { - CCerror = "bid is empty"; - return ""; - } - mtx.vin.push_back(CTxIn(bidtxid, 0, CScript())); // coins in Assets - - if((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0) - { - if (funcid == 's') mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' - else if (funcid=='S') mtx.vin.push_back(CTxIn(bidtxid, 3, CScript())); // spend marker if funcid='B' - } - - mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - - std::vector voutTokenPubkeys; // should be empty, no token vouts - - return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee, - EncodeTokenOpRet(assetid, voutTokenPubkeys, - std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('o', zeroid, 0, Mypubkey()))))); - } - } - return(""); -} - -//unlocks tokens -std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx; uint64_t mask; - uint256 hashBlock; int64_t askamount; - CPubKey mypk; - struct CCcontract_info *cpTokens, *cpAssets, tokensC, assetsC; - uint8_t funcid, dummyEvalCode; - uint256 dummyAssetid, dummyAssetid2; - int64_t dummyPrice; - std::vector dummyOrigpubkey; - - cpAssets = CCinit(&assetsC, EVAL_ASSETS); - - if (txfee == 0) - txfee = 10000; - - mypk = pubkey2pk(Mypubkey()); - - if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) - { - mask = ~((1LL << mtx.vin.size()) - 1); - if (myGetTransaction(asktxid, vintx, hashBlock) != 0) - { - std::vector vopretNonfungible; - GetNonfungibleData(assetid, vopretNonfungible); - - askamount = vintx.vout[0].nValue; - if (askamount == 0) { - CCerror = "ask is empty"; - return ""; - } - mtx.vin.push_back(CTxIn(asktxid, 0, CScript())); - - if ((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0) - { - if (funcid == 's') - mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // marker if funcid='s' - else if (funcid=='S') - mtx.vin.push_back(CTxIn(asktxid, 3, CScript())); // marker if funcid='S' - } - - if (vopretNonfungible.size() > 0) - cpAssets->evalcodeAdd = vopretNonfungible.begin()[0]; - - mtx.vout.push_back(MakeTokensCC1vout(cpAssets->evalcodeAdd == 0 ? EVAL_TOKENS : cpAssets->evalcodeAdd, askamount, mypk)); // one-eval token vout - mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - - std::vector voutTokenPubkeys; - voutTokenPubkeys.push_back(mypk); - - // this is only for unspendable addresses: - //CCaddr2set(cpTokens, EVAL_ASSETS, mypk, myPrivkey, myCCaddr); //do we need this? Seems FinalizeCCTx can attach to any evalcode cc addr by calling Getscriptaddress - - uint8_t unspendableAssetsPrivkey[32]; - char unspendableAssetsAddr[64]; - // init assets 'unspendable' privkey and pubkey - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk); - - // add additional eval-tokens unspendable assets privkey: - CCaddr2set(cpAssets, EVAL_TOKENS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); - - return(FinalizeCCTx(0, cpAssets, mtx, mypk, txfee, - EncodeTokenOpRet(assetid, voutTokenPubkeys, - std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('x', zeroid, 0, Mypubkey()))))); - } - } - return(""); -} - -//send tokens, receive coins: -std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t fillamount) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx; - uint256 hashBlock; - CPubKey mypk; - std::vector origpubkey; - int32_t bidvout=0; - uint64_t mask; - int64_t origprice, bidamount, paid_amount, remaining_required, inputs, CCchange=0; - struct CCcontract_info *cpTokens, tokensC; - struct CCcontract_info *cpAssets, assetsC; - - if (fillamount < 0) - { - fprintf(stderr,"negative fillamount %lld\n", (long long)fillamount); - return(""); - } - cpTokens = CCinit(&tokensC, EVAL_TOKENS); - - if (txfee == 0) - txfee = 10000; - - mypk = pubkey2pk(Mypubkey()); - - if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0) - { - mask = ~((1LL << mtx.vin.size()) - 1); - if (myGetTransaction(bidtxid, vintx, hashBlock) != 0) - { - bidamount = vintx.vout[bidvout].nValue; - SetAssetOrigpubkey(origpubkey, origprice, vintx); - - mtx.vin.push_back(CTxIn(bidtxid, bidvout, CScript())); // Coins on Assets unspendable - - std::vector vopretNonfungible; - if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, fillamount, 60, vopretNonfungible)) > 0) - { - if (inputs < fillamount) { - std::cerr << "FillBuyOffer(): insufficient tokens to fill buy offer" << std::endl; - CCerror = strprintf("insufficient tokens to fill buy offer"); - return (""); - } - - SetBidFillamounts(paid_amount, remaining_required, bidamount, fillamount, origprice); - - uint8_t additionalTokensEvalcode2 = 0; - if (vopretNonfungible.size() > 0) - additionalTokensEvalcode2 = vopretNonfungible.begin()[0]; - - if (inputs > fillamount) - CCchange = (inputs - fillamount); - - uint8_t unspendableAssetsPrivkey[32]; - cpAssets = CCinit(&assetsC, EVAL_ASSETS); - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder - mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to normal - mtx.vout.push_back(MakeTokensCC1vout(additionalTokensEvalcode2 == 0 ? EVAL_TOKENS : additionalTokensEvalcode2, fillamount, pubkey2pk(origpubkey))); // vout2 single-eval tokens sent to the originator - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, origpubkey)); // vout3 marker to origpubkey - - if (CCchange != 0) - mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); // vout4 change in single-eval tokens - - fprintf(stderr,"FillBuyOffer() remaining %llu -> origpubkey\n", (long long)remaining_required); - - char unspendableAssetsAddr[64]; - cpAssets = CCinit(&assetsC, EVAL_ASSETS); - GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk); - - // add additional unspendable addr from Assets: - CCaddr2set(cpTokens, EVAL_ASSETS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); - - // token vout verification pubkeys: - std::vector voutTokenPubkeys; - voutTokenPubkeys.push_back(pubkey2pk(origpubkey)); - - return(FinalizeCCTx(0, cpTokens, mtx, mypk, txfee, - EncodeTokenOpRet(assetid, voutTokenPubkeys, - std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('B', zeroid, remaining_required, origpubkey))))); - } - else { - CCerror = "dont have any assets to fill bid"; - return ""; - } - } - else - CCerror = "bid txid not found"; - } - else - CCerror = "no normal coins left"; - return ""; -} - - -// send coins, receive tokens -std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 asktxid, int64_t fillunits) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx,filltx; - uint256 hashBlock; - CPubKey mypk; - std::vector origpubkey; - double dprice; - uint64_t mask = 0; - int32_t askvout = 0; - int64_t received_assetoshis, total_nValue, orig_assetoshis, paid_nValue, remaining_nValue, inputs, CCchange=0; - //struct CCcontract_info *cpTokens, tokensC; - struct CCcontract_info *cpAssets, assetsC; - - if (fillunits < 0) - { - CCerror = strprintf("negative fillunits %lld\n",(long long)fillunits); - fprintf(stderr,"%s\n",CCerror.get_msg()); - return(""); - } - if (assetid2 != zeroid) - { - CCerror = "asset swaps disabled"; - fprintf(stderr,"%s\n",CCerror.get_msg()); - return(""); - } - - std::vector vopretNonfungible; - uint8_t additionalTokensEvalcode2 = 0; - GetNonfungibleData(assetid, vopretNonfungible); - if (vopretNonfungible.size() > 0) - additionalTokensEvalcode2 = vopretNonfungible.begin()[0]; - - cpAssets = CCinit(&assetsC, EVAL_ASSETS); - - if (txfee == 0) - txfee = 10000; - - mypk = pubkey2pk(Mypubkey()); - //if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0) - //{ - //mask = ~((1LL << mtx.vin.size()) - 1); - if (myGetTransaction(asktxid, vintx, hashBlock) != 0) - { - orig_assetoshis = vintx.vout[askvout].nValue; - SetAssetOrigpubkey(origpubkey, total_nValue, vintx); - dprice = (double)total_nValue / orig_assetoshis; - paid_nValue = dprice * fillunits; - - if (assetid2 != zeroid) { - inputs = 0; // = AddAssetInputs(cpAssets, mtx, mypk, assetid2, paid_nValue, 60); // not implemented yet - } - else - { - inputs = AddNormalinputs(mtx, mypk, 2 * txfee + paid_nValue, 60); // Better to use single AddNormalinputs() to allow payment if user has only single utxo with normal funds - mask = ~((1LL << mtx.vin.size()) - 1); - } - if (inputs > 0) - { - if (inputs < paid_nValue) { - std::cerr << "FillSell(): insufficient coins to fill sell" << std::endl; - CCerror = strprintf("insufficient coins to fill sell"); - return (""); - } - - // cc vin should be after normal vin - mtx.vin.push_back(CTxIn(asktxid, askvout, CScript())); - - if (assetid2 != zeroid) - SetSwapFillamounts(received_assetoshis, remaining_nValue, orig_assetoshis, paid_nValue, total_nValue); //not implemented correctly yet - else - SetAskFillamounts(received_assetoshis, remaining_nValue, orig_assetoshis, paid_nValue, total_nValue); - - if (assetid2 != zeroid && inputs > paid_nValue) - CCchange = (inputs - paid_nValue); - - // vout.0 tokens remainder to unspendable cc addr: - mtx.vout.push_back(MakeTokensCC1vout(EVAL_ASSETS, additionalTokensEvalcode2, orig_assetoshis - received_assetoshis, GetUnspendable(cpAssets, NULL))); - //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: - mtx.vout.push_back(MakeTokensCC1vout(additionalTokensEvalcode2 == 0 ? EVAL_TOKENS : additionalTokensEvalcode2, received_assetoshis, mypk)); - - if (assetid2 != zeroid) { - std::cerr << "FillSell() WARNING: asset swap not implemented yet! (paid_nValue)" << std::endl; - // TODO: change MakeCC1vout appropriately when implementing: - //mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, paid_nValue, origpubkey)); //vout.2 tokens... (swap is not implemented yet) - } - else { - //std::cerr << "FillSell() paid_value=" << paid_nValue << " origpubkey=" << HexStr(pubkey2pk(origpubkey)) << std::endl; - mtx.vout.push_back(CTxOut(paid_nValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to tokens seller's normal addr - } - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,txfee,origpubkey)); //vout.3 marker to origpubkey - - // not implemented - if (CCchange != 0) { - std::cerr << "FillSell() WARNING: asset swap not implemented yet! (CCchange)" << std::endl; - // TODO: change MakeCC1vout appropriately when implementing: - //mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk)); //vout.3 coins in Assets cc addr (swap not implemented) - } - - uint8_t unspendableAssetsPrivkey[32]; - char unspendableAssetsAddr[64]; - // init assets 'unspendable' privkey and pubkey - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk); - - // add additional eval-tokens unspendable assets privkey: - CCaddr2set(cpAssets, EVAL_TOKENS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); - - // vout verification pubkeys: - std::vector voutTokenPubkeys; - voutTokenPubkeys.push_back(mypk); - - cpAssets->evalcodeAdd = additionalTokensEvalcode2; - - return(FinalizeCCTx(0, cpAssets, mtx, mypk, txfee, - EncodeTokenOpRet(assetid, voutTokenPubkeys, - std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet(assetid2 != zeroid ? 'E' : 'S', assetid2, remaining_nValue, origpubkey))))); - } else { - CCerror = strprintf("filltx not enough utxos"); - fprintf(stderr,"%s\n", CCerror.get_msg()); - } - } - else - CCerror = "ask txid not found"; - //} - return(""); -} - -}; \ No newline at end of file diff --git a/src/cc/old/CCtokens_v0.cpp b/src/cc/old/CCtokens_v0.cpp deleted file mode 100644 index 964691cfe92..00000000000 --- a/src/cc/old/CCtokens_v0.cpp +++ /dev/null @@ -1,1059 +0,0 @@ -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - -#include "CCtokens_v0.h" -#include "importcoin.h" - -namespace tokensv0 { - -/* TODO: correct this: ------------------------------ - The SetTokenFillamounts() and ValidateTokenRemainder() work in tandem to calculate the vouts for a fill and to validate the vouts, respectively. - - This pair of functions are critical to make sure the trading is correct and is the trickiest part of the tokens contract. - - //vin.0: normal input - //vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] - //vin.2+: valid CC output satisfies buyoffer (*tx.vin[2])->nValue - //vout.0: remaining amount of bid to unspendable - //vout.1: vin.1 value to signer of vin.2 - //vout.2: vin.2 tokenoshis to original pubkey - //vout.3: CC output for tokenoshis change (if any) - //vout.4: normal output for change (if any) - //vout.n-1: opreturn [EVAL_ASSETS] ['B'] [tokenid] [remaining token required] [origpubkey] - ValidateTokenRemainder(remaining_price,tx.vout[0].nValue,nValue,tx.vout[1].nValue,tx.vout[2].nValue,totalunits); - - Yes, this is quite confusing... - - In ValidateTokenRemainder the naming convention is nValue is the coin/token with the offer on the books and "units" is what it is being paid in. The high level check is to make sure we didnt lose any coins or tokens, the harder to validate is the actual price paid as the "orderbook" is in terms of the combined nValue for the combined totalunits. - - We assume that the effective unit cost in the orderbook is valid and that that amount was paid and also that any remainder will be close enough in effective unit cost to not matter. At the edge cases, this will probably be not true and maybe some orders wont be practically fillable when reduced to fractional state. However, the original pubkey that created the offer can always reclaim it. - ------------------------------ -*/ - -// extract cc token vins' pubkeys: -static bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector &vinPubkeys) { - - bool found = false; - CPubKey pubkey; - struct CCcontract_info *cpTokens, tokensC; - - cpTokens = CCinit(&tokensC, EVAL_TOKENS); - vinPubkeys.clear(); - - for (int32_t i = 0; i < tx.vin.size(); i++) - { - // check for cc token vins: - if( (*cpTokens->ismyvin)(tx.vin[i].scriptSig) ) - { - - auto findEval = [](CC *cond, struct CCVisitor _) { - bool r = false; - - if (cc_typeId(cond) == CC_Secp256k1) { - *(CPubKey*)_.context = buf2pk(cond->publicKey); - //std::cerr << "findEval found pubkey=" << HexStr(*(CPubKey*)_.context) << std::endl; - r = true; - } - // false for a match, true for continue - return r ? 0 : 1; - }; - - CC *cond = GetCryptoCondition(tx.vin[i].scriptSig); - - if (cond) { - CCVisitor visitor = { findEval, (uint8_t*)"", 0, &pubkey }; - bool out = !cc_visit(cond, visitor); - cc_free(cond); - - if (pubkey.IsValid()) { - vinPubkeys.push_back(pubkey); - found = true; - } - } - } - } - return found; -} - -// tx validation -bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) -{ - static uint256 zero; - CTxDestination address; CTransaction vinTx, createTx; uint256 hashBlock, tokenid, tokenid2; - int32_t i, starti, numvins, numvouts, preventCCvins, preventCCvouts; - int64_t remaining_price, nValue, tokenoshis, outputs, inputs, tmpprice, totalunits, ignore; - std::vector> oprets; - vscript_t /*vopretExtra,*/ tmporigpubkey, ignorepubkey; - uint8_t funcid, evalCodeInOpret; - char destaddr[64], origaddr[64], CCaddr[64]; - std::vector voutTokenPubkeys, vinTokenPubkeys; - - if (strcmp(ASSETCHAINS_SYMBOL, "ROGUE") == 0 && chainActive.Height() <= 12500) - return true; - - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - outputs = inputs = 0; - preventCCvins = preventCCvouts = -1; - - // check boundaries: - if (numvouts < 1) - return eval->Invalid("no vouts"); - - if ((funcid = DecodeTokenOpRet(tx.vout[numvouts - 1].scriptPubKey, evalCodeInOpret, tokenid, voutTokenPubkeys, oprets)) == 0) - return eval->Invalid("TokenValidate: invalid opreturn payload"); - - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokensValidate funcId=" << (char)(funcid?funcid:' ') << " evalcode=" << std::hex << (int)cp->evalcode << std::endl); - - if (eval->GetTxUnconfirmed(tokenid, createTx, hashBlock) == 0) - return eval->Invalid("cant find token create txid"); - //else if (IsCCInput(tx.vin[0].scriptSig) != 0) - // return eval->Invalid("illegal token vin0"); // <-- this validation was removed because some token tx might not have normal vins - else if (funcid != 'c') - { - if (tokenid == zeroid) - return eval->Invalid("illegal tokenid"); - else if (!TokensExactAmounts(true, cp, inputs, outputs, eval, tx, tokenid)) { - if (!eval->Valid()) - return false; //TokenExactAmounts must call eval->Invalid()! - else - return eval->Invalid("tokens cc inputs != cc outputs"); - } - } - - // validate spending from token cc addr: allowed only for burned non-fungible tokens: - if (ExtractTokensCCVinPubkeys(tx, vinTokenPubkeys) && std::find(vinTokenPubkeys.begin(), vinTokenPubkeys.end(), GetUnspendable(cp, NULL)) != vinTokenPubkeys.end()) { - // validate spending from token unspendable cc addr: - int64_t burnedAmount = HasBurnedTokensvouts(cp, eval, tx, tokenid); - if (burnedAmount > 0) { - vscript_t vopretNonfungible; - GetNonfungibleData(tokenid, vopretNonfungible); - if( vopretNonfungible.empty() ) - return eval->Invalid("spending cc marker not supported for fungible tokens"); - } - } - - switch (funcid) - { - case 'c': // token create should not be validated as it has no CC inputs, so return 'invalid' - // token tx structure for 'c': - //vin.0: normal input - //vout.0: issuance tokenoshis to CC - //vout.1: normal output for change (if any) - //vout.n-1: opreturn EVAL_TOKENS 'c' - return eval->Invalid("incorrect token funcid"); - - case 't': // transfer - // token tx structure for 't' - //vin.0: normal input - //vin.1 .. vin.n-1: valid CC outputs - //vout.0 to n-2: tokenoshis output to CC - //vout.n-2: normal output for change (if any) - //vout.n-1: opreturn EVAL_TOKENS 't' tokenid - if (inputs == 0) - return eval->Invalid("no token inputs for transfer"); - - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "token transfer preliminarily validated inputs=" << inputs << "->outputs=" << outputs << " preventCCvins=" << preventCCvins<< " preventCCvouts=" << preventCCvouts << std::endl); - break; // breaking to other contract validation... - - default: - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "illegal tokens funcid=" << (char)(funcid?funcid:' ') << std::endl); - return eval->Invalid("unexpected token funcid"); - } - - return true; -} - -// helper funcs: - - -// this is just for log messages indentation fur debugging recursive calls: -thread_local uint32_t tokenValIndentSize = 0; - -// validates opret for token tx: -uint8_t ValidateTokenOpret(CTransaction tx, uint256 tokenid) { - - uint256 tokenidOpret = zeroid; - uint8_t funcid; - uint8_t dummyEvalCode; - std::vector voutPubkeysDummy; - std::vector> opretsDummy; - - // this is just for log messages indentation fur debugging recursive calls: - std::string indentStr = std::string().append(tokenValIndentSize, '.'); - - if (tx.vout.size() == 0) - return (uint8_t)0; - - if ((funcid = DecodeTokenOpRet(tx.vout.back().scriptPubKey, dummyEvalCode, tokenidOpret, voutPubkeysDummy, opretsDummy)) == 0) - { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << indentStr << "ValidateTokenOpret() DecodeTokenOpret could not parse opret for txid=" << tx.GetHash().GetHex() << std::endl); - return (uint8_t)0; - } - else if (funcid == 'c') - { - if (tokenid != zeroid && tokenid == tx.GetHash()) { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() this is tokenbase 'c' tx, txid=" << tx.GetHash().GetHex() << " returning true" << std::endl); - return funcid; - } - else { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() not my tokenbase txid=" << tx.GetHash().GetHex() << std::endl); - } - } - else if (funcid == 'i') - { - if (tokenid != zeroid && tokenid == tx.GetHash()) { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() this is import 'i' tx, txid=" << tx.GetHash().GetHex() << " returning true" << std::endl); - return funcid; - } - else { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() not my import txid=" << tx.GetHash().GetHex() << std::endl); - } - } - else if (funcid == 't') - { - //std::cerr << indentStr << "ValidateTokenOpret() tokenid=" << tokenid.GetHex() << " tokenIdOpret=" << tokenidOpret.GetHex() << " txid=" << tx.GetHash().GetHex() << std::endl; - if (tokenid != zeroid && tokenid == tokenidOpret) { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() this is a transfer 't' tx, txid=" << tx.GetHash().GetHex() << " returning true" << std::endl); - return funcid; - } - else { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() not my tokenid=" << tokenidOpret.GetHex() << std::endl); - } - } - else { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() not supported funcid=" << (char)funcid << " tokenIdOpret=" << tokenidOpret.GetHex() << " txid=" << tx.GetHash().GetHex() << std::endl); - } - return (uint8_t)0; -} - -// remove token->unspendablePk (it is only for marker usage) -void FilterOutTokensUnspendablePk(const std::vector &sourcePubkeys, std::vector &destPubkeys) { - struct CCcontract_info *cpTokens, tokensC; - cpTokens = CCinit(&tokensC, EVAL_TOKENS); - CPubKey tokensUnspendablePk = GetUnspendable(cpTokens, NULL); - destPubkeys.clear(); - - for (auto pk : sourcePubkeys) - if (pk != tokensUnspendablePk) - destPubkeys.push_back(pk); - -} - -void FilterOutNonCCOprets(const std::vector> &oprets, vscript_t &vopret) { - - vopret.clear(); - - if (oprets.size() > 2) - LOGSTREAM("cctokens", CCLOG_INFO, stream << "FilterOutNonCCOprets() warning!! oprets.size > 2 currently not supported" << oprets.size() << std::endl); - - for (auto o : oprets) { - if (o.first < OPRETID_FIRSTNONCCDATA) { // skip burn, import, etc opret data - vopret = o.second; // return first contract opret (more than 1 is not supported yet) - break; - } - } -} - -// Checks if the vout is a really Tokens CC vout -// also checks tokenid in opret or txid if this is 'c' tx -// goDeeper is true: the func also validates amounts of the passed transaction: -// it should be either sum(cc vins) == sum(cc vouts) or the transaction is the 'tokenbase' ('c') tx -// checkPubkeys is true: validates if the vout is token vout1 or token vout1of2. Should always be true! -int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true*/, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid) -{ - - // this is just for log messages indentation fur debugging recursive calls: - std::string indentStr = std::string().append(tokenValIndentSize, '.'); - - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() entered for txid=" << tx.GetHash().GetHex() << " v=" << v << " for tokenid=" << reftokenid.GetHex() << std::endl); - - int32_t n = tx.vout.size(); - // just check boundaries: - if (n == 0 || v < 0 || v >= n-1) { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << indentStr << "isTokensvout() incorrect params: (n == 0 or v < 0 or v >= n-1)" << " v=" << v << " n=" << n << " returning 0" << std::endl); - return(0); - } - - if (tx.vout[v].scriptPubKey.IsPayToCryptoCondition()) - { - if (goDeeper) { - //validate all tx - int64_t myCCVinsAmount = 0, myCCVoutsAmount = 0; - - tokenValIndentSize++; - // false --> because we already at the 1-st level ancestor tx and do not need to dereference ancestors of next levels - bool isEqual = TokensExactAmounts(false, cp, myCCVinsAmount, myCCVoutsAmount, eval, tx, reftokenid); - tokenValIndentSize--; - - if (!isEqual) { - // if ccInputs != ccOutputs and it is not the tokenbase tx - // this means it is possibly a fake tx (dimxy): - if (reftokenid != tx.GetHash()) { // checking that this is the true tokenbase tx, by verifying that funcid=c, is done further in this function (dimxy) - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << indentStr << "IsTokensvout() warning: for the verified tx detected a bad vintx=" << tx.GetHash().GetHex() << ": cc inputs != cc outputs and not the 'tokenbase' tx, skipping the verified tx" << std::endl); - return 0; - } - } - } - - // token opret most important checks (tokenid == reftokenid, tokenid is non-zero, tx is 'tokenbase'): - const uint8_t funcId = ValidateTokenOpret(tx, reftokenid); - //std::cerr << indentStr << "IsTokensvout() ValidateTokenOpret returned=" << (char)(funcId?funcId:' ') << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; - if (funcId != 0) { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() ValidateTokenOpret returned not-null funcId=" << (char)(funcId ? funcId : ' ') << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); - - uint8_t dummyEvalCode; - uint256 tokenIdOpret; - std::vector voutPubkeys, voutPubkeysInOpret; - vscript_t vopretExtra, vopretNonfungible; - std::vector> oprets; - - uint8_t evalCodeNonfungible = 0; - uint8_t evalCode1 = EVAL_TOKENS; // if both payloads are empty maybe it is a transfer to non-payload-one-eval-token vout like GatewaysDeposit - uint8_t evalCode2 = 0; // will be checked if zero or not - - // test vouts for possible token use-cases: - std::vector> testVouts; - - DecodeTokenOpRet(tx.vout.back().scriptPubKey, dummyEvalCode, tokenIdOpret, voutPubkeysInOpret, oprets); - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "IsTokensvout() oprets.size()=" << oprets.size() << std::endl); - - // get assets/channels/gateways token data: - FilterOutNonCCOprets(oprets, vopretExtra); // NOTE: only 1 additional evalcode in token opret is currently supported - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "IsTokensvout() vopretExtra=" << HexStr(vopretExtra) << std::endl); - - // get non-fungible data - GetNonfungibleData(reftokenid, vopretNonfungible); - FilterOutTokensUnspendablePk(voutPubkeysInOpret, voutPubkeys); // cannot send tokens to token unspendable cc addr (only marker is allowed there) - - // NOTE: evalcode order in vouts is important: - // non-fungible-eval -> EVAL_TOKENS -> assets-eval - - if (vopretNonfungible.size() > 0) - evalCodeNonfungible = evalCode1 = vopretNonfungible.begin()[0]; - if (vopretExtra.size() > 0) - evalCode2 = vopretExtra.begin()[0]; - - if (evalCode1 == EVAL_TOKENS && evalCode2 != 0) { - evalCode1 = evalCode2; // for using MakeTokensCC1vout(evalcode,...) instead of MakeCC1vout(EVAL_TOKENS, evalcode...) - evalCode2 = 0; - } - - if( /*checkPubkeys &&*/ funcId != 'c' ) { // for 'c' there is no pubkeys - // verify that the vout is token by constructing vouts with the pubkeys in the opret: - - // maybe this is dual-eval 1 pubkey or 1of2 pubkey vout? - if (voutPubkeys.size() >= 1 && voutPubkeys.size() <= 2) { - // check dual/three-eval 1 pubkey vout with the first pubkey - testVouts.push_back( std::make_pair(MakeTokensCC1vout(evalCode1, evalCode2, tx.vout[v].nValue, voutPubkeys[0]), std::string("three-eval cc1 pk[0]")) ); - if (evalCode2 != 0) - // also check in backward evalcode order - testVouts.push_back( std::make_pair(MakeTokensCC1vout(evalCode2, evalCode1, tx.vout[v].nValue, voutPubkeys[0]), std::string("three-eval cc1 pk[0] backward-eval")) ); - - if(voutPubkeys.size() == 2) { - // check dual/three eval 1of2 pubkeys vout - testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode1, evalCode2, tx.vout[v].nValue, voutPubkeys[0], voutPubkeys[1]), std::string("three-eval cc1of2")) ); - // check dual/three eval 1 pubkey vout with the second pubkey - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, evalCode2, tx.vout[v].nValue, voutPubkeys[1]), std::string("three-eval cc1 pk[1]"))); - if (evalCode2 != 0) { - // also check in backward evalcode order: - // check dual/three eval 1of2 pubkeys vout - testVouts.push_back(std::make_pair(MakeTokensCC1of2vout(evalCode2, evalCode1, tx.vout[v].nValue, voutPubkeys[0], voutPubkeys[1]), std::string("three-eval cc1of2 backward-eval"))); - // check dual/three eval 1 pubkey vout with the second pubkey - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, evalCode1, tx.vout[v].nValue, voutPubkeys[1]), std::string("three-eval cc1 pk[1] backward-eval"))); - } - } - - // maybe this is like gatewayclaim to single-eval token? - if( evalCodeNonfungible == 0 ) // do not allow to convert non-fungible to fungible token - testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[0]), std::string("single-eval cc1 pk[0]"))); - - // maybe this is like FillSell for non-fungible token? - if( evalCode1 != 0 ) - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, tx.vout[v].nValue, voutPubkeys[0]), std::string("dual-eval-token cc1 pk[0]"))); - if( evalCode2 != 0 ) - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, tx.vout[v].nValue, voutPubkeys[0]), std::string("dual-eval2-token cc1 pk[0]"))); - - // the same for pk[1]: - if (voutPubkeys.size() == 2) { - if (evalCodeNonfungible == 0) // do not allow to convert non-fungible to fungible token - testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[1]), std::string("single-eval cc1 pk[1]"))); - if (evalCode1 != 0) - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, tx.vout[v].nValue, voutPubkeys[1]), std::string("dual-eval-token cc1 pk[1]"))); - if (evalCode2 != 0) - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, tx.vout[v].nValue, voutPubkeys[1]), std::string("dual-eval2-token cc1 pk[1]"))); - } - - //special check for tx when spending from 1of2 CC address and one of pubkeys is global CC pubkey - struct CCcontract_info *cpEvalCode1,CEvalCode1; - cpEvalCode1 = CCinit(&CEvalCode1,evalCode1); - CPubKey pk=GetUnspendable(cpEvalCode1,0); - testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode1, tx.vout[v].nValue, voutPubkeys[0], pk), std::string("dual-eval1 pegscc cc1of2 pk[0] globalccpk")) ); - if (voutPubkeys.size() == 2) testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode1, tx.vout[v].nValue, voutPubkeys[1], pk), std::string("dual-eval1 pegscc cc1of2 pk[1] globalccpk")) ); - if (evalCode2!=0) - { - struct CCcontract_info *cpEvalCode2,CEvalCode2; - cpEvalCode2 = CCinit(&CEvalCode2,evalCode2); - CPubKey pk=GetUnspendable(cpEvalCode2,0); - testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode2, tx.vout[v].nValue, voutPubkeys[0], pk), std::string("dual-eval2 pegscc cc1of2 pk[0] globalccpk")) ); - if (voutPubkeys.size() == 2) testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode2, tx.vout[v].nValue, voutPubkeys[1], pk), std::string("dual-eval2 pegscc cc1of2 pk[1] globalccpk")) ); - } - } - - // maybe it is single-eval or dual/three-eval token change? - std::vector vinPubkeys, vinPubkeysUnfiltered; - ExtractTokensCCVinPubkeys(tx, vinPubkeysUnfiltered); - FilterOutTokensUnspendablePk(vinPubkeysUnfiltered, vinPubkeys); // cannot send tokens to token unspendable cc addr (only marker is allowed there) - - for(std::vector::iterator it = vinPubkeys.begin(); it != vinPubkeys.end(); it++) { - if (evalCodeNonfungible == 0) // do not allow to convert non-fungible to fungible token - testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, *it), std::string("single-eval cc1 self vin pk"))); - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, evalCode2, tx.vout[v].nValue, *it), std::string("three-eval cc1 self vin pk"))); - - if (evalCode2 != 0) - // also check in backward evalcode order: - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, evalCode1, tx.vout[v].nValue, *it), std::string("three-eval cc1 self vin pk backward-eval"))); - } - - // try all test vouts: - for (auto t : testVouts) { - if (t.first == tx.vout[v]) { // test vout matches - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "IsTokensvout() valid amount=" << tx.vout[v].nValue << " msg=" << t.second << " evalCode=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " txid=" << tx.GetHash().GetHex() << " tokenid=" << reftokenid.GetHex() << std::endl); - return tx.vout[v].nValue; - } - } - - } - else { // funcid == 'c' - - if (!tx.IsCoinImport()) { - - vscript_t vorigPubkey; - std::string dummyName, dummyDescription; - std::vector> oprets; - - if (DecodeTokenCreateOpRet(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, oprets) == 0) { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << indentStr << "IsTokensvout() could not decode create opret" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); - return 0; - } - - CPubKey origPubkey = pubkey2pk(vorigPubkey); - - - // TODO: add voutPubkeys for 'c' tx - - /* this would not work for imported tokens: - // for 'c' recognize the tokens only to token originator pubkey (but not to unspendable <-- closed sec violation) - // maybe this is like gatewayclaim to single-eval token? - if (evalCodeNonfungible == 0) // do not allow to convert non-fungible to fungible token - testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, origPubkey), std::string("single-eval cc1 orig-pk"))); - // maybe this is like FillSell for non-fungible token? - if (evalCode1 != 0) - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, tx.vout[v].nValue, origPubkey), std::string("dual-eval-token cc1 orig-pk"))); */ - - // note: this would not work if there are several pubkeys in the tokencreator's wallet (AddNormalinputs does not use pubkey param): - // for tokenbase tx check that normal inputs sent from origpubkey > cc outputs - int64_t ccOutputs = 0; - for (auto vout : tx.vout) - if (vout.scriptPubKey.IsPayToCryptoCondition() //TODO: add voutPubkey validation - && !IsTokenMarkerVout(vout)) // should not be marker here - ccOutputs += vout.nValue; - - int64_t normalInputs = TotalPubkeyNormalInputs(eval, tx, origPubkey); // check if normal inputs are really signed by originator pubkey (someone not cheating with originator pubkey) - LOGSTREAM("cctokens", CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() normalInputs=" << normalInputs << " ccOutputs=" << ccOutputs << " for tokenbase=" << reftokenid.GetHex() << std::endl); - - if (normalInputs >= ccOutputs) { - LOGSTREAM("cctokens", CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() assured normalInputs >= ccOutputs" << " for tokenbase=" << reftokenid.GetHex() << std::endl); - if (!IsTokenMarkerVout(tx.vout[v])) // exclude marker - return tx.vout[v].nValue; - else - return 0; // vout is good, but do not take marker into account - } - else { - LOGSTREAM("cctokens", CCLOG_INFO, stream << indentStr << "IsTokensvout() skipping vout not fulfilled normalInputs >= ccOutput" << " for tokenbase=" << reftokenid.GetHex() << " normalInputs=" << normalInputs << " ccOutputs=" << ccOutputs << std::endl); - } - } - else { - // imported tokens are checked in the eval::ImportCoin() validation code - if (!IsTokenMarkerVout(tx.vout[v])) // exclude marker - return tx.vout[v].nValue; - else - return 0; // vout is good, but do not take marker into account - } - } - LOGSTREAM("cctokens", CCLOG_DEBUG1, stream << indentStr << "IsTokensvout() no valid vouts evalCode=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); - } - //std::cerr << indentStr; fprintf(stderr,"IsTokensvout() CC vout v.%d of n=%d amount=%.8f txid=%s\n",v,n,(double)0/COIN, tx.GetHash().GetHex().c_str()); - } - //std::cerr << indentStr; fprintf(stderr,"IsTokensvout() normal output v.%d %.8f\n",v,(double)tx.vout[v].nValue/COIN); - return(0); -} - -bool IsTokenMarkerVout(CTxOut vout) { - struct CCcontract_info *cpTokens, CCtokens_info; - cpTokens = CCinit(&CCtokens_info, EVAL_TOKENS); - return vout == MakeCC1vout(EVAL_TOKENS, vout.nValue, GetUnspendable(cpTokens, NULL)); -} - -// compares cc inputs vs cc outputs (to prevent feeding vouts from normal inputs) -bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 reftokenid) -{ - CTransaction vinTx; - uint256 hashBlock; - int64_t tokenoshis; - - struct CCcontract_info *cpTokens, tokensC; - cpTokens = CCinit(&tokensC, EVAL_TOKENS); - - int32_t numvins = tx.vin.size(); - int32_t numvouts = tx.vout.size(); - inputs = outputs = 0; - - // this is just for log messages indentation for debugging recursive calls: - std::string indentStr = std::string().append(tokenValIndentSize, '.'); - - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << indentStr << "TokensExactAmounts() entered for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); - - for (int32_t i = 0; iismyvin)(tx.vin[i].scriptSig) /*|| IsVinAllowed(tx.vin[i].scriptSig) != 0*/) - { - //std::cerr << indentStr << "TokensExactAmounts() eval is true=" << (eval != NULL) << " ismyvin=ok for_i=" << i << std::endl; - // we are not inside the validation code -- dimxy - if ((eval && eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock) == 0) || (!eval && !myGetTransaction(tx.vin[i].prevout.hash, vinTx, hashBlock))) - { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << indentStr << "TokensExactAmounts() cannot read vintx for i." << i << " numvins." << numvins << std::endl); - return (!eval) ? false : eval->Invalid("always should find vin tx, but didnt"); - } - else { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << indentStr << "TokenExactAmounts() checking vintx.vout for tx.vin[" << i << "] nValue=" << vinTx.vout[tx.vin[i].prevout.n].nValue << std::endl); - - // validate vouts of vintx - tokenValIndentSize++; - tokenoshis = IsTokensvout(goDeeper, true, cpTokens, eval, vinTx, tx.vin[i].prevout.n, reftokenid); - tokenValIndentSize--; - if (tokenoshis != 0) - { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() adding vintx.vout for tx.vin[" << i << "] tokenoshis=" << tokenoshis << std::endl); - inputs += tokenoshis; - } - } - } - } - - for (int32_t i = 0; i < numvouts-1; i ++) // 'numvouts-1' <-- do not check opret - { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << indentStr << "TokenExactAmounts() recursively checking tx.vout[" << i << "] nValue=" << tx.vout[i].nValue << std::endl); - - // Note: we pass in here IsTokenvout(false,...) because we don't need to call TokenExactAmounts() recursively from IsTokensvout here - // indeed, if we pass 'true' we'll be checking this tx vout again - tokenValIndentSize++; - tokenoshis = IsTokensvout(false /*<--do not recursion here*/, true /*<--exclude non-tokens vouts*/, cpTokens, eval, tx, i, reftokenid); - tokenValIndentSize--; - - if (tokenoshis != 0) - { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() adding tx.vout[" << i << "] tokenoshis=" << tokenoshis << std::endl); - outputs += tokenoshis; - } - } - - //std::cerr << indentStr << "TokensExactAmounts() inputs=" << inputs << " outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << std::endl; - - if (inputs != outputs) { - if (tx.GetHash() != reftokenid) - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "TokenExactAmounts() found unequal token cc inputs=" << inputs << " vs cc outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << " and this is not the create tx" << std::endl); - //fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs); - return false; // do not call eval->Invalid() here! - } - else - return true; -} - - -// get non-fungible data from 'tokenbase' tx (the data might be empty) -void GetNonfungibleData(uint256 tokenid, vscript_t &vopretNonfungible) -{ - CTransaction tokenbasetx; - uint256 hashBlock; - - if (!myGetTransaction(tokenid, tokenbasetx, hashBlock)) { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "GetNonfungibleData() cound not load token creation tx=" << tokenid.GetHex() << std::endl); - return; - } - - vopretNonfungible.clear(); - // check if it is non-fungible tx and get its second evalcode from non-fungible payload - if (tokenbasetx.vout.size() > 0) { - std::vector origpubkey; - std::string name, description; - std::vector> oprets; - - if (DecodeTokenCreateOpRet(tokenbasetx.vout.back().scriptPubKey, origpubkey, name, description, oprets) == 'c') { - GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vopretNonfungible); - } - } -} - - -// overload, adds inputs from token cc addr -int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs) { - vscript_t vopretNonfungibleDummy; - return AddTokenCCInputs(cp, mtx, pk, tokenid, total, maxinputs, vopretNonfungibleDummy); -} - -// adds inputs from token cc addr and returns non-fungible opret payload if present -// also sets evalcode in cp, if needed -int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs, vscript_t &vopretNonfungible) -{ - char tokenaddr[64], destaddr[64]; - int64_t threshold, nValue, price, totalinputs = 0; - int32_t n = 0; - std::vector > unspentOutputs; - - GetNonfungibleData(tokenid, vopretNonfungible); - if (vopretNonfungible.size() > 0) - cp->evalcodeAdd = vopretNonfungible.begin()[0]; - - GetTokensCCaddress(cp, tokenaddr, pk); - SetCCunspents(unspentOutputs, tokenaddr,true); - - - if (unspentOutputs.empty()) { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "AddTokenCCInputs() no utxos for token dual/three eval addr=" << tokenaddr << " evalcode=" << (int)cp->evalcode << " additionalTokensEvalcode2=" << (int)cp->evalcodeAdd << std::endl); - } - - threshold = total / (maxinputs != 0 ? maxinputs : CC_MAXVINS); - - for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) - { - CTransaction vintx; - uint256 hashBlock; - uint256 vintxid = it->first.txhash; - int32_t vout = (int32_t)it->first.index; - - if (it->second.satoshis < threshold) // this should work also for non-fungible tokens (there should be only 1 satoshi for non-fungible token issue) - continue; - - int32_t ivin; - for (ivin = 0; ivin < mtx.vin.size(); ivin ++) - if (vintxid == mtx.vin[ivin].prevout.hash && vout == mtx.vin[ivin].prevout.n) - break; - if (ivin != mtx.vin.size()) // that is, the tx.vout is already added to mtx.vin (in some previous calls) - continue; - - if (myGetTransaction(vintxid, vintx, hashBlock) != 0) - { - Getscriptaddress(destaddr, vintx.vout[vout].scriptPubKey); - if (strcmp(destaddr, tokenaddr) != 0 && - strcmp(destaddr, cp->unspendableCCaddr) != 0 && // TODO: check why this. Should not we add token inputs from unspendable cc addr if mypubkey is used? - strcmp(destaddr, cp->unspendableaddr2) != 0) // or the logic is to allow to spend all available tokens (what about unspendableaddr3)? - continue; - - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "AddTokenCCInputs() check vintx vout destaddress=" << destaddr << " amount=" << vintx.vout[vout].nValue << std::endl); - - if ((nValue = IsTokensvout(true, true/*<--add only valid token uxtos */, cp, NULL, vintx, vout, tokenid)) > 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,vintxid, vout) == 0) - { - //for non-fungible tokens check payload: - if (!vopretNonfungible.empty()) { - vscript_t vopret; - - // check if it is non-fungible token: - GetNonfungibleData(tokenid, vopret); - if (vopret != vopretNonfungible) { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "AddTokenCCInputs() found incorrect non-fungible opret payload for vintxid=" << vintxid.GetHex() << std::endl); - continue; - } - // non-fungible evalCode2 cc contract should also check if there exists only one non-fungible vout with amount = 1 - } - - - if (total != 0 && maxinputs != 0) // if it is not just to calc amount... - mtx.vin.push_back(CTxIn(vintxid, vout, CScript())); - - nValue = it->second.satoshis; - totalinputs += nValue; - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "AddTokenCCInputs() adding input nValue=" << nValue << std::endl); - n++; - - if ((total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) - break; - } - } - } - - //std::cerr << "AddTokenCCInputs() found totalinputs=" << totalinputs << std::endl; - return(totalinputs); -} - -// checks if any token vouts are sent to 'dead' pubkey -int64_t HasBurnedTokensvouts(struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, uint256 reftokenid) -{ - uint8_t dummyEvalCode; - uint256 tokenIdOpret; - std::vector voutPubkeys, voutPubkeysDummy; - std::vector> oprets; - vscript_t vopretExtra, vopretNonfungible; - - uint8_t evalCode = EVAL_TOKENS; // if both payloads are empty maybe it is a transfer to non-payload-one-eval-token vout like GatewaysDepost - uint8_t evalCode2 = 0; // will be checked if zero or not - - // test vouts for possible token use-cases: - std::vector> testVouts; - - int32_t n = tx.vout.size(); - // just check boundaries: - if (n == 0) { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "HasBurnedTokensvouts() incorrect params: tx.vout.size() == 0, txid=" << tx.GetHash().GetHex() << std::endl); - return(0); - } - - - if (DecodeTokenOpRet(tx.vout.back().scriptPubKey, dummyEvalCode, tokenIdOpret, voutPubkeysDummy, oprets) == 0) { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "HasBurnedTokensvouts() cannot parse opret DecodeTokenOpRet returned 0, txid=" << tx.GetHash().GetHex() << std::endl); - return 0; - } - - // get assets/channels/gateways token data: - FilterOutNonCCOprets(oprets, vopretExtra); // NOTE: only 1 additional evalcode in token opret is currently supported - - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "HasBurnedTokensvouts() vopretExtra=" << HexStr(vopretExtra) << std::endl); - - GetNonfungibleData(reftokenid, vopretNonfungible); - - if (vopretNonfungible.size() > 0) - evalCode = vopretNonfungible.begin()[0]; - if (vopretExtra.size() > 0) - evalCode2 = vopretExtra.begin()[0]; - - if (evalCode == EVAL_TOKENS && evalCode2 != 0) { - evalCode = evalCode2; - evalCode2 = 0; - } - - voutPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); - - int64_t burnedAmount = 0; - - for (int i = 0; i < tx.vout.size(); i++) { - - if (tx.vout[i].scriptPubKey.IsPayToCryptoCondition()) - { - // make all possible token vouts for dead pk: - for (std::vector::iterator it = voutPubkeys.begin(); it != voutPubkeys.end(); it++) { - testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[i].nValue, *it), std::string("single-eval cc1 burn pk"))); - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode, evalCode2, tx.vout[i].nValue, *it), std::string("three-eval cc1 burn pk"))); - - if (evalCode2 != 0) - // also check in backward evalcode order: - testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, evalCode, tx.vout[i].nValue, *it), std::string("three-eval cc1 burn pk backward-eval"))); - } - - // try all test vouts: - for (auto t : testVouts) { - if (t.first == tx.vout[i]) { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "HasBurnedTokensvouts() burned amount=" << tx.vout[i].nValue << " msg=" << t.second << " evalCode=" << (int)evalCode << " evalCode2=" << (int)evalCode2 << " txid=" << tx.GetHash().GetHex() << " tokenid=" << reftokenid.GetHex() << std::endl); - burnedAmount += tx.vout[i].nValue; - } - } - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "HasBurnedTokensvouts() total burned=" << burnedAmount << " evalCode=" << (int)evalCode << " evalCode2=" << (int)evalCode2 << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl); - } - } - - return burnedAmount; -} - -CPubKey GetTokenOriginatorPubKey(CScript scriptPubKey) { - - uint8_t funcId, evalCode; - uint256 tokenid; - std::vector voutTokenPubkeys; - std::vector> oprets; - - if ((funcId = DecodeTokenOpRet(scriptPubKey, evalCode, tokenid, voutTokenPubkeys, oprets)) != 0) { - CTransaction tokenbasetx; - uint256 hashBlock; - - if (myGetTransaction(tokenid, tokenbasetx, hashBlock) && tokenbasetx.vout.size() > 0) { - vscript_t vorigpubkey; - std::string name, desc; - if (DecodeTokenCreateOpRet(tokenbasetx.vout.back().scriptPubKey, vorigpubkey, name, desc) != 0) - return pubkey2pk(vorigpubkey); - } - } - return CPubKey(); //return invalid pubkey -} - -// returns token creation signed raw tx -std::string CreateToken(int64_t txfee, int64_t tokensupply, std::string name, std::string description, vscript_t nonfungibleData) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; struct CCcontract_info *cp, C; - if (tokensupply < 0) { - CCerror = "negative tokensupply"; - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "CreateToken() =" << CCerror << "=" << tokensupply << std::endl); - return std::string(""); - } - if (!nonfungibleData.empty() && tokensupply != 1) { - CCerror = "for non-fungible tokens tokensupply should be equal to 1"; - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "CreateToken() " << CCerror << std::endl); - return std::string(""); - } - - - cp = CCinit(&C, EVAL_TOKENS); - if (name.size() > 32 || description.size() > 4096) // this is also checked on rpc level - { - LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "name len=" << name.size() << " or description len=" << description.size() << " is too big" << std::endl); - CCerror = "name should be <= 32, description should be <= 4096"; - return(""); - } - if (txfee == 0) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - - if (AddNormalinputs2(mtx, tokensupply + 2 * txfee, 64) > 0) // add normal inputs only from mypk - { - int64_t mypkInputs = TotalPubkeyNormalInputs(NULL, mtx, mypk); - if (mypkInputs < tokensupply) { // check that tokens amount are really issued with mypk (because in the wallet there maybe other privkeys) - CCerror = "some inputs signed not with -pubkey=pk"; - return std::string(""); - } - - uint8_t destEvalCode = EVAL_TOKENS; - if( nonfungibleData.size() > 0 ) - destEvalCode = nonfungibleData.begin()[0]; - - // NOTE: we should prevent spending fake-tokens from this marker in IsTokenvout(): - mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, txfee, GetUnspendable(cp, NULL))); // new marker to token cc addr, burnable and validated, vout pos now changed to 0 (from 1) - mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, tokensupply, mypk)); - //mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(cp->CChexstr) << OP_CHECKSIG)); // old marker (non-burnable because spending could not be validated) - //mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, txfee, GetUnspendable(cp, NULL))); // ...moved to vout=0 for matching with rogue-game token - - return(FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeTokenCreateOpRet('c', Mypubkey(), name, description, nonfungibleData))); - } - - CCerror = "cant find normal inputs"; - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "CreateToken() " << CCerror << std::endl); - return std::string(""); -} - -// transfer tokens to another pubkey -// param additionalEvalCode allows transfer of dual-eval non-fungible tokens -std::string TokenTransfer(int64_t txfee, uint256 tokenid, vscript_t destpubkey, int64_t total) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; uint64_t mask; int64_t CCchange = 0, inputs = 0; struct CCcontract_info *cp, C; - vscript_t vopretNonfungible, vopretEmpty; - - if (total < 0) { - CCerror = strprintf("negative total"); - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << CCerror << "=" << total << std::endl); - return(""); - } - - cp = CCinit(&C, EVAL_TOKENS); - - if (txfee == 0) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - /*if ( cp->tokens1of2addr[0] == 0 ) - { - GetTokensCCaddress(cp, cp->tokens1of2addr, mypk); - fprintf(stderr,"set tokens1of2addr <- %s\n",cp->tokens1of2addr); - }*/ - if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) - { - mask = ~((1LL << mtx.vin.size()) - 1); // seems, mask is not used anymore - - if ((inputs = AddTokenCCInputs(cp, mtx, mypk, tokenid, total, 60, vopretNonfungible)) > 0) // NOTE: AddTokenCCInputs might set cp->additionalEvalCode which is used in FinalizeCCtx! - { - if (inputs < total) { //added dimxy - CCerror = strprintf("insufficient token inputs"); - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenTransfer() " << CCerror << std::endl); - return std::string(""); - } - - uint8_t destEvalCode = EVAL_TOKENS; - if (vopretNonfungible.size() > 0) - destEvalCode = vopretNonfungible.begin()[0]; - - if (inputs > total) - CCchange = (inputs - total); - mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, total, pubkey2pk(destpubkey))); // if destEvalCode == EVAL_TOKENS then it is actually MakeCC1vout(EVAL_TOKENS,...) - if (CCchange != 0) - mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, CCchange, mypk)); - - std::vector voutTokenPubkeys; - voutTokenPubkeys.push_back(pubkey2pk(destpubkey)); // dest pubkey for validating vout - - return FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeTokenOpRet(tokenid, voutTokenPubkeys, std::make_pair((uint8_t)0, vopretEmpty))); - } - else { - CCerror = strprintf("no token inputs"); - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenTransfer() " << CCerror << " for amount=" << total << std::endl); - } - //} else fprintf(stderr,"numoutputs.%d != numamounts.%d\n",n,(int32_t)amounts.size()); - } - else { - CCerror = strprintf("insufficient normal inputs for tx fee"); - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenTransfer() " << CCerror << std::endl); - } - return(""); -} - - -int64_t GetTokenBalance(CPubKey pk, uint256 tokenid) -{ - uint256 hashBlock; - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction tokentx; - - // CCerror = strprintf("obsolete, cannot return correct value without eval"); - // return 0; - - if (myGetTransaction(tokenid, tokentx, hashBlock) == 0) - { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "cant find tokenid" << std::endl); - CCerror = strprintf("cant find tokenid"); - return 0; - } - - struct CCcontract_info *cp, C; - cp = CCinit(&C, EVAL_TOKENS); - return(AddTokenCCInputs(cp, mtx, pk, tokenid, 0, 0)); -} - -UniValue TokenInfo(uint256 tokenid) -{ - UniValue result(UniValue::VOBJ); - uint256 hashBlock; - CTransaction tokenbaseTx; - std::vector origpubkey; - std::vector> oprets; - vscript_t vopretNonfungible; - std::string name, description; - struct CCcontract_info *cpTokens, tokensCCinfo; - - cpTokens = CCinit(&tokensCCinfo, EVAL_TOKENS); - - if( !myGetTransaction(tokenid, tokenbaseTx, hashBlock) ) - { - fprintf(stderr, "TokenInfo() cant find tokenid\n"); - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "cant find tokenid")); - return(result); - } - if ( KOMODO_NSPV_FULLNODE && hashBlock.IsNull()) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "the transaction is still in mempool")); - return(result); - } - - if (tokenbaseTx.vout.size() > 0 && DecodeTokenCreateOpRet(tokenbaseTx.vout[tokenbaseTx.vout.size() - 1].scriptPubKey, origpubkey, name, description, oprets) != 'c') - { - LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenInfo() passed tokenid isnt token creation txid" << std::endl); - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "tokenid isnt token creation txid")); - return result; - } - result.push_back(Pair("result", "success")); - result.push_back(Pair("tokenid", tokenid.GetHex())); - result.push_back(Pair("owner", HexStr(origpubkey))); - result.push_back(Pair("name", name)); - - int64_t supply = 0, output; - for (int v = 0; v < tokenbaseTx.vout.size() - 1; v++) - if ((output = IsTokensvout(false, true, cpTokens, NULL, tokenbaseTx, v, tokenid)) > 0) - supply += output; - result.push_back(Pair("supply", supply)); - result.push_back(Pair("description", description)); - - GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vopretNonfungible); - if( !vopretNonfungible.empty() ) - result.push_back(Pair("data", HexStr(vopretNonfungible))); - - if (tokenbaseTx.IsCoinImport()) { // if imported token - ImportProof proof; - CTransaction burnTx; - std::vector payouts; - CTxDestination importaddress; - - std::string sourceSymbol = "can't decode"; - std::string sourceTokenId = "can't decode"; - - if (UnmarshalImportTx(tokenbaseTx, proof, burnTx, payouts)) - { - // extract op_return to get burn source chain. - std::vector burnOpret; - std::string targetSymbol; - uint32_t targetCCid; - uint256 payoutsHash; - std::vector rawproof; - if (UnmarshalBurnTx(burnTx, targetSymbol, &targetCCid, payoutsHash, rawproof)) { - if (rawproof.size() > 0) { - CTransaction tokenbasetx; - E_UNMARSHAL(rawproof, ss >> sourceSymbol; - if (!ss.eof()) - ss >> tokenbasetx); - - if (!tokenbasetx.IsNull()) - sourceTokenId = tokenbasetx.GetHash().GetHex(); - } - } - } - result.push_back(Pair("IsImported", "yes")); - result.push_back(Pair("sourceChain", sourceSymbol)); - result.push_back(Pair("sourceTokenId", sourceTokenId)); - } - - return result; -} - -UniValue TokenList() -{ - UniValue result(UniValue::VARR); - std::vector txids; - std::vector > addressIndexCCMarker; - - struct CCcontract_info *cp, C; uint256 txid, hashBlock; - CTransaction vintx; std::vector origpubkey; - std::string name, description; - - cp = CCinit(&C, EVAL_TOKENS); - - auto addTokenId = [&](uint256 txid) { - if (myGetTransaction(txid, vintx, hashBlock) != 0) { - if (vintx.vout.size() > 0 && DecodeTokenCreateOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, origpubkey, name, description) != 0) { - result.push_back(txid.GetHex()); - } - } - }; - - SetCCtxids(txids, cp->normaladdr,false,cp->evalcode,10000,zeroid,'c'); // find by old normal addr marker - for (std::vector::const_iterator it = txids.begin(); it != txids.end(); it++) { - addTokenId(*it); - } - - SetCCunspents(addressIndexCCMarker, cp->unspendableCCaddr,true); // find by burnable validated cc addr marker - for (std::vector >::const_iterator it = addressIndexCCMarker.begin(); it != addressIndexCCMarker.end(); it++) { - addTokenId(it->first.txhash); - } - - return(result); -} - -}; \ No newline at end of file diff --git a/src/cc/old/CCtokens_v0.h b/src/cc/old/CCtokens_v0.h deleted file mode 100644 index 2738a680b70..00000000000 --- a/src/cc/old/CCtokens_v0.h +++ /dev/null @@ -1,99 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2018 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. * - * * - ******************************************************************************/ - - -/* - old code for compatibility with tokens cc version 0 - */ - -#ifndef CC_TOKENS_V0_H -#define CC_TOKENS_V0_H - -#include "../CCinclude.h" - -namespace tokensv0 { - -/// identifiers of additional data blobs in token opreturn script: -/// @see EncodeTokenCreateOpRet(uint8_t funcid, std::vector origpubkey, std::string name, std::string description, std::vector> oprets) -/// @see GetOpretBlob -enum opretid : uint8_t { - // cc contracts data: - OPRETID_NONFUNGIBLEDATA = 0x11, //!< NFT data id - OPRETID_ASSETSDATA = 0x12, //!< assets contract data id - OPRETID_GATEWAYSDATA = 0x13, //!< gateways contract data id - OPRETID_CHANNELSDATA = 0x14, //!< channels contract data id - OPRETID_HEIRDATA = 0x15, //!< heir contract data id - OPRETID_ROGUEGAMEDATA = 0x16, //!< rogue contract data id - OPRETID_PEGSDATA = 0x17, //!< pegs contract data id - - /*! \cond INTERNAL */ - // non cc contract data: - OPRETID_FIRSTNONCCDATA = 0x80, - /*! \endcond */ - OPRETID_BURNDATA = 0x80, //!< burned token data id - OPRETID_IMPORTDATA = 0x81 //!< imported token data id -}; - -/// finds opret blob data by opretid in the vector of oprets -/// @param oprets vector of oprets -/// @param id opret id to search -/// @param vopret found opret blob as byte array -/// @returns true if found -/// @see opretid -inline bool GetOpretBlob(const std::vector>> &oprets, uint8_t id, std::vector &vopret) { - vopret.clear(); - for(auto p : oprets) if (p.first == id) { vopret = p.second; return true; } - return false; -} - -CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector origpubkey, std::string name, std::string description, vscript_t vopretNonfungible); -CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector origpubkey, std::string name, std::string description, std::vector> oprets); -uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector &origpubkey, std::string &name, std::string &description); -uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector &origpubkey, std::string &name, std::string &description, std::vector> &oprets); -CScript EncodeTokenOpRet(uint256 tokenid, std::vector voutPubkeys, std::pair opretWithId); -CScript EncodeTokenOpRet(uint256 tokenid, std::vector voutPubkeys, std::vector> oprets); -uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector &voutPubkeys, std::vector> &oprets); -CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk); -CC *MakeTokensCCcond1(uint8_t evalcode, uint8_t evalcode2, CPubKey pk); -CC *MakeTokensCCcond1of2(uint8_t evalcode, CPubKey pk1, CPubKey pk2); -CC *MakeTokensCCcond1of2(uint8_t evalcode, uint8_t evalcode2, CPubKey pk1, CPubKey pk2); -CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk); -CTxOut MakeTokensCC1vout(uint8_t evalcode, uint8_t evalcode2, CAmount nValue, CPubKey pk); -CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2); -CTxOut MakeTokensCC1of2vout(uint8_t evalcode, uint8_t evalcode2, CAmount nValue, CPubKey pk1, CPubKey pk2); -//bool GetTokensCCaddress(struct CCcontract_info *cp, char *destaddr, CPubKey pk); -//bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey pk, CPubKey pk2); -//void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, uint8_t *priv, char *coinaddr); - -// CCcustom -bool TokensValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); -bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cpTokens, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 tokenid); -std::string CreateToken(int64_t txfee, int64_t assetsupply, std::string name, std::string description, std::vector nonfungibleData); -std::string TokenTransfer(int64_t txfee, uint256 assetid, std::vector destpubkey, int64_t total); -int64_t HasBurnedTokensvouts(struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, uint256 reftokenid); -CPubKey GetTokenOriginatorPubKey(CScript scriptPubKey); -int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid); -bool IsTokenMarkerVout(CTxOut vout); -void GetNonfungibleData(uint256 tokenid, vscript_t &vopretNonfungible); -int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs); -int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs, vscript_t &vopretNonfungible); - -int64_t GetTokenBalance(CPubKey pk, uint256 tokenid); -UniValue TokenInfo(uint256 tokenid); -UniValue TokenList(); - -}; - -#endif diff --git a/src/cc/old/CCtokenutils_v0.cpp b/src/cc/old/CCtokenutils_v0.cpp deleted file mode 100644 index af74e742dc1..00000000000 --- a/src/cc/old/CCtokenutils_v0.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/****************************************************************************** -* 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. * -* * -******************************************************************************/ - -// encode decode tokens opret -// make token cryptoconditions and vouts -// This code was moved to a separate source file to enable linking libcommon.so (with importcoin.cpp which depends on some token functions) - -#include "CCtokens_v0.h" - -namespace tokensv0 { - -#ifndef IS_CHARINSTR -#define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos) -#endif - -// NOTE: this inital tx won't be used by other contract -// 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 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> oprets; - - if(!vopretNonfungible.empty()) - oprets.push_back(std::make_pair(OPRETID_NONFUNGIBLEDATA, vopretNonfungible)); - return EncodeTokenCreateOpRet(funcid, origpubkey, name, description, oprets); -} - -CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector origpubkey, std::string name, std::string description, std::vector> 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); -} - -/* -// opret 'i' for imported tokens -CScript EncodeTokenImportOpRet(std::vector origpubkey, std::string name, std::string description, uint256 srctokenid, std::vector> 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 voutPubkeys, std::pair opretWithId) -{ - std::vector> oprets; - oprets.push_back(opretWithId); - return EncodeTokenOpRet(tokenid, voutPubkeys, oprets); -} - -CScript EncodeTokenOpRet(uint256 tokenid, std::vector voutPubkeys, std::vector> 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 { - LOGSTREAMFN("cctokens", CCLOG_DEBUG2, stream << "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; -} - -// overload for compatibility -//CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector 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 &origpubkey, std::string &name, std::string &description) { - //vopret_t vopretNonfungibleDummy; - std::vector> opretsDummy; - return DecodeTokenCreateOpRet(scriptPubKey, origpubkey, name, description, opretsDummy); -} - -uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector &origpubkey, std::string &name, std::string &description, std::vector> &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); - } - } - LOGSTREAMFN("cctokens", CCLOG_DEBUG1, stream << "incorrect token create opret" << std::endl); - return (uint8_t)0; -} - -// decode token opret: -// for 't' returns all data from opret, vopretExtra contains other contract's data (currently only assets'). -// for 'c' returns only funcid. NOTE: nonfungible data is not returned -uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector &voutPubkeys, std::vector> &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) { - LOGSTREAMFN("cctokens", CCLOG_DEBUG1, stream << "incorrect evalcode in tokens opret" << std::endl); - return (uint8_t)0; - } - - funcId = script[1]; - LOGSTREAMFN("cctokens", CCLOG_DEBUG2, stream << "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 - LOGSTREAMFN("cctokens", CCLOG_DEBUG1, stream << "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 - LOGSTREAMFN("cctokens", CCLOG_DEBUG1, stream << "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); - } - LOGSTREAMFN("cctokens", CCLOG_DEBUG1, stream << "bad opret format," << " ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl); - return (uint8_t)0; - - default: - LOGSTREAMFN("cctokens", CCLOG_DEBUG1, stream << "illegal funcid=" << (int)funcId << std::endl); - return (uint8_t)0; - } - } - else { - LOGSTREAMFN("cctokens", CCLOG_DEBUG1, stream << "empty opret, could not parse" << std::endl); - } - return (uint8_t)0; -} - - -// 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 pks; - pks.push_back(CCNewSecp256k1(pk1)); - pks.push_back(CCNewSecp256k1(pk2)); - - std::vector 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 pks; - pks.push_back(CCNewSecp256k1(pk)); - - std::vector 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); -} - -}; \ No newline at end of file diff --git a/src/cc/old/assets_v0.cpp b/src/cc/old/assets_v0.cpp deleted file mode 100644 index eb0e5e5af08..00000000000 --- a/src/cc/old/assets_v0.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - -#include "CCassets_v0.h" -#include "CCtokens_v0.h" - -namespace tokensv0 { - -/* - Assets can be created or transferred. - - native coins are also locked in the EVAL_ASSETS address, so we need a strict rule on when utxo in the special address are native coins and when they are assets. The specific rule that must not be violated is that vout0 for 'b'/'B' funcid are native coins. All other utxo locked in the special address are assets. - - To create an asset use CC EVAL_ASSETS to create a transaction where vout[0] funds the assets. Externally each satoshi can be interpreted to represent 1 asset, or 100 million satoshis for one asset with 8 decimals, and the other decimals in between. The interpretation of the number of decimals is left to the higher level usages. - - Once created, the assetid is the txid of the create transaction and using the assetid/0 it can spend the assets to however many outputs it creates. The restriction is that the last output must be an opreturn with the assetid. The sum of all but the first output needs to add up to the total assetoshis input. The first output is ignored and used for change from txfee. - - What this means is that vout 0 of the creation txid and vouts 1 ... n-2 for transfer vouts are assetoshi outputs. - - There is a special type of transfer to an unspendable address, that locks the asset and creates an offer for all. The details specified in the opreturn. In order to be compatible with the signing restrictions, the "unspendable" address is actually an address whose privkey is known to all. Funds sent to this address can only be spent if the swap parameters are fulfilled, or if the original pubkey cancels the offer by spending it. - - Types of transactions: - create name:description -> txid for assetid - transfer -> [{address:amount}, ... ] // like withdraw api - selloffer -> cancel or fillsell -> mempool txid or rejected, might not confirm - buyoffer -> cancelbuy or fillbuy -> mempool txid or rejected, might not confirm - exchange -> cancel or fillexchange -> mempool txid or rejected, might not confirm - - assetsaddress // all assets end up in a special address for each pubkey - assetbalance - assetutxos - assetsbalances - asks - bids - swaps - - valid CC output: create or transfer or buyoffer or selloffer or exchange or cancel or fill - - - buyoffer: - vins.*: normal inputs (bid + change) - vout.0: amount of bid to unspendable - vout.1: CC output for marker - vout.2: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['b'] [assetid] [amount of asset required] [origpubkey] - - cancelbuy: - vin.0: normal input - vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] - vin.2: CC marker from buyoffer for txfee - vout.0: vin.1 value to original pubkey buyTx.vout[0].nValue -> [origpubkey] - vout.1: vin.2 back to users pubkey - vout.2: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['o'] [assetid] 0 0 [origpubkey] - - fillbuy: - vin.0: normal input - vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] - vin.2+: valid CC output satisfies buyoffer (*tx.vin[2])->nValue - vout.0: remaining amount of bid to unspendable - vout.1: vin.1 value to signer of vin.2 - vout.2: vin.2 assetoshis to original pubkey - vout.3: CC output for assetoshis change (if any) - vout.4: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['B'] [assetid] [remaining asset required] [origpubkey] - - selloffer: - vin.0: normal input - vin.1+: valid CC output for sale - vout.0: vin.1 assetoshis output to CC to unspendable - vout.1: CC output for marker - vout.2: CC output for change (if any) - vout.3: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey] - - exchange: - vin.0: normal input - vin.1+: valid CC output - vout.0: vin.1 assetoshis output to CC to unspendable - vout.1: CC output for change (if any) - vout.2: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey] - - cancel: - vin.0: normal input - vin.1: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx - vin.2: CC marker from selloffer for txfee - vout.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey] - vout.1: vin.2 back to users pubkey - vout.2: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid] - - fillsell: - vin.0: normal input - vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0] - vin.2+: normal output that satisfies selloffer (*tx.vin[2])->nValue - vout.0: remaining assetoshis -> unspendable - vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any - vout.2: vin.2 value to original pubkey [origpubkey] - vout.3: CC asset for change (if any) - vout.4: CC asset2 for change (if any) 'E' only - vout.5: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey] - - fillexchange: - vin.0: normal input - vin.1: unspendable.(vout.0 assetoshis from exchange) exchangeTx.vout[0] - vin.2+: valid CC assetid2 output that satisfies exchange (*tx.vin[2])->nValue - vout.0: remaining assetoshis -> unspendable - vout.1: vin.1 assetoshis to signer of vin.2 exchangeTx.vout[0].nValue -> any - vout.2: vin.2 assetoshis2 to original pubkey [origpubkey] - vout.3: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey] -*/ - -using namespace tokensv0; - -// tx validation -bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransaction &tx, uint32_t nIn) -{ - static uint256 zero; - CTxDestination address; - CTransaction vinTx, createTx; - uint256 hashBlock, assetid, assetid2; - int32_t i,starti, numvins, numvouts, preventCCvins, preventCCvouts; - int64_t remaining_price, nValue, assetoshis, outputsDummy,inputs,tmpprice,totalunits,ignore; - std::vector origpubkey, tmporigpubkey, ignorepubkey, vopretNonfungible, vopretNonfungibleDummy; - uint8_t funcid, evalCodeInOpret; - char destaddr[64], origNormalAddr[64], origTokensCCaddr[64], origCCaddrDummy[64]; - char tokensDualEvalUnspendableCCaddr[64], origAssetsCCaddr[64]; - - //return true; - - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - outputsDummy = inputs = 0; - preventCCvins = preventCCvouts = -1; - - // add specific chains exceptions for old token support: - if (strcmp(ASSETCHAINS_SYMBOL, "SEC") == 0 && chainActive.Height() <= 144073) - return true; - - if (strcmp(ASSETCHAINS_SYMBOL, "MGNX") == 0 && chainActive.Height() <= 210190) - return true; - - // add specific chains exceptions for old token support: - if (strcmp(ASSETCHAINS_SYMBOL, "SEC") == 0 && chainActive.Height() <= 144073) - return true; - - if (strcmp(ASSETCHAINS_SYMBOL, "MGNX") == 0 && chainActive.Height() <= 210190) - return true; - - if (numvouts == 0) - return eval->Invalid("AssetValidate: no vouts"); - - if((funcid = DecodeAssetTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCodeInOpret, assetid, assetid2, remaining_price, origpubkey)) == 0 ) - return eval->Invalid("AssetValidate: invalid opreturn payload"); - - // non-fungible tokens support: - GetNonfungibleData(assetid, vopretNonfungible); - if (vopretNonfungible.size() > 0) - cpAssets->evalcodeAdd = vopretNonfungible.begin()[0]; - - // find dual-eval tokens unspendable addr: - GetTokensCCaddress(cpAssets, tokensDualEvalUnspendableCCaddr, GetUnspendable(cpAssets, NULL)); - // this is for marker validation: - GetCCaddress(cpAssets, origAssetsCCaddr, origpubkey); - - // we need this for validating single-eval tokens' vins/vous: - struct CCcontract_info *cpTokens, tokensC; - cpTokens = CCinit(&tokensC, EVAL_TOKENS); - - // find single-eval token user cc addr: - //GetCCaddress(cpTokens, signleEvalTokensCCaddr, pubkey2pk(origpubkey)); - - //fprintf(stderr,"AssetValidate (%c)\n",funcid); - - if( funcid != 'o' && funcid != 'x' && eval->GetTxUnconfirmed(assetid, createTx, hashBlock) == 0 ) - return eval->Invalid("cant find asset create txid"); - else if( funcid != 'o' && funcid != 'x' && assetid2 != zero && eval->GetTxUnconfirmed(assetid2, createTx, hashBlock) == 0 ) - return eval->Invalid("cant find asset2 create txid"); - else if( IsCCInput(tx.vin[0].scriptSig) != 0 ) // vin0 should be normal vin - return eval->Invalid("illegal asset vin0"); - else if( numvouts < 2 ) - return eval->Invalid("too few vouts"); // it was if(numvouts < 1) but it refers at least to vout[1] below - else if( funcid != 'c' ) - { - /* if( funcid == 't' ) - starti = 0; - else - starti = 1; */ - - if( assetid == zero ) - return eval->Invalid("illegal assetid"); - - else if (!AssetCalcAmounts(cpAssets, inputs, outputsDummy/*outputsDummy is calculated incorrectly but not used*/, eval, tx, assetid)) { // Only set inputs and outputs. NOTE: we do not need to check cc inputs == cc outputs - return false; // returns false if some problems with reading vintxes - } - } - - switch( funcid ) - { - case 'c': // create wont be called to be verified as it has no CC inputs - //vin.0: normal input - //vout.0: issuance assetoshis to CC - //vout.1: normal output for change (if any) - //vout.n-1: opreturn [EVAL_ASSETS] ['c'] [{"":""}] - //if (evalCodeInOpret == EVAL_ASSETS) - // return eval->Invalid("unexpected AssetValidate for createasset"); - // return - return eval->Invalid("invalid asset funcid \'c\'"); - break; - case 't': // transfer - //vin.0: normal input - //vin.1 .. vin.n-1: valid CC outputs - //vout.0 to n-2: assetoshis output to CC - //vout.n-2: normal output for change (if any) - //vout.n-1: opreturn [EVAL_ASSETS] ['t'] [assetid] - //if (inputs == 0) - // return eval->Invalid("no asset inputs for transfer"); - //fprintf(stderr,"transfer preliminarily validated %.8f -> %.8f (%d %d)\n",(double)inputs/COIN,(double)outputs/COIN,preventCCvins,preventCCvouts); - return eval->Invalid("invalid asset funcid \'t\'"); - break; - - case 'b': // buyoffer - //vins.*: normal inputs (bid + change) - //vout.0: amount of bid to unspendable - //vout.1: CC output for marker - //vout.2: normal output for change (if any) - // vout.n-1: opreturn [EVAL_ASSETS] ['b'] [assetid] [amount of asset required] [origpubkey] - - // as we don't use tokenconvert we should not be here: - return eval->Invalid("invalid asset funcid (b)"); - - if( remaining_price == 0 ) - return eval->Invalid("illegal null amount for buyoffer"); - else if( ConstrainVout(tx.vout[0], 1, cpAssets->unspendableCCaddr,0) == 0 ) // coins to assets unspendable cc addr - return eval->Invalid("invalid vout for buyoffer"); - preventCCvins = 1; - preventCCvouts = 1; - fprintf(stderr,"buy offer validated to destaddr.(%s)\n",cpAssets->unspendableCCaddr); - break; - - case 'o': // cancelbuy - //vin.0: normal input - //vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] - //vin.2: CC marker from buyoffer for txfee - //vout.0: vin.1 value to original pubkey buyTx.vout[0].nValue -> [origpubkey] - //vout.1: vin.2 back to users pubkey - //vout.2: normal output for change (if any) - //vout.n-1: opreturn [EVAL_ASSETS] ['o'] - if( (nValue= AssetValidateBuyvin(cpAssets, eval, tmpprice, tmporigpubkey, origCCaddrDummy, origNormalAddr, tx, assetid)) == 0 ) - return(false); - else if( ConstrainVout(tx.vout[0],0, origNormalAddr, nValue) == 0 ) - return eval->Invalid("invalid refund for cancelbuy"); - preventCCvins = 3; - preventCCvouts = 0; - //fprintf(stderr,"cancelbuy validated to origaddr.(%s)\n",origNormalAddr); - break; - - case 'B': // fillbuy: - //vin.0: normal input - //vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] - //vin.2+: valid CC output satisfies buyoffer (*tx.vin[2])->nValue - //vout.0: remaining amount of bid to unspendable - //vout.1: vin.1 value to signer of vin.2 - //vout.2: vin.2 assetoshis to original pubkey - //vout.3: CC output for assetoshis change (if any) - //vout.4: normal output for change (if any) - //vout.n-1: opreturn [EVAL_ASSETS] ['B'] [assetid] [remaining asset required] [origpubkey] - preventCCvouts = 4; - - if( (nValue = AssetValidateBuyvin(cpAssets, eval, totalunits, tmporigpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 ) - return(false); - else if( numvouts < 4 ) - return eval->Invalid("not enough vouts for fillbuy"); - else if( tmporigpubkey != origpubkey ) - return eval->Invalid("mismatched origpubkeys for fillbuy"); - else - { - if( nValue != tx.vout[0].nValue + tx.vout[1].nValue ) - return eval->Invalid("locked value doesnt match vout0+1 fillbuy"); - else if( tx.vout[4].scriptPubKey.IsPayToCryptoCondition() != 0 ) // if cc change present - { - if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, 0) == 0 ) // tokens to originator cc addr (tokens+nonfungible evals) - return eval->Invalid("vout2 doesnt go to origpubkey fillbuy"); - else if ( inputs != tx.vout[2].nValue + tx.vout[4].nValue ) - return eval->Invalid("asset inputs doesnt match vout2+3 fillbuy"); - preventCCvouts ++; - } - else if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, inputs) == 0 ) // tokens to originator cc addr (tokens+nonfungible evals) - return eval->Invalid("vout2 doesnt match inputs fillbuy"); - else if( ConstrainVout(tx.vout[1], 0, NULL, 0) == 0 ) - return eval->Invalid("vout1 is CC for fillbuy"); - else if( ConstrainVout(tx.vout[3], 1, origAssetsCCaddr, 10000) == 0 ) // marker to asset cc addr - return eval->Invalid("invalid marker for original pubkey"); - else if( ValidateBidRemainder(remaining_price, tx.vout[0].nValue, nValue, tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false ) - return eval->Invalid("mismatched remainder for fillbuy"); - else if( remaining_price != 0 ) - { - if( ConstrainVout(tx.vout[0], 1, cpAssets->unspendableCCaddr, 0) == 0 ) // coins to asset unspendable cc addr - return eval->Invalid("mismatched vout0 AssetsCCaddr for fillbuy"); - } - } - //fprintf(stderr,"fillbuy validated\n"); - break; - //case 'e': // selloffer - // break; // disable swaps - case 's': // selloffer - //vin.0: normal input - //vin.1+: valid CC output for sale - //vout.0: vin.1 assetoshis output to CC to unspendable - //vout.1: CC output for marker - //vout.2: CC output for change (if any) - //vout.3: normal output for change (if any) - //'s'.vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey] - //'e'.vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey] - - // as we don't use tokenconvert we should not be here: - return eval->Invalid("invalid asset funcid (s)"); - - preventCCvouts = 2; - if( remaining_price == 0 ) - return eval->Invalid("illegal null remaining_price for selloffer"); - if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("invalid normal vout1 for sellvin"); - if( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 ) // if cc change presents - { - preventCCvouts++; - if( ConstrainVout(tx.vout[0], 1, (char *)cpTokens->unspendableCCaddr, 0) == 0 ) // tokens to tokens unspendable cc addr. TODO: this in incorrect, should be assets if we got here! - return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer"); - else if( tx.vout[0].nValue + tx.vout[2].nValue != inputs ) - return eval->Invalid("mismatched vout0+vout2 total for selloffer"); - } - // no cc change: - else if( ConstrainVout(tx.vout[0], 1, (char *)cpTokens->unspendableCCaddr, inputs) == 0 ) // tokens to tokens unspendable cc addr TODO: this in incorrect, should be assets if got here! - return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer"); - //fprintf(stderr,"remaining.%d for sell\n",(int32_t)remaining_price); - break; - - case 'x': // cancel sell - //vin.0: normal input - //vin.1: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx - //vin.2: CC marker from selloffer for txfee - //vout.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey] - //vout.1: vin.2 back to users pubkey - //vout.2: normal output for change (if any) - //vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid] - - if( (assetoshis = AssetValidateSellvin(cpAssets, eval, tmpprice, tmporigpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 ) // NOTE: - return(false); - else if( ConstrainVout(tx.vout[0], 1, origTokensCCaddr, assetoshis) == 0 ) // tokens returning to originator cc addr - return eval->Invalid("invalid vout for cancel"); - preventCCvins = 3; - preventCCvouts = 1; - break; - - case 'S': // fillsell - //vin.0: normal input - //vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0] - //'S'.vin.2+: normal output that satisfies selloffer (*tx.vin[2])->nValue - //vout.0: remaining assetoshis -> unspendable - //vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any - //'S'.vout.2: vin.2 value to original pubkey [origpubkey] - //vout.3: normal output for change (if any) - //'S'.vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey] - - if( (assetoshis = AssetValidateSellvin(cpAssets, eval, totalunits, tmporigpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 ) - return(false); - else if( numvouts < 4 ) - return eval->Invalid("not enough vouts for fillask"); - else if( tmporigpubkey != origpubkey ) - return eval->Invalid("mismatched origpubkeys for fillask"); - else - { - if( assetoshis != tx.vout[0].nValue + tx.vout[1].nValue ) - return eval->Invalid("locked value doesnt match vout0+1 fillask"); - if( ValidateAskRemainder(remaining_price, tx.vout[0].nValue, assetoshis, tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false ) - return eval->Invalid("mismatched remainder for fillask"); - else if( ConstrainVout(tx.vout[1], 1, NULL, 0) == 0 ) // do not check token buyer's cc addr - return eval->Invalid("normal vout1 for fillask"); - else if( ConstrainVout(tx.vout[2], 0, origNormalAddr, 0) == 0 ) // coins to originator normal addr - return eval->Invalid("normal vout1 for fillask"); - else if( ConstrainVout(tx.vout[3], 1, origAssetsCCaddr, 10000) == 0 ) // marker to originator asset cc addr - return eval->Invalid("invalid marker for original pubkey"); - else if( remaining_price != 0 ) - { - if ( ConstrainVout(tx.vout[0], 1, tokensDualEvalUnspendableCCaddr, 0) == 0 ) - return eval->Invalid("mismatched vout0 assets dual unspendable CCaddr for fill sell"); - } - } - //fprintf(stderr,"fill validated\n"); - break; - case 'E': // fillexchange - ////////// not implemented yet //////////// - return eval->Invalid("unexpected assets fillexchange funcid"); - break; // disable asset swaps - //vin.0: normal input - //vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0] - //vin.2+: valid CC assetid2 output that satisfies exchange (*tx.vin[2])->nValue - //vout.0: remaining assetoshis -> unspendable - //vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any - //vout.2: vin.2+ assetoshis2 to original pubkey [origpubkey] - //vout.3: CC output for asset2 change (if any) - //vout.3/4: normal output for change (if any) - //vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey] - - //if ( AssetExactAmounts(false, cp,inputs,outputs,eval,tx,assetid2) == false ) - // eval->Invalid("asset2 inputs != outputs"); - - ////////// not implemented yet //////////// - if( (assetoshis= AssetValidateSellvin(cpTokens, eval, totalunits, tmporigpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 ) - return(false); - else if( numvouts < 3 ) - return eval->Invalid("not enough vouts for fillex"); - else if( tmporigpubkey != origpubkey ) - return eval->Invalid("mismatched origpubkeys for fillex"); - else - { - if( assetoshis != tx.vout[0].nValue + tx.vout[1].nValue ) - return eval->Invalid("locked value doesnt match vout0+1 fillex"); - else if( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 ) - ////////// not implemented yet //////////// - { - if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, 0) == 0 ) - return eval->Invalid("vout2 doesnt go to origpubkey fillex"); - else if( inputs != tx.vout[2].nValue + tx.vout[3].nValue ) - { - fprintf(stderr,"inputs %.8f != %.8f + %.8f\n",(double)inputs/COIN,(double)tx.vout[2].nValue/COIN,(double)tx.vout[3].nValue/COIN); - return eval->Invalid("asset inputs doesnt match vout2+3 fillex"); - } - } - ////////// not implemented yet //////////// - else if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, inputs) == 0 ) - return eval->Invalid("vout2 doesnt match inputs fillex"); - else if( ConstrainVout(tx.vout[1], 0, 0, 0) == 0 ) - return eval->Invalid("vout1 is CC for fillex"); - fprintf(stderr,"assets vout0 %llu, vin1 %llu, vout2 %llu -> orig, vout1 %llu, total %llu\n",(long long)tx.vout[0].nValue,(long long)assetoshis,(long long)tx.vout[2].nValue,(long long)tx.vout[1].nValue,(long long)totalunits); - if( ValidateSwapRemainder(remaining_price, tx.vout[0].nValue, assetoshis,tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false ) - return eval->Invalid("mismatched remainder for fillex"); - else if( ConstrainVout(tx.vout[1], 1, 0, 0) == 0 ) - ////////// not implemented yet //////////// - return eval->Invalid("normal vout1 for fillex"); - else if( remaining_price != 0 ) - { - if( ConstrainVout(tx.vout[0], 1, (char *)cpAssets->unspendableCCaddr, 0) == 0 ) // TODO: unsure about this, but this is not impl yet anyway - return eval->Invalid("mismatched vout0 AssetsCCaddr for fillex"); - } - } - ////////// not implemented yet //////////// - //fprintf(stderr,"fill validated\n"); - break; - - default: - fprintf(stderr,"illegal assets funcid.(%c)\n",funcid); - return eval->Invalid("unexpected assets funcid"); - //break; - } - - // what does this do? - bool bPrevent = PreventCC(eval, tx, preventCCvins, numvins, preventCCvouts, numvouts); // seems we do not need this call as we already checked vouts well - //std::cerr << "AssetsValidate() PreventCC returned=" << bPrevent << std::endl; - return (bPrevent); -} - -}; diff --git a/src/cc/old/heir_v0.cpp b/src/cc/old/heir_v0.cpp deleted file mode 100644 index 6429c1a25b1..00000000000 --- a/src/cc/old/heir_v0.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - -// #include "CCHeir_v0.h" -#include "heir_validate_v0.h" -#include - -namespace heirv0 { - -// makes coin initial tx opret -vscript_t EncodeHeirCreateOpRet(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo) -{ - uint8_t evalcode = EVAL_HEIR; - - return E_MARSHAL(ss << evalcode << funcid << ownerPubkey << heirPubkey << inactivityTimeSec << heirName << memo); -} - -// makes coin additional tx opret -vscript_t EncodeHeirOpRet(uint8_t funcid, uint256 fundingtxid, uint8_t hasHeirSpendingBegun) -{ - uint8_t evalcode = EVAL_HEIR; - - fundingtxid = revuint256(fundingtxid); - return E_MARSHAL(ss << evalcode << funcid << fundingtxid << hasHeirSpendingBegun); -} - - -// decode opret vout for Heir contract -uint8_t _DecodeHeirOpRet(vscript_t vopret, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging) -{ - uint8_t evalCodeInOpret = 0; - uint8_t heirFuncId = 0; - - fundingTxidInOpret = zeroid; //to init - - evalCodeInOpret = vopret.begin()[0]; - - if (vopret.size() > 1 && evalCodeInOpret == EVAL_HEIR) { - // NOTE: it unmarshals for all F, A and C - uint8_t heirFuncId = 0; - hasHeirSpendingBegun = 0; - - bool result = E_UNMARSHAL(vopret, { ss >> evalCodeInOpret; ss >> heirFuncId; - if (heirFuncId == 'F') { - ss >> ownerPubkey; ss >> heirPubkey; ss >> inactivityTime; ss >> heirName; ss >> memo; - } - else { - ss >> fundingTxidInOpret >> hasHeirSpendingBegun; - } - }); - - if (!result) { - // if (!noLogging) std::cerr << "_DecodeHeirOpRet() could not unmarshal opret, evalCode=" << (int)evalCodeInOpret << std::endl; - return (uint8_t)0; - } - - if (isMyFuncId(heirFuncId)) { - fundingTxidInOpret = revuint256(fundingTxidInOpret); - return heirFuncId; - } - else { - if(!noLogging) std::cerr << "_DecodeHeirOpRet() unexpected opret type, heirFuncId=" << (char)(heirFuncId ? heirFuncId : ' ') << std::endl; - } - } - else { - if (!noLogging) std::cerr << "_DecodeHeirOpRet() not a heir opret, vopretExtra.size() == 0 or not EVAL_HEIR evalcode=" << (int)evalCodeInOpret << std::endl; - } - return (uint8_t)0; -} - -// decode combined opret: -uint8_t _DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging) -{ - uint8_t evalCodeTokens = 0; - std::vector voutPubkeysDummy; - std::vector oprets; - vscript_t vopretExtra /*, vopretStripped*/; - - - if (DecodeTokenOpRetV1(scriptPubKey, tokenid, voutPubkeysDummy, oprets) != 0 && GetOpReturnCCBlob(oprets, vopretExtra)) { - if (vopretExtra.size() < 1) { - if (!noLogging) std::cerr << "_DecodeHeirEitherOpret() empty vopretExtra" << std::endl; - return (uint8_t)0; - } - } - else { - GetOpReturnData(scriptPubKey, vopretExtra); - } - - return _DecodeHeirOpRet(vopretExtra, ownerPubkey, heirPubkey, inactivityTime, heirName, memo, fundingTxidInOpret, hasHeirSpendingBegun, noLogging); -} - -// overload to decode opret in fundingtxid: -uint8_t DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, bool noLogging) { - uint256 dummyFundingTxidInOpret; - uint8_t dummyHasHeirSpendingBegun; - - return _DecodeHeirEitherOpRet(scriptPubKey, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, memo, dummyFundingTxidInOpret, dummyHasHeirSpendingBegun, noLogging); -} - -// overload to decode opret in A and C heir tx: -uint8_t DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, uint256 &fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging) { - CPubKey dummyOwnerPubkey, dummyHeirPubkey; - int64_t dummyInactivityTime; - std::string dummyHeirName, dummyMemo; - - return _DecodeHeirEitherOpRet(scriptPubKey, tokenid, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, dummyMemo, fundingTxidInOpret, hasHeirSpendingBegun, noLogging); -} - -// check if pubkey is in vins -void CheckVinPubkey(std::vector vins, CPubKey pubkey, bool &hasPubkey, bool &hasOtherPubkey) { - - hasPubkey = false; - hasOtherPubkey = false; - - for (auto vin : vins) { - CPubKey vinPubkey = check_signing_pubkey(vin.scriptSig); - if (vinPubkey.IsValid()) { - if (vinPubkey == pubkey) - hasPubkey = true; - if (vinPubkey != pubkey) - hasOtherPubkey = true; - } - } -} - -/** - * find the latest funding tx: it may be the first F tx or one of A or C tx's - * Note: this function is also called from validation code (use non-locking calls) - */ -uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, CScript& fundingOpretScript, uint8_t &hasHeirSpendingBegun) -{ - CTransaction fundingtx; - uint256 hashBlock; - const bool allowSlow = false; - - hasHeirSpendingBegun = 0; - funcId = 0; - - // get initial funding tx and set it as initial lasttx: - if (myGetTransaction(fundingtxid, fundingtx, hashBlock) && fundingtx.vout.size()) { - - CScript heirScript = (fundingtx.vout.size() > 0) ? fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey : CScript(); - uint8_t funcId = DecodeHeirEitherOpRet(heirScript, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, memo, true); - if (funcId != 0) { - // found at least funding tx! - //std::cerr << "FindLatestFundingTx() lasttx currently is fundingtx, txid=" << fundingtxid.GetHex() << " opreturn type=" << (char)funcId << '\n'; - fundingOpretScript = fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey; - } else { - std::cerr << "FindLatestFundingTx() could not decode opreturn for fundingtxid=" << fundingtxid.GetHex() << '\n'; - return zeroid; - } - } else { - std::cerr << "FindLatestFundingTx() could not find funding tx for fundingtxid=" << fundingtxid.GetHex() << '\n'; - return zeroid; - } - - // TODO: correct cc addr: - std::vector> unspentOutputs; - struct CCcontract_info *cp, C; - cp = CCinit(&C, EVAL_HEIR); - char coinaddr[64]; - GetCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey); // get the address of cryptocondition '1 of 2 pubkeys' - - SetCCunspents(unspentOutputs, coinaddr,true); // get vector with tx's with unspent vouts of 1of2pubkey address: - //std::cerr << "FindLatestFundingTx() using 1of2address=" << coinaddr << " unspentOutputs.size()=" << unspentOutputs.size() << '\n'; - - int32_t maxBlockHeight = 0; // max block height - uint256 latesttxid = fundingtxid; - - // try to find the last funding or spending tx by checking fundingtxid in 'opreturn': - for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { - CTransaction regtx; - uint256 hash; - - uint256 txid = it->first.txhash; - //std::cerr << "FindLatestFundingTx() checking unspents for txid=" << txid.GetHex() << '\n'; - - int32_t blockHeight = (int32_t)it->second.blockHeight; - - //NOTE: maybe called from validation code: - if (myGetTransaction(txid, regtx, hash)) { - //std::cerr << "FindLatestFundingTx() found tx for txid=" << txid.GetHex() << " blockHeight=" << blockHeight << " maxBlockHeight=" << maxBlockHeight << '\n'; - uint256 fundingTxidInOpret; - uint256 tokenidInOpret; // not to contaminate the tokenid from the params! - uint8_t tmpFuncId; - uint8_t hasHeirSpendingBegunInOpret; - - CScript heirScript = (regtx.vout.size() > 0) ? regtx.vout[regtx.vout.size() - 1].scriptPubKey : CScript(); - tmpFuncId = DecodeHeirEitherOpRet(heirScript, tokenidInOpret, fundingTxidInOpret, hasHeirSpendingBegunInOpret, true); - if (tmpFuncId != 0 && fundingtxid == fundingTxidInOpret && (tokenid == zeroid || tokenid == tokenidInOpret)) { // check tokenid also - - if (blockHeight > maxBlockHeight) { - - // check owner pubkey in vins - bool isOwner = false; - bool isNonOwner = false; - - CheckVinPubkey(regtx.vin, ownerPubkey, isOwner, isNonOwner); - - // we ignore 'donations' tx (with non-owner inputs) for calculating if heir is allowed to spend: - if (isOwner && !isNonOwner) { - hasHeirSpendingBegun = hasHeirSpendingBegunInOpret; - maxBlockHeight = blockHeight; - latesttxid = txid; - funcId = tmpFuncId; - } - - //std::cerr << "FindLatestFundingTx() txid=" << latesttxid.GetHex() << " at blockHeight=" << maxBlockHeight - // << " opreturn type=" << (char)(funcId ? funcId : ' ') << " hasHeirSpendingBegun=" << (int)hasHeirSpendingBegun << " - set as current lasttxid" << '\n'; - } - } - } - } - - return latesttxid; -} - -}; \ No newline at end of file diff --git a/src/cc/old/heir_validate_v0.h b/src/cc/old/heir_validate_v0.h deleted file mode 100644 index 45939889f76..00000000000 --- a/src/cc/old/heir_validate_v0.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef HEIR_VALIDATE_V0_H -#define HEIR_VALIDATE_V0_H - -#include "../CCinclude.h" -//#include "CCHeir_v0.h" - -namespace heirv0 { - -#define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos) - -// makes coin initial tx opret -vscript_t EncodeHeirCreateOpRet(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo); -vscript_t EncodeHeirOpRet(uint8_t funcid, uint256 fundingtxid, uint8_t isHeirSpendingBegan); - -uint256 FindLatestFundingTx(uint256 fundingtxid, uint256 &tokenid, CScript& opRetScript, uint8_t &isHeirSpendingBegan); -uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, CScript& fundingOpretScript, uint8_t &hasHeirSpendingBegun); - -uint8_t DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, bool noLogging = false); -uint8_t DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, uint256 &fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging = false); -uint8_t _DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging); - -inline static bool isMyFuncId(uint8_t funcid) { return IS_CHARINSTR(funcid, "FAC"); } -inline static bool isSpendingTx(uint8_t funcid) { return (funcid == 'C'); } - -}; - -#endif diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index f1e8fcad1a6..a84be01229c 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -363,10 +363,6 @@ UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const if (vopretNonfungible.empty()) throw runtime_error("No non-fungible token data\n"); */ - uint8_t destEvalCode = EVAL_TOKENS; - if (!vopretNonfungible.empty()) - destEvalCode = vopretNonfungible.begin()[0]; - // check non-fungible tokens amount if (!vopretNonfungible.empty() && burnAmount != 1) throw JSONRPCError(RPC_TYPE_ERROR, "For non-fungible tokens amount should be equal to 1."); @@ -386,7 +382,7 @@ UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const // make payouts (which will be in the import tx with token): mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, txfee, GetUnspendable(cpTokens, NULL))); // new marker to token cc addr, burnable and validated, vout position now changed to 0 (from 1) - mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, burnAmount, destPubKey)); + mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, burnAmount, destPubKey)); std::vector opretsnft; if (!vopretNonfungible.empty()) @@ -401,7 +397,7 @@ UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const mtx.vout.clear(); // remove payouts // now make burn transaction: - mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, burnAmount, pubkey2pk(ParseHex(CC_BURNPUBKEY)))); // burn tokens + mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, burnAmount, pubkey2pk(ParseHex(CC_BURNPUBKEY)))); // burn tokens int64_t change = inputs - txfee; if (change != 0) @@ -412,7 +408,7 @@ UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const int64_t ccChange = ccInputs - burnAmount; if (ccChange != 0) - mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, ccChange, myPubKey)); + mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, ccChange, myPubKey)); GetOpReturnData(burnOut.scriptPubKey, vopretBurnData); mtx.vout.push_back(CTxOut(txfee, EncodeTokenOpRetV1(tokenid, voutTokenPubkeys, { vopretBurnData }))); //burn txfee for miners in dest chain @@ -1413,16 +1409,10 @@ UniValue getwalletburntransactions(const UniValue& params, bool fHelp, const CPu if (tokenbasetx.vout.size() > 0 && DecodeTokenCreateOpRetV1(tokenbasetx.vout.back().scriptPubKey, vorigpubkey, name, description, oprets) == 'c') { - uint8_t destEvalCode = EVAL_TOKENS; // init set to fungible token: - vscript_t vopretNonfungible; - GetOpReturnCCBlob(oprets, vopretNonfungible); - if (!vopretNonfungible.empty()) - destEvalCode = vopretNonfungible.begin()[0]; - int64_t burnAmount = 0; for (auto v : pwtx->vout) if (v.scriptPubKey.IsPayToCryptoCondition() && - CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(destEvalCode ? destEvalCode : EVAL_TOKENS, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY)))) // burned to dead pubkey + CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(EVAL_TOKENS, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY)))) // burned to dead pubkey burnAmount += v.nValue; entry.push_back(Pair("burnedAmount", ValueFromAmount(burnAmount))); diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 1a8596270b6..e3a22ebcf77 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -166,13 +166,12 @@ template UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& mypk) { uint256 tokenid; - uint8_t evalcodeAdd = 0; const CPubKey emptypk; - if ( fHelp || params.size() > 2 ) - throw runtime_error(name + " [tokenid|'*'] [evalcode]\n" + if ( fHelp || params.size() > 1 ) + throw runtime_error(name + " [tokenid|'*']\n" "returns token orders for the tokenid or all available token orders if tokenid is not set\n" - "returns also NFT ask orders if NFT evalcode is set\n" "\n"); + "\n"); if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (params.size() >= 1) @@ -184,13 +183,7 @@ UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp throw runtime_error("incorrect tokenid\n"); } } - if (params.size() == 2) - evalcodeAdd = strtol(params[1].get_str().c_str(), NULL, 0); // supports also 0xEE-like values - - if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - return AssetOrders(tokenid, emptypk, evalcodeAdd); - else - return tokensv0::AssetOrders(tokenid, emptypk, evalcodeAdd); + return AssetOrders(tokenid, emptypk); } UniValue tokenorders(const UniValue& params, bool fHelp, const CPubKey& remotepk) @@ -213,16 +206,11 @@ UniValue mytokenorders(const std::string& name, const UniValue& params, bool fHe /*"if evalcode is set then returns mypubkey's token orders for non-fungible tokens with this evalcode\n"*/ "\n"); if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - //uint8_t evalcodeAdd = 0; - //if (params.size() == 1) - // evalcodeAdd = strtol(params[0].get_str().c_str(), NULL, 0); // supports also 0xEE-like values - + + CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); - if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - return AssetOrders(zeroid, mypk, 0); - else - return tokensv0::AssetOrders(zeroid, Mypubkey(), 0); + return AssetOrders(zeroid, mypk); } UniValue mytokenorders(const UniValue& params, bool fHelp, const CPubKey& remotepk) @@ -387,7 +375,7 @@ UniValue tokencreatetokel(const UniValue& params, bool fHelp, const CPubKey& rem tokenData = ParseTokelJson(jsonParams); if (tokenData.empty()) - return MakeResultError("Tokel token data incorrect"); + throw runtime_error("Tokel token data incorrect"); } return tokencreate(params, tokenData, fHelp, remotepk); @@ -595,20 +583,13 @@ UniValue tokentransfermany(const std::string& name, const UniValue& params, bool for (const auto &tokenid : tokenids) { - TokenDataTuple tokenData; - vuint8_t vtokenData; - GetTokenData(NULL, tokenid, tokenData, vtokenData); CCwrapper probeCond; - if (vtokenData.size() > 0) - probeCond.reset( V::MakeTokensCCcond1(vtokenData[0], mypk) ); - else - probeCond.reset( MakeCCcond1(V::EvalCode(), mypk) ); + probeCond.reset( MakeCCcond1(V::EvalCode(), mypk) ); uint8_t mypriv[32]; Myprivkey(mypriv); char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; - cpTokens->evalcodeAdd = vtokenData.size() > 0 ? vtokenData[0] : 0; GetTokensCCaddress(cpTokens, tokenaddr, mypk, V::IsMixed()); UniValue addtxResult = TokenAddTransferVout(mtx, cpTokens, remotepk, tokenid, tokenaddr, { destpk }, {probeCond, mypriv}, amount, false); @@ -711,15 +692,7 @@ UniValue tokenbid(const std::string& name, const UniValue& params, bool fHelp, c CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); - if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - result = CreateBuyOffer(mypk, 0, bidamount, tokenid, numtokens, expiryHeight); - else { - hex = tokensv0::CreateBuyOffer(0, bidamount, tokenid, numtokens); - if (!hex.empty()) - result = MakeResultSuccess(hex); - else - result = MakeResultError("could not create bid"); - } + result = CreateBuyOffer(mypk, 0, bidamount, tokenid, numtokens, expiryHeight); RETURN_IF_ERROR(CCerror); return result; } @@ -755,15 +728,7 @@ UniValue tokencancelbid(const std::string& name, const UniValue& params, bool fH CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); - if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - result = CancelBuyOffer(mypk, 0,tokenid,bidtxid); - else { - hex = tokensv0::CancelBuyOffer(0,tokenid,bidtxid); - if (!hex.empty()) - result = MakeResultSuccess(hex); - else - result = MakeResultError("could not cancel bid"); - } + result = CancelBuyOffer(mypk, 0,tokenid,bidtxid); RETURN_IF_ERROR(CCerror); return result; } @@ -811,15 +776,7 @@ UniValue tokenfillbid(const std::string& name, const UniValue& params, bool fHel CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); - if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - result = FillBuyOffer(mypk, 0, tokenid, bidtxid, fillamount, unit_price); - else { - hex = tokensv0::FillBuyOffer(0, tokenid, bidtxid, fillamount); - if (!hex.empty()) - result = MakeResultSuccess(hex); - else - result = MakeResultError("could not fill bid"); - } + result = FillBuyOffer(mypk, 0, tokenid, bidtxid, fillamount, unit_price); RETURN_IF_ERROR(CCerror); return result; } @@ -873,16 +830,7 @@ UniValue tokenask(const std::string& name, const UniValue& params, bool fHelp, c CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); - - if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - result = CreateSell(mypk, 0, numtokens, tokenid, askamount, expiryHeight); - else { - hex = tokensv0::CreateSell(0, numtokens, tokenid, askamount); - if (!hex.empty()) - result = MakeResultSuccess(hex); - else - result = MakeResultError("could not create ask"); - } + result = CreateSell(mypk, 0, numtokens, tokenid, askamount, expiryHeight); RETURN_IF_ERROR(CCerror); return result; } @@ -958,15 +906,7 @@ UniValue tokencancelask(const std::string& name, const UniValue& params, bool fH CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); - if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - result = CancelSell(mypk, 0, tokenid, asktxid); - else { - hex = tokensv0::CancelSell(0, tokenid, asktxid); - if (!hex.empty()) - result = MakeResultSuccess(hex); - else - result = MakeResultError("could not cancel ask"); - } + result = CancelSell(mypk, 0, tokenid, asktxid); RETURN_IF_ERROR(CCerror); return(result); } @@ -1010,15 +950,7 @@ UniValue tokenfillask(const std::string& name, const UniValue& params, bool fHel CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); - if (A::EvalCode() == EVAL_ASSETSV2 || TokensIsVer1Active(NULL)) - result = FillSell(mypk, 0, tokenid, asktxid, fillunits, unit_price); - else { - hex = tokensv0::FillSell(0, tokenid, zeroid, asktxid, fillunits); - if (!hex.empty()) - result = MakeResultSuccess(hex); - else - result = MakeResultError("could not fill ask"); - } + result = FillSell(mypk, 0, tokenid, asktxid, fillunits, unit_price); RETURN_IF_ERROR(CCerror); return result; } diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 7aee2b941bd..e35fc0569ad 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -273,8 +273,8 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ std::cerr << __func__ << " vini." << i << " found myccaddr=" << myccaddr << std::endl; } else if (strcmp(destaddr, mytokenaddr) == 0) { privkey = myprivkey; - cond.reset(MakeTokensv2CCcond1(cp->evalcode, cp->evalcodeAdd, mypk)); - std::cerr << __func__ << " vini." << i << " found mytokenaddr=" << mytokenaddr << " evalcode=" << (int)cp->evalcode << " evalcodeAdd=" << (int)cp->evalcodeAdd << std::endl; + cond.reset(MakeTokensv2CCcond1(cp->evalcode, mypk)); + std::cerr << __func__ << " vini." << i << " found mytokenaddr=" << mytokenaddr << " evalcode=" << (int)cp->evalcode << std::endl; } else { const uint8_t nullpriv[32] = {'\0'}; // use vector of dest addresses and conds to probe vintxconds @@ -499,15 +499,12 @@ class TestAssetsCC : public ::testing::Test { TokenDataTuple tokenData; vuint8_t vextraData; - uint8_t evalcodeAdd = 0; int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { std::cerr << __func__ << " cant get tokendata" << std::endl; return CTransaction(); } - if (vextraData.size() > 0) { - evalcodeAdd = vextraData[0]; - } + CAmount inputs = TestAddTokenInputs(mtx, mypk, tokenid, numtokens); if (inputs == 0) { @@ -516,16 +513,16 @@ class TestAssetsCC : public ::testing::Test { } CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens, unspendableAssetsPubkey)); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), numtokens, unspendableAssetsPubkey)); mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); CAmount CCchange = inputs - numtokens; if (CCchange != 0LL) { // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), CCchange, mypk)); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), CCchange, mypk)); } // cond to spend NFT from mypk - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(evalcodeAdd, mypk)); + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), mypk)); CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey // sign vins: @@ -592,14 +589,12 @@ class TestAssetsCC : public ::testing::Test { TokenDataTuple tokenData; vuint8_t vextraData; - uint8_t evalcodeAdd = 0; int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { std::cerr << __func__ << " cant get tokendata" << std::endl; return CTransaction(); } if (vextraData.size() > 0) { - evalcodeAdd = vextraData[0]; GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); if (royaltyFract > TKLROYALTY_DIVISOR-1) royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit @@ -625,10 +620,10 @@ class TestAssetsCC : public ::testing::Test { mtx.vin.push_back(CTxIn(asktx.GetHash(), askvout, CScript())); // spend order tx // vout.0 tokens remainder to unspendable cc addr: - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, orig_assetoshis - fill_units, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), orig_assetoshis - fill_units, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), fill_units, mypk)); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, mypk)); mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr if (royaltyValue > 0) // note it makes the vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner @@ -639,7 +634,7 @@ class TestAssetsCC : public ::testing::Test { uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - CCwrapper wrCond1(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), evalcodeAdd, unspendableAssetsPk)); + CCwrapper wrCond1(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond1, unspendableAssetsPrivkey); // probe to spend marker @@ -689,14 +684,12 @@ class TestAssetsCC : public ::testing::Test { TokenDataTuple tokenData; vuint8_t vextraData; - uint8_t evalcodeAdd = 0; int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { std::cerr << __func__ << " cant get token data" << std::endl; return CTransaction(); } if (vextraData.size() > 0) { - evalcodeAdd = vextraData.begin()[0]; GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); if (royaltyFract > TKLROYALTY_DIVISOR-1) royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit @@ -758,19 +751,19 @@ class TestAssetsCC : public ::testing::Test { mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to mypk normal if (royaltyValue > 0) // note it makes vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator if (orig_units - fill_units > 0) // order is not finished yet mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(origpubkey), unspendableAssetsPk)); // vout3(4 if royalty) marker to origpubkey if (tokensChange != 0LL) - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(evalcodeAdd ? evalcodeAdd : TokensV2::EvalCode(), tokensChange, mypk)); // change in single-eval tokens + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), tokensChange, mypk)); // change in single-eval tokens CMutableTransaction mtx2(mtx); // copy CCwrapper wrCond1(MakeCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); // spend coins CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); - CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(evalcodeAdd, mypk)); // spend my tokens to fill buy + CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), mypk)); // spend my tokens to fill buy CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey // probe to spend marker @@ -810,9 +803,6 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " could not load token data" << std::endl; return CTransaction(); } - uint8_t evalcodeAdd = 0; - if (vextraData.size() > 0) - evalcodeAdd = vextraData[0]; vuint8_t ownerpubkey = std::get<0>(tokenData); if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { @@ -836,13 +826,13 @@ class TestAssetsCC : public ::testing::Test { return CTransaction(); } - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(cpAssets->evalcodeAdd ? cpAssets->evalcodeAdd : TokensV2::EvalCode(), askamount, origpubkey)); // one-eval token vout + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), askamount, origpubkey)); // one-eval token vout // init assets 'unspendable' privkey and pubkey uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), cpAssets->evalcodeAdd, unspendableAssetsPk)); + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // probe to spend marker @@ -890,9 +880,6 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " could not load token data" << std::endl; return CTransaction(); } - uint8_t evalcodeAdd = 0; - if (vextraData.size() > 0) - evalcodeAdd = vextraData[0]; vuint8_t ownerpubkey = std::get<0>(tokenData); if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { @@ -963,7 +950,6 @@ TEST_F(TestAssetsCC, tokenv2ask) CAmount numtokens = 2LL; CPubKey mypk = pk1; uint256 mytokenid = tokenid1; - uint8_t evalcodeAdd = 0; struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! @@ -1020,7 +1006,7 @@ TEST_F(TestAssetsCC, tokenv2ask) { // test: send to non-global assets destination CMutableTransaction mtx1(mtx); - mtx1.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens, pkunused); + mtx1.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), numtokens, pkunused); mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, @@ -1031,8 +1017,8 @@ TEST_F(TestAssetsCC, tokenv2ask) // test: add extra global addr vout CMutableTransaction mtx1(mtx); // add two vouts with numtokens/2 (to have token balance correct). Assets cc should fail however: - mtx1.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens/2, unspendableAssetsPubkey); - mtx1.vout.insert(mtx1.vout.begin(), TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens/2, unspendableAssetsPubkey)); + mtx1.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), numtokens/2, unspendableAssetsPubkey); + mtx1.vout.insert(mtx1.vout.begin(), TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), numtokens/2, unspendableAssetsPubkey)); mtx1.vout.pop_back(); // remove old opreturn ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, @@ -1043,8 +1029,8 @@ TEST_F(TestAssetsCC, tokenv2ask) // test: add extra global addr null vout CMutableTransaction mtx1(mtx); // add two vouts with numtokens/2 (to have token balance correct). Assets cc should fail however: - mtx1.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, numtokens, unspendableAssetsPubkey); - mtx1.vout.insert(mtx1.vout.begin(), TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), evalcodeAdd, 0, unspendableAssetsPubkey)); + mtx1.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), numtokens, unspendableAssetsPubkey); + mtx1.vout.insert(mtx1.vout.begin(), TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), 0, unspendableAssetsPubkey)); mtx1.vout.pop_back(); // remove old opreturn ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, @@ -1358,7 +1344,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask) { // test: invalid pk where to funds sent CMutableTransaction mtx4(mtx); - mtx4.vout[0] = TokensV2::MakeTokensCC1vout(cpAssets->evalcodeAdd ? cpAssets->evalcodeAdd : TokensV2::EvalCode(), askamount, pk2); + mtx4.vout[0] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), askamount, pk2); EXPECT_FALSE(TestRunCCEval(mtx4)); // must fail } { From db54dfaf352413df3e3ecd8e986a98a7168bd707 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 21 Jul 2021 21:00:58 +0500 Subject: [PATCH 064/348] fixed tokens setting eval state error --- src/cc/CCtokens.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 7ced57f5c27..e8f4b4ee7f3 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -580,7 +580,7 @@ CAmount TokensV2::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const // call extra data validators for (auto const &vd : vdatas) if (vd.size() > 0 && vd[0] != 0) - if (!SubcallCCValidate(eval, vd[0], tx, 0)) + if (!SubcallCCValidate(eval, vd[0], tx, 0)) return -1; // set returned tokend to tokenbase txid: @@ -681,7 +681,7 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction & if (!TokensExactAmounts(true, cp, eval, tx, errorStr)) { LOGSTREAMFN(cctokens_log, CCLOG_ERROR, stream << "validation error: " << errorStr << " tx=" << HexStr(E_MARSHAL(ss << tx)) << std::endl); - if (eval->state.IsInvalid()) + if (!eval->state.IsValid()) return false; //TokenExactAmounts has already called eval->Invalid() else return eval->Invalid(errorStr); @@ -692,7 +692,7 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction & static bool report_validation_error(const std::string &func, Eval* eval, const CTransaction &tx, const std::string &errorStr) { LOGSTREAM(cctokens_log, CCLOG_ERROR, stream << func << " validation error: " << errorStr << " tx=" << HexStr(E_MARSHAL(ss << tx)) << std::endl); - return eval->Invalid(errorStr); + return !eval->state.IsValid() ? false/*error state already set*/ : eval->Invalid(errorStr) /* set error state and exit*/; } // checking creation txns is available with cryptocondition v2 mixed mode From 691be934c12501179c78d5bb4e0a1e01eece6acd Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 21 Jul 2021 22:34:10 +0500 Subject: [PATCH 065/348] added json param with filtering params to tokenv2list --- src/cc/CCtokens.cpp | 36 ++++++++++++++++++++++++++++++------ src/cc/CCtokens.h | 2 +- src/rpc/tokensrpc.cpp | 36 ++++++++++++++++++++++++++---------- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index e8f4b4ee7f3..8272d07b51c 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -858,23 +858,47 @@ UniValue TokenList() return CreateTokenLocal(txfee, tokensupply, name, description, nonfungibleData); }*/ -UniValue TokenV2List(int32_t beginHeight, int32_t endHeight) +UniValue TokenV2List(const UniValue ¶ms) { UniValue result(UniValue::VARR); const bool CC_OUTPUTS_TRUE = true; + int32_t beginHeight = 0; + int32_t endHeight = 0; + CPubKey checkPK; + std::string checkAddr; + if (params.exists("beginHeight")) + beginHeight = atoi(params["beginHeight"].getValStr().c_str()); + if (params.exists("endHeight")) + endHeight = atoi(params["endHeight"].getValStr().c_str()); + if (params.exists("pubkey")) + checkPK = pubkey2pk(ParseHex(params["pubkey"].getValStr().c_str())); + if (params.exists("address")) + checkAddr = params["address"].getValStr(); + struct CCcontract_info *cp, C; cp = CCinit(&C, EVAL_TOKENSV2); auto addTokenId = [&](uint256 tokenid, const CScript &opreturn) { - std::vector origpubkey; + vscript_t origpubkey; std::string name, description; std::vector oprets; if (IsTxidInActiveChain(tokenid)) { if (DecodeTokenCreateOpRetV2(opreturn, origpubkey, name, description, oprets) != 0) { - result.push_back(tokenid.GetHex()); + if (checkPK.IsValid()) { + if (checkPK == pubkey2pk(origpubkey)) + result.push_back(tokenid.GetHex()); + } + else if (!checkAddr.empty()) { + char origaddr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(origaddr, TokensV2::MakeCC1vout(EVAL_TOKENSV2, 0LL, pubkey2pk(origpubkey)).scriptPubKey); + if (checkAddr == origaddr) + result.push_back(tokenid.GetHex()); + } + else + result.push_back(tokenid.GetHex()); } else { LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "DecodeTokenCreateOpRetV2 failed for tokenid=" << tokenid.GetHex() << " opreturn.size=" << opreturn.size() << std::endl); @@ -882,13 +906,13 @@ UniValue TokenV2List(int32_t beginHeight, int32_t endHeight) } }; - if (beginHeight > 0) { + if (beginHeight > 0 || endHeight > 0) { if (endHeight <= 0) endHeight = chainActive.Height(); std::vector> addressIndexOutputs; SetAddressIndexOutputs(addressIndexOutputs, cp->unspendableCCaddr, CC_OUTPUTS_TRUE, beginHeight, endHeight); LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetAddressIndexOutputs addressIndexOutputs.size()=" << addressIndexOutputs.size() << std::endl); - for (const auto it : addressIndexOutputs) { + for (const auto &it : addressIndexOutputs) { CTransaction creationtx; uint256 hashBlock; if (!it.first.spending && @@ -920,7 +944,7 @@ UniValue TokenV2List(int32_t beginHeight, int32_t endHeight) SetCCunspents(unspentOutputs, cp->unspendableCCaddr, CC_OUTPUTS_TRUE); LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); - for (const auto it : unspentOutputs) { + for (const auto &it : unspentOutputs) { CTransaction creationtx; uint256 hashBlock; if (myGetTransaction(it.first.txhash, creationtx, hashBlock) && creationtx.vout.size() > 0) diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index 56400852c64..60acdbb4eac 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -273,7 +273,7 @@ CTxOut MakeTokensCC1of2voutMixed(uint8_t evalcode, uint8_t evalcode2, CAmount nV CTxOut MakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, uint8_t M, const std::vector & pks, vscript_t* pvData = nullptr); UniValue TokenList(); -UniValue TokenV2List(int32_t beginHeight, int32_t endHeight); +UniValue TokenV2List(const UniValue ¶ms); inline bool IsTokenCreateFuncid(uint8_t funcid) { return funcid == 'c'; } inline bool IsTokenTransferFuncid(uint8_t funcid) { return funcid == 't'; } diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index e3a22ebcf77..fcd36b8a274 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -105,19 +105,35 @@ UniValue tokenlist(const UniValue& params, bool fHelp, const CPubKey& remotepk) UniValue tokenv2list(const UniValue& params, bool fHelp, const CPubKey& remotepk) { uint256 tokenid; - if (fHelp || params.size() > 2) - throw runtime_error("tokenv2list [begin-height] [end-height]\n"); + const static std::set acceptable = { "beginHeight", "endHeight", "pubkey", "address" }; + + if (fHelp || params.size() > 1) + throw runtime_error("tokenv2list [json-params]\n" + "json-params optional params as a json object, limiting tokenv2list output:\n" + " { \"beginHeight\": number \"endHeight\": number, \"pubkey\": hexstring, \"address\": string }\n" + " \"beginHeight\", \"endHeight\" - height interval where to search tokenv2create transactions, if beginHeight omitted the first block used, if endHeight omitted the chain tip used" + " \"pubkey\" - search tokens created by a specific pubkey\n" + " \"address\" - search created on a specific cc address\n"); if (ensure_CCrequirements(EVAL_TOKENSV2) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - int32_t beginHeight = 0; - int32_t endHeight = 0; - if (params.size() > 0) - beginHeight = atoi(params[0].get_str().c_str()); - if (params.size() > 1) - endHeight = atoi(params[1].get_str().c_str()); - return TokenV2List(beginHeight, endHeight); + UniValue jsonParams; + if (params.size() == 1) + { + if (params[0].getType() == UniValue::VOBJ) + jsonParams = params[0].get_array(); + else if (params[0].getType() == UniValue::VSTR) // json in quoted string '{...}' + jsonParams.read(params[0].get_str().c_str()); + if (jsonParams.getType() != UniValue::VOBJ) + throw runtime_error("parameter 1 must be a json object"); + + // check unused params: + for (int i = 0; i < jsonParams.getKeys().size(); i ++) + if (acceptable.count(jsonParams.getKeys()[i]) == 0) + throw runtime_error(std::string("invalid json param") + jsonParams.getKeys()[i]); + } + return TokenV2List(jsonParams); } template @@ -170,7 +186,7 @@ UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp if ( fHelp || params.size() > 1 ) throw runtime_error(name + " [tokenid|'*']\n" - "returns token orders for the tokenid or all available token orders if tokenid is not set\n" + "returns tokens orders for the tokenid or all available token orders if tokenid is not set\n" "\n"); if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); From 24885e7bf7a92a25a06540a190ebb665385a966f Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 22 Jul 2021 11:30:54 +0500 Subject: [PATCH 066/348] set default expiry height 4 weeks --- src/rpc/tokensrpc.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index fcd36b8a274..c56f00dd2ac 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -698,7 +698,11 @@ UniValue tokenbid(const std::string& name, const UniValue& params, bool fHelp, c if (bidamount <= 0) return MakeResultError("bid amount must be positive"); - int32_t expiryHeight = std::numeric_limits::max(); + int32_t expiryHeight; + { + LOCK(cs_main); + expiryHeight = chainActive.Height() + 4 * 7 * 24 * 60; // 2 weeks for blocktime 60 sec + } if (params.size() == 4) { expiryHeight = atol(params[3].get_str().c_str()); if (!remotepk.IsValid() && expiryHeight < chainActive.LastTip()->GetHeight()) @@ -837,7 +841,11 @@ UniValue tokenask(const std::string& name, const UniValue& params, bool fHelp, c if (askamount <= 0) return MakeResultError("askamount invalid"); - int32_t expiryHeight = std::numeric_limits::max(); + int32_t expiryHeight; + { + LOCK(cs_main); + expiryHeight = chainActive.Height() + 4 * 7 * 24 * 60; // 2 weeks for blocktime 60 sec + } if (params.size() == 4) { expiryHeight = atol(params[3].get_str().c_str()); if (!remotepk.IsValid() && expiryHeight < chainActive.LastTip()->GetHeight()) From bd4cd8ab5bbe9d9b0bf5be148c4baeb16eaecd67 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 22 Jul 2021 11:31:38 +0500 Subject: [PATCH 067/348] fixed missed check for expiry for fillask/bid --- src/cc/assets.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 0492b924d9f..8c3bf758fe8 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -423,6 +423,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest return eval->Invalid("vout2 invalid royalty detination for fillask"); } + if (eval->GetCurrentHeight() >= vin_expiryHeight) + return eval->Invalid("order is expired"); } break; @@ -564,6 +566,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("invalid marker vout for original pubkey"); ccvouts ++; } + if (eval->GetCurrentHeight() >= vin_expiryHeight) + return eval->Invalid("order is expired"); } break; @@ -642,13 +646,6 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // redirect to AssetsValidateInternal and log error bool AssetsValidate(struct CCcontract_info *cpAssets, Eval* eval,const CTransaction &tx, uint32_t nIn) { - // add specific chains exceptions for old token support: - if (strcmp(ASSETCHAINS_SYMBOL, "SEC") == 0 && chainActive.Height() <= 144073) - return true; - - if (strcmp(ASSETCHAINS_SYMBOL, "MGNX") == 0 && chainActive.Height() <= 210190) - return true; - if (!AssetsValidateInternal(cpAssets, eval, tx, nIn)) { LOGSTREAMFN(ccassets_log, CCLOG_ERROR, stream << "validation error: " << eval->state.GetRejectReason() << ", code: " << eval->state.GetRejectCode() << ", tx: " << HexStr(E_MARSHAL(ss << tx)) << std::endl); return false; From ad4279c765d8907aef79d133c1c29f793182ea5e Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 22 Jul 2021 11:31:56 +0500 Subject: [PATCH 068/348] tests for expired orders --- src/test-komodo-cc/test-assets.cpp | 96 +++++++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 8 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index e35fc0569ad..8d7dde7540a 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -426,17 +426,17 @@ class TestAssetsCC : public ::testing::Test { eval.AddTx(txtokencreateUnused); tokenidUnused = txtokencreateUnused.GetHash(); - txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 0); + txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); eval.AddTx(txask1); - txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 0); + txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); eval.AddTx(txask2); - txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 0); + txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 222); eval.AddTx(txbid1); - //txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2, 0); // test dust + //txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2, 222); // test dust } @@ -947,6 +947,9 @@ TEST_F(TestAssetsCC, tokenv2ask) { struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + eval.SetCurrentHeight(111); //set height + CAmount numtokens = 2LL; CPubKey mypk = pk1; uint256 mytokenid = tokenid1; @@ -955,7 +958,7 @@ TEST_F(TestAssetsCC, tokenv2ask) cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, mypk, mytokenid, numtokens, 501, 0); // price more than dust + CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, mypk, mytokenid, numtokens, 501, 222); // price more than dust ASSERT_FALSE(CTransaction(mtx).IsNull()); vuint8_t origpubkey; @@ -1053,11 +1056,13 @@ TEST_F(TestAssetsCC, tokenv2ask) TEST_F(TestAssetsCC, tokenv2bid) { CAmount txfee = 10000; + eval.SetCurrentHeight(111); //set height + struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); - CMutableTransaction mtx = MakeTokenV2BidTx(cpAssets, pk2, tokenid1, 2, 501, 0); // price more than dust + CMutableTransaction mtx = MakeTokenV2BidTx(cpAssets, pk2, tokenid1, 2, 501, 222); // price more than dust ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2bid @@ -1083,6 +1088,9 @@ TEST_F(TestAssetsCC, tokenv2fillask) UniValue data(UniValue::VOBJ); struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); + + eval.SetCurrentHeight(111); //set height + CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, txask1.GetHash(), 2, 0, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); @@ -1181,6 +1189,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid) UniValue data(UniValue::VOBJ); struct CCcontract_info *cpTokens, C; cpTokens = CCinit(&C, TokensV2::EvalCode()); + eval.SetCurrentHeight(111); //set height CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, txbid1.GetHash(), 2, 0, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); @@ -1241,6 +1250,8 @@ TEST_F(TestAssetsCC, tokenv2fillbid) TEST_F(TestAssetsCC, tokenv2fillbid_royalty) { + eval.SetCurrentHeight(111); //set height + for(int r = 0; r < 1000; r += 100) { UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx @@ -1256,7 +1267,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_royalty) uint256 mytokenid = mytxtokencreate.GetHash(); eval.AddTx(mytxtokencreate); - static CTransaction mytxbid = MakeTokenV2BidTx(cpAssets, pk2, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 0); + static CTransaction mytxbid = MakeTokenV2BidTx(cpAssets, pk2, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); eval.AddTx(mytxbid); CMutableTransaction mytxfill = MakeTokenV2FillBidTx(cpTokens, pk1, mytokenid, mytxbid.GetHash(), 1, 0, data); @@ -1269,6 +1280,8 @@ TEST_F(TestAssetsCC, tokenv2fillbid_royalty) TEST_F(TestAssetsCC, tokenv2fillask_royalty) { + eval.SetCurrentHeight(111); //set height + for(int r = 0; r < 1000; r += 100) { UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx @@ -1283,7 +1296,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty) uint256 mytokenid = mytxtokencreate.GetHash(); eval.AddTx(mytxtokencreate); - static CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 0); + static CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); eval.AddTx(mytxask); CMutableTransaction mytxfill = MakeTokenV2FillAskTx(cpAssets, pk2, mytokenid, mytxask.GetHash(), 1, 0, data); @@ -1299,6 +1312,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask) { struct CCcontract_info *cpAssets, C; struct CCcontract_info *cpTokens, tokensC; + eval.SetCurrentHeight(111); //set height CAmount txfee = 10000; @@ -1369,6 +1383,8 @@ TEST_F(TestAssetsCC, tokenv2cancelask) TEST_F(TestAssetsCC, tokenv2cancelask_expired) { CAmount txfee = 10000; + eval.SetCurrentHeight(111); //set height + { struct CCcontract_info *cpTokens, tokensC; @@ -1441,11 +1457,41 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) } } +TEST_F(TestAssetsCC, tokenv2fillask_expired) +{ + CAmount txfee = 10000; + eval.SetCurrentHeight(111); //set height + { + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + static CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + ASSERT_FALSE(CTransaction(txaskexp).IsNull()); + eval.AddTx(txaskexp); + EXPECT_TRUE(TestRunCCEval(txaskexp)); + + UniValue data(UniValue::VOBJ); + uint256 asktxid = txaskexp.GetHash(); + + eval.SetCurrentHeight(222); //set height expired + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + + CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, asktxid, 1, 0, data); + + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: try tokenv2fillask already expired + EXPECT_FALSE(TestRunCCEval(mtx)); // should fail + } +} + TEST_F(TestAssetsCC, tokenv2cancelbid) { struct CCcontract_info *cpAssets, C; struct CCcontract_info *cpTokens, tokensC; CAmount txfee = 10000; + eval.SetCurrentHeight(111); //set height cpAssets = CCinit(&C, AssetsV2::EvalCode()); cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); @@ -1520,6 +1566,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) TEST_F(TestAssetsCC, tokenv2cancelbid_expired) { CAmount txfee = 10000; + eval.SetCurrentHeight(111); //set height { struct CCcontract_info *cpAssets0, C0; @@ -1592,6 +1639,36 @@ TEST_F(TestAssetsCC, tokenv2cancelbid_expired) } } +TEST_F(TestAssetsCC, tokenv2fillbid_expired) +{ + CAmount txfee = 10000; + eval.SetCurrentHeight(111); //set height + { + struct CCcontract_info *cpAssets, assetsC; + cpAssets = CCinit(&assetsC, AssetsV2::EvalCode()); + + static CTransaction txbidexp = MakeTokenV2BidTx(cpAssets, pk1, tokenid2, 2, 10000, 222); // set expiry height 222 + ASSERT_FALSE(CTransaction(txbidexp).IsNull()); + eval.AddTx(txbidexp); + EXPECT_TRUE(TestRunCCEval(txbidexp)); + + UniValue data(UniValue::VOBJ); + uint256 bidtxid = txbidexp.GetHash(); + + eval.SetCurrentHeight(222); //set height expired + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, bidtxid, 1, 0, data); + + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: try tokenv2fillask already expired + EXPECT_FALSE(TestRunCCEval(mtx)); // should fail + } +} + + /* ---------------------------------------------------------------------------------------------------------------------------------- */ // tokens tests: @@ -1599,6 +1676,9 @@ TEST_F(TestAssetsCC, tokenv2create) { struct CCcontract_info *cpTokens, C; cpTokens = CCinit(&C, TokensV2::EvalCode()); + + eval.SetCurrentHeight(111); //set height + CMutableTransaction mtx = MakeTokenV2CreateTx(pk1, 10); ASSERT_FALSE(CTransaction(mtx).IsNull()); From fbd744d6c770d6ed438c70030b8ed41f7be4a7f2 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 22 Jul 2021 12:04:30 +0500 Subject: [PATCH 069/348] comment updated --- src/rpc/tokensrpc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index c56f00dd2ac..2b6a0ff722f 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -701,7 +701,7 @@ UniValue tokenbid(const std::string& name, const UniValue& params, bool fHelp, c int32_t expiryHeight; { LOCK(cs_main); - expiryHeight = chainActive.Height() + 4 * 7 * 24 * 60; // 2 weeks for blocktime 60 sec + expiryHeight = chainActive.Height() + 4 * 7 * 24 * 60; // 4 weeks for blocktime 60 sec } if (params.size() == 4) { expiryHeight = atol(params[3].get_str().c_str()); @@ -844,7 +844,7 @@ UniValue tokenask(const std::string& name, const UniValue& params, bool fHelp, c int32_t expiryHeight; { LOCK(cs_main); - expiryHeight = chainActive.Height() + 4 * 7 * 24 * 60; // 2 weeks for blocktime 60 sec + expiryHeight = chainActive.Height() + 4 * 7 * 24 * 60; // 4 weeks for blocktime 60 sec } if (params.size() == 4) { expiryHeight = atol(params[3].get_str().c_str()); From dfe82e8f5139025d0a00a4c21e7f8687af44a1fa Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 22 Jul 2021 13:40:02 +0500 Subject: [PATCH 070/348] refactor on review notes --- src/cc/CCTokelData.cpp | 2 +- src/cc/CCassetstx_impl.h | 33 ++++++++++----------- src/cc/CCtokens.cpp | 2 -- src/cc/CCtokens_impl.h | 2 +- src/cc/CCutils.cpp | 23 ++++++--------- src/cc/heir.cpp | 19 ++++++------ src/cc/heir_validate.h | 2 +- src/init.cpp | 2 +- src/rpc/tokensrpc.cpp | 50 ++++++++++++++++---------------- src/test-komodo-cc/test-main.cpp | 1 + 10 files changed, 64 insertions(+), 72 deletions(-) diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index e48b152cd5d..dd52f9246e2 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -88,7 +88,7 @@ static tklPropId FindTokelDataIdByName(const std::string &name) static tklPropDesc_t GetTokelDataDesc(tklPropId id) { - tklPropDesc_t empty = std::make_tuple( TKLTYP_INVALID, std::string(), nullptr, nullptr ); + static const tklPropDesc_t empty = std::make_tuple( TKLTYP_INVALID, std::string(), nullptr, nullptr ); auto found = tklPropDesc.find(id); if (found != tklPropDesc.end()) return found->second; diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index 771f918d86d..806f90ee0bc 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -32,7 +32,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) cpAssets = CCinit(&assetsC, A::EvalCode()); cpTokens = CCinit(&tokensC, T::EvalCode()); - auto addOrders = [&](struct CCcontract_info *cp, std::vector >::const_iterator it) + auto addOrders = [&](struct CCcontract_info *cp, const CAddressUnspentKey &key) { uint256 txid, hashBlock, assetid; CAmount unit_price; @@ -42,7 +42,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) char origaddr[KOMODO_ADDRESS_BUFSIZE], origtokenaddr[KOMODO_ADDRESS_BUFSIZE]; int32_t expiryHeight; - txid = it->first.txhash; + txid = key.txhash; LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " checking txid=" << txid.GetHex() << std::endl); if (!myGetTransaction(txid, ordertx, hashBlock)) { LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname <<" could not load order txid=" << txid.GetHex() << std::endl); @@ -121,7 +121,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) item.push_back(Pair("ExpiryHeight", expiryHeight)); result.push_back(item); - LOGSTREAM(ccassets_log, CCLOG_DEBUG1, stream << funcname << " added order funcId=" << (char)(funcid ? funcid : ' ') << " it->first.index=" << it->first.index << " ordertx.vout[it->first.index].nValue=" << ordertx.vout[it->first.index].nValue << " tokenid=" << assetid.GetHex() << std::endl); + LOGSTREAM(ccassets_log, CCLOG_DEBUG1, stream << funcname << " added order funcId=" << (char)(funcid ? funcid : ' ') << " key.index=" << key.index << " ordertx.vout[key.index].nValue=" << ordertx.vout[key.index].nValue << " tokenid=" << assetid.GetHex() << std::endl); } } }; @@ -136,7 +136,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) for (std::vector >::const_iterator itCoins = unspentOutputsCoins.begin(); itCoins != unspentOutputsCoins.end(); itCoins++) - addOrders(cpAssets, itCoins); + addOrders(cpAssets, itCoins->first); // tokenasks: std::vector > unspentOutputsTokens; @@ -146,7 +146,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) for (std::vector >::const_iterator itTokens = unspentOutputsTokens.begin(); itTokens != unspentOutputsTokens.end(); itTokens++) - addOrders(cpAssets, itTokens); + addOrders(cpAssets, itTokens->first); } else { @@ -158,7 +158,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) for (std::vector >::const_iterator itOrders = unspentsMyAddr.begin(); itOrders != unspentsMyAddr.end(); itOrders++) - addOrders(cpAssets, itOrders); + addOrders(cpAssets, itOrders->first); } return(result); } @@ -180,6 +180,11 @@ UniValue CreateBuyOffer(const CPubKey &mypk, CAmount txfee, CAmount bidamount, u CCerror = "invalid bidamount or numtokens"; return(""); } + CAmount unit_price = bidamount / numtokens; + if (unit_price <= 0) { + CCerror = "invalid bid params"; + return (""); + } // check if valid token if (myGetTransaction(assetid, vintx, hashBlock) == 0) { @@ -203,11 +208,6 @@ UniValue CreateBuyOffer(const CPubKey &mypk, CAmount txfee, CAmount bidamount, u return (""); } - CAmount unit_price = bidamount / numtokens; - if (unit_price <= 0) { - CCerror = "invalid bid params"; - return (""); - } CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, unspendableAssetsPubkey)); mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); // 1of2 marker for my orders @@ -296,7 +296,7 @@ template std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C; + CPubKey mypk; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C; ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// fprintf(stderr,"asset swaps disabled\n"); @@ -317,7 +317,6 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a if (AddNormalinputs(mtx, mypk, txfee, 0x10000) > 0) { - mask = ~((1LL << mtx.vin.size()) - 1); if ((inputs = AddAssetInputs(cp, mtx, mypk, assetid, askamount, 60)) > 0) { ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// @@ -417,7 +416,7 @@ UniValue CancelBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uin else { // send dust back to global addr mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, unspendableAssetsPk)); - std::cerr << __func__ << " dust detected bidamount=" << bidamount << std::endl; + LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "dust detected bidamount=" << bidamount << std::endl); } // probe to spend marker: @@ -607,14 +606,14 @@ UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint2 if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { // bidder has coins for more tokens or only dust is sent back to global address mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bid_amount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder or the dust is sent back to cc global addr if (bid_amount - paid_amount <= ASSETS_NORMAL_DUST) - std::cerr << __func__ << " dust detected (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; + LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "dust detected (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl); } else mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to mypk normal if (royaltyValue > 0) { // note it makes vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner - std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_amount - royaltyValue=" << paid_amount - royaltyValue << std::endl; + LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_amount - royaltyValue=" << paid_amount - royaltyValue << std::endl); } mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator if (orig_units - fill_units > 0) // order is not finished yet @@ -751,7 +750,7 @@ UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 a mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr if (royaltyValue > 0) { // note it makes the vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner - std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_nValue - royaltyValue=" << paid_nValue - royaltyValue << std::endl; + LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_nValue - royaltyValue=" << paid_nValue - royaltyValue << std::endl); } if (orig_assetoshis - fillunits > 0) // we dont need the marker if order is filled diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 8272d07b51c..6b19ee55e5c 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -313,8 +313,6 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const // test vouts for possible token use-cases: std::vector> testVouts; - - uint8_t version; std::vector vdatas; DecodeTokenOpRetV1(tx.vout.back().scriptPubKey, tokenIdOpret, voutPubkeysInOpret, vdatas); LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << funcname << "()" << " vdatas.size()=" << vdatas.size() << std::endl); diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 7ee1dbc9481..35a0d342874 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -465,7 +465,7 @@ UniValue CreateTokenExt(const CPubKey &remotepk, CAmount txfee, CAmount tokensup // This what the AddNormalinputsRemote does (and it is not necessary that this is done only for nspv calls): if ((totalInputs = AddNormalinputsRemote(mtx, mypk, tokensupply + txfee + markerCount * TOKENS_MARKER_VALUE, 0x10000, useMempool)) > 0) { - CAmount mypkInputs = TotalPubkeyNormalInputs(NULL, mtx, mypk); + CAmount mypkInputs = TotalPubkeyNormalInputs(nullptr, mtx, mypk); if (mypkInputs < tokensupply) { // check that the token amount is really issued with mypk (because in the wallet there may be some other privkeys) CCerror = "some inputs signed not with mypubkey (-pubkey=pk)"; return NullUniValue; diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 9b651089516..6721f4b7a5c 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -1017,19 +1017,15 @@ CAmount TotalPubkeyCCInputs(Eval *eval, const CTransaction &tx, const CPubKey &p bool ProcessCC(struct CCcontract_info* cp, Eval* eval, std::vector paramsNull, const CTransaction& ctx, unsigned int nIn, std::shared_ptr evalcodeChecker) { - //CTransaction createTx; - //uint256 assetid, assetid2, hashBlock; - //uint8_t funcid; - int32_t height, from_mempool = 0; - //int64_t amount; - std::vector origpubkey; + int32_t height; + //int32_t from_mempool = 0; height = KOMODO_CONNECTING; if (KOMODO_CONNECTING < 0) // always comes back with > 0 for final confirmation - return (true); + 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; + //from_mempool = 1; height &= ((1 << 30) - 1); } if (cp->validate == NULL) @@ -1043,7 +1039,7 @@ bool ProcessCC(struct CCcontract_info* cp, Eval* eval, std::vector para //fprintf(stderr,"process CC %02x\n",cp->evalcode); CCclearvars(cp); if (paramsNull.size() != 0) // Don't expect params - return eval->Invalid("Cannot have params"); + return eval->Invalid("eval conds cannot have params yet"); //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) { @@ -1051,10 +1047,10 @@ bool ProcessCC(struct CCcontract_info* cp, Eval* eval, std::vector para //cp->prevtxid = txid; if (evalcodeChecker.get() != NULL) evalcodeChecker->MarkEvalCode(ctx.GetHash(), cp->evalcode); - return (true); + return true; } //fprintf(stderr,"invalid CC %02x\n",cp->evalcode); - return (false); + return false; } bool SubcallCCValidate(Eval* eval, uint8_t evalcode, const CTransaction& ctx, int32_t nIn) @@ -1667,9 +1663,6 @@ UniValue CCaddress(struct CCcontract_info *cp, const char *name, const std::vect // return funcid, version and creationid bool CCDecodeTxVout(const CTransaction &tx, int32_t n, uint8_t &evalcode, uint8_t &funcid, uint8_t &version, uint256 &creationId) { - CScript opdrop; - vscript_t vccdata; - if (tx.vout.size() > 0) { // note: assumes that this is a cc vout (does not check this) @@ -1677,6 +1670,8 @@ bool CCDecodeTxVout(const CTransaction &tx, int32_t n, uint8_t &evalcode, uint8_ // first try if OP_DROP data exists bool usedOpreturn; CScript opdrop; + vscript_t vccdata; + if (!(opdrop = GetCCDropAsOpret(tx.vout[n].scriptPubKey)).empty()) { GetOpReturnData(opdrop, vccdata); usedOpreturn = false; diff --git a/src/cc/heir.cpp b/src/cc/heir.cpp index 3129e636aaa..c1efb10bca1 100644 --- a/src/cc/heir.cpp +++ b/src/cc/heir.cpp @@ -137,7 +137,7 @@ bool HeirValidate(struct CCcontract_info* cpHeir, Eval* eval, const CTransaction if (fundingTxidInOpret == zeroid) { return eval->Invalid("incorrect tx opreturn: no fundingtxid present"); } - latestTxid = FindLatestFundingTx(fundingTxidInOpret, tokenid, fundingTxOpRetScript, hasHeirSpendingBegun); + latestTxid = FindLatestFundingTx(eval, fundingTxidInOpret, tokenid, fundingTxOpRetScript, hasHeirSpendingBegun); if( tokenid != zeroid && tokenid != tokenidThis ) return eval->Invalid("incorrect tx tokenid"); @@ -360,7 +360,7 @@ uint8_t DecodeHeirEitherOpRetV1(CScript scriptPubKey, uint256 &tokenid, uint256 * find the latest funding tx: it may be the first F tx or one of A or C tx's * Note: this function is also called from validation code (use non-locking calls) */ -uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, CScript& fundingOpretScript, uint8_t &hasHeirSpendingBegun) +uint256 _FindLatestFundingTx(Eval *eval, uint256 fundingtxid, uint8_t& funcId, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, CScript& fundingOpretScript, uint8_t &hasHeirSpendingBegun) { CTransaction fundingtx; uint256 hashBlock; @@ -414,7 +414,7 @@ uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &toke int32_t blockHeight = (int32_t)it->second.blockHeight; //NOTE: maybe called from validation code: - if (myGetTransaction(txid, regtx, hash)) { + if (GetTxUnconfirmedOpt(eval, txid, regtx, hash)) { // std::cerr << __func__ << " found tx for txid=" << txid.GetHex() << " blockHeight=" << blockHeight << " maxBlockHeight=" << maxBlockHeight << '\n'; uint256 fundingTxidInOpret; uint256 tokenidInOpret; // not to contaminate the tokenid from the params! @@ -432,8 +432,7 @@ uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &toke bool isNonOwner = false; // we ignore 'donations' tx (with non-owner inputs) for calculating if heir is allowed to spend: - // TODO: pass Eval instead of NULL - if (TotalPubkeyNormalInputs(NULL, regtx, ownerPubkey) > 0 || TotalPubkeyCCInputs(NULL, regtx, ownerPubkey) > 0) + if (TotalPubkeyNormalInputs(eval, regtx, ownerPubkey) > 0 || TotalPubkeyCCInputs(eval, regtx, ownerPubkey) > 0) { // CheckVinPubkey(regtx.vin, ownerPubkey, isOwner, isNonOwner); // if (isOwner && !isNonOwner) { @@ -452,7 +451,7 @@ uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &toke } // overload for validation code -uint256 FindLatestFundingTx(uint256 fundingtxid, uint256 &tokenid, CScript& opRetScript, uint8_t &hasHeirSpendingBegun) +uint256 FindLatestFundingTx(Eval *eval, uint256 fundingtxid, uint256 &tokenid, CScript& opRetScript, uint8_t &hasHeirSpendingBegun) { uint8_t funcId; CPubKey ownerPubkey; @@ -460,7 +459,7 @@ uint256 FindLatestFundingTx(uint256 fundingtxid, uint256 &tokenid, CScript& opRe int64_t inactivityTime; std::string heirName, memo; - return _FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, memo, opRetScript, hasHeirSpendingBegun); + return _FindLatestFundingTx(eval, fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, memo, opRetScript, hasHeirSpendingBegun); } // overload for transaction creation code @@ -468,7 +467,7 @@ uint256 FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &token { CScript opRetScript; - return _FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, memo, opRetScript, hasHeirSpendingBegun); + return _FindLatestFundingTx(nullptr, fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, memo, opRetScript, hasHeirSpendingBegun); } // add inputs of 1 of 2 cc address @@ -629,7 +628,7 @@ template UniValue _HeirFund(int64_t txfee, int64_t amount, std // for initial funding do not allow to sign by non-owner key: // if (hasNotMypubkey) { - if (TotalPubkeyNormalInputs(NULL, mtx, myPubkey) < amount && TotalPubkeyCCInputs(NULL, mtx, myPubkey) < amount) + if (TotalPubkeyNormalInputs(nullptr, mtx, myPubkey) < amount && TotalPubkeyCCInputs(NULL, mtx, myPubkey) < amount) { result.push_back(Pair("result", "error")); result.push_back(Pair("error", "using non-owner inputs not allowed")); @@ -756,7 +755,7 @@ template UniValue _HeirAdd(uint256 fundingtxid, int64_t txfee, in // warn the user he's making a donation if this is all non-owner keys: // if (hasNotMypubkey) { // TODO: change to Eval instead of NULL - if (TotalPubkeyNormalInputs(NULL, mtx, myPubkey) < amount && TotalPubkeyCCInputs(NULL, mtx, myPubkey) < amount) { + if (TotalPubkeyNormalInputs(nullptr, mtx, myPubkey) < amount && TotalPubkeyCCInputs(NULL, mtx, myPubkey) < amount) { result.push_back(Pair("result", "warning")); result.push_back(Pair("warning", "you are about to make a donation to heir fund")); } diff --git a/src/cc/heir_validate.h b/src/cc/heir_validate.h index 1fd955b810e..7605d2cbb2f 100644 --- a/src/cc/heir_validate.h +++ b/src/cc/heir_validate.h @@ -13,7 +13,7 @@ vscript_t EncodeHeirCreateOpRetV1(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo); vscript_t EncodeHeirOpRetV1(uint8_t funcid, uint256 fundingtxid, uint8_t isHeirSpendingBegan); -uint256 FindLatestFundingTx(uint256 fundingtxid, uint256 &tokenid, CScript& opRetScript, uint8_t &isHeirSpendingBegan); +uint256 FindLatestFundingTx(Eval *eval, uint256 fundingtxid, uint256 &tokenid, CScript& opRetScript, uint8_t &isHeirSpendingBegan); uint8_t DecodeHeirEitherOpRetV1(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, bool noLogging = false); uint8_t DecodeHeirEitherOpRetV1(CScript scriptPubKey, uint256 &tokenid, uint256 &fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging = false); diff --git a/src/init.cpp b/src/init.cpp index 8898bb77971..fdbb56fd765 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2113,7 +2113,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) threadGroup.create_thread(boost::bind(ThreadSendAlert)); if (KOMODO_NSPV_FULLNODE) - fprintf(stderr,"nLocalServices %llx %d, %d\n",(long long)nLocalServices,GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX),GetBoolArg("-spentindex", DEFAULT_SPENTINDEX)); + LogPrintf("nLocalServices %llx %d, %d\n", (long long)nLocalServices, GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX), GetBoolArg("-spentindex", DEFAULT_SPENTINDEX)); return !fRequestShutdown; } diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 2b6a0ff722f..71ed2bca829 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -104,7 +104,6 @@ UniValue tokenlist(const UniValue& params, bool fHelp, const CPubKey& remotepk) } UniValue tokenv2list(const UniValue& params, bool fHelp, const CPubKey& remotepk) { - uint256 tokenid; const static std::set acceptable = { "beginHeight", "endHeight", "pubkey", "address" }; if (fHelp || params.size() > 1) @@ -139,12 +138,11 @@ UniValue tokenv2list(const UniValue& params, bool fHelp, const CPubKey& remotepk template static UniValue tokeninfo(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) { - uint256 tokenid; - if ( fHelp || params.size() != 1 ) + if (fHelp || params.size() != 1) throw runtime_error(name + " tokenid\n"); - if ( ensure_CCrequirements(V::EvalCode()) < 0 ) + if (ensure_CCrequirements(V::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - tokenid = Parseuint256((char *)params[0].get_str().c_str()); + uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str()); return TokenInfo(tokenid, [](const vuint8_t &data){ return NullUniValue; }); } @@ -160,12 +158,11 @@ UniValue tokenv2info(const UniValue& params, bool fHelp, const CPubKey& remotepk template static UniValue tokeninfotokel(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) { - uint256 tokenid; - if ( fHelp || params.size() != 1 ) + if (fHelp || params.size() != 1) throw runtime_error(name + " tokenid\n"); - if ( ensure_CCrequirements(V::EvalCode()) < 0 ) + if (ensure_CCrequirements(V::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - tokenid = Parseuint256((char *)params[0].get_str().c_str()); + uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str()); return TokenInfo(tokenid, ParseTokelVData); } @@ -184,10 +181,10 @@ UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp uint256 tokenid; const CPubKey emptypk; - if ( fHelp || params.size() > 1 ) + if (fHelp || params.size() > 1) throw runtime_error(name + " [tokenid|'*']\n" - "returns tokens orders for the tokenid or all available token orders if tokenid is not set\n" - "\n"); + "returns tokens orders for the tokenid or all available token orders if tokenid is not set\n" + "\n"); if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (params.size() >= 1) @@ -214,7 +211,6 @@ UniValue tokenv2orders(const UniValue& params, bool fHelp, const CPubKey& remote template UniValue mytokenorders(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) { - uint256 tokenid; if (fHelp || params.size() > 0) throw runtime_error(name + "\n" "returns all tokens orders for mypubkey\n" @@ -241,29 +237,33 @@ UniValue mytokenv2orders(const UniValue& params, bool fHelp, const CPubKey& remo template static UniValue tokenbalance(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) { - UniValue result(UniValue::VOBJ); uint256 tokenid; uint64_t balance; std::vector vpubkey; struct CCcontract_info *cp,C; - CCerror.clear(); + UniValue result(UniValue::VOBJ); + CCerror.clear(); - if ( fHelp || params.size() < 1 || params.size() > 2 ) + if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error(name + " tokenid [pubkey]\n"); - if ( ensure_CCrequirements(V::EvalCode()) < 0 ) + if (ensure_CCrequirements(V::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - - //LOCK(cs_main); - tokenid = Parseuint256((char *)params[0].get_str().c_str()); - if ( params.size() == 2 ) + // LOCK(cs_main); + // no need to lock cs_main as we use only indexes in this rpc + // but still use lock if you need to get chainActive.Height() or something like that + + uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str()); + std::vector vpubkey; + if (params.size() == 2) vpubkey = ParseHex(params[1].get_str().c_str()); - else - vpubkey = Mypubkey(); + else + vpubkey = Mypubkey(); - balance = GetTokenBalance(pubkey2pk(vpubkey), tokenid, false); + CAmount balance = GetTokenBalance(pubkey2pk(vpubkey), tokenid, false); if (CCerror.empty()) { char destaddr[KOMODO_ADDRESS_BUFSIZE]; + struct CCcontract_info *cp, C; + cp = CCinit(&C, V::EvalCode()); result.push_back(Pair("result", "success")); - cp = CCinit(&C, V::EvalCode()); if (GetCCaddress(cp, destaddr, pubkey2pk(vpubkey), V::IsMixed()) != 0) result.push_back(Pair("CCaddress", destaddr)); diff --git a/src/test-komodo-cc/test-main.cpp b/src/test-komodo-cc/test-main.cpp index cfbdf9b5783..02da2b45cb2 100644 --- a/src/test-komodo-cc/test-main.cpp +++ b/src/test-komodo-cc/test-main.cpp @@ -6,6 +6,7 @@ int main(int argc, char **argv) { + std::cerr << "testing cc modules consensus code..." << std::endl; assert(init_and_check_sodium() != -1); ECC_Start(); ECCVerifyHandle handle; // Inits secp256k1 verify context From 3a6dcb51aa523d2761ab8300fcda2c7887797e9b Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Tue, 27 Jul 2021 21:13:30 +1000 Subject: [PATCH 071/348] Updated readme to add Tokel specific data --- README.md | 276 +++++++++++++++--------------------------------------- 1 file changed, 77 insertions(+), 199 deletions(-) diff --git a/README.md b/README.md index c8f99f2e16f..603f7f3e591 100644 --- a/README.md +++ b/README.md @@ -1,203 +1,81 @@ -[![Build Status](https://travis-ci.org/KomodoPlatform/komodo.svg?branch=master)](https://travis-ci.org/KomodoPlatform/komodo) -[![Version](https://img.shields.io/github/v/release/komodoplatform/komodo)](https://github.com/KomodoPlatform/komodo/releases) -[![Issues](https://img.shields.io/github/issues-raw/komodoplatform/komodo)](https://github.com/KomodoPlatform/komodo/issues) -[![PRs](https://img.shields.io/github/issues-pr-closed/komodoplatform/komodo)](https://github.com/KomodoPlatform/komodo/pulls) -[![Commits](https://img.shields.io/github/commit-activity/y/komodoplatform/komodo)](https://github.com/KomodoPlatform/komodo/commits/dev) -[![Contributors](https://img.shields.io/github/contributors/komodoplatform/komodo)](https://github.com/KomodoPlatform/komodo/graphs/contributors) -[![Last Commit](https://img.shields.io/github/last-commit/komodoplatform/komodo)](https://github.com/KomodoPlatform/komodo/graphs/commit-activity) - -[![gitstars](https://img.shields.io/github/stars/komodoplatform/komodo?style=social)](https://github.com/KomodoPlatform/komodo/stargazers) -[![twitter](https://img.shields.io/twitter/follow/komodoplatform?style=social)](https://twitter.com/komodoplatform) -[![discord](https://img.shields.io/discord/412898016371015680)](https://discord.gg/tvp96Gf) - ---- -![Komodo Logo](https://i.imgur.com/E8LtkAa.png "Komodo Logo") - - -## Komodo - -This is the official Komodo sourcecode repository based on https://github.com/jl777/komodo. - -## Development Resources - -- Komodo Website: [https://komodoplatform.com](https://komodoplatform.com/) -- Komodo Blockexplorer: [https://kmdexplorer.io](https://kmdexplorer.io/) -- Komodo Discord: [https://komodoplatform.com/discord](https://komodoplatform.com/discord) -- Forum: [https://forum.komodoplatform.com](https://forum.komodoplatform.com/) -- Mail: [info@komodoplatform.com](mailto:info@komodoplatform.com) -- Support: [https://support.komodoplatform.com/support/home](https://support.komodoplatform.com/support/home) -- Knowledgebase & How-to: [https://support.komodoplatform.com/en/support/solutions](https://support.komodoplatform.com/en/support/solutions) -- API references & Dev Documentation: [https://developers.komodoplatform.com](https://developers.komodoplatform.com/) -- Blog: [https://blog.komodoplatform.com](https://blog.komodoplatform.com/) -- Whitepaper: [Komodo Whitepaper](https://komodoplatform.com/whitepaper) -- Komodo Platform public material: [Komodo Platform public material](https://docs.google.com/document/d/1AbhWrtagu4vYdkl-vsWz-HSNyNvK-W-ZasHCqe7CZy0) - -## List of Komodo Platform Technologies - -- Delayed Proof of Work (dPoW) - Additional security layer and Komodos own consensus algorithm -- zk-SNARKs - Komodo Platform's privacy technology for shielded transactions -- Tokens/Assets Technology - create "colored coins" on the Komodo Platform and use them as a layer for securites -- Reward API - Komodo CC technology for securities -- CC - Crypto Conditions to realize "smart contract" logic on top of the Komodo Platform -- Jumblr - Decentralized tumbler for KMD and other cryptocurrencies -- Assetchains - Create your own Blockchain that inherits all Komodo Platform functionalities and blockchain interoperability -- Pegged Assets - Chains that maintain a peg to fiat currencies -- Peerchains - Scalability solution where sibling chains form a network of blockchains -- More in depth covered [here](https://docs.google.com/document/d/1AbhWrtagu4vYdkl-vsWz-HSNyNvK-W-ZasHCqe7CZy0) -- Also note you receive 5% Active User Reward on your balance. -[See this article for more details](https://support.komodoplatform.com/en/support/solutions/articles/29000024515-how-to-claim-the-kmd-active-user-reward-in-agama) - -## Tech Specification -- Max Supply: 200 million KMD + + + +## Tokel Branch + +This is the `'tokel'` branch of Komodo's sourcecode repository. + + +## What is the Tokel platform? +Tokel is a dedicated token platform. This platform will provide a solid foundation, using existing Komodo Technologies, for token projects to launch and succeed from by offering end-to-end token solutions for fixed supply and non-fungible tokens (NFT's). Furthermore Tokel aims to provide a wealth of knowledge, information and assistance for open-sourced applications, projects and businesses looking to capitalize on token economics or token applications. The Tokel platform will provide simple to use, streamlined token creation, explorer and wallet integration, decentralized exchange integration assistance and more. + +#### What Tokel aims to offer: +- The blockchain that facilitates the tokens. +- An open-sourced all-in-one GUI application. +- A tokenDEX for all tokens on Tokel. +- An NFT marketplace for NFTs on Tokel. +- A free-to-use token test blockchain. +- Easy to use integrations +- Easy to use token creation, usage and management tools. +- Immediate token explorer integration. +- Immediate token wallet integration. +- Open source Discord bot integration. + +#### The benefits of creating a token on the Tokel blockchain: +- There are no requirements to create and manage your own blockchain. +- Free, simple to use GUI for token usage, management and creation. +- Extremely cheap token creation and transaction fees (1 satoshi of TKL per token created and 0.0001 TKL txfee by default). +- Free to use TKLTEST chain for any token or custom consensus testing prior to launch or integration. +- Your token will have immediate token wallet integration. +- Your token will have immediate token explorer integration. +- Your token is safe from 51% attacks as Tokel is secured through dPoW. +- You will have the ability to sell your tokens immediately after creation with Tokel’s inbuilt tokenDEX and NFT marketplace integration. +- Tokel exchange partnerships mean your token will have a centralized exchange listing option. The exchanges are only required to run the Tokel chain to access every single token on it. + +## The Tokel Application +The all-in-one Tokel application is an open-sourced application that will be the one stop shop for all Tokel related features. This application is built using nSPV superlite wallet technology that has been developed by the Komodo platform, for an incredibly fast and reliable experience. This application accesses all of the features offered on the Tokel blockchain whilst keeping users funds in their own wallets (completely non-custodial). + +This application is in development. You can keep up with progress on the github, or find out more by having a chat in our discord. +https://github.com/TokelPlatform/tokel_app + +#### Application features include: +- A TKL coin wallet +- A multi-token wallet (you are able to hold all tokens that are in existence on the Tokel blockchain) +- A tokenDEX trading platform +- A decentralized NFT marketplace +- A simple to use Token creation tool +- A token explorer for all tokens on the Tokel blockchain + +## Tokel Resources + +- Tokel Website: [https://tokel.io](https://tokel.io) +- Tokel Block Explorer: [https://explorer.tokel.io](https://explorer.tokel.io) +- Tokel Discord: [Tokel Discord Invitation](http://discord.tokel.io) +- Email: [contact@tokel.io](mailto:contact@tokel.io) +- Whitepaper: [Tokel Paper](https://tokel.io/TokelPaper1stEdition.pdf) +- Knowledgebase & How-to: [Tokel Documentation](https://docs.tokel.io) + - [How to run the blockchain](https://docs.tokel.io/guides/LaunchTheChain/) + - [Tokens RPC/API documentation](https://docs.tokel.io/api/tokens/) + - [Assets RPC/API documentation](https://docs.tokel.io/api/assets/) + +## List of Tokel Platform Technologies + +- [Delayed Proof of Work (dPoW)](https://blog.komodoplatform.com/en/delayed-proof-of-work/)- Bitcoin hashrate level protection. An additional security layer that protects from 51% attacks by notarizing Tokels hash onto Komodo's chain, then on to the Bitcoin blockchain. +- [Tokens](https://docs.tokel.io/api/tokens/)/[Assets](https://docs.tokel.io/api/assets/) Technology - Create your own tokens or non-fungible tokens (NFTs) and trade them immediately on-chain with the assets based tokenDEX. + +## Tokel Blockchain Specifics + +[Documentation on how to launch & run the Tokel blockchain (CLI).](https://docs.tokel.io/guides/LaunchTheChain/) + +- Max Supply: Approximately 200.25 million TKL - Block Time: 60 seconds -- Block Reward: 3 KMD -- Mining Algorithm: Equihash - -## About this Project -Komodo is based on Zcash and has been extended by our innovative consensus algorithm called dPoW which utilizes Bitcoin's hashrate to store Komodo blockchain information into the Bitcoin blockchain. Other new and native Komodo features are the privacy technology called JUMBLR, our assetchain capabilities (one click plug and play blockchain solutions) and a set of financial decentralization and interoperability technologies. More details are available under https://komodoplatform.com/ and https://blog.komodoplatform.com. - -## Getting started - -### Dependencies - -```shell -#The following packages are needed: -sudo apt-get install build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python python-zmq zlib1g-dev wget libcurl4-gnutls-dev bsdmainutils automake curl libsodium-dev -``` - -### Build Komodo - -This software is based on zcash and considered experimental and is continously undergoing heavy development. - -The dev branch is considered the bleeding edge codebase while the master-branch is considered tested (unit tests, runtime tests, functionality). At no point of time do the Komodo Platform developers take any responsbility for any damage out of the usage of this software. -Komodo builds for all operating systems out of the same codebase. Follow the OS specific instructions from below. - -#### Linux -```shell -git clone https://github.com/komodoplatform/komodo --branch master --single-branch -cd komodo -./zcutil/fetch-params.sh -./zcutil/build.sh -j$(expr $(nproc) - 1) -#This can take some time. -``` - - -#### OSX -Ensure you have [brew](https://brew.sh) and Command Line Tools installed. -```shell -# Install brew -/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" -# Install Xcode, opens a pop-up window to install CLT without installing the entire Xcode package -xcode-select --install -# Update brew and install dependencies -brew update -brew upgrade -brew tap discoteq/discoteq; brew install flock -brew install autoconf autogen automake -brew update && brew install gcc@8 -brew install binutils -brew install protobuf -brew install coreutils -brew install wget -# Clone the Komodo repo -git clone https://github.com/komodoplatform/komodo --branch master --single-branch -# Change master branch to other branch you wish to compile -cd komodo -./zcutil/fetch-params.sh -./zcutil/build-mac.sh -j$(expr $(sysctl -n hw.ncpu) - 1) -# This can take some time. -``` - -#### Windows -Use a debian cross-compilation setup with mingw for windows and run: -```shell -sudo apt-get install build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python python-zmq zlib1g-dev wget libcurl4-gnutls-dev bsdmainutils automake curl cmake mingw-w64 libsodium-dev libevent-dev -curl https://sh.rustup.rs -sSf | sh -source $HOME/.cargo/env -rustup target add x86_64-pc-windows-gnu - -sudo update-alternatives --config x86_64-w64-mingw32-gcc -# (configure to use POSIX variant) -sudo update-alternatives --config x86_64-w64-mingw32-g++ -# (configure to use POSIX variant) - -git clone https://github.com/jl777/komodo --branch master --single-branch -cd komodo -./zcutil/fetch-params.sh -./zcutil/build-win.sh -j$(expr $(nproc) - 1) -#This can take some time. -``` -**komodo is experimental and a work-in-progress.** Use at your own risk. - -To reset the Komodo blockchain change into the *~/.komodo* data directory and delete the corresponding files by running `rm -rf blocks chainstate debug.log komodostate db.log` - -#### Create komodo.conf - -Create a komodo.conf file: - -``` -mkdir ~/.komodo -cd ~/.komodo -touch komodo.conf - -#Add the following lines to the komodo.conf file: -rpcuser=yourrpcusername -rpcpassword=yoursecurerpcpassword -rpcbind=127.0.0.1 -txindex=1 -addnode=77.75.121.138 -addnode=95.213.238.100 -addnode=94.130.148.142 -addnode=103.6.12.105 -addnode=139.99.209.214 -addnode=185.130.212.13 -addnode=5.9.142.219 -addnode=200.25.4.38 -addnode=139.99.136.148 - -``` -### Create your own Blockchain based on Komodo - -Komodo allows anyone to create a runtime fork which represents an independent Blockchain. Below are the detailed instructions: -Setup two independent servers with at least 1 server having a static IP and build komodod on those servers. - -#### On server 1 (with static IP) run: -```shell -./komodod -ac_name=name_of_your_chain -ac_supply=100000 -bind=ip_of_server_1 & -``` - -#### On server 2 run: -```shell -./komodod -ac_name=name_of_your_chain -ac_supply=100000 -addnode=ip_of_server_1 -gen & -``` - -**Komodo is based on Zcash which is unfinished and highly experimental.** Use at your own risk. - -License -------- -For license information see the file [COPYING](COPYING). - -**NOTE TO EXCHANGES:** -https://bitcointalk.org/index.php?topic=1605144.msg17732151#msg17732151 -There is a small chance that an outbound transaction will give an error due to mismatched values in wallet calculations. There is a -exchange option that you can run komodod with, but make sure to have the entire transaction history under the same -exchange mode. Otherwise you will get wallet conflicts. - -**To change modes:** - -a) backup all privkeys (launch komodod with `-exportdir=` and `dumpwallet`) -b) start a totally new sync including `wallet.dat`, launch with same `exportdir` -c) stop it before it gets too far and import all the privkeys from a) using `komodo-cli importwallet filename` -d) resume sync till it gets to chaintip - -For example: -```shell -./komodod -exportdir=/tmp & -./komodo-cli dumpwallet example -./komodo-cli stop -mv ~/.komodo ~/.komodo.old && mkdir ~/.komodo && cp ~/.komodo.old/komodo.conf ~/.komodo.old/peers.dat ~/.komodo -./komodod -exchange -exportdir=/tmp & -./komodo-cli importwallet /tmp/example -``` ---- +- Starting Block Reward (Era 1): 1 TKL (for ~8 weeks) +- Block reward after ~8 weeks: 42.5 TKL +- Block reward reduction time period: Every 525600 blocks following Era 1 (roughly every year) +- Reduction amount: 23% +- Mining Algorithm: Equihash - Proof of Work - Secured by dPoW +- Specific coin emission broken down in the whitepaper + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: From b147dec53325b32532d3107965ddcaab30e5360d Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Tue, 27 Jul 2021 21:14:27 +1000 Subject: [PATCH 072/348] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 603f7f3e591..f97a4ac2271 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This is the `'tokel'` branch of Komodo's sourcecode repository. -## What is the Tokel platform? +## What is the Tokel Platform? Tokel is a dedicated token platform. This platform will provide a solid foundation, using existing Komodo Technologies, for token projects to launch and succeed from by offering end-to-end token solutions for fixed supply and non-fungible tokens (NFT's). Furthermore Tokel aims to provide a wealth of knowledge, information and assistance for open-sourced applications, projects and businesses looking to capitalize on token economics or token applications. The Tokel platform will provide simple to use, streamlined token creation, explorer and wallet integration, decentralized exchange integration assistance and more. #### What Tokel aims to offer: From 3847a3bdc3e4692c9296f26c900b1065328d9345 Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Tue, 27 Jul 2021 21:15:36 +1000 Subject: [PATCH 073/348] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f97a4ac2271..500dca35c1c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ - +![Tokel Logo](https://raw.githubusercontent.com/TokelPlatform/tokel_app/brand_pack/brand_package/assets/tokel.svg "Tokel Logo") -## Tokel Branch +## Komodo's 'Tokel' Branch -This is the `'tokel'` branch of Komodo's sourcecode repository. +This is the `tokel` branch of Komodo's sourcecode repository. ## What is the Tokel Platform? From 6af1cedbf31745f36f4c6fb3246f8df6ce68fe82 Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Tue, 27 Jul 2021 21:17:22 +1000 Subject: [PATCH 074/348] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 500dca35c1c..65cf26e94b5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Tokel Logo](https://raw.githubusercontent.com/TokelPlatform/tokel_app/brand_pack/brand_package/assets/tokel.svg "Tokel Logo") +![Tokel Header](https://github.com/TokelPlatform/tokel_app/blob/development/assets/tokel-header.png "Tokel Header") ## Komodo's 'Tokel' Branch From 83be9c49e6e86b3be67448ab84bf8fc80c99029e Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Tue, 27 Jul 2021 21:21:47 +1000 Subject: [PATCH 075/348] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 65cf26e94b5..4cf02462efd 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,10 @@ ## Komodo's 'Tokel' Branch -This is the `tokel` branch of Komodo's sourcecode repository. +This is the `tokel` branch of Komodo's sourcecode repository. This branch is required to run and use the main Tokel blockchain and hosts Tokel specific developments. + +To run Tokel's test chain, please use the repository below instead. +- https://github.com/TokelPlatform/komodo/ ## What is the Tokel Platform? From 49a5b92c51704c9fe27b42a77c27b5f58b72dc4c Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Tue, 27 Jul 2021 21:22:49 +1000 Subject: [PATCH 076/348] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4cf02462efd..f3179378402 100644 --- a/README.md +++ b/README.md @@ -57,9 +57,10 @@ https://github.com/TokelPlatform/tokel_app - Email: [contact@tokel.io](mailto:contact@tokel.io) - Whitepaper: [Tokel Paper](https://tokel.io/TokelPaper1stEdition.pdf) - Knowledgebase & How-to: [Tokel Documentation](https://docs.tokel.io) - - [How to run the blockchain](https://docs.tokel.io/guides/LaunchTheChain/) + - [How to run the Tokel blockchain](https://docs.tokel.io/guides/LaunchTheChain/) - [Tokens RPC/API documentation](https://docs.tokel.io/api/tokens/) - [Assets RPC/API documentation](https://docs.tokel.io/api/assets/) + - [How to run the Tokel test chain](https://docs.tokel.io/guides/LaunchTKLTESTchain/) ## List of Tokel Platform Technologies From f2c42729c8b1a8eb02ac1697478acb9913165f49 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 27 Jul 2021 18:04:26 +0500 Subject: [PATCH 077/348] fix origpubkey in tokencancelask/bid --- src/cc/CCassetstx_impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index 806f90ee0bc..e0272c54212 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -412,7 +412,7 @@ UniValue CancelBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uin } if (bidamount > ASSETS_NORMAL_DUST) - mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); else { // send dust back to global addr mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, unspendableAssetsPk)); @@ -488,7 +488,7 @@ UniValue CancelSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 CCerror = "invalid ask tx or not enough vouts"; return ""; } - mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), askamount, mypk)); // one-eval token vout + mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), askamount, pubkey2pk(origpubkey))); // one-eval token vout // mtx.vout.push_back(CTxOut(ASSETS_MARKER_AMOUNT, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // we dont need marker for cancelled orders // init assets 'unspendable' privkey and pubkey From 48fc0b42c9bf9e501e9b622e193d96ec7df413b2 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 27 Jul 2021 18:05:02 +0500 Subject: [PATCH 078/348] added consensus tests for assets cc expiry --- src/test-komodo-cc/test-assets.cpp | 126 ++++++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 13 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 8d7dde7540a..d72d12ae5d1 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -654,8 +654,40 @@ class TestAssetsCC : public ::testing::Test { return mtx; } + bool TestSetBidFillamounts(CAmount unit_price, CAmount &received_nValue, CAmount orig_nValue, CAmount &paid_units, CAmount orig_units, CAmount paid_unit_price) + { + if (orig_units == 0) + { + received_nValue = paid_units = 0; + return(false); + } + if (paid_units > orig_units) // not + { + paid_units = 0; + // received_nValue = orig_nValue; + received_nValue = (paid_units * paid_unit_price); // as paid unit_price might be less than original unit_price + // remaining_units = 0; + fprintf(stderr, "%s not enough units!\n", __func__); + return(false); + } + + received_nValue = (paid_units * paid_unit_price); + fprintf(stderr, "%s orig_units.%lld - paid_units.%lld, (orig_value.%lld - received_value.%lld)\n", __func__, + (long long)orig_units, (long long)paid_units, (long long)orig_nValue, (long long)received_nValue); + if (unit_price > 0 && received_nValue > 0 && received_nValue <= orig_nValue) + { + CAmount remaining_nValue = (orig_nValue - received_nValue); + return true; + } + else + { + fprintf(stderr, "%s incorrect values: unit_price %lld > 0, orig_value.%lld >= received_value.%lld\n", __func__, + (long long)unit_price, (long long)orig_nValue, (long long)received_nValue); + return(false); + } + } - static CMutableTransaction MakeTokenV2FillBidTx(struct CCcontract_info *cpTokens, CPubKey mypk, uint256 tokenid, uint256 bidtxid, CAmount fill_units, CAmount unit_price, UniValue &data) + static CMutableTransaction MakeTokenV2FillBidTx(struct CCcontract_info *cpTokens, CPubKey mypk, uint256 tokenid, uint256 bidtxid, CAmount fill_units, CAmount paid_unit_price, UniValue &data) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); struct CCcontract_info *cpAssets, C; @@ -669,7 +701,6 @@ class TestAssetsCC : public ::testing::Test { //CAmount fill_units = 2; CAmount txfee = 10000; uint256 assetidOpret; - CAmount paid_unit_price = 0; // not set cpAssets = CCinit(&C, AssetsV2::EvalCode()); //cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); @@ -701,6 +732,7 @@ class TestAssetsCC : public ::testing::Test { CAmount bid_amount = bidtx.vout[bidvout].nValue; vuint8_t origpubkey; int32_t expiryHeight; + CAmount unit_price; if (GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, bidtx) == 0) { // get orig pk, orig value std::cerr << __func__ << " cant get order data" << std::endl; return CTransaction(); @@ -728,8 +760,7 @@ class TestAssetsCC : public ::testing::Test { mtx.vin.push_back(CTxIn(bidtx.GetHash(), bidvout, CScript())); // spend order tx if (!SetBidFillamounts(unit_price, paid_amount, bid_amount, fill_units, orig_units, paid_unit_price)) { - std::cerr << __func__ << " SetBidFillamounts return false" << std::endl; - return CTransaction(); + std::cerr << __func__ << " SetBidFillamounts return false, continue..." << std::endl; } CAmount royaltyValue = royaltyFract > 0 ? paid_amount / TKLROYALTY_DIVISOR * royaltyFract : 0; @@ -747,12 +778,14 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " dust detected (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; } else - mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator - mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to mypk normal + mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << origpubkey << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator + mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << vuint8_t(mypk.begin(), mypk.end()) << OP_CHECKSIG)); // vout1 coins to mypk normal if (royaltyValue > 0) // note it makes vout even if roaltyValue is 0 - mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout2 trade royalty to token owner mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator - if (orig_units - fill_units > 0) // order is not finished yet + //specially change to make valid tx if bidder takes tokens for lower price + //if (orig_units - fill_units > 0) // order is not finished yet + if (mtx.vout[0].scriptPubKey.IsPayToCryptoCondition() && mtx.vout[0].nValue / unit_price > 0) mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(origpubkey), unspendableAssetsPk)); // vout3(4 if royalty) marker to origpubkey if (tokensChange != 0LL) @@ -943,7 +976,7 @@ class TestAssetsCC : public ::testing::Test { // -------------------------------------------------- // assets cc tests: -TEST_F(TestAssetsCC, tokenv2ask) +TEST_F(TestAssetsCC, tokenv2ask_basic) { struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); @@ -1053,7 +1086,7 @@ TEST_F(TestAssetsCC, tokenv2ask) } } -TEST_F(TestAssetsCC, tokenv2bid) +TEST_F(TestAssetsCC, tokenv2bid_basic) { CAmount txfee = 10000; eval.SetCurrentHeight(111); //set height @@ -1083,7 +1116,7 @@ TEST_F(TestAssetsCC, tokenv2bid) } -TEST_F(TestAssetsCC, tokenv2fillask) +TEST_F(TestAssetsCC, tokenv2fillask_basic) { UniValue data(UniValue::VOBJ); struct CCcontract_info *cpAssets, C; @@ -1181,10 +1214,37 @@ TEST_F(TestAssetsCC, tokenv2fillask) { AssetsV2::EncodeAssetOpRet('S', unit_price, vuint8_t(pkunused.begin(), pkunused.end()), expiryHeight) }))); // not matched origpk (should be pk1) EXPECT_FALSE(TestRunCCEval(mtx1)); } + { + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); + + CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, txask1.GetHash(), 2, unit_price-1, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: invalid tokenv2fillask with a lower price + EXPECT_FALSE(TestRunCCEval(mtx)); // must fail + } + { + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); + + CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, txask1.GetHash(), 2, unit_price+1, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: valid tokenv2fillask with a bigger price + EXPECT_TRUE(TestRunCCEval(mtx)); + } + } -TEST_F(TestAssetsCC, tokenv2fillbid) +TEST_F(TestAssetsCC, tokenv2fillbid_basic) { UniValue data(UniValue::VOBJ); struct CCcontract_info *cpTokens, C; @@ -1244,7 +1304,47 @@ TEST_F(TestAssetsCC, tokenv2fillbid) ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, { AssetsV2::EncodeAssetOpRet('B', unit_price, vuint8_t(pkunused.begin(), pkunused.end()), expiryHeight) }))); // not matched origpk (should be pk1) - EXPECT_FALSE(TestRunCCEval(mtx1)); + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail changed origpk + } + { + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value + + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, txbid1.GetHash(), 1, unit_price, data); + mtx.vout[1].nValue += 1; // imitate lower price + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: invalid tokenv2fillbid with lower price but invalid cc inputs != cc outputs + EXPECT_FALSE(TestRunCCEval(mtx)); // must fail + } + { + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value + + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, txbid1.GetHash(), 1, unit_price-1, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: valid tokenv2fillbid with lower sell price than requested + EXPECT_TRUE(TestRunCCEval(mtx)); + } + { + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value + + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, txbid1.GetHash(), 1, unit_price+1, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: invalid tokenv2fillbid with bigger sell price than requested + EXPECT_FALSE(TestRunCCEval(mtx)); // must fail } } From 7c5c80069f58d4f3d006b7746d76e4eb34b6f285 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 27 Jul 2021 18:07:06 +0500 Subject: [PATCH 079/348] added rpc tests for order expiration --- src/tui/tui_assets_orders.py | 99 ++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 0493e0fac66..e2db27965ee 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -53,8 +53,9 @@ def run_tokens_create(rpc): rpc3 = rpclib.rpc_connect("user972794450", "passe7eb16f5c015a53463cc5f27a004854cb76f4ec5c9aece177f01d8b3d13119e445", 16723) - ## for v in ["", "v2"] : - for v in ["v2"] : + for v in ["", "v2"] : + ## for v in [""] : + ## for v in ["v2"] : print("creating fungible token 1...") result = call_rpc(rpc1, "token"+v+"create", "T1", str(0.000001)) # 100 assert(check_tx(result)) @@ -128,6 +129,8 @@ def run_tokens_create(rpc): print("starting assets tests for nftf7id4 with unit price creating dust royalty and checking that round correct, version=" + v + "...") run_assets_orders(rpc1, rpc2, v, nftf7id4, 1, 1, 0.0000_1001, True) + print("starting assets order expiration tests for tokenid1 version=" + v + "...") + run_assets_expired_orders(rpc1, rpc2, v, tokenid1, 10, 8, 0.0001, False) if v == "v2" : # MofN supported for tokens cc v2 only print("running MofN tests for tokens v2:") @@ -136,7 +139,7 @@ def run_tokens_create(rpc): print("starting MofN tests for nft00id1...") run_MofN_transfers(rpc1, rpc2, rpc3, nft00id1, 1) print("starting MofN tests for nftf7id1...") - run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) + run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) print("token/assets tests finished okay") time.sleep(3) @@ -579,6 +582,96 @@ def run_assets_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, isnft): assert(int(finresult["balance"]) == initial_balance) + +# test expiration height in orders +def run_assets_expired_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, isnft): + + askunits = bidunits = units + + getinfo = rpc1.getinfo() + hoff = 5 + h0 = getinfo["blocks"] + + # create tokenask with expiration height + print("creating token"+v+"ask with expiration tx #1...") + askid1 = call_token_rpc_send_tx(rpc1, "token"+v+"ask", '', str(total), tokenid, str(unitprice), str(h0+hoff)) + + print("trying to cancel not yet expired order with other pk: token"+v+"cancelask...") + result = call_token_rpc_create_tx(rpc2, "token"+v+"cancelask", 'ask is empty', tokenid, askid1) + assert(check_tx(result)) + try : + cancelid = rpc2.sendrawtransaction(result['hex']) + assert(get_result_error(cancelid)) # should return error for not yet expired order + except RpcException as e : + print ('got a normal exception for tokencancelask not expired', e.message) + pass # exception is a normal execution + + # wait for expiration height + while True : + time.sleep(30) + getinfo = rpc1.getinfo() + h1 = getinfo["blocks"] + if h1 >= h0 + hoff : + break + print ('waiting for expiration height...') + + print("trying to fill expired order token"+v+"fillask tx #1...") + result = call_token_rpc_create_tx(rpc2, "token"+v+"fillask", '', tokenid, askid1, str(askunits)) + assert(check_tx(result)) + try : + fillaskid1 = rpc2.sendrawtransaction(result['hex']) + print("fillaskid1", fillaskid1) + print("get_result_error(fillaskid1)", get_result_error(fillaskid1)) + assert(get_result_error(fillaskid1)) # should return error for yet expired order + except RpcException as e : + print ('got a normal exception for tokenfillask expired', e.message) + pass # exception is a normal execution + + print("trying to cancel not yet expired order with other pk: token"+v+"cancelask...") + cancelid2 = call_token_rpc_send_tx(rpc2, "token"+v+"cancelask", 'ask is empty', tokenid, askid1) + + # same for tokenbid + getinfo = rpc1.getinfo() + h0 = getinfo["blocks"] + + # create tokenbid with expiration height + print("creating token"+v+"bid with expiration tx #1...") + bidid1 = call_token_rpc_send_tx(rpc2, "token"+v+"bid", '', str(total), tokenid, str(unitprice), str(h0+hoff)) + + print("trying to cancel not yet expired order with other pk: token"+v+"cancelbid...") + result = call_token_rpc_create_tx(rpc1, "token"+v+"cancelbid", 'bid is empty', tokenid, bidid1) + assert(check_tx(result)) + try : + cancelid = rpc1.sendrawtransaction(result['hex']) + assert(get_result_error(cancelid)) # should return error for not yet expired order + except RpcException as e : + print ('got a normal exception for tokencancelbid not expired', e.message) + pass # should be exception + + # wait for expiration height + while True : + time.sleep(30) + getinfo = rpc1.getinfo() + h1 = getinfo["blocks"] + if h1 >= h0 + hoff : + break + print ('waiting for expiration height...') + + print("trying to fill expired order token"+v+"fillbid tx #1...") + result = call_token_rpc_create_tx(rpc1, "token"+v+"fillbid", '', tokenid, bidid1, str(bidunits)) + assert(check_tx(result)) + try : + fillbidid1 = rpc1.sendrawtransaction(result['hex']) + assert(get_result_error(fillbidid1)) # should return error for yet expired order + except RpcException as e : + print ('got a normal exception for tokenfillbid expired', e.message) + pass # should be exception here + + print("trying to cancel not yet expired order with other pk: token"+v+"cancelbid...") + cancelid3 = call_token_rpc_send_tx(rpc1, "token"+v+"cancelbid", 'bid is empty', tokenid, bidid1) + + + menuItems = [ {"run token create/transfers and assets orders": run_tokens_create}, {"Exit": exit} From 8c1d0aa7ce9bc4e92b846d6378fee518e61c9363 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 27 Jul 2021 22:36:50 +0500 Subject: [PATCH 080/348] make import validation more reliable by checking non empty targetSymbol --- src/cc/import.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 7eb20f01665..1a8c2f4519b 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -704,6 +704,8 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp return Invalid("wrong-payouts"); if (targetCcid < KOMODO_FIRSTFUNGIBLEID) return Invalid("chain-not-fungible"); + if (targetSymbol.empty()) + return Invalid("target-symbol-empty"); if ( targetCcid != 0xffffffff ) { From 574e4cd8be85418c76509caf5df23c1a9f2a833a Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 27 Jul 2021 23:29:15 +0500 Subject: [PATCH 081/348] do not add totally filled orders to tokenorders list --- src/cc/CCassetstx_impl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index e0272c54212..a98d9abd17a 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -120,7 +120,8 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) if (expiryHeight > 0) item.push_back(Pair("ExpiryHeight", expiryHeight)); - result.push_back(item); + if (ordertx.vout[0].nValue > 0LL) // do not add totally filled orders + result.push_back(item); LOGSTREAM(ccassets_log, CCLOG_DEBUG1, stream << funcname << " added order funcId=" << (char)(funcid ? funcid : ' ') << " key.index=" << key.index << " ordertx.vout[key.index].nValue=" << ordertx.vout[key.index].nValue << " tokenid=" << assetid.GetHex() << std::endl); } } From 00cc9862df4abaea96c7c074f9d5db2727b221ce Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 27 Jul 2021 23:31:43 +0500 Subject: [PATCH 082/348] modify qa test_token.py for new tokencancelbid/ask response (when non-owner pk used) --- qa/pytest_komodo/cc_modules/test_token.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/qa/pytest_komodo/cc_modules/test_token.py b/qa/pytest_komodo/cc_modules/test_token.py index 5e02c1b5fb0..376247db756 100644 --- a/qa/pytest_komodo/cc_modules/test_token.py +++ b/qa/pytest_komodo/cc_modules/test_token.py @@ -186,8 +186,12 @@ def test_token(test_params): assert result > 0.1 print("making invalid node token" + v + "cancelask(s)...") - result = call_token_rpc(rpc1, "token"+v+"cancelask", tokenid, testorderid) - assert_error(result) + badcancel = call_token_rpc(rpc1, "token"+v+"cancelask", tokenid, testorderid) + try : + rpc1.sendrawtransaction(badcancel["hex"]) # checked at consensus + assert False, "order should not be cancelled with another pk" # should be exception + except RPCError : + pass # exception is normal here print("making valid node token" + v + "cancelask...") # from valid node From 4a1e3277c10dab2fc87a69c957db47832b9bb5e8 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 28 Jul 2021 01:52:57 +0500 Subject: [PATCH 083/348] fix missed addrman init in komodo-test --- src/test-komodo/test_addrman.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test-komodo/test_addrman.cpp b/src/test-komodo/test_addrman.cpp index f283b971090..8518200a064 100644 --- a/src/test-komodo/test_addrman.cpp +++ b/src/test-komodo/test_addrman.cpp @@ -68,6 +68,7 @@ class CAddrManTest : public CAddrMan explicit CAddrManTest(bool makeDeterministic = true, std::vector asmap = std::vector()) { + Clear(); if (makeDeterministic) { // Set addrman addr placement to be deterministic. MakeDeterministic(); From fccce06f545d6410b74a92d64dc592cec4feae70 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 29 Jul 2021 13:04:08 +0500 Subject: [PATCH 084/348] more tokel data validation (max compact size, is hex string arbitrary) --- src/cc/CCTokelData.cpp | 40 +++++++++++++++++++++++++++------------- src/cc/CCTokelData.h | 3 ++- src/rpc/tokensrpc.cpp | 6 ++++++ 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index dd52f9246e2..cd204539d21 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -42,29 +42,36 @@ static UniValue tklReadVuint8(CDataStream &ss) return ret; } -static bool tklWriteString(CDataStream &ss, const UniValue &val) +static bool tklWriteString(CDataStream &ss, const UniValue &val, std::string &err) { std::string sval = val.getValStr(); ::Serialize(ss, sval); return true; } -static bool tklWriteInt64(CDataStream &ss, const UniValue &val) +static bool tklWriteInt64(CDataStream &ss, const UniValue &val, std::string &err) { int64_t i64val = 0; if (!val.isNum()) return false; ParseInt64(val.getValStr(), &i64val); - //::Serialize(ss, i64val); + if (i64val > MAX_SIZE) { + err = "value too big"; + return false; + } ss << COMPACTSIZE((uint64_t)i64val); return true; } -static bool tklWriteVuint8(CDataStream &ss, const UniValue &val) +static bool tklWriteVuint8(CDataStream &ss, const UniValue &val, std::string &err) { - vuint8_t vuint8val = ParseHex(val.getValStr()); - if (vuint8val.empty() && !val.getValStr().empty()) // can't decode hex string - return false; + std::string s = val.getValStr(); + for(auto const &c : s) + if (!std::isxdigit(c)) { + err = "not hex string"; + return false; + } + vuint8_t vuint8val = ParseHex(s); ::Serialize(ss, vuint8val); return true; } @@ -106,11 +113,12 @@ vuint8_t ParseTokelJson(const UniValue &jsonParams) std::string key = jsonParams.getKeys()[i]; tklPropId id; if ((id = FindTokelDataIdByName(key)) == (tklPropId)0) - throw std::runtime_error("invalid token data id: " + key); + throw std::runtime_error("invalid token data id: '" + key + "'"); tklPropDesc_t entry = GetTokelDataDesc(id); ss << (uint8_t)id; - if (!(*std::get<3>(entry))(ss, jsonParams[key])) - throw std::runtime_error(std::string("tokel data invalid: ") + key); + std::string err; + if (!(*std::get<3>(entry))(ss, jsonParams[key], err)) + throw std::runtime_error(std::string("tokel data invalid: '") + key + "' " + err); } return vuint8_t(ss.begin(), ss.end()); @@ -154,8 +162,12 @@ static bool UnmarshalTokelVData(const vuint8_t &vdata, std::map propMap; - if( UnmarshalTokelVData(vdata, propMap, sError) ) { + if (UnmarshalTokelVData(vdata, propMap, sError)) { // check props if present + std::cerr << __func__ << " propMap.count(TKLPROP_ROYALTY)=" << propMap.count(TKLPROP_ROYALTY) << std::endl; if (propMap.count(TKLPROP_ROYALTY) > 0) { int64_t val; if (!ParseInt64(propMap[TKLPROP_ROYALTY].getValStr(), &val)) { sError = "could not parse tokel royalty"; return false; } + std::cerr << __func__ << " val=" << val << std::endl; if (val < 0 || val >= TKLROYALTY_DIVISOR) { sError = "invalid tokel royalty value (must be in 0...999)"; return false; diff --git a/src/cc/CCTokelData.h b/src/cc/CCTokelData.h index 89dbd8f0b80..b1b5b8b13fb 100644 --- a/src/cc/CCTokelData.h +++ b/src/cc/CCTokelData.h @@ -23,7 +23,7 @@ enum tklPropType : uint8_t { TKLTYP_VUINT8 = 0x2 }; -typedef bool tklWriteSS(CDataStream &ss, const UniValue &val); +typedef bool tklWriteSS(CDataStream &ss, const UniValue &val, std::string &err); typedef UniValue tklReadSS(CDataStream &ss); @@ -34,6 +34,7 @@ bool GetTokelDataAsInt64(const vuint8_t &vdata, tklPropId propId, int64_t &val); bool GetTokelDataAsVuint8(const vuint8_t &vdata, tklPropId propId, vuint8_t &val); vuint8_t ParseTokelJson(const UniValue &jsonParams); UniValue ParseTokelVData(const vuint8_t &vdata); +bool CheckTokelData(const vuint8_t &vdata, std::string &sError); bool TokelDataValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 71ed2bca829..6bd4903b34b 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -381,6 +381,7 @@ UniValue tokencreatetokel(const UniValue& params, bool fHelp, const CPubKey& rem vuint8_t tokenData; if (params.size() >= 4) { UniValue jsonParams; + std::string sError; if (params[3].getType() == UniValue::VOBJ) jsonParams = params[3].get_array(); @@ -392,6 +393,8 @@ UniValue tokencreatetokel(const UniValue& params, bool fHelp, const CPubKey& rem tokenData = ParseTokelJson(jsonParams); if (tokenData.empty()) throw runtime_error("Tokel token data incorrect"); + if (!CheckTokelData(tokenData, sError)) + throw runtime_error("Tokel token data incorrect: " + sError); } return tokencreate(params, tokenData, fHelp, remotepk); @@ -411,6 +414,7 @@ UniValue tokenv2createtokel(const UniValue& params, bool fHelp, const CPubKey& r vuint8_t tokenData; if (params.size() >= 4) { UniValue jsonParams; + std::string sError; if (params[3].getType() == UniValue::VOBJ) jsonParams = params[3].get_array(); @@ -422,6 +426,8 @@ UniValue tokenv2createtokel(const UniValue& params, bool fHelp, const CPubKey& r tokenData = ParseTokelJson(jsonParams); if (tokenData.empty()) return MakeResultError("Token data incorrect"); + if (!CheckTokelData(tokenData, sError)) + throw runtime_error("Tokel token data incorrect: " + sError); } return tokencreate(params, tokenData, fHelp, remotepk); } From 075dc1ce3baddd0726816e1d0d3ab57894f2bc83 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 29 Jul 2021 13:24:01 +0500 Subject: [PATCH 085/348] del extra logging --- src/cc/CCTokelData.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index cd204539d21..6927d263a52 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -223,14 +223,12 @@ bool CheckTokelData(const vuint8_t &vdata, std::string &sError) std::map propMap; if (UnmarshalTokelVData(vdata, propMap, sError)) { // check props if present - std::cerr << __func__ << " propMap.count(TKLPROP_ROYALTY)=" << propMap.count(TKLPROP_ROYALTY) << std::endl; if (propMap.count(TKLPROP_ROYALTY) > 0) { int64_t val; if (!ParseInt64(propMap[TKLPROP_ROYALTY].getValStr(), &val)) { sError = "could not parse tokel royalty"; return false; } - std::cerr << __func__ << " val=" << val << std::endl; if (val < 0 || val >= TKLROYALTY_DIVISOR) { sError = "invalid tokel royalty value (must be in 0...999)"; return false; From e47e4e01d706743d89f755f3016711349b974cd3 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 29 Jul 2021 20:44:02 +0300 Subject: [PATCH 086/348] add S5 3rd-party notaries pubkeys for TOKEL - 3rd-party pubkeys for S5 added - S5 starts from nS5Timestamp = 1627466969 (TOKEL block #1 timestamp) --- src/komodo_defs.h | 80 +++++++++++++++++++++++++++++++++++++++++--- src/komodo_globals.h | 3 ++ 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 8db4492586e..6c2f7967d54 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -50,7 +50,7 @@ // 7113400 = 5x current KMD blockheight. // to add 4th season, change NUM_KMD_SEASONS to 4, and add timestamp and height of activation to these arrays. -#define NUM_KMD_SEASONS 5 +#define NUM_KMD_SEASONS 6 #define NUM_KMD_NOTARIES 64 extern const uint32_t nStakedDecemberHardforkTimestamp; //December 2019 hardfork @@ -59,8 +59,11 @@ extern const int32_t nDecemberHardforkHeight; //December 2019 hardfork extern const uint32_t nS4Timestamp; //dPoW Season 4 2020 hardfork extern const int32_t nS4HardforkHeight; //dPoW Season 4 2020 hardfork -static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, 1751328000}; -static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, 7113400}; +extern const uint32_t nS5Timestamp; //dPoW Season 5 June 14th, 2021 hardfork (03:00:00 PM UTC) (defined in komodo_globals.h) +extern const int32_t nS5HardforkHeight; //dPoW Season 5 June 14th, 2021 hardfork estimated block height (defined in komodo_globals.h) + +static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, 1751328000}; +static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, 7113400}; // Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = @@ -268,7 +271,7 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, - {"hunter_EU", "0378224b4e9d8a0083ce36f2963ec0a4e231ec06b0c780de108e37f41181a89f6a" }, // FIXME verify this, kolo. Change name if you want + {"hunter_EU", "0378224b4e9d8a0083ce36f2963ec0a4e231ec06b0c780de108e37f41181a89f6a" }, {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, @@ -324,7 +327,7 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, - {"hunter_SH", "02407db70ad30ce4dfaee8b4ae35fae88390cad2b0ba0373fdd6231967537ccfdf" }, // FIXME verify this, Decker. Change name if you want + {"hunter_SH", "02407db70ad30ce4dfaee8b4ae35fae88390cad2b0ba0373fdd6231967537ccfdf" }, {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, @@ -396,6 +399,73 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } + }, + { + // Season 5 + {"alrighttt_DEV", "02a876c6c35060041f6beadb201f4dfc567e80eedd3a4206ff10d99878087bd440" }, // 0 + {"alien_AR", "024f20c096b085308e21893383f44b4faf1cdedea9ad53cc7d7e7fbfa0c30c1e71" }, + {"artempikulin_AR", "03a45c4ad7f279cbc50acb48d81fc0eb63c4c5f556e3a4393fb3d6414df09c6e4c" }, + {"chmex_AR", "030cd487e10fbf142e0e8d582e702ecb775f378569c3cb5acd0ff97b6b12803588" }, + {"cipi_AR", "02336758998f474659020e6887ece61ac7b8567f9b2d38724ebf77ae800c1fb2b7" }, + {"shadowbit_AR", "03949b06c2773b4573aeb0b52e70ccc2d98dc5794a47e24eeb902c9d28e0e8d28b" }, + {"goldenman_AR", "03d745bc6921104b73734e6d9615671bc70b9e11e26c9b0c9abf0d2f9babd01a4d" }, + {"kolo_AR", "027579d0722b2f75b3d11a73829449e4251b4471716b6cb743c7667379750c8fb0" }, + {"madmax_AR", "02ddb23f18e61ea792ae0f28be5a52859e7963bf7f1d2c4f19eec18ac6497cfa2a" }, + {"mcrypt_AR", "02845d016c68c3e5ce924b164abc271511f3092ae359677a515e8f81a9533472f4" }, + {"mrlynch_AR", "03e67440141f53a08684c329ebc852b018e41f905da88e52aa4a6dc5aa4b12447a" }, // 10 + {"ocean_AR", "02d216e72d37a38449d661413cbc6e1f008b21cffdb06865f7be636e2cbc1e5346" }, + {"smdmitry_AR", "0397b7584cb29717b721c0c587d4462477efc1f36a56921f133c9d17b0cd7f278a" }, + {"tokel_AR", "02e4e07060fcd3640a3fd6d54cc15924f2bf63f8172b96a9f1d538ca7a0e490dc5" }, + {"tonyl_AR", "02e2d9ecdc9f462a4767f7dfe8ed243c98fcccc1511989a60e3f859dc6fda42d16" }, + {"tonyl_DEV", "0399c4f8c5b604cda64c1ccb8fdbd7a89730131519f87491a79b0811e619102d8f" }, + {"artem_DEV", "025ee88d1c12f546c1c8942d7a3e0678f10bc27cc566e27bf4a2d2178e018d18c6" }, + {"alien_EU", "022b85908191788f409506ebcf96a892f3274f352864c3ed566c5a16de63953236" }, + {"alienx_EU", "025de0911bab55616c307f02ea8a5915a2e0c8e479aa97968e7f00d1025cbe6c6d" }, + {"ca333_EU", "03a582cfae3760bb1cb38311d686cfeede8f8c4ce263aa1c082fc836c367859122" }, + {"chmex_EU", "030bf7bd7ad0515c33b5d5d9a91e0729baf801b9002f80495ae535ea1cebb352cb" }, // 20 + {"cipi_EU", "033a812d6cccdc4208378728f3a0e15db5b12074def9ab686ddc3752715ff1a194" }, + {"cipi2_EU", "0302ca28a041ed00544de737651bdec9bafe3b7f1c0bf2c6092f2368d59fec75c2" }, + {"shadowbit_EU", "025f8de3a6181270ceb5c31654e6a6e95d0339bc14b46b5e3050e8a69861c91baa" }, + {"komodopioneers_EU", "02fb31b130babe79ac780a6118702555a8c66875835f35c2232a6cb8b1438fe71d" }, + {"madmax_EU", "02e7e5306f159df252ecfded9bab6297050d12640b908b456ea553f90872f8a160" }, + {"marmarachain_EU", "027029380f49b0c3cc1b814976f1a83f0c25d84020ad0a27454e55ebdb2ccc83d7" }, + {"node-9_EU", "029401e427cffa29bb2bd7664110e160d525fac6f1518ac7b59343b16de301e0ac" }, + {"slyris_EU", "02a0705ec221a94a6a5b3ea2e763ba0350f8213c73e8dad49a708fb1e87acdc5f8" }, + {"smdmitry_EU", "0338f30ca34d0aca0d79b69abde447036aaaa75f482b6c75801fd382e984337d01" }, + {"van_EU", "0370305b9e91d46331da202ae733d6050d01038ef6eceb2036ada394a48fae84b9" }, // 30 + {"shadowbit_DEV", "03e2de3418c88be0cfe2fa0dcfdaea001b5a36ad86e6833ad284d79021ae7e2b94" }, + {"gcharang_DEV", "0321868e0eb39271330fa2c3a9f4e542275d9719f8b87773c5432448ab10d6943d" }, + {"alien_NA", "022f62b56ddfd07c9860921c701285ac39bb3ac8f6f083d1b59c8f4943be3de162" }, + {"alienx_NA", "025d5e11725233ab161f4f63d697c5f9f0c6b9d3aa2b9c68299638f8cc63faa9c2" }, + {"cipi_NA", "0335352862da521bd90b99d394db1ee3ecde379db9cf7ba2f28b16fa76153e289f" }, + {"computergenie_NA", "02f945d87b7cd6e9f2173a110399d36b369edb1f10bdf5a4ba6fd4923e2986e137" }, + {"dragonhound_NA", "0366a87a476a09e05560c5aae0e44d2ab9ba56e69701cee24307871ddd37c86258" }, + {"hyper_NA", "0303503ea8f5ec8bcab474962dfadd3561b44732b6ad308acd8d04276dd2f1baf3" }, + {"madmax_NA", "0378e47061572e4a406bbad1522c03c3331d0a6c820fde1248ccf2cbc72fec47c2" }, + {"node-9_NA", "03fac1468a949244dd4c563062459d46e966479fe23748382fc2e3e8d05218023e" }, // 40 + {"nodeone_NA", "0310a249c6c2dcc29f2135715138a9ddb8e01c0eab701cbd0b96d9cec660dbdc58" }, + {"pbca26_NA", "03e8485883eba6d4f2902338ab6aac87654a4b98d3bc01f89638aaf9c37db66ccf" }, + {"ptyx_NA", "028267c92db3c48a99dfb8d88e9cdab60d8a1525913ab3978b1b629667b12b1ee2" }, + {"strob_NA", "02285bf2f9e96068ecac14bc6f770e394927b4da9f5ba833eaa9468b5d47f203a3" }, + {"karasugoi_NA", "02f803e6f159824a181cc5d709f3d1e7ff65f19e1899920724aeb4e3d2d869f911" }, + {"webworker01_NA", "03d6c76aabe24fde7ce7cc37cff0899d50a20d4147ac0b2db812e2a1edcf0d5232" }, + {"yurii_DEV", "0243977da0533c7c1a37f0f6e30175225c9012d9f3f426180ff6e5710f5a50e32b" }, + {"ca333_DEV", "035f3413d71856ac0859f564ced42fe1ce5c5058df888f4592b8a11d34a5ba3a45" }, + {"chmex_SH", "03e09c8ee6ae20cde64857d116c4bb5d50db6de2887ac39ea3ccf6434b1abf8698" }, + {"collider_SH", "033a1b62de10c3802f359da7767b033eac3837b58530722f3ddd2f359a2cd0a8f9" }, // 50 + {"dappvader_SH", "02684e2e7425ffa36d331f7a2f9c4542b61e88370dc6b4313a5025643f82ee17fa" }, + {"drkush_SH", "0210320b03f00f10f16313eb6e8929b5be7e66a034a4e9b7d11f2d87aa92708c6c" }, + {"majora31_SH", "03bc75c112ac7c6a99d6eb3fe5582feef4fd1b43f11c08ad887e21c4c3bc4e9104" }, + {"mcrypt_SH", "027a4ca7b11d3456ff558c08bb04483a89c7f383448461fd0b6b3b07424aabe9a4" }, + {"metaphilibert_SH", "03b21ff042bf1730b28bde43f44c064578b41996117ac7634b567c3773089e3be3" }, + {"mylo_SH", "026a52dba25ca4deb225a5ef7fca117d59e20ef2319b00e1bb6750a5d61e5ed601" }, + {"nutellaLicka_SH", "03ca46ea9a32de632823419948188088069f5820023920d810da6076624adb9901" }, + {"pbca26_SH", "021b39173b2b966ab277799a1f148a1d9e6cf26020f5f7eb9708f020ee0461e9c0" }, + {"phit_SH", "021b893b7978284e3d73701a623f23104fcce27e70fb49427c215f9a7481f652da" }, + {"sheeba_SH", "030dd2c3c02cbc5b3c25e3c54ed02c1541951a6f5ecf8adbd353e8d9052d08b8fc" }, // 60 + {"strob_SH", "0213751a1c59d3489ca85b3d62a3d606dcef7f0428aa021c1978ea16fb38a2fad6" }, + {"strobnidan_SH", "033e33ef18effb979437cd202bb87dc32385e16ebd52d6f762d8a3b308d6f89c52" }, + {"dragonhound_DEV", "02b3c168ed4acd96594288cee3114c77de51b6afe1ab6a866887a13a96ee80f33c" } } }; diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 564be0bf4e1..ab3ed76f3a9 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -47,6 +47,9 @@ const int32_t nDecemberHardforkHeight = 1670000; //December 2019 hardfork const uint32_t nS4Timestamp = 1592146800; //dPoW Season 4 2020 hardfork Sunday, June 14th, 2020 03:00:00 PM UTC const int32_t nS4HardforkHeight = 1922000; //dPoW Season 4 2020 hardfork Sunday, June 14th, 2020 +const uint32_t nS5Timestamp = 1627466969; //dPoW Season 5 Wed Jul 28 2021 10:09:29 GMT+0000 (timestamp of TOKEL block #1) +const int32_t nS5HardforkHeight = 2437300; //dPoW Season 5 Monday, June 14th, 2021 + #define _COINBASE_MATURITY 100 int COINBASE_MATURITY = _COINBASE_MATURITY;//100; unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; From 85de12fde9748ae6131b5a310d2c79714cff083b Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 16 Aug 2021 14:11:48 +0500 Subject: [PATCH 087/348] added nspv token helpers --- src/cc/CCtokenutils.cpp | 2 + src/komodo_nSPV_fullnode.h | 4 +- src/rpc/tokensrpc.cpp | 95 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index d1521c618f1..3cd1731a326 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -416,6 +416,8 @@ CTxOut MakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount n CCwrapper payoutCond( MakeTokensv2CCcondMofN(evalcode1, evalcode2, M, pks) ); if (!CCtoAnon(payoutCond.get())) return vout; + + std::cerr << " CCtoAnon=" << cc_conditionToJSONString(payoutCond.get()) << std::endl; vout = CTxOut(nValue, CCPubKey(payoutCond.get(),true)); { diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index bd306331f20..5054d6a9377 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -35,7 +35,9 @@ static std::map nspv_remote_commands = { { "tokenask", false }, { "tokenbid", false }, { "tokenfillask", false }, { "tokenfillbid", false }, { "tokencancelask", false }, { "tokencancelbid", false }, { "tokenorders", false }, { "mytokenorders", false }, { "tokentransfer", false },{ "tokencreate", false }, { "tokenv2ask", true }, { "tokenv2bid", true }, { "tokenv2fillask", true }, { "tokenv2fillbid", true }, { "tokenv2cancelask", true }, { "tokenv2cancelbid", true }, - { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", true },{ "tokenv2create", true } + { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", true },{ "tokenv2create", true }, + // nspv helpers + { "createtxwithnormalinputs", true }, { "tokenv2addccinputs", true }, }; struct NSPV_ntzargs diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 6bd4903b34b..3c3f2995309 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -1063,6 +1063,97 @@ UniValue addccv2signature(const UniValue& params, bool fHelp, const CPubKey& rem } +UniValue createtxwithnormalinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || (params.size() < 1 || params.size() > 2)) + { + string msg = "createtxwithnormalinputs amount [pubkey]\n" + "\nReturns a new tx with added normal inputs and previous txns. Note that the caller must add the change output\n" + "\nArguments:\n" + //"address which utxos are added from\n" + "amount (in satoshi) which will be added as normal inputs (equal or more)\n" + "pubkey optional, if not set -pubkey used\n" + "Result: json object with created tx and added vin txns\n\n"; + throw runtime_error(msg); + } + /*std::string address = params[0].get_str(); + if (!CBitcoinAddress(address.c_str()).IsValid()) + throw runtime_error("address invalid");*/ + CAmount amount = atoll(params[0].get_str().c_str()); + if (amount <= 0) + throw runtime_error("amount invalid"); + + CPubKey usedpk = remotepk; + if (params.size() >= 2) { + CPubKey pk = pubkey2pk(ParseHex(params[1].get_str())); + if (!pk.IsValid()) + throw runtime_error("pubkey invalid"); + usedpk = pk; + } + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + std::vector vintxns; + CAmount added = AddNormalinputsRemote(mtx, usedpk, amount, CC_MAXVINS, &vintxns); + if (added < amount) + throw runtime_error("could not find normal inputs"); + + for (auto const & vin : mtx.vin) { + CTransaction tx; + uint256 hashBlock; + if (myGetTransaction(vin.prevout.hash, tx, hashBlock)) + vintxns.push_back(tx); + } + UniValue result (UniValue::VOBJ); + UniValue array (UniValue::VARR); + + result.pushKV("txhex", HexStr(E_MARSHAL(ss << mtx))); + for (auto const &vtx : vintxns) + array.push_back(HexStr(E_MARSHAL(ss << vtx))); + result.pushKV("previousTxns", array); + return result; +} + +UniValue tokenv2addccinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() != 3) + { + string msg = "tokenv2addccinputs tokenid pubkey amount\n" + "\nReturns a new tx with added token inputs and the matching previous txns. Note that the caller must add the change output\n" + "\nArguments:\n" + //"address which utxos are added from\n" + "amount (in satoshi) which will be added as normal inputs (equal or more)\n" + "Result: json object with created tx and added vin txns\n\n"; + throw runtime_error(msg); + } + + uint256 tokenid = Parseuint256(params[0].get_str().c_str()); + CPubKey pk = pubkey2pk( ParseHex(params[1].get_str().c_str()) ); + CAmount amount = atoll(params[2].get_str().c_str()); + if (amount <= 0) + throw runtime_error("amount invalid"); + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cp, C; + cp = CCinit(&C, EVAL_TOKENSV2); + + CAmount added = AddTokenCCInputs(cp, mtx, pk, tokenid, amount, CC_MAXVINS, false); + if (added < amount) + throw runtime_error("could not find token cc inputs"); + + UniValue result (UniValue::VOBJ); + UniValue array (UniValue::VARR); + + result.pushKV("txhex", HexStr(E_MARSHAL(ss << mtx))); + for (auto const &vin : mtx.vin) { + CTransaction vintx; + uint256 hashBlock; + if (myGetTransaction(vin.prevout.hash, vintx, hashBlock)) + array.push_back(HexStr(E_MARSHAL(ss << vintx))); + } + result.pushKV("previousTxns", array); + return result; +} + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- @@ -1109,6 +1200,10 @@ static const CRPCCommand commands[] = { "tokens v2", "tokenv2createtokel", &tokenv2createtokel, true }, { "tokens", "tokeninfotokel", &tokeninfotokel, true }, { "tokens v2", "tokenv2infotokel", &tokenv2infotokel, true }, + { "nspv", "createtxwithnormalinputs", &createtxwithnormalinputs, true }, + { "nspv", "tokenv2addccinputs", &tokenv2addccinputs, true }, + + }; void RegisterTokensRPCCommands(CRPCTable &tableRPC) From a9bf27452f832ea813a70ce338257fcac48f3468 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 25 Aug 2021 10:45:39 +0300 Subject: [PATCH 088/348] added missed locks for cs_main for nspv server side added AssertLockHeld(cs_main) to komodo_xxx() added tokenv2infotokel to enabled nspv rpcs --- src/komodo.h | 2 + src/komodo_bitcoind.h | 8 +++ src/komodo_nSPV_fullnode.h | 101 ++++++++++++++++++++++++++----------- src/komodo_nSPV_wallet.h | 1 + src/rpc/misc.cpp | 10 ++-- 5 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/komodo.h b/src/komodo.h index 88e741df7f7..71e8abe1421 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -820,6 +820,8 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash; int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count; + + AssertLockHeld(cs_main); if ( pindex == 0 ) { fprintf(stderr,"komodo_connectblock null pindex\n"); diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 15ab79f0e68..7a094b025d6 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -942,6 +942,7 @@ int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) uint32_t komodo_chainactive_timestamp() { + AssertLockHeld(cs_main); if ( chainActive.LastTip() != 0 ) return((uint32_t)chainActive.LastTip()->GetBlockTime()); else return(0); @@ -949,6 +950,7 @@ uint32_t komodo_chainactive_timestamp() CBlockIndex *komodo_chainactive(int32_t height) { + AssertLockHeld(cs_main); if ( chainActive.LastTip() != 0 ) { if ( height <= chainActive.LastTip()->GetHeight() ) @@ -961,6 +963,7 @@ CBlockIndex *komodo_chainactive(int32_t height) uint32_t komodo_heightstamp(int32_t height) { + AssertLockHeld(cs_main); CBlockIndex *ptr; if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 ) return(ptr->nTime); @@ -1273,6 +1276,8 @@ uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uin uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight) { uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex; + AssertLockHeld(cs_main); + if ( (pindex= chainActive[tipheight]) != 0 ) tiptime = (uint32_t)pindex->nTime; else fprintf(stderr,"cant find height[%d]\n",tipheight); @@ -1288,6 +1293,7 @@ uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 int32_t komodo_nextheight() { + AssertLockHeld(cs_main); CBlockIndex *pindex; int32_t ht; if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->GetHeight()) > 0 ) return(ht+1); @@ -1297,6 +1303,8 @@ int32_t komodo_nextheight() int32_t komodo_isrealtime(int32_t *kmdheightp) { struct komodo_state *sp; CBlockIndex *pindex; + + AssertLockHeld(cs_main); if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) *kmdheightp = sp->CURRENT_HEIGHT; else *kmdheightp = 0; diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 5054d6a9377..2075590e41d 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -37,7 +37,7 @@ static std::map nspv_remote_commands = { { "tokenv2ask", true }, { "tokenv2bid", true }, { "tokenv2fillask", true }, { "tokenv2fillbid", true }, { "tokenv2cancelask", true }, { "tokenv2cancelbid", true }, { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", true },{ "tokenv2create", true }, // nspv helpers - { "createtxwithnormalinputs", true }, { "tokenv2addccinputs", true }, + { "createtxwithnormalinputs", true }, { "tokenv2addccinputs", true }, { "tokenv2infotokel", true } }; struct NSPV_ntzargs @@ -89,6 +89,8 @@ int32_t NSPV_notarized_bracket(struct NSPV_ntzargs *prev,struct NSPV_ntzargs *ne int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint256 desttxid,int32_t ntzheight) { CBlockIndex *pindex; + + LOCK(cs_main); ptr->blockhash = *chainActive[ntzheight]->phashBlock; ptr->height = ntzheight; ptr->txidheight = txidht; @@ -102,8 +104,11 @@ int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint int32_t NSPV_getntzsresp(struct NSPV_ntzsresp *ptr,int32_t origreqheight) { struct NSPV_ntzargs prev,next; int32_t reqheight = origreqheight; - if ( reqheight < chainActive.LastTip()->GetHeight() ) - reqheight++; + { + LOCK(cs_main); + if ( reqheight < chainActive.LastTip()->GetHeight() ) + reqheight++; + } if ( NSPV_notarized_bracket(&prev,&next,reqheight) == 0 ) { if ( prev.ntzheight != 0 ) @@ -124,6 +129,8 @@ int32_t NSPV_getntzsresp(struct NSPV_ntzsresp *ptr,int32_t origreqheight) int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) { CBlockIndex *pindex; + LOCK(cs_main); + if ( (pindex= komodo_chainactive(height)) != 0 ) { hdr->nVersion = pindex->nVersion; @@ -143,33 +150,46 @@ int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) { - int32_t prevMoMheight,len = 0; CBlockIndex *pindex, *pindex2; struct NSPV_ntzsresp pair; - if ( (pindex= chainActive.LastTip()) != 0 ) - { + int32_t prevMoMheight, len = 0; + CBlockIndex *pindex, *pindex2; + struct NSPV_ntzsresp pair; + LOCK(cs_main); + + if ((pindex = chainActive.LastTip()) != 0) { ptr->height = pindex->GetHeight(); ptr->blockhash = pindex->GetBlockHash(); - memset(&pair,0,sizeof(pair)); - if ( NSPV_getntzsresp(&pair,ptr->height-1) < 0 ) - return(-1); + memset(&pair, 0, sizeof(pair)); + if (NSPV_getntzsresp(&pair, ptr->height - 1) < 0) + return (-1); ptr->notarization = pair.prevntz; - if ( (pindex2= komodo_chainactive(ptr->notarization.txidheight)) != 0 ) + if ((pindex2 = komodo_chainactive(ptr->notarization.txidheight)) != 0) ptr->notarization.timestamp = pindex->nTime; //fprintf(stderr, "timestamp.%i\n", ptr->notarization.timestamp ); - if ( reqheight == 0 ) + if (reqheight == 0) reqheight = ptr->height; ptr->hdrheight = reqheight; ptr->version = NSPV_PROTOCOL_VERSION; - if ( NSPV_setequihdr(&ptr->H,reqheight) < 0 ) - return(-1); - return(sizeof(*ptr)); - } else return(-1); + if (NSPV_setequihdr(&ptr->H, reqheight) < 0) + return (-1); + return (sizeof(*ptr)); + } else + return (-1); } int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC,int32_t skipcount,uint32_t filter) { - int64_t total = 0,interest=0; uint32_t locktime; int32_t ind=0,tipheight,maxlen,txheight,n = 0,len = 0; + CAmount total = 0, interest = 0; + uint32_t locktime; + int32_t ind = 0, tipheight, maxlen, txheight, n = 0, len = 0; + std::vector > unspentOutputs; SetCCunspents(unspentOutputs,coinaddr,isCC); + + { + LOCK(cs_main); + tipheight = chainActive.LastTip()->GetHeight(); + } + maxlen = MAX_BLOCK_SIZE(tipheight) - 512; maxlen /= sizeof(*ptr->utxos); strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); @@ -179,7 +199,6 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC skipcount = 0; if ( (ptr->numutxos= (int32_t)unspentOutputs.size()) >= 0 && ptr->numutxos < maxlen ) { - tipheight = chainActive.LastTip()->GetHeight(); ptr->nodeheight = tipheight; if ( skipcount >= ptr->numutxos ) skipcount = ptr->numutxos-1; @@ -335,6 +354,10 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ std::vector > unspentOutputs; SetCCunspents(unspentOutputs, coinaddr, true); + { + LOCK(cs_main); + tipheight = chainActive.LastTip()->GetHeight(); + } maxlen = MAX_BLOCK_SIZE(tipheight) - 512; //maxlen /= sizeof(*ptr->utxos); // TODO why was this? we need maxlen in bytes, don't we? @@ -345,7 +368,7 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ ptr->numutxos = 0; strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = 1; - tipheight = chainActive.LastTip()->GetHeight(); + ptr->nodeheight = tipheight; // will be checked in libnspv //} @@ -631,7 +654,10 @@ int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector txids; bits256 satoshis; uint256 tmp,tmpdest; int32_t i,len = 0; - ptr->nodeheight = chainActive.LastTip()->GetHeight(); + { + LOCK(cs_main); + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + } strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); ptr->CCflag = isCC; ptr->txid = txid; @@ -753,7 +779,7 @@ int32_t NSPV_sendrawtransaction(struct NSPV_broadcastresp *ptr,uint8_t *data,int //LOCK(cs_main); ptr->txid = tx.GetHash(); //fprintf(stderr,"try to addmempool transaction %s\n",ptr->txid.GetHex().c_str()); - if ( myAddtomempool(tx) != 0 ) + if (myAddtomempool(tx) != 0) { ptr->retcode = 1; //int32_t i; @@ -761,9 +787,13 @@ int32_t NSPV_sendrawtransaction(struct NSPV_broadcastresp *ptr,uint8_t *data,int // fprintf(stderr,"%02x",data[i]); fprintf(stderr," relay transaction %s retcode.%d\n",ptr->txid.GetHex().c_str(),ptr->retcode); RelayTransaction(tx); - } else ptr->retcode = -3; + } + else + ptr->retcode = -3; - } else ptr->retcode = -1; + } + else + ptr->retcode = -1; return(sizeof(*ptr)); } @@ -772,29 +802,36 @@ int32_t NSPV_sendrawtransaction(struct NSPV_broadcastresp *ptr,uint8_t *data,int // otherwise only block hash alone will be returned int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid, int32_t height) { - int32_t flag = 0, len = 0; + int32_t len = 0; CTransaction _tx; uint256 hashBlock; CBlock block; CBlockIndex* pindex; ptr->height = -1; - if ((ptr->tx = NSPV_getrawtx(_tx, hashBlock, &ptr->txlen, txid)) != 0) { + if ((ptr->tx = NSPV_getrawtx(_tx, hashBlock, &ptr->txlen, txid)) != nullptr) { ptr->txid = txid; ptr->vout = vout; ptr->hashblock = hashBlock; - if (height == 0) + if (height == 0) { + LOCK(cs_main); ptr->height = komodo_blockheight(hashBlock); + } else { ptr->height = height; - if ((pindex = komodo_chainactive(height)) != 0 && komodo_blockload(block, pindex) == 0) { + { + LOCK(cs_main); + pindex = komodo_chainactive(height); + } + if (pindex != nullptr && komodo_blockload(block, pindex) == 0) { + bool found = false; BOOST_FOREACH (const CTransaction& tx, block.vtx) { if (tx.GetHash() == txid) { - flag = 1; + found = true; break; } } - if (flag != 0) { + if (found) { set setTxids; CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); setTxids.insert(txid); @@ -809,6 +846,9 @@ int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid, in } //fprintf(stderr,"gettxproof slen.%d\n",(int32_t)(sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen)); } + else { + LogPrint("nspv-details", "%s txid=%s not found in the block of ht=%d", __func__, txid.GetHex().c_str(), ptr->height); + } } } ptr->unspentvalue = CCgettxout(txid, vout, 1, 1); @@ -819,6 +859,9 @@ int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid, in int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp *ptr,uint256 prevntztxid,uint256 nextntztxid) { int32_t i; uint256 hashBlock,bhash0,bhash1,desttxid0,desttxid1; CTransaction tx; + + LOCK(cs_main); + ptr->prevtxid = prevntztxid; ptr->prevntz = NSPV_getrawtx(tx,hashBlock,&ptr->prevtxlen,ptr->prevtxid); ptr->prevtxidht = komodo_blockheight(hashBlock); @@ -829,7 +872,7 @@ int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp *ptr,uint256 prevntztxid ptr->nexttxid = nextntztxid; ptr->nextntz = NSPV_getrawtx(tx,hashBlock,&ptr->nexttxlen,ptr->nexttxid); - ptr->nexttxidht = komodo_blockheight(hashBlock); + ptr->nexttxidht = ptr->prevtxidht; // komodo_blockheight(hashBlock); if ( NSPV_notarizationextract(0,&ptr->common.nextht,&bhash1,&desttxid1,tx) < 0 ) return(-5); else if ( komodo_blockheight(bhash1) != ptr->common.nextht ) diff --git a/src/komodo_nSPV_wallet.h b/src/komodo_nSPV_wallet.h index 658d782c976..465af980754 100644 --- a/src/komodo_nSPV_wallet.h +++ b/src/komodo_nSPV_wallet.h @@ -389,6 +389,7 @@ UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis) // what its a mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; mtx.nVersion = SAPLING_TX_VERSION; if ( ASSETCHAINS_SYMBOL[0] == 0 ) { + LOCK(cs_main); if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) mtx.nLockTime = (uint32_t)time(NULL) - 777; else diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 56b3a515b77..46b6077726b 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -221,11 +221,11 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) + HelpExampleCli("getinfo", "") + HelpExampleRpc("getinfo", "") ); - //#ifdef ENABLE_WALLET - // LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); - //#else - LOCK(cs_main); - //#endif + #ifdef ENABLE_WALLET + LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); + #else + LOCK(cs_main); + #endif proxyType proxy; GetProxy(NET_IPV4, proxy); From 4b563361d77a8f52e53251d31f92f49b503d2700 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 26 Aug 2021 22:19:06 +0300 Subject: [PATCH 089/348] added LOCK(cs_main) in komodo_nextheight --- src/komodo_bitcoind.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 7a094b025d6..1395932e166 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1293,11 +1293,18 @@ uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 int32_t komodo_nextheight() { - AssertLockHeld(cs_main); - CBlockIndex *pindex; int32_t ht; - if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->GetHeight()) > 0 ) - return(ht+1); - else return(komodo_longestchain() + 1); + CBlockIndex* pindex; + int32_t ht; + + { + LOCK(cs_main); // dimxy added to protect chainActive concurrent use. + pindex = chainActive.LastTip(); + } + + if (pindex != nullptr && (ht = pindex->GetHeight()) > 0) + return (ht + 1); + else + return (komodo_longestchain() + 1); } int32_t komodo_isrealtime(int32_t *kmdheightp) From 735b5de09a04b9f15d6da9abbc0e8ce5f7d08b4d Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 26 Aug 2021 22:20:28 +0300 Subject: [PATCH 090/348] some func decls in .cpp removed --- src/bitcoind.cpp | 22 +++++++++++++--------- src/komodo_globals.h | 1 + src/wallet/wallet.cpp | 4 +++- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index ef7b09a37f0..ce16e6ddd38 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -57,15 +57,19 @@ static bool fDaemon; #include "komodo_defs.h" -#define KOMODO_ASSETCHAIN_MAXLEN 65 -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern int32_t ASSETCHAINS_BLOCKTIME; -extern uint64_t ASSETCHAINS_CBOPRET; -void komodo_passport_iteration(); -uint64_t komodo_interestsum(); -int32_t komodo_longestchain(); -void komodo_cbopretupdate(int32_t forceflag); -CBlockIndex *komodo_chainactive(int32_t height); +#include "komodo_globals.h" + +// #define KOMODO_ASSETCHAIN_MAXLEN 65 + +// extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +// extern int32_t ASSETCHAINS_BLOCKTIME; +// extern uint64_t ASSETCHAINS_CBOPRET; +// void komodo_passport_iteration(); +// uint64_t komodo_interestsum(); +// int32_t komodo_longestchain(); +// void komodo_cbopretupdate(int32_t forceflag); +// CBlockIndex *komodo_chainactive(int32_t height); + void WaitForShutdown(boost::thread_group* threadGroup) { diff --git a/src/komodo_globals.h b/src/komodo_globals.h index ab3ed76f3a9..21c86e859e1 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -14,6 +14,7 @@ ******************************************************************************/ #include "komodo_defs.h" +#include "komodo_structs.h" void komodo_prefetch(FILE *fp); uint32_t komodo_heightstamp(int32_t height); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index db66de052c4..5b5ea57bae1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -38,6 +38,8 @@ #include "crypter.h" #include "coins.h" #include "zcash/zip32.h" + +#include "komodo_globals.h" #include "cc/CCinclude.h" #include @@ -4222,7 +4224,7 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge } -void komodo_prefetch(FILE *fp); +//void komodo_prefetch(FILE *fp); DBErrors CWallet::LoadWallet(bool& fFirstRunRet) { From fd100afbafcbabbdb7cf82a795c63984f16157a2 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 26 Aug 2021 22:36:59 +0300 Subject: [PATCH 091/348] some func decls moved to komodo_defs to avoid redeclaration in .cpp --- src/bitcoind.cpp | 1 - src/komodo-tx.cpp | 3 ++- src/komodo_defs.h | 16 ++++++++++++++++ src/komodo_globals.h | 16 ---------------- src/wallet/wallet.cpp | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index ce16e6ddd38..2d8382a7439 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -57,7 +57,6 @@ static bool fDaemon; #include "komodo_defs.h" -#include "komodo_globals.h" // #define KOMODO_ASSETCHAIN_MAXLEN 65 diff --git a/src/komodo-tx.cpp b/src/komodo-tx.cpp index 21752778454..d25cbc8af42 100644 --- a/src/komodo-tx.cpp +++ b/src/komodo-tx.cpp @@ -41,9 +41,10 @@ using namespace std; #include "uint256.h" #include "arith_uint256.h" +#include "komodo_defs.h" #include "komodo_structs.h" #include "komodo_globals.h" -#include "komodo_defs.h" + #include "komodo_interest.h" diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 6c2f7967d54..091bba306a4 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -581,6 +581,22 @@ uint32_t komodo_chainactive_timestamp(); uint32_t GetLatestTimestamp(int32_t height); int32_t komodo_get_current_height(); +void komodo_prefetch(FILE *fp); +uint32_t komodo_heightstamp(int32_t height); +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); +void komodo_init(int32_t height); +int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); +int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); +char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); +void komodo_init(int32_t height); +int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); +int32_t komodo_isrealtime(int32_t *kmdheightp); +uint64_t komodo_paxtotal(); +int32_t komodo_longestchain(); +uint64_t komodo_maxallowed(int32_t baseid); +int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); +int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); + #ifndef KOMODO_NSPV_FULLNODE #define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) #endif // !KOMODO_NSPV_FULLNODE diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 21c86e859e1..a5f8ad453b0 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -16,22 +16,6 @@ #include "komodo_defs.h" #include "komodo_structs.h" -void komodo_prefetch(FILE *fp); -uint32_t komodo_heightstamp(int32_t height); -void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); -void komodo_init(int32_t height); -int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); -int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); -char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); -void komodo_init(int32_t height); -int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); -int32_t komodo_isrealtime(int32_t *kmdheightp); -uint64_t komodo_paxtotal(); -int32_t komodo_longestchain(); -uint64_t komodo_maxallowed(int32_t baseid); -int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); -int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); - pthread_mutex_t komodo_mutex,staked_mutex; #define KOMODO_ELECTION_GAP 2000 //((ASSETCHAINS_SYMBOL[0] == 0) ? 2000 : 100) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5b5ea57bae1..6db007fb2fb 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -39,7 +39,7 @@ #include "coins.h" #include "zcash/zip32.h" -#include "komodo_globals.h" +#include "komodo_defs.h" #include "cc/CCinclude.h" #include From afc6ba420045483c7f805e5e9b1db331ae6adef7 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 27 Aug 2021 15:40:34 +0300 Subject: [PATCH 092/348] code refactor: declarations moved from .cpp to komodo_defs.h or else --- src/alert.h | 2 + src/bitcoind.cpp | 15 +- src/cc/CCImportGateway.h | 4 + src/cc/CCcustom.cpp | 1 + src/cc/CCinclude.h | 10 - src/cc/CCutils.cpp | 153 +--- src/cc/import.cpp | 11 +- src/cc/importgateway.cpp | 2 +- src/crosschain.cpp | 2 - src/deprecation.cpp | 2 +- src/importcoin.cpp | 3 - src/importcoin.h | 3 + src/init.cpp | 13 +- src/init.h | 2 + src/komodo.h | 7 +- src/komodo_DEX.h | 56 +- src/komodo_bitcoind.h | 14 +- src/komodo_defs.h | 88 +- src/komodo_gateway.h | 4 - src/komodo_globals.h | 1 - src/komodo_nSPV_wallet.h | 4 +- src/komodo_utils.h | 161 +++- src/main.cpp | 21 +- src/miner.cpp | 37 +- src/rest.cpp | 6 - src/rpc/blockchain.cpp | 18 +- src/rpc/misc.cpp | 26 +- src/rpc/net.cpp | 63 -- src/rpc/rawtransaction.cpp | 10 +- src/rpc/server.h | 11 + src/rpcblockchain.old | 1625 ------------------------------------ src/wallet/rpcwallet.cpp | 10 - src/wallet/wallet.cpp | 5 - 33 files changed, 368 insertions(+), 2022 deletions(-) delete mode 100644 src/rpcblockchain.old diff --git a/src/alert.h b/src/alert.h index 16204c9c533..cd978c5546f 100644 --- a/src/alert.h +++ b/src/alert.h @@ -124,4 +124,6 @@ class CAlert : public CUnsignedAlert static CAlert getAlertByHash(const uint256 &hash); }; +void ThreadSendAlert(); + #endif // BITCOIN_ALERT_H diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 2d8382a7439..0374b2e90e1 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -58,18 +58,6 @@ static bool fDaemon; #include "komodo_defs.h" -// #define KOMODO_ASSETCHAIN_MAXLEN 65 - -// extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -// extern int32_t ASSETCHAINS_BLOCKTIME; -// extern uint64_t ASSETCHAINS_CBOPRET; -// void komodo_passport_iteration(); -// uint64_t komodo_interestsum(); -// int32_t komodo_longestchain(); -// void komodo_cbopretupdate(int32_t forceflag); -// CBlockIndex *komodo_chainactive(int32_t height); - - void WaitForShutdown(boost::thread_group* threadGroup) { int32_t i,height; CBlockIndex *pindex; const uint256 zeroid; @@ -111,11 +99,12 @@ void WaitForShutdown(boost::thread_group* threadGroup) // // Start // +/* extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY; extern uint32_t ASSETCHAIN_INIT; extern std::string NOTARY_PUBKEY; int32_t komodo_is_issuer(); -void komodo_passport_iteration(); +*/ bool AppInit(int argc, char* argv[]) { diff --git a/src/cc/CCImportGateway.h b/src/cc/CCImportGateway.h index ee741a1487e..a139538803e 100644 --- a/src/cc/CCImportGateway.h +++ b/src/cc/CCImportGateway.h @@ -33,4 +33,8 @@ UniValue ImportGatewayExternalAddress(uint256 bindtxid,CPubKey pubkey); UniValue ImportGatewayDumpPrivKey(uint256 bindtxid,CKey key); UniValue ImportGatewayList(); UniValue ImportGatewayInfo(uint256 bindtxid); + +int64_t ImportGatewayVerify(char *refdepositaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2); +uint8_t DecodeImportGatewayBindOpRet(char *depositaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); + #endif diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 18d92ceb92c..9a460f96780 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -14,6 +14,7 @@ ******************************************************************************/ #include "key_io.h" + #include "CCinclude.h" #include "CCassets.h" #include "CCfaucet.h" diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index dff7522e2e1..e21371f5278 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -1037,16 +1037,6 @@ UniValue OracleFormat(uint8_t *data,int32_t datalen,char *format,int32_t formatl /// @private CScript GetCCDropAsOpret(const CScript &scriptPubKey); -/*! \cond INTERNAL */ -// curve25519 and sha256 -bits256 curve25519_shared(bits256 privkey,bits256 otherpub); -bits256 curve25519_basepoint9(); -bits256 curve25519(bits256 mysecret,bits256 basepoint); -void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); -bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); -// UniValue ValueFromAmount(const CAmount& amount); // defined in server.h -/*! \endcond */ - /*! \cond INTERNAL */ CAmount TotalPubkeyNormalInputs(Eval *eval, const CTransaction &tx, const CPubKey &pubkey); CAmount TotalPubkeyCCInputs(Eval *eval, const CTransaction &tx, const CPubKey &pubkey); diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 6721f4b7a5c..aa28ef33e17 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -16,25 +16,14 @@ /* CCutils has low level functions that are universally useful for all contracts. */ - +#include "key_io.h" +#include "komodo_defs.h" +#include "komodo_structs.h" #include "CCinclude.h" #include "CCtokens.h" -#include "komodo_structs.h" -#include "komodo_defs.h" -#include "key_io.h" - thread_local CCERROR CCerror = ""; -#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; - void endiancpy(uint8_t *dest,uint8_t *src,int32_t len) { int32_t i,j=0; @@ -846,94 +835,6 @@ uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::ve return merkleBlock.txn.ExtractMatches(txids); } -int64_t komodo_get_blocktime(uint256 hashBlock) -{ - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi != mapBlockIndex.end() && (*mi).second) - { - CBlockIndex* pindex = (*mi).second; - if (chainActive.Contains(pindex)) - return pindex->GetBlockTime(); - } - return 0; -} - -extern struct NSPV_inforesp NSPV_inforesult; -int32_t komodo_get_current_height() -{ - if ( KOMODO_NSPV_SUPERLITE ) - { - return (NSPV_inforesult.height); - } - else return chainActive.LastTip()->GetHeight(); -} - -bool komodo_txnotarizedconfirmed(uint256 txid, int32_t minconfirms) -{ - char str[65]; - int32_t confirms,minimumconfirms,notarized=0,txheight=0,currentheight=0;; - CTransaction tx; - uint256 hashBlock; - CBlockIndex *pindex; - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - - if (minconfirms==0) return (true); - if ( KOMODO_NSPV_SUPERLITE ) - { - if ( NSPV_myGetTransaction(txid,tx,hashBlock,txheight,currentheight) == 0 ) - { - fprintf(stderr,"komodo_txnotarizedconfirmed cant find txid %s\n",txid.ToString().c_str()); - return(0); - } - else if (txheight<=0) - { - fprintf(stderr,"komodo_txnotarizedconfirmed no txheight.%d for txid %s\n",txheight,txid.ToString().c_str()); - return(0); - } - else if (txheight>currentheight) - { - fprintf(stderr,"komodo_txnotarizedconfirmed backwards heights for txid %s hts.(%d %d)\n",txid.ToString().c_str(),txheight,currentheight); - return(0); - } - confirms=1 + currentheight - txheight; - } - else - { - 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= komodo_blockindex(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 (minconfirms>1) minimumconfirms=minconfirms; - else minimumconfirms=MIN_NON_NOTARIZED_CONFIRMS; - 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 >= minimumconfirms) - return (true); - return (false); -} - CPubKey check_signing_pubkey(CScript scriptSig) { bool found = false; @@ -1234,54 +1135,6 @@ uint8_t *SuperNET_ciphercalc(uint8_t **ptrp,int32_t *cipherlenp,bits256 privkey, return(origptr); } -uint8_t *komodo_DEX_encrypt(uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 destpubkey,bits256 privkey) -{ - int32_t cipherlen; uint8_t *cipher; - cipher = SuperNET_ciphercalc(allocatedp,&cipherlen,privkey,destpubkey,data,*datalenp); - *datalenp = cipherlen; - return(cipher); -} - -uint8_t *komodo_DEX_decrypt(uint8_t *senderpub,uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 privkey) -{ - int32_t msglen; - *allocatedp = 0; - if ( (msglen= *datalenp) <= crypto_box_NONCEBYTES + crypto_box_ZEROBYTES + sizeof(bits256) ) - { - *datalenp = 0; - return(0); - } - if ( (data= SuperNET_deciphercalc(senderpub,allocatedp,&msglen,privkey,data,*datalenp)) == 0 ) - { - //printf("komodo_DEX_decrypt decrytion error\n"); - *datalenp = 0; - return(0); - } else *datalenp = msglen; - return(data); -} - -void komodo_DEX_privkey(bits256 &privkey) -{ - bits256 priv,hash; - Myprivkey(priv.bytes); - vcalc_sha256(0,hash.bytes,priv.bytes,32); - vcalc_sha256(0,privkey.bytes,hash.bytes,32); - memset(priv.bytes,0,sizeof(priv)); - memset(hash.bytes,0,sizeof(hash)); -} - -void komodo_DEX_pubkey(bits256 &pubkey) -{ - bits256 privkey; - komodo_DEX_privkey(privkey); - /*{ - char *bits256_str(char hexstr[65],bits256 x); - char str[65]; - fprintf(stderr,"new DEX_privkey %s\n",bits256_str(str,privkey)); - }*/ - pubkey = curve25519(privkey,curve25519_basepoint9()); - memset(privkey.bytes,0,sizeof(privkey)); -} // add probe vintx conditions for making CCSig in FinalizeCCTx void CCAddVintxCond(struct CCcontract_info *cp, const CCwrapper &condWrapped, const uint8_t *priv) diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 1a8c2f4519b..d59ecc282d5 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -13,14 +13,16 @@ * * ******************************************************************************/ +#include #include "cc/eval.h" #include "cc/utils.h" +#include "komodo_defs.h" #include "importcoin.h" #include "crosschain.h" #include "primitives/transaction.h" #include "cc/CCinclude.h" -#include #include "cc/CCtokens.h" +#include "cc/CCImportGateway.h" #include "key_io.h" #define CODA_BURN_ADDRESS "KPrrRoPfHOnNpZZQ6laHXdQDkSQDkVHaN0V+LizLlHxz7NaA59sBAAAA" @@ -33,8 +35,9 @@ ##### 0xffffffff is a special CCid for single chain/dual daemon imports */ -extern std::string ASSETCHAINS_SELFIMPORT; -extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT; +/* todo remove*/ + +/* extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; extern uint256 KOMODO_EARLYTXID; @@ -47,7 +50,7 @@ int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvo char *nonportable_path(char *str); char *portable_path(char *str); void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); -void *filestr(long *allocsizep,char *_fname); +void *filestr(long *allocsizep,char *_fname);*/ cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,char const *arg3,char const *arg4,char const *arg5) { diff --git a/src/cc/importgateway.cpp b/src/cc/importgateway.cpp index 782fcc9e6fc..8948ec5c731 100644 --- a/src/cc/importgateway.cpp +++ b/src/cc/importgateway.cpp @@ -13,9 +13,9 @@ * * ******************************************************************************/ -#include "CCImportGateway.h" #include "key_io.h" #include "../importcoin.h" +#include "CCImportGateway.h" // start of consensus code diff --git a/src/crosschain.cpp b/src/crosschain.cpp index 0a081c0868a..375d5ac9174 100644 --- a/src/crosschain.cpp +++ b/src/crosschain.cpp @@ -43,8 +43,6 @@ int NOTARISATION_SCAN_LIMIT_BLOCKS = 1440; -CBlockIndex *komodo_getblockindex(uint256 hash); - /* On KMD */ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, diff --git a/src/deprecation.cpp b/src/deprecation.cpp index 6005918ec66..9d84fab0761 100644 --- a/src/deprecation.cpp +++ b/src/deprecation.cpp @@ -25,9 +25,9 @@ #include "ui_interface.h" #include "util.h" #include "chainparams.h" +#include "komodo_defs.h" static const std::string CLIENT_VERSION_STR = FormatVersion(CLIENT_VERSION); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; void EnforceNodeDeprecation(int nHeight, bool forceLogging, bool fThread) { diff --git a/src/importcoin.cpp b/src/importcoin.cpp index db1346f286c..1b0224685a5 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -28,9 +28,6 @@ #include "cc/CCtokens.h" #include "cc/CCtokens_impl.h" - -//int32_t komodo_nextheight(); - // makes import tx for either coins or tokens CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride) { diff --git a/src/importcoin.h b/src/importcoin.h index 0f7c52aa520..16dc49150d1 100644 --- a/src/importcoin.h +++ b/src/importcoin.h @@ -122,4 +122,7 @@ bool CheckVinPubKey(const CTransaction &sourcetx, int32_t i, uint8_t pubkey33[33 CMutableTransaction MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount); int32_t GetSelfimportProof(const CMutableTransaction sourceMtx, CMutableTransaction &templateMtx, ImportProof &proofNull); +extern std::string ASSETCHAINS_SELFIMPORT; +extern uint16_t ASSETCHAINS_CODAPORT, ASSETCHAINS_BEAMPORT; + #endif /* IMPORTCOIN_H */ \ No newline at end of file diff --git a/src/init.cpp b/src/init.cpp index fdbb56fd765..74c23c977fc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -23,6 +23,7 @@ #endif #include "init.h" +#include "alert.h" #include "crypto/common.h" #include "primitives/block.h" #include "addrman.h" @@ -93,14 +94,6 @@ using namespace std; #include "komodo_defs.h" -extern void ThreadSendAlert(); -extern bool komodo_dailysnapshot(int32_t height); -extern int32_t KOMODO_LOADINGBLOCKS; -extern bool VERUS_MINTBLOCKS; -extern char ASSETCHAINS_SYMBOL[]; -extern int32_t KOMODO_SNAPSHOT_INTERVAL; - -extern void komodo_init(int32_t height); ZCJoinSplit* pzcashParams = NULL; @@ -754,10 +747,6 @@ void ThreadNotifyRecentlyAdded() } } -/* declarations needed for ThreadUpdateKomodoInternals */ -void komodo_passport_iteration(); -void komodo_cbopretupdate(int32_t forceflag); - void ThreadUpdateKomodoInternals() { RenameThread("int-updater"); diff --git a/src/init.h b/src/init.h index 108339865be..7bef5d37836 100644 --- a/src/init.h +++ b/src/init.h @@ -51,4 +51,6 @@ enum HelpMessageMode { /** Help for options shared between UI and daemon (for -help) */ std::string HelpMessage(HelpMessageMode mode); +extern std::atomic fRequestShutdown; + #endif // BITCOIN_INIT_H diff --git a/src/komodo.h b/src/komodo.h index 71e8abe1421..6404729fbdd 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -37,10 +37,7 @@ uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID; #include "uthash.h" #include "utlist.h" -int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); -void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); -int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); -bool check_pprevnotarizedht(); +//bool check_pprevnotarizedht(); #include "komodo_structs.h" #include "komodo_globals.h" @@ -792,7 +789,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar // if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed // OP_RETURN: 'D' -> deposit, 'W' -> withdraw -int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); +//int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]) { diff --git a/src/komodo_DEX.h b/src/komodo_DEX.h index 4eb4c9ef524..c2711f0af57 100644 --- a/src/komodo_DEX.h +++ b/src/komodo_DEX.h @@ -60,11 +60,6 @@ detect evil peer: 'Q' is directly protected by txpow, G is a fixed size, so it cant be very big and invalid request can be detected. 'P' message will lead to 'G' queries that cannot be answered, 'R' needs to have high priority */ -uint8_t *komodo_DEX_encrypt(uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 pubkey,bits256 privkey); -uint8_t *komodo_DEX_decrypt(uint8_t *senderpub,uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 privkey); -void komodo_DEX_pubkey(bits256 &pub0); -void komodo_DEX_privkey(bits256 &priv0); -int32_t komodo_DEX_request(int32_t priority,uint32_t shorthash,uint32_t timestamp,char *tagA,char *tagB); #define KOMODO_DEX_PURGELIST 0 @@ -171,6 +166,29 @@ static struct DEX_globals FILE *fp; } *G; +void komodo_DEX_privkey(bits256 &privkey) +{ + bits256 priv,hash; + Myprivkey(priv.bytes); + vcalc_sha256(0,hash.bytes,priv.bytes,32); + vcalc_sha256(0,privkey.bytes,hash.bytes,32); + memset(priv.bytes,0,sizeof(priv)); + memset(hash.bytes,0,sizeof(hash)); +} + +void komodo_DEX_pubkey(bits256 &pubkey) +{ + bits256 privkey; + komodo_DEX_privkey(privkey); + /*{ + char *bits256_str(char hexstr[65],bits256 x); + char str[65]; + fprintf(stderr,"new DEX_privkey %s\n",bits256_str(str,privkey)); + }*/ + pubkey = curve25519(privkey,curve25519_basepoint9()); + memset(privkey.bytes,0,sizeof(privkey)); +} + void komodo_DEX_pubkeyupdate() { komodo_DEX_pubkey(DEX_pubkey); @@ -253,6 +271,34 @@ uint32_t komodo_DEXquotehash(bits256 &hash,uint8_t *msg,int32_t len) return(_komodo_DEXquotehash(hash,len)); } +uint8_t *komodo_DEX_encrypt(uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 destpubkey,bits256 privkey) +{ + int32_t cipherlen; uint8_t *cipher; + cipher = SuperNET_ciphercalc(allocatedp,&cipherlen,privkey,destpubkey,data,*datalenp); + *datalenp = cipherlen; + return(cipher); +} + +uint8_t *komodo_DEX_decrypt(uint8_t *senderpub,uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 privkey) +{ + int32_t msglen; + *allocatedp = 0; + if ( (msglen= *datalenp) <= crypto_box_NONCEBYTES + crypto_box_ZEROBYTES + sizeof(bits256) ) + { + *datalenp = 0; + return(0); + } + if ( (data= SuperNET_deciphercalc(senderpub,allocatedp,&msglen,privkey,data,*datalenp)) == 0 ) + { + //printf("komodo_DEX_decrypt decrytion error\n"); + *datalenp = 0; + return(0); + } else *datalenp = msglen; + return(data); +} + + + uint16_t _komodo_DEXpeerpos(uint32_t timestamp,int32_t peerid) { // this needs to maintain the bitposition from epoch to epoch, to preserve the accuracy of the GETBIT() diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 1395932e166..34ae9e5e34f 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -19,22 +19,14 @@ #include #include "primitives/nonce.h" #include "consensus/params.h" -#include "komodo_defs.h" #include "script/standard.h" +#include "init.h" +#include "main.h" +#include "komodo_defs.h" #include "cc/CCinclude.h" const char *LOG_KOMODOBITCOIND = "komodostaking"; -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); -int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp); -unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); -bool EnsureWalletIsAvailable(bool avoidException); -extern bool fRequestShutdown; -extern CScript KOMODO_EARLYTXID_SCRIPTPUB; - -uint32_t komodo_heightstamp(int32_t height); - //#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr)) struct MemoryStruct { char *memory; size_t size; }; diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 091bba306a4..708c754a9ed 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -18,7 +18,11 @@ #include #include "arith_uint256.h" +#include "script/script.h" +#include "pubkey.h" #include "chain.h" +#include "primitives/transaction.h" + #include "komodo_nk.h" #define KOMODO_EARLYTXID_HEIGHT 100 @@ -580,6 +584,7 @@ int32_t komodo_blockload(CBlock& block, CBlockIndex *pindex); uint32_t komodo_chainactive_timestamp(); uint32_t GetLatestTimestamp(int32_t height); int32_t komodo_get_current_height(); +struct komodo_state *komodo_stateptrget(char *base); void komodo_prefetch(FILE *fp); uint32_t komodo_heightstamp(int32_t height); @@ -588,7 +593,6 @@ void komodo_init(int32_t height); int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); -void komodo_init(int32_t height); int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); int32_t komodo_isrealtime(int32_t *kmdheightp); uint64_t komodo_paxtotal(); @@ -596,6 +600,55 @@ int32_t komodo_longestchain(); uint64_t komodo_maxallowed(int32_t baseid); int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); +int64_t komodo_block_unlocktime(uint32_t nHeight); +int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void *pTr); +uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); +CScript komodo_mineropret(int32_t nHeight); +bool komodo_appendACscriptpub(); +uint64_t komodo_commission(const CBlock *pblock,int32_t height); +int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); +uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); +int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk); +int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len); +int32_t komodo_is_notarytx(const CTransaction& tx); +int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag); +uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len); +CScript komodo_makeopret(CBlock *pblock, bool fNew); +int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); +int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); +int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); +int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime); +void komodo_passport_iteration(); +void komodo_cbopretupdate(int32_t forceflag); +uint64_t komodo_interestsum(); +bool komodo_dailysnapshot(int32_t height); +void komodo_setactivation(int32_t height); +void komodo_pricesupdate(int32_t height,CBlock *pblock); +void komodo_broadcast(CBlock *pblock,int32_t limit); +int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); +void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); +int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); + +int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); +bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); + +char *nonportable_path(char *str); +char *portable_path(char *str); +void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); +void *filestr(long *allocsizep,char *_fname); + +extern uint64_t KOMODO_INTERESTSUM, KOMODO_WALLETBALANCE; +extern int32_t KOMODO_INSYNC, KOMODO_LASTMINED, prevKOMODO_LASTMINED; +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS + 1], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS + 1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS + 1]; +extern uint32_t ASSETCHAINS_MAGIC; +extern uint64_t ASSETCHAINS_LINEAR, ASSETCHAINS_COMMISSION, ASSETCHAINS_SUPPLY; +extern uint8_t ASSETCHAINS_PUBLIC, ASSETCHAINS_PRIVATE; +extern int32_t ASSETCHAINS_STAKED; +extern uint64_t ASSETCHAINS_DECAY[]; +extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; +extern int32_t KOMODO_LOADINGBLOCKS; #ifndef KOMODO_NSPV_FULLNODE #define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) @@ -618,8 +671,41 @@ struct komodo_staking *komodo_addutxo(struct komodo_staking *array, int32_t *num void komodo_createminerstransactions(); uint32_t komodo_segid32(char *coinaddr); +int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp); + + // #ifndef _WIN32 void OS_randombytes(unsigned char *x, long xlen); // this func impl exists for win too // #endif +// curve25519 and sha256 +#ifndef _BITS256 +#define _BITS256 + union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; + typedef union _bits256 bits256; +#endif + +bits256 curve25519_shared(bits256 privkey,bits256 otherpub); +bits256 curve25519_basepoint9(); +bits256 curve25519(bits256 mysecret,bits256 basepoint); +void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); +bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); + +// supernet cipher +int32_t _SuperNET_cipher(uint8_t nonce[crypto_box_NONCEBYTES],uint8_t *cipher,uint8_t *message,int32_t len,bits256 destpub,bits256 srcpriv,uint8_t *buf); +uint8_t *_SuperNET_decipher(uint8_t nonce[crypto_box_NONCEBYTES],uint8_t *cipher,uint8_t *message,int32_t len,bits256 srcpub,bits256 mypriv); +uint8_t *SuperNET_deciphercalc(uint8_t *senderpub,uint8_t **ptrp,int32_t *msglenp,bits256 privkey,uint8_t *cipher,int32_t cipherlen); +uint8_t *SuperNET_ciphercalc(uint8_t **ptrp,int32_t *cipherlenp,bits256 privkey,bits256 destpubkey,uint8_t *data,int32_t datalen); + +#ifdef TESTMODE + #define MIN_NON_NOTARIZED_CONFIRMS 2 +#else + #define MIN_NON_NOTARIZED_CONFIRMS 101 +#endif // TESTMODE + + +extern int32_t JUMBLR_PAUSE; +int32_t Jumblr_depositaddradd(char *depositaddr); +int32_t Jumblr_secretaddradd(char *secretaddr); + #endif diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index de72ab0d30f..9c804b08268 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -682,8 +682,6 @@ int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max) return(i); } -void komodo_passport_iteration(); - int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime) // verify above block is valid pax pricing { static uint256 array[64]; static int32_t numbanned,indallvouts; @@ -1426,8 +1424,6 @@ int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,ch return(-1); } -uint64_t komodo_interestsum(); - void komodo_passport_iteration() { static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest; diff --git a/src/komodo_globals.h b/src/komodo_globals.h index a5f8ad453b0..101a79e9ae8 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -103,7 +103,6 @@ uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REW uint32_t KOMODO_INITDONE; char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; uint64_t PENDING_KOMODO_TX; -extern int32_t KOMODO_LOADINGBLOCKS; unsigned int MAX_BLOCK_SIGOPS = 20000; int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL; diff --git a/src/komodo_nSPV_wallet.h b/src/komodo_nSPV_wallet.h index 465af980754..e50ace003c5 100644 --- a/src/komodo_nSPV_wallet.h +++ b/src/komodo_nSPV_wallet.h @@ -17,8 +17,10 @@ #ifndef KOMODO_NSPVWALLET_H #define KOMODO_NSPVWALLET_H +#include "rpc/server.h" + // nSPV wallet uses superlite functions (and some komodod built in functions) to implement nSPV_spend -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +//extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); int32_t NSPV_validatehdrs(struct NSPV_ntzsproofresp *ptr) { diff --git a/src/komodo_utils.h b/src/komodo_utils.h index e3a9e58dbd7..a2468af71ce 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -12,8 +12,10 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ -#include "komodo_defs.h" #include "key_io.h" +#include "net.h" +#include "util.h" +#include "komodo_defs.h" #include "cc/CCinclude.h" #include @@ -1669,10 +1671,6 @@ uint64_t komodo_ac_block_subsidy(int nHeight) return(subsidy); } -extern int64_t MAX_MONEY; -void komodo_cbopretupdate(int32_t forceflag); -void SplitStr(const std::string& strVal, std::vector &outVals); - int8_t equihash_params_possible(uint64_t n, uint64_t k) { /* To add more of these you also need to edit: @@ -2494,4 +2492,155 @@ void komodo_prefetch(FILE *fp) /* bool komodo_Is2021JuneHFActive() { return GetLatestTimestamp(komodo_currentheight()) > JUNE2021_NNELECTION_HARDFORK; -} */ \ No newline at end of file +} */ + +int32_t KOMODO_LONGESTCHAIN; +int32_t komodo_longestchain() +{ + static int32_t depth; + int32_t ht,n=0,num=0,maxheight=0,height = 0; + if ( depth < 0 ) + depth = 0; + if ( depth == 0 ) + { + + /** + * Seems here we need to try to lock cs_main, to avoid wrong order of lock (cs_main, cs_vNodes), + * implementation of getting max(nStartingHeight, nSyncHeight, nCommonHeight) from CNodeStateStats + * and loop here is similar to getpeerinfo RPC and there we have LOCK(cs_main). If we'll not able + * to acquire lock on cs_main komodo_longestchain() will return previous saved value of + * KOMODO_LONGESTCHAIN, anyway, on next call it will be updated, when lock will success. + */ + + TRY_LOCK(cs_main, lockMain); // Acquire cs_main + if (!lockMain) { + return(KOMODO_LONGESTCHAIN); + } + + depth++; + vector vstats; + { + //LOCK(cs_main); + CopyNodeStats(vstats); + } + BOOST_FOREACH(const CNodeStats& stats, vstats) + { + //fprintf(stderr,"komodo_longestchain iter.%d\n",n); + CNodeStateStats statestats; + bool fStateStats = GetNodeStateStats(stats.nodeid,statestats); + if ( statestats.nSyncHeight < 0 ) + continue; + ht = 0; + if ( stats.nStartingHeight > ht ) + ht = stats.nStartingHeight; + if ( statestats.nSyncHeight > ht ) + ht = statestats.nSyncHeight; + if ( statestats.nCommonHeight > ht ) + ht = statestats.nCommonHeight; + if ( maxheight == 0 || ht > maxheight*1.01 ) + maxheight = ht, num = 1; + else if ( ht > maxheight*0.99 ) + num++; + if ( ht > height ) + height = ht; + } + depth--; + if ( num > (n >> 1) ) + { + if ( 0 && height != KOMODO_LONGESTCHAIN ) + fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",ASSETCHAINS_SYMBOL,height); + KOMODO_LONGESTCHAIN = height; + return(height); + } + KOMODO_LONGESTCHAIN = 0; + } + return(KOMODO_LONGESTCHAIN); +} + +int64_t komodo_get_blocktime(uint256 hashBlock) +{ + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) + { + CBlockIndex* pindex = (*mi).second; + if (chainActive.Contains(pindex)) + return pindex->GetBlockTime(); + } + return 0; +} + +extern struct NSPV_inforesp NSPV_inforesult; +int32_t komodo_get_current_height() +{ + if ( KOMODO_NSPV_SUPERLITE ) + { + return (NSPV_inforesult.height); + } + else return chainActive.LastTip()->GetHeight(); +} + +bool komodo_txnotarizedconfirmed(uint256 txid, int32_t minconfirms) +{ + char str[65]; + int32_t confirms,minimumconfirms,notarized=0,txheight=0,currentheight=0;; + CTransaction tx; + uint256 hashBlock; + CBlockIndex *pindex; + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + + if (minconfirms==0) return (true); + if ( KOMODO_NSPV_SUPERLITE ) + { + if ( NSPV_myGetTransaction(txid,tx,hashBlock,txheight,currentheight) == 0 ) + { + fprintf(stderr,"komodo_txnotarizedconfirmed cant find txid %s\n",txid.ToString().c_str()); + return(0); + } + else if (txheight<=0) + { + fprintf(stderr,"komodo_txnotarizedconfirmed no txheight.%d for txid %s\n",txheight,txid.ToString().c_str()); + return(0); + } + else if (txheight>currentheight) + { + fprintf(stderr,"komodo_txnotarizedconfirmed backwards heights for txid %s hts.(%d %d)\n",txid.ToString().c_str(),txheight,currentheight); + return(0); + } + confirms=1 + currentheight - txheight; + } + else + { + 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= komodo_blockindex(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 (minconfirms>1) minimumconfirms=minconfirms; + else minimumconfirms=MIN_NON_NOTARIZED_CONFIRMS; + 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 >= minimumconfirms) + return (true); + return (false); +} diff --git a/src/main.cpp b/src/main.cpp index 572e137390d..b7dc91e2c15 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -80,14 +80,14 @@ using namespace std; #define TMPFILE_START 100000000 CCriticalSection cs_main; -extern uint8_t NOTARY_PUBKEY33[33]; -extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI; +//extern uint8_t NOTARY_PUBKEY33[33]; +//extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI; int32_t KOMODO_NEWBLOCKS; -int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); +//int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); //void komodo_broadcast(CBlock *pblock,int32_t limit); -bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); -void komodo_setactivation(int32_t height); -void komodo_pricesupdate(int32_t height,CBlock *pblock); +//bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); +//void komodo_setactivation(int32_t height); +//void komodo_pricesupdate(int32_t height,CBlock *pblock); BlockMap mapBlockIndex; CChain chainActive; @@ -649,6 +649,7 @@ CBlockTreeDB *pblocktree = NULL; // Komodo globals #define KOMODO_ZCASH +#include "komodo_defs.h" #include "komodo.h" UniValue komodo_snapshot(int top) @@ -1453,7 +1454,7 @@ int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime) // from ac_private return(0); } -int32_t komodo_acpublic(uint32_t tiptime); +//int32_t komodo_acpublic(uint32_t tiptime); bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransaction& tx, CValidationState &state) { @@ -2467,12 +2468,6 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW) } //uint64_t komodo_moneysupply(int32_t height); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1]; -extern uint32_t ASSETCHAINS_MAGIC; -extern uint64_t ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; -extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; -extern int32_t ASSETCHAINS_STAKED; CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) { diff --git a/src/miner.cpp b/src/miner.cpp index 7e44511d49f..2a8c7351413 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -64,6 +64,9 @@ #endif #include +#include "komodo_defs.h" +#include "cc/CCinclude.h" + using namespace std; ////////////////////////////////////////////////////////////////////////////// @@ -71,6 +74,12 @@ using namespace std; // BitcoinMiner // + +extern CCriticalSection cs_metrics; + +uint32_t Mining_start,Mining_height; +int32_t My_notaryid = -1; + // // Unconfirmed transactions in the memory pool often depend on other // transactions in the memory pool. When we select transactions from the @@ -133,34 +142,6 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); } } -#include "komodo_defs.h" -#include "cc/CCinclude.h" - -extern CCriticalSection cs_metrics; -void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); - -uint32_t Mining_start,Mining_height; -int32_t My_notaryid = -1; -int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); -int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize); -int32_t komodo_baseid(char *origbase); -int32_t komodo_longestchain(); -int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); -int64_t komodo_block_unlocktime(uint32_t nHeight); -uint64_t komodo_commission(const CBlock *block,int32_t height); -int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); -int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk); -uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); -int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); -int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void* ptr); -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); -int32_t komodo_is_notarytx(const CTransaction& tx); -uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len); -CScript komodo_mineropret(int32_t nHeight); -bool komodo_appendACscriptpub(); -CScript komodo_makeopret(CBlock *pblock, bool fNew); int32_t komodo_waituntilelegible(uint32_t blocktime, int32_t stakeHeight, uint32_t delay) { diff --git a/src/rest.cpp b/src/rest.cpp index 3fb87f8f386..63de162c8fb 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -71,12 +71,6 @@ struct CCoin { } }; -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); -extern UniValue mempoolInfoToJSON(); -extern UniValue mempoolToJSON(bool fVerbose = false); -extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -extern UniValue blockheaderToJSON(const CBlockIndex* blockindex); static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, string message) { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 565a5bfb92d..8e564d5b2a0 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -46,15 +46,17 @@ #include "cc/CCinclude.h" #include "cc/CCPrices.h" -using namespace std; - -extern int32_t KOMODO_INSYNC; -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -int32_t komodo_notarized_height(int32_t *prevMoMheightp, uint256 *hashp, uint256 *txidp); #include "komodo_defs.h" #include "komodo_structs.h" +using namespace std; + +//extern int32_t KOMODO_INSYNC; +//extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +//void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +//int32_t komodo_notarized_height(int32_t *prevMoMheightp, uint256 *hashp, uint256 *txidp); + + double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) { // Floating point number that is a multiple of the minimum difficulty, @@ -288,7 +290,7 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) return result; } -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails) { UniValue result(UniValue::VOBJ); uint256 notarized_hash, notarized_desttxid; int32_t prevMoMheight, notarized_height; @@ -451,7 +453,7 @@ bool mytxid_inmempool(uint256 txid) return(false); } -UniValue mempoolToJSON(bool fVerbose = false) +UniValue mempoolToJSON(bool fVerbose) { if (fVerbose) { diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 46b6077726b..1235f46eed0 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -28,6 +28,7 @@ #include "txmempool.h" #include "util.h" #include "notaries_staked.h" +#include "komodo_defs.h" #include "cc/eval.h" #include "cc/CCinclude.h" #ifdef ENABLE_WALLET @@ -59,33 +60,8 @@ using namespace std; * Or alternatively, create a specific query method for the information. **/ -int32_t Jumblr_depositaddradd(char *depositaddr); -int32_t Jumblr_secretaddradd(char *secretaddr); -uint64_t komodo_interestsum(); -int32_t komodo_longestchain(); -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); -//bool komodo_txnotarizedconfirmed(uint256 txid); -uint32_t komodo_chainactive_timestamp(); -int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); -extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; -extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN,IS_STAKED_NOTARY,IS_KOMODO_NOTARY,STAKED_ERA,KOMODO_INSYNC; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -uint32_t komodo_segid32(char *coinaddr); -int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); -int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); -int8_t StakedNotaryID(std::string ¬aryname, char *Raddress); -uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); - #define KOMODO_VERSION "0.6.1" #define VERUS_VERSION "0.4.0g" -extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; -extern uint32_t ASSETCHAINS_CC; -extern uint32_t ASSETCHAINS_MAGIC,ASSETCHAINS_ALGO; -extern uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; -extern int32_t ASSETCHAINS_LWMAPOS,ASSETCHAINS_SAPLING,ASSETCHAINS_STAKED; -extern uint64_t ASSETCHAINS_ENDSUBSIDY[],ASSETCHAINS_REWARD[],ASSETCHAINS_HALVING[],ASSETCHAINS_DECAY[],ASSETCHAINS_NOTARY_PAY[]; -extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS; extern uint8_t NOTARY_PUBKEY33[]; int32_t getera(int timestamp) { diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index f87d953eaf1..68a5c915063 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -171,69 +171,6 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) return ret; } -int32_t KOMODO_LONGESTCHAIN; -int32_t komodo_longestchain() -{ - static int32_t depth; - int32_t ht,n=0,num=0,maxheight=0,height = 0; - if ( depth < 0 ) - depth = 0; - if ( depth == 0 ) - { - - /** - * Seems here we need to try to lock cs_main, to avoid wrong order of lock (cs_main, cs_vNodes), - * implementation of getting max(nStartingHeight, nSyncHeight, nCommonHeight) from CNodeStateStats - * and loop here is similar to getpeerinfo RPC and there we have LOCK(cs_main). If we'll not able - * to acquire lock on cs_main komodo_longestchain() will return previous saved value of - * KOMODO_LONGESTCHAIN, anyway, on next call it will be updated, when lock will success. - */ - - TRY_LOCK(cs_main, lockMain); // Acquire cs_main - if (!lockMain) { - return(KOMODO_LONGESTCHAIN); - } - - depth++; - vector vstats; - { - //LOCK(cs_main); - CopyNodeStats(vstats); - } - BOOST_FOREACH(const CNodeStats& stats, vstats) - { - //fprintf(stderr,"komodo_longestchain iter.%d\n",n); - CNodeStateStats statestats; - bool fStateStats = GetNodeStateStats(stats.nodeid,statestats); - if ( statestats.nSyncHeight < 0 ) - continue; - ht = 0; - if ( stats.nStartingHeight > ht ) - ht = stats.nStartingHeight; - if ( statestats.nSyncHeight > ht ) - ht = statestats.nSyncHeight; - if ( statestats.nCommonHeight > ht ) - ht = statestats.nCommonHeight; - if ( maxheight == 0 || ht > maxheight*1.01 ) - maxheight = ht, num = 1; - else if ( ht > maxheight*0.99 ) - num++; - if ( ht > height ) - height = ht; - } - depth--; - if ( num > (n >> 1) ) - { - if ( 0 && height != KOMODO_LONGESTCHAIN ) - fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",ASSETCHAINS_SYMBOL,height); - KOMODO_LONGESTCHAIN = height; - return(height); - } - KOMODO_LONGESTCHAIN = 0; - } - return(KOMODO_LONGESTCHAIN); -} - UniValue addnode(const UniValue& params, bool fHelp, const CPubKey& mypk) { string strCommand; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index eaf1ec002c5..db61ae5b8c3 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -41,20 +41,12 @@ #endif #include "komodo_defs.h" - #include - #include - #include -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); - using namespace std; -extern char ASSETCHAINS_SYMBOL[]; -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); - void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex) { txnouttype type; @@ -140,7 +132,7 @@ UniValue TxJoinSplitToJSON(const CTransaction& tx) { return vjoinsplit; } -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); +//uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); UniValue TxShieldedSpendsToJSON(const CTransaction& tx) { UniValue vdesc(UniValue::VARR); diff --git a/src/rpc/server.h b/src/rpc/server.h index 5975e0e1d8b..2bfd1d75926 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -35,6 +35,9 @@ #include #include +#include "primitives/block.h" +#include "primitives/transaction.h" +#include "script/script.h" class AsyncRPCQueue; class CRPCCommand; @@ -194,6 +197,14 @@ extern std::string HelpRequiringPassphrase(); extern std::string HelpExampleCli(const std::string& methodname, const std::string& args); extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args); +extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); +extern UniValue mempoolInfoToJSON(); +extern UniValue mempoolToJSON(bool fVerbose = false); +extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +extern UniValue blockheaderToJSON(const CBlockIndex* blockindex); +extern UniValue TxJoinSplitToJSON(const CTransaction& tx); + extern void EnsureWalletIsUnlocked(); bool StartRPC(); diff --git a/src/rpcblockchain.old b/src/rpcblockchain.old deleted file mode 100644 index a91f73a6364..00000000000 --- a/src/rpcblockchain.old +++ /dev/null @@ -1,1625 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "crosschain.h" -#include "base58.h" -#include "consensus/validation.h" -#include "cc/eval.h" -#include "main.h" -#include "primitives/transaction.h" -#include "rpcserver.h" -#include "sync.h" -#include "util.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "script/standard.h" - -#include - -#include - -#include - -using namespace std; - -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -int32_t komodo_longestchain(); -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -<<<<<<< HEAD:src/rpcblockchain.old -extern int32_t KOMODO_LONGESTCHAIN; -======= ->>>>>>> master:src/rpcblockchain.cpp - -double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) -{ - // Floating point number that is a multiple of the minimum difficulty, - // minimum difficulty = 1.0. - if (blockindex == NULL) - { - if (chainActive.LastTip() == NULL) - return 1.0; - else - blockindex = chainActive.LastTip(); - } - - uint32_t bits; - if (networkDifficulty) { - bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus()); - } else { - bits = blockindex->nBits; - } - - uint32_t powLimit = - UintToArith256(Params().GetConsensus().powLimit).GetCompact(); - int nShift = (bits >> 24) & 0xff; - int nShiftAmount = (powLimit >> 24) & 0xff; - - double dDiff = - (double)(powLimit & 0x00ffffff) / - (double)(bits & 0x00ffffff); - - while (nShift < nShiftAmount) - { - dDiff *= 256.0; - nShift++; - } - while (nShift > nShiftAmount) - { - dDiff /= 256.0; - nShift--; - } - - return dDiff; -} - -double GetDifficulty(const CBlockIndex* blockindex) -{ - return GetDifficultyINTERNAL(blockindex, false); -} - -double GetNetworkDifficulty(const CBlockIndex* blockindex) -{ - return GetDifficultyINTERNAL(blockindex, true); -} - -static UniValue ValuePoolDesc( - const std::string &name, - const boost::optional chainValue, - const boost::optional valueDelta) -{ - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("id", name)); - rv.push_back(Pair("monitored", (bool)chainValue)); - if (chainValue) { - rv.push_back(Pair("chainValue", ValueFromAmount(*chainValue))); - rv.push_back(Pair("chainValueZat", *chainValue)); - } - if (valueDelta) { - rv.push_back(Pair("valueDelta", ValueFromAmount(*valueDelta))); - rv.push_back(Pair("valueDeltaZat", *valueDelta)); - } - return rv; -} - -UniValue blockheaderToJSON(const CBlockIndex* blockindex) -{ - UniValue result(UniValue::VOBJ); - if ( blockindex == 0 ) - { - result.push_back(Pair("error", "null blockhash")); - return(result); - } - result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) - confirmations = chainActive.Height() - blockindex->nHeight + 1; - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", blockindex->nVersion)); - result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex())); - result.push_back(Pair("time", (int64_t)blockindex->nTime)); - result.push_back(Pair("nonce", blockindex->nNonce.GetHex())); - result.push_back(Pair("solution", HexStr(blockindex->nSolution))); - result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) -{ - UniValue result(UniValue::VOBJ); - result.push_back(Pair("hash", block.GetHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) { - confirmations = chainActive.Height() - blockindex->nHeight + 1; - } else { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block is an orphan"); - } - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - - UniValue deltas(UniValue::VARR); - - for (unsigned int i = 0; i < block.vtx.size(); i++) { - const CTransaction &tx = block.vtx[i]; - const uint256 txhash = tx.GetHash(); - - UniValue entry(UniValue::VOBJ); - entry.push_back(Pair("txid", txhash.GetHex())); - entry.push_back(Pair("index", (int)i)); - - UniValue inputs(UniValue::VARR); - - if (!tx.IsCoinBase()) { - - for (size_t j = 0; j < tx.vin.size(); j++) { - const CTxIn input = tx.vin[j]; - - UniValue delta(UniValue::VOBJ); - - CSpentIndexValue spentInfo; - CSpentIndexKey spentKey(input.prevout.hash, input.prevout.n); - - if (GetSpentIndex(spentKey, spentInfo)) { - if (spentInfo.addressType == 1) { - delta.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); - } - else if (spentInfo.addressType == 2) { - delta.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); - } - else { - continue; - } - delta.push_back(Pair("satoshis", -1 * spentInfo.satoshis)); - delta.push_back(Pair("index", (int)j)); - delta.push_back(Pair("prevtxid", input.prevout.hash.GetHex())); - delta.push_back(Pair("prevout", (int)input.prevout.n)); - - inputs.push_back(delta); - } else { - throw JSONRPCError(RPC_INTERNAL_ERROR, "Spent information not available"); - } - - } - } - - entry.push_back(Pair("inputs", inputs)); - - UniValue outputs(UniValue::VARR); - - for (unsigned int k = 0; k < tx.vout.size(); k++) { - const CTxOut &out = tx.vout[k]; - - UniValue delta(UniValue::VOBJ); - - if (out.scriptPubKey.IsPayToScriptHash()) { - vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); - delta.push_back(Pair("address", CBitcoinAddress(CScriptID(uint160(hashBytes))).ToString())); - - } - else if (out.scriptPubKey.IsPayToPublicKeyHash()) { - vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); - delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); - } - else if (out.scriptPubKey.IsPayToPublicKey() || out.scriptPubKey.IsPayToCryptoCondition()) { - CTxDestination address; - if (ExtractDestination(out.scriptPubKey, address)) - { - //vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); - //xxx delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); - delta.push_back(Pair("address", CBitcoinAddress(address).ToString())); - } - } - else { - continue; - } - - delta.push_back(Pair("satoshis", out.nValue)); - delta.push_back(Pair("index", (int)k)); - - outputs.push_back(delta); - } - - entry.push_back(Pair("outputs", outputs)); - deltas.push_back(entry); - - } - result.push_back(Pair("deltas", deltas)); - result.push_back(Pair("time", block.GetBlockTime())); - result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast())); - result.push_back(Pair("nonce", block.nNonce.GetHex())); - result.push_back(Pair("bits", strprintf("%08x", block.nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) -{ - UniValue result(UniValue::VOBJ); - result.push_back(Pair("hash", block.GetHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) - confirmations = chainActive.Height() - blockindex->nHeight + 1; - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - UniValue txs(UniValue::VARR); - BOOST_FOREACH(const CTransaction&tx, block.vtx) - { - if(txDetails) - { - UniValue objTx(UniValue::VOBJ); - TxToJSON(tx, uint256(), objTx); - txs.push_back(objTx); - } - else - txs.push_back(tx.GetHash().GetHex()); - } - result.push_back(Pair("tx", txs)); - result.push_back(Pair("time", block.GetBlockTime())); - result.push_back(Pair("nonce", block.nNonce.GetHex())); - result.push_back(Pair("solution", HexStr(block.nSolution))); - result.push_back(Pair("bits", strprintf("%08x", block.nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex())); - - UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue)); - result.push_back(Pair("valuePools", valuePools)); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue getblockcount(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getblockcount\n" - "\nReturns the number of blocks in the best valid block chain.\n" - "\nResult:\n" - "n (numeric) The current block count\n" - "\nExamples:\n" - + HelpExampleCli("getblockcount", "") - + HelpExampleRpc("getblockcount", "") - ); - - LOCK(cs_main); - return chainActive.Height(); -} - -UniValue getbestblockhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getbestblockhash\n" - "\nReturns the hash of the best (tip) block in the longest block chain.\n" - "\nResult\n" - "\"hex\" (string) the block hash hex encoded\n" - "\nExamples\n" - + HelpExampleCli("getbestblockhash", "") - + HelpExampleRpc("getbestblockhash", "") - ); - - LOCK(cs_main); - return chainActive.LastTip()->GetBlockHash().GetHex(); -} - -UniValue getdifficulty(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getdifficulty\n" - "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - "\nResult:\n" - "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - "\nExamples:\n" - + HelpExampleCli("getdifficulty", "") - + HelpExampleRpc("getdifficulty", "") - ); - - LOCK(cs_main); - return GetNetworkDifficulty(); -} - -bool myIsutxo_spentinmempool(uint256 txid,int32_t vout) -{ - //char *uint256_str(char *str,uint256); char str[65]; - //LOCK(mempool.cs); - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - BOOST_FOREACH(const CTxIn &txin,tx.vin) - { - //fprintf(stderr,"%s/v%d ",uint256_str(str,txin.prevout.hash),txin.prevout.n); - if ( txin.prevout.n == vout && txin.prevout.hash == txid ) - return(true); - } - //fprintf(stderr,"are vins for %s\n",uint256_str(str,hash)); - } - return(false); -} - -bool mytxid_inmempool(uint256 txid) -{ - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - if ( txid == hash ) - return(true); - } - return(false); -} - -UniValue mempoolToJSON(bool fVerbose = false) -{ - if (fVerbose) - { - LOCK(mempool.cs); - UniValue o(UniValue::VOBJ); - BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) - { - const uint256& hash = e.GetTx().GetHash(); - UniValue info(UniValue::VOBJ); - info.push_back(Pair("size", (int)e.GetTxSize())); - info.push_back(Pair("fee", ValueFromAmount(e.GetFee()))); - info.push_back(Pair("time", e.GetTime())); - info.push_back(Pair("height", (int)e.GetHeight())); - info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight()))); - info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height()))); - const CTransaction& tx = e.GetTx(); - set setDepends; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - { - if (mempool.exists(txin.prevout.hash)) - setDepends.insert(txin.prevout.hash.ToString()); - } - - UniValue depends(UniValue::VARR); - BOOST_FOREACH(const string& dep, setDepends) - { - depends.push_back(dep); - } - - info.push_back(Pair("depends", depends)); - o.push_back(Pair(hash.ToString(), info)); - } - return o; - } - else - { - vector vtxid; - mempool.queryHashes(vtxid); - - UniValue a(UniValue::VARR); - BOOST_FOREACH(const uint256& hash, vtxid) - a.push_back(hash.ToString()); - - return a; - } -} - -UniValue getrawmempool(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() > 1) - throw runtime_error( - "getrawmempool ( verbose )\n" - "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" - "\nArguments:\n" - "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" - "\nResult: (for verbose = false):\n" - "[ (json array of string)\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - "]\n" - "\nResult: (for verbose = true):\n" - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - " \"size\" : n, (numeric) transaction size in bytes\n" - " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" - " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" - " \"height\" : n, (numeric) block height when transaction entered pool\n" - " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n" - " \"currentpriority\" : n, (numeric) transaction priority now\n" - " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" - " \"transactionid\", (string) parent transaction id\n" - " ... ]\n" - " }, ...\n" - "}\n" - "\nExamples\n" - + HelpExampleCli("getrawmempool", "true") - + HelpExampleRpc("getrawmempool", "true") - ); - - LOCK(cs_main); - - bool fVerbose = false; - if (params.size() > 0) - fVerbose = params[0].get_bool(); - - return mempoolToJSON(fVerbose); -} - -UniValue getblockdeltas(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error(""); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - - if(!ReadBlockFromDisk(block, pblockindex,1)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); - - return blockToDeltasJSON(block, pblockindex); -} - -UniValue getblockhashes(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 2) - throw runtime_error( - "getblockhashes timestamp\n" - "\nReturns array of hashes of blocks within the timestamp range provided.\n" - "\nArguments:\n" - "1. high (numeric, required) The newer block timestamp\n" - "2. low (numeric, required) The older block timestamp\n" - "3. options (string, required) A json object\n" - " {\n" - " \"noOrphans\":true (boolean) will only include blocks on the main chain\n" - " \"logicalTimes\":true (boolean) will include logical timestamps with hashes\n" - " }\n" - "\nResult:\n" - "[\n" - " \"hash\" (string) The block hash\n" - "]\n" - "[\n" - " {\n" - " \"blockhash\": (string) The block hash\n" - " \"logicalts\": (numeric) The logical timestamp\n" - " }\n" - "]\n" - "\nExamples:\n" - + HelpExampleCli("getblockhashes", "1231614698 1231024505") - + HelpExampleRpc("getblockhashes", "1231614698, 1231024505") - + HelpExampleCli("getblockhashes", "1231614698 1231024505 '{\"noOrphans\":false, \"logicalTimes\":true}'") - ); - - unsigned int high = params[0].get_int(); - unsigned int low = params[1].get_int(); - bool fActiveOnly = false; - bool fLogicalTS = false; - - if (params.size() > 2) { - if (params[2].isObject()) { - UniValue noOrphans = find_value(params[2].get_obj(), "noOrphans"); - UniValue returnLogical = find_value(params[2].get_obj(), "logicalTimes"); - - if (noOrphans.isBool()) - fActiveOnly = noOrphans.get_bool(); - - if (returnLogical.isBool()) - fLogicalTS = returnLogical.get_bool(); - } - } - - std::vector > blockHashes; - - if (fActiveOnly) - LOCK(cs_main); - - if (!GetTimestampIndex(high, low, fActiveOnly, blockHashes)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for block hashes"); - } - - UniValue result(UniValue::VARR); - - for (std::vector >::const_iterator it=blockHashes.begin(); it!=blockHashes.end(); it++) { - if (fLogicalTS) { - UniValue item(UniValue::VOBJ); - item.push_back(Pair("blockhash", it->first.GetHex())); - item.push_back(Pair("logicalts", (int)it->second)); - result.push_back(item); - } else { - result.push_back(it->first.GetHex()); - } - } - - return result; -} - -UniValue getblockhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "getblockhash index\n" - "\nReturns hash of block in best-block-chain at index provided.\n" - "\nArguments:\n" - "1. index (numeric, required) The block index\n" - "\nResult:\n" - "\"hash\" (string) The block hash\n" - "\nExamples:\n" - + HelpExampleCli("getblockhash", "1000") - + HelpExampleRpc("getblockhash", "1000") - ); - - LOCK(cs_main); - - int nHeight = params[0].get_int(); - if (nHeight < 0 || nHeight > chainActive.Height()) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - - CBlockIndex* pblockindex = chainActive[nHeight]; - return pblockindex->GetBlockHash().GetHex(); -} - -/*uint256 _komodo_getblockhash(int32_t nHeight) -{ - uint256 hash; - LOCK(cs_main); - if ( nHeight >= 0 && nHeight <= chainActive.Height() ) - { - CBlockIndex* pblockindex = chainActive[nHeight]; - hash = pblockindex->GetBlockHash(); - int32_t i; - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&hash)[i]); - printf(" blockhash.%d\n",nHeight); - } else memset(&hash,0,sizeof(hash)); - return(hash); -}*/ - -UniValue getblockheader(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getblockheader \"hash\" ( verbose )\n" - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" - "If verbose is true, returns an Object with information about blockheader .\n" - "\nArguments:\n" - "1. \"hash\" (string, required) The block hash\n" - "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" - "\nResult (for verbose = true):\n" - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - "\nResult (for verbose=false):\n" - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - "\nExamples:\n" - + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - ); - - LOCK(cs_main); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - - bool fVerbose = true; - if (params.size() > 1) - fVerbose = params[1].get_bool(); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (!fVerbose) - { - CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); - ssBlock << pblockindex->GetBlockHeader(); - std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); - return strHex; - } - - return blockheaderToJSON(pblockindex); -} - -UniValue getblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getblock \"hash|height\" ( verbose )\n" - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash|height'.\n" - "If verbose is true, returns an Object with information about block .\n" - "\nArguments:\n" - "1. \"hash|height\" (string, required) The block hash or height\n" - "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" - "\nResult (for verbose = true):\n" - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided hash)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"size\" : n, (numeric) The block size\n" - " \"height\" : n, (numeric) The block height or index (same as provided height)\n" - " \"version\" : n, (numeric) The block version\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"tx\" : [ (array of string) The transaction ids\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - " ],\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - "\nResult (for verbose=false):\n" - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - "\nExamples:\n" - + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleCli("getblock", "12800") - + HelpExampleRpc("getblock", "12800") - ); - - LOCK(cs_main); - - std::string strHash = params[0].get_str(); - - // If height is supplied, find the hash - if (strHash.size() < (2 * sizeof(uint256))) { - // std::stoi allows characters, whereas we want to be strict - regex r("[[:digit:]]+"); - if (!regex_match(strHash, r)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); - } - - int nHeight = -1; - try { - nHeight = std::stoi(strHash); - } - catch (const std::exception &e) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); - } - - if (nHeight < 0 || nHeight > chainActive.Height()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - } - strHash = chainActive[nHeight]->GetBlockHash().GetHex(); - } - - uint256 hash(uint256S(strHash)); - - bool fVerbose = true; - if (params.size() > 1) - fVerbose = params[1].get_bool(); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - - if(!ReadBlockFromDisk(block, pblockindex,1)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); - - if (!fVerbose) - { - CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); - ssBlock << block; - std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); - return strHex; - } - - return blockToJSON(block, pblockindex); -} - -UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "gettxoutsetinfo\n" - "\nReturns statistics about the unspent transaction output set.\n" - "Note this call may take some time.\n" - "\nResult:\n" - "{\n" - " \"height\":n, (numeric) The current block height (index)\n" - " \"bestblock\": \"hex\", (string) the best block hash hex\n" - " \"transactions\": n, (numeric) The number of transactions\n" - " \"txouts\": n, (numeric) The number of output transactions\n" - " \"bytes_serialized\": n, (numeric) The serialized size\n" - " \"hash_serialized\": \"hash\", (string) The serialized hash\n" - " \"total_amount\": x.xxx (numeric) The total amount\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("gettxoutsetinfo", "") - + HelpExampleRpc("gettxoutsetinfo", "") - ); - - UniValue ret(UniValue::VOBJ); - - CCoinsStats stats; - FlushStateToDisk(); - if (pcoinsTip->GetStats(stats)) { - ret.push_back(Pair("height", (int64_t)stats.nHeight)); - ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); - ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); - ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs)); - ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize)); - ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex())); - ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount))); - } - return ret; -} - -#include "komodo_defs.h" -#include "komodo_structs.h" - -#define IGUANA_MAXSCRIPTSIZE 10001 -#define KOMODO_KVDURATION 1440 -#define KOMODO_KVBINARY 2 -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume); -int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); -int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); -int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); - -UniValue kvsearch(const UniValue& params, bool fHelp) -{ - UniValue ret(UniValue::VOBJ); uint32_t flags; uint8_t value[IGUANA_MAXSCRIPTSIZE*8],key[IGUANA_MAXSCRIPTSIZE*8]; int32_t duration,j,height,valuesize,keylen; uint256 refpubkey; static uint256 zeroes; - if (fHelp || params.size() != 1 ) - throw runtime_error( - "kvsearch key\n" - "\nSearch for a key stored via the kvupdate command. This feature is only available for asset chains.\n" - "\nArguments:\n" - "1. key (string, required) search the chain for this key\n" - "\nResult:\n" - "{\n" - " \"coin\": \"xxxxx\", (string) chain the key is stored on\n" - " \"currentheight\": xxxxx, (numeric) current height of the chain\n" - " \"key\": \"xxxxx\", (string) key\n" - " \"keylen\": xxxxx, (string) length of the key \n" - " \"owner\": \"xxxxx\" (string) hex string representing the owner of the key \n" - " \"height\": xxxxx, (numeric) height the key was stored at\n" - " \"expiration\": xxxxx, (numeric) height the key will expire\n" - " \"flags\": x (numeric) 1 if the key was created with a password; 0 otherwise.\n" - " \"value\": \"xxxxx\", (string) stored value\n" - " \"valuesize\": xxxxx (string) amount of characters stored\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("kvsearch", "examplekey") - + HelpExampleRpc("kvsearch", "\"examplekey\"") - ); - LOCK(cs_main); - if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 ) - { - ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - ret.push_back(Pair("currentheight", (int64_t)chainActive.LastTip()->nHeight)); - ret.push_back(Pair("key",params[0].get_str())); - ret.push_back(Pair("keylen",keylen)); - if ( keylen < sizeof(key) ) - { - memcpy(key,params[0].get_str().c_str(),keylen); - if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&flags,&height,value,key,keylen)) >= 0 ) - { - std::string val; char *valuestr; - val.resize(valuesize); - valuestr = (char *)val.data(); - memcpy(valuestr,value,valuesize); - if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) - ret.push_back(Pair("owner",refpubkey.GetHex())); - ret.push_back(Pair("height",height)); - duration = ((flags >> 2) + 1) * KOMODO_KVDURATION; - ret.push_back(Pair("expiration", (int64_t)(height+duration))); - ret.push_back(Pair("flags",(int64_t)flags)); - ret.push_back(Pair("value",val)); - ret.push_back(Pair("valuesize",valuesize)); - } else ret.push_back(Pair("error",(char *)"cant find key")); - } else ret.push_back(Pair("error",(char *)"key too big")); - } else ret.push_back(Pair("error",(char *)"null key")); - return ret; -} - -UniValue minerids(const UniValue& params, bool fHelp) -{ - uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); uint8_t minerids[2000],pubkeys[65][33]; int32_t i,j,n,numnotaries,tally[129]; - if ( fHelp || params.size() != 1 ) - throw runtime_error("minerids needs height\n"); - LOCK(cs_main); - int32_t height = atoi(params[0].get_str().c_str()); - if ( height <= 0 ) - height = chainActive.LastTip()->nHeight; - else - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - timestamp = pblockindex->GetBlockTime(); - } - if ( (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 ) - { - memset(tally,0,sizeof(tally)); - numnotaries = komodo_notaries(pubkeys,height,timestamp); - if ( numnotaries > 0 ) - { - for (i=0; i= numnotaries ) - tally[128]++; - else tally[minerids[i]]++; - } - for (i=0; i<64; i++) - { - UniValue item(UniValue::VOBJ); std::string hex,kmdaddress; char *hexstr,kmdaddr[64],*ptr; int32_t m; - hex.resize(66); - hexstr = (char *)hex.data(); - for (j=0; j<33; j++) - sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]); - item.push_back(Pair("notaryid", i)); - - bitcoin_address(kmdaddr,60,pubkeys[i],33); - m = (int32_t)strlen(kmdaddr); - kmdaddress.resize(m); - ptr = (char *)kmdaddress.data(); - memcpy(ptr,kmdaddr,m); - item.push_back(Pair("KMDaddress", kmdaddress)); - - item.push_back(Pair("pubkey", hex)); - item.push_back(Pair("blocks", tally[i])); - a.push_back(item); - } - UniValue item(UniValue::VOBJ); - item.push_back(Pair("pubkey", (char *)"external miners")); - item.push_back(Pair("blocks", tally[128])); - a.push_back(item); - } - ret.push_back(Pair("mined", a)); - ret.push_back(Pair("numnotaries", numnotaries)); - } else ret.push_back(Pair("error", (char *)"couldnt extract minerids")); - return ret; -} - -UniValue notaries(const UniValue& params, bool fHelp) -{ - UniValue a(UniValue::VARR); uint32_t timestamp=0; UniValue ret(UniValue::VOBJ); int32_t i,j,n,m; char *hexstr; uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr; - if ( fHelp || (params.size() != 1 && params.size() != 2) ) - throw runtime_error("notaries height timestamp\n"); - LOCK(cs_main); - int32_t height = atoi(params[0].get_str().c_str()); - if ( params.size() == 2 ) - timestamp = (uint32_t)atol(params[1].get_str().c_str()); - else timestamp = (uint32_t)time(NULL); - if ( height < 0 ) - { - height = chainActive.LastTip()->nHeight; - timestamp = chainActive.LastTip()->GetBlockTime(); - } - else if ( params.size() < 2 ) - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - timestamp = pblockindex->GetBlockTime(); - } - if ( (n= komodo_notaries(pubkeys,height,timestamp)) > 0 ) - { - for (i=0; i 0 ) - ret.push_back(Pair("withdraws", opretbuf)); - else ret.push_back(Pair("withdraws", (char *)"")); - for (baseid=0; baseid<32; baseid++) - { - UniValue item(UniValue::VOBJ); UniValue obj(UniValue::VOBJ); - if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 ) - { - if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 ) - { - item.push_back(Pair("available", ValueFromAmount(available))); - item.push_back(Pair("deposited", ValueFromAmount(deposited))); - item.push_back(Pair("issued", ValueFromAmount(issued))); - item.push_back(Pair("withdrawn", ValueFromAmount(withdrawn))); - item.push_back(Pair("approved", ValueFromAmount(approved))); - item.push_back(Pair("redeemed", ValueFromAmount(redeemed))); - obj.push_back(Pair(CURRENCIES[baseid],item)); - a.push_back(obj); - } - } - } - ret.push_back(Pair("fiatstatus", a)); - return ret; -} - -UniValue paxprice(const UniValue& params, bool fHelp) -{ - if ( fHelp || params.size() > 4 || params.size() < 2 ) - throw runtime_error("paxprice \"base\" \"rel\" height\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); uint64_t basevolume=0,relvolume,seed; - std::string base = params[0].get_str(); - std::string rel = params[1].get_str(); - int32_t height; - if ( params.size() == 2 ) - height = chainActive.LastTip()->nHeight; - else height = atoi(params[2].get_str().c_str()); - //if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 ) - basevolume = 100000; - relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume); - ret.push_back(Pair("base", base)); - ret.push_back(Pair("rel", rel)); - ret.push_back(Pair("height", height)); - char seedstr[32]; - sprintf(seedstr,"%llu",(long long)seed); - ret.push_back(Pair("seed", seedstr)); - if ( height < 0 || height > chainActive.Height() ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - else - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime)); - if ( basevolume != 0 && relvolume != 0 ) - { - ret.push_back(Pair("price",((double)relvolume / (double)basevolume))); - ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume))); - ret.push_back(Pair("basevolume",ValueFromAmount(basevolume))); - ret.push_back(Pair("relvolume",ValueFromAmount(relvolume))); - } else ret.push_back(Pair("error", "overflow or error in one or more of parameters")); - } - return ret; -} - -UniValue paxprices(const UniValue& params, bool fHelp) -{ - if ( fHelp || params.size() != 3 ) - throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)]; - std::string base = params[0].get_str(); - std::string rel = params[1].get_str(); - int32_t maxsamples = atoi(params[2].get_str().c_str()); - if ( maxsamples < 1 ) - maxsamples = 1; - else if ( maxsamples > sizeof(heights)/sizeof(*heights) ) - maxsamples = sizeof(heights)/sizeof(*heights); - ret.push_back(Pair("base", base)); - ret.push_back(Pair("rel", rel)); - n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str()); - UniValue a(UniValue::VARR); - for (i=0; i chainActive.Height() ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - else - { - CBlockIndex *pblockindex = chainActive[heights[i]]; - - item.push_back(Pair("t", (int64_t)pblockindex->nTime)); - item.push_back(Pair("p", (double)prices[i] / COIN)); - a.push_back(item); - } - } - ret.push_back(Pair("array", a)); - return ret; -} - -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - -UniValue gettxout(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 2 || params.size() > 3) - throw runtime_error( - "gettxout \"txid\" n ( includemempool )\n" - "\nReturns details about an unspent transaction output.\n" - "\nArguments:\n" - "1. \"txid\" (string, required) The transaction id\n" - "2. n (numeric, required) vout value\n" - "3. includemempool (boolean, optional) Whether to include the mempool\n" - "\nResult:\n" - "{\n" - " \"bestblock\" : \"hash\", (string) the block hash\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"code\", (string) \n" - " \"hex\" : \"hex\", (string) \n" - " \"reqSigs\" : n, (numeric) Number of required signatures\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" - " \"addresses\" : [ (array of string) array of Komodo addresses\n" - " \"komodoaddress\" (string) Komodo address\n" - " ,...\n" - " ]\n" - " },\n" - " \"version\" : n, (numeric) The version\n" - " \"coinbase\" : true|false (boolean) Coinbase or not\n" - "}\n" - - "\nExamples:\n" - "\nGet unspent transactions\n" - + HelpExampleCli("listunspent", "") + - "\nView the details\n" - + HelpExampleCli("gettxout", "\"txid\" 1") + - "\nAs a json rpc call\n" - + HelpExampleRpc("gettxout", "\"txid\", 1") - ); - - LOCK(cs_main); - - UniValue ret(UniValue::VOBJ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - int n = params[1].get_int(); - bool fMempool = true; - if (params.size() > 2) - fMempool = params[2].get_bool(); - - CCoins coins; - if (fMempool) { - LOCK(mempool.cs); - CCoinsViewMemPool view(pcoinsTip, mempool); - if (!view.GetCoins(hash, coins)) - return NullUniValue; - mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool - } else { - if (!pcoinsTip->GetCoins(hash, coins)) - return NullUniValue; - } - if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull()) - return NullUniValue; - - BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); - CBlockIndex *pindex = it->second; - ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex())); - if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT) - ret.push_back(Pair("confirmations", 0)); - else - { - ret.push_back(Pair("confirmations", komodo_dpowconfs(coins.nHeight,pindex->nHeight - coins.nHeight + 1))); - ret.push_back(Pair("rawconfirmations", pindex->nHeight - coins.nHeight + 1)); - } - ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue))); - uint64_t interest; int32_t txheight; uint32_t locktime; - if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue,(int32_t)pindex->nHeight)) != 0 ) - ret.push_back(Pair("interest", ValueFromAmount(interest))); - UniValue o(UniValue::VOBJ); - ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true); - ret.push_back(Pair("scriptPubKey", o)); - ret.push_back(Pair("version", coins.nVersion)); - ret.push_back(Pair("coinbase", coins.fCoinBase)); - - return ret; -} - -UniValue verifychain(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() > 2) - throw runtime_error( - "verifychain ( checklevel numblocks )\n" - "\nVerifies blockchain database.\n" - "\nArguments:\n" - "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n" - "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n" - "\nResult:\n" - "true|false (boolean) Verified or not\n" - "\nExamples:\n" - + HelpExampleCli("verifychain", "") - + HelpExampleRpc("verifychain", "") - ); - - LOCK(cs_main); - - int nCheckLevel = GetArg("-checklevel", 3); - int nCheckDepth = GetArg("-checkblocks", 288); - if (params.size() > 0) - nCheckLevel = params[0].get_int(); - if (params.size() > 1) - nCheckDepth = params[1].get_int(); - - return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth); -} - -/** Implementation of IsSuperMajority with better feedback */ -static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams) -{ - int nFound = 0; - CBlockIndex* pstart = pindex; - for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++) - { - if (pstart->nVersion >= minVersion) - ++nFound; - pstart = pstart->pprev; - } - - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("status", nFound >= nRequired)); - rv.push_back(Pair("found", nFound)); - rv.push_back(Pair("required", nRequired)); - rv.push_back(Pair("window", consensusParams.nMajorityWindow)); - return rv; -} - -static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) -{ - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("id", name)); - rv.push_back(Pair("version", version)); - rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))); - rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams))); - return rv; -} - -static UniValue NetworkUpgradeDesc(const Consensus::Params& consensusParams, Consensus::UpgradeIndex idx, int height) -{ - UniValue rv(UniValue::VOBJ); - auto upgrade = NetworkUpgradeInfo[idx]; - rv.push_back(Pair("name", upgrade.strName)); - rv.push_back(Pair("activationheight", consensusParams.vUpgrades[idx].nActivationHeight)); - switch (NetworkUpgradeState(height, consensusParams, idx)) { - case UPGRADE_DISABLED: rv.push_back(Pair("status", "disabled")); break; - case UPGRADE_PENDING: rv.push_back(Pair("status", "pending")); break; - case UPGRADE_ACTIVE: rv.push_back(Pair("status", "active")); break; - } - rv.push_back(Pair("info", upgrade.strInfo)); - return rv; -} - -void NetworkUpgradeDescPushBack( - UniValue& networkUpgrades, - const Consensus::Params& consensusParams, - Consensus::UpgradeIndex idx, - int height) -{ - // Network upgrades with an activation height of NO_ACTIVATION_HEIGHT are - // hidden. This is used when network upgrade implementations are merged - // without specifying the activation height. - if (consensusParams.vUpgrades[idx].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) { - networkUpgrades.push_back(Pair( - HexInt(NetworkUpgradeInfo[idx].nBranchId), - NetworkUpgradeDesc(consensusParams, idx, height))); - } -} - - -UniValue getblockchaininfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getblockchaininfo\n" - "Returns an object containing various state info regarding block chain processing.\n" - "\nNote that when the chain tip is at the last block before a network upgrade activation,\n" - "consensus.chaintip != consensus.nextblock.\n" - "\nResult:\n" - "{\n" - " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" - " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" - " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" - " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" - " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" - " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" - " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" - " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" - " \"commitments\": xxxxxx, (numeric) the current number of note commitments in the commitment tree\n" - " \"softforks\": [ (array) status of softforks in progress\n" - " {\n" - " \"id\": \"xxxx\", (string) name of softfork\n" - " \"version\": xx, (numeric) block version\n" - " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n" - " \"status\": xx, (boolean) true if threshold reached\n" - " \"found\": xx, (numeric) number of blocks with the new version found\n" - " \"required\": xx, (numeric) number of blocks required to trigger\n" - " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n" - " },\n" - " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" - " }, ...\n" - " ],\n" - " \"upgrades\": { (object) status of network upgrades\n" - " \"xxxx\" : { (string) branch ID of the upgrade\n" - " \"name\": \"xxxx\", (string) name of upgrade\n" - " \"activationheight\": xxxxxx, (numeric) block height of activation\n" - " \"status\": \"xxxx\", (string) status of upgrade\n" - " \"info\": \"xxxx\", (string) additional information about upgrade\n" - " }, ...\n" - " },\n" - " \"consensus\": { (object) branch IDs of the current and upcoming consensus rules\n" - " \"chaintip\": \"xxxxxxxx\", (string) branch ID used to validate the current chain tip\n" - " \"nextblock\": \"xxxxxxxx\" (string) branch ID that the next block will be validated under\n" - " }\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getblockchaininfo", "") - + HelpExampleRpc("getblockchaininfo", "") - ); - - LOCK(cs_main); - double progress; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - progress = Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.LastTip()); - } else { - int32_t longestchain = KOMODO_LONGESTCHAIN;//komodo_longestchain(); - progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0; - } - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("chain", Params().NetworkIDString())); - obj.push_back(Pair("blocks", (int)chainActive.Height())); - obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1)); - obj.push_back(Pair("bestblockhash", chainActive.LastTip()->GetBlockHash().GetHex())); - obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); - obj.push_back(Pair("verificationprogress", progress)); - obj.push_back(Pair("chainwork", chainActive.LastTip()->nChainWork.GetHex())); - obj.push_back(Pair("pruned", fPruneMode)); - obj.push_back(Pair("size_on_disk", CalculateCurrentUsage())); - - ZCIncrementalMerkleTree tree; - pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree); - #ifdef __APPLE__ - obj.push_back(Pair("commitments", (uint64_t)tree.size())); - #else - obj.push_back(Pair("commitments", tree.size())); - #endif - - CBlockIndex* tip = chainActive.LastTip(); - UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none)); - obj.push_back(Pair("valuePools", valuePools)); - - const Consensus::Params& consensusParams = Params().GetConsensus(); - UniValue softforks(UniValue::VARR); - softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); - softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); - softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - obj.push_back(Pair("softforks", softforks)); - - UniValue upgrades(UniValue::VOBJ); - for (int i = Consensus::UPGRADE_OVERWINTER; i < Consensus::MAX_NETWORK_UPGRADES; i++) { - NetworkUpgradeDescPushBack(upgrades, consensusParams, Consensus::UpgradeIndex(i), tip->nHeight); - } - obj.push_back(Pair("upgrades", upgrades)); - - UniValue consensus(UniValue::VOBJ); - consensus.push_back(Pair("chaintip", HexInt(CurrentEpochBranchId(tip->nHeight, consensusParams)))); - consensus.push_back(Pair("nextblock", HexInt(CurrentEpochBranchId(tip->nHeight + 1, consensusParams)))); - obj.push_back(Pair("consensus", consensus)); - - if (fPruneMode) - { - CBlockIndex *block = chainActive.LastTip(); - while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) - block = block->pprev; - - obj.push_back(Pair("pruneheight", block->nHeight)); - } - return obj; -} - -/** Comparison function for sorting the getchaintips heads. */ -struct CompareBlocksByHeight -{ - bool operator()(const CBlockIndex* a, const CBlockIndex* b) const - { - /* Make sure that unequal blocks with the same height do not compare - equal. Use the pointers themselves to make a distinction. */ - - if (a->nHeight != b->nHeight) - return (a->nHeight > b->nHeight); - - return a < b; - } -}; - -#include - -UniValue getchaintips(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getchaintips\n" - "Return information about all known tips in the block tree," - " including the main chain as well as orphaned branches.\n" - "\nResult:\n" - "[\n" - " {\n" - " \"height\": xxxx, (numeric) height of the chain tip\n" - " \"hash\": \"xxxx\", (string) block hash of the tip\n" - " \"branchlen\": 0 (numeric) zero for main chain\n" - " \"status\": \"active\" (string) \"active\" for the main chain\n" - " },\n" - " {\n" - " \"height\": xxxx,\n" - " \"hash\": \"xxxx\",\n" - " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" - " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" - " }\n" - "]\n" - "Possible values for status:\n" - "1. \"invalid\" This branch contains at least one invalid block\n" - "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" - "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" - "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" - "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" - "\nExamples:\n" - + HelpExampleCli("getchaintips", "") - + HelpExampleRpc("getchaintips", "") - ); - - LOCK(cs_main); - - /* Build up a list of chain tips. We start with the list of all - known blocks, and successively remove blocks that appear as pprev - of another block. */ - /*static pthread_mutex_t mutex; static int32_t didinit; - if ( didinit == 0 ) - { - pthread_mutex_init(&mutex,NULL); - didinit = 1; - } - pthread_mutex_lock(&mutex);*/ - std::set setTips; - int32_t n = 0; - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) - { - n++; - setTips.insert(item.second); - } - fprintf(stderr,"iterations getchaintips %d\n",n); - n = 0; - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) - { - const CBlockIndex* pprev=0; - n++; - if ( item.second != 0 ) - pprev = item.second->pprev; - if (pprev) - setTips.erase(pprev); - } - fprintf(stderr,"iterations getchaintips %d\n",n); - //pthread_mutex_unlock(&mutex); - - // Always report the currently active tip. - setTips.insert(chainActive.LastTip()); - - /* Construct the output array. */ - UniValue res(UniValue::VARR); const CBlockIndex *forked; - BOOST_FOREACH(const CBlockIndex* block, setTips) - BOOST_FOREACH(const CBlockIndex* block, setTips) - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("height", block->nHeight)); - obj.push_back(Pair("hash", block->phashBlock->GetHex())); - forked = chainActive.FindFork(block); - if ( forked != 0 ) - { - const int branchLen = block->nHeight - forked->nHeight; - obj.push_back(Pair("branchlen", branchLen)); - - string status; - if (chainActive.Contains(block)) { - // This block is part of the currently active chain. - status = "active"; - } else if (block->nStatus & BLOCK_FAILED_MASK) { - // This block or one of its ancestors is invalid. - status = "invalid"; - } else if (block->nChainTx == 0) { - // This block cannot be connected because full block data for it or one of its parents is missing. - status = "headers-only"; - } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) { - // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized. - status = "valid-fork"; - } else if (block->IsValid(BLOCK_VALID_TREE)) { - // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain. - status = "valid-headers"; - } else { - // No clue. - status = "unknown"; - } - obj.push_back(Pair("status", status)); - } - res.push_back(obj); - } - - return res; -} - -UniValue mempoolInfoToJSON() -{ - UniValue ret(UniValue::VOBJ); - ret.push_back(Pair("size", (int64_t) mempool.size())); - ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize())); - ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); - - return ret; -} - -UniValue getmempoolinfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getmempoolinfo\n" - "\nReturns details on the active state of the TX memory pool.\n" - "\nResult:\n" - "{\n" - " \"size\": xxxxx (numeric) Current tx count\n" - " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n" - " \"usage\": xxxxx (numeric) Total memory usage for the mempool\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getmempoolinfo", "") - + HelpExampleRpc("getmempoolinfo", "") - ); - - return mempoolInfoToJSON(); -} - -UniValue invalidateblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "invalidateblock \"hash\"\n" - "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the block to mark as invalid\n" - "\nResult:\n" - "\nExamples:\n" - + HelpExampleCli("invalidateblock", "\"blockhash\"") - + HelpExampleRpc("invalidateblock", "\"blockhash\"") - ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - CValidationState state; - - { - LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - InvalidateBlock(state, pblockindex); - } - - if (state.IsValid()) { - ActivateBestChain(state); - } - - if (!state.IsValid()) { - throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); - } - - return NullUniValue; -} - -UniValue reconsiderblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "reconsiderblock \"hash\"\n" - "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" - "This can be used to undo the effects of invalidateblock.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the block to reconsider\n" - "\nResult:\n" - "\nExamples:\n" - + HelpExampleCli("reconsiderblock", "\"blockhash\"") - + HelpExampleRpc("reconsiderblock", "\"blockhash\"") - ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - CValidationState state; - - { - LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - ReconsiderBlock(state, pblockindex); - } - - if (state.IsValid()) { - ActivateBestChain(state); - } - - if (!state.IsValid()) { - throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); - } - - return NullUniValue; -} diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index fa5dce4eb89..e0f6123b6e9 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -81,16 +81,8 @@ using namespace std; using namespace libzcash; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; const std::string ADDR_TYPE_SPROUT = "sprout"; const std::string ADDR_TYPE_SAPLING = "sapling"; -extern UniValue TxJoinSplitToJSON(const CTransaction& tx); -extern int32_t KOMODO_INSYNC; -uint32_t komodo_segid32(char *coinaddr); -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime); // from ac_private chains only -CBlockIndex *komodo_getblockindex(uint256 hash); int64_t nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; @@ -102,8 +94,6 @@ UniValue z_getoperationstatus_IMPL(const UniValue&, bool); #define VALID_PLAN_NAME(x) (strlen(x) <= PLAN_NAME_MAX) #define THROW_IF_SYNCING(INSYNC) if (INSYNC == 0) { throw runtime_error(strprintf("%s: Chain still syncing at height %d, aborting to prevent linkability analysis!",__FUNCTION__,chainActive.Tip()->GetHeight())); } -int tx_height( const uint256 &hash ); - std::string HelpRequiringPassphrase() { return pwalletMain && pwalletMain->IsCrypted() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6db007fb2fb..9f9d55c9347 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -60,12 +60,7 @@ unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; bool bSpendZeroConfChange = true; bool fSendFreeTransactions = false; bool fPayAtLeastCustomFee = true; -#include "komodo_defs.h" -CBlockIndex *komodo_chainactive(int32_t height); -extern std::string DONATION_PUBKEY; -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -int tx_height( const uint256 &hash ); /** * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) From e2b6d115d569caf7ffaffededd84aa340a62f8fe Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 27 Aug 2021 16:24:22 +0300 Subject: [PATCH 093/348] more refactoring: decl moved to komodo_defs.h --- src/cc/import.cpp | 17 ----------------- src/komodo_defs.h | 4 ++++ src/miner.cpp | 9 +++------ src/rpc/mining.cpp | 6 ------ src/wallet/rpcdisclosure.cpp | 4 ++-- src/wallet/rpcdump.cpp | 5 ++--- src/wallet/rpcwallet.cpp | 2 ++ src/wallet/rpcwallet.h | 1 + 8 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/cc/import.cpp b/src/cc/import.cpp index d59ecc282d5..74344e951a4 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -35,23 +35,6 @@ ##### 0xffffffff is a special CCid for single chain/dual daemon imports */ -/* todo remove*/ - -/* -extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; -extern uint256 KOMODO_EARLYTXID; - -// utilities from gateways.cpp -uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::vector &txids); -uint256 GatewaysReverseScan(uint256 &txid, int32_t height, uint256 reforacletxid, uint256 batontxid); -int32_t GatewaysCointxidExists(struct CCcontract_info *cp, uint256 cointxid); -uint8_t DecodeImportGatewayBindOpRet(char *burnaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); -int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2); -char *nonportable_path(char *str); -char *portable_path(char *str); -void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); -void *filestr(long *allocsizep,char *_fname);*/ - cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,char const *arg3,char const *arg4,char const *arg5) { char cmdstr[5000],fname[256],*jsonstr; diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 708c754a9ed..12e4f1553f0 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -629,6 +629,9 @@ void komodo_broadcast(CBlock *pblock,int32_t limit); int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); +arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); +int32_t komodo_baseid(char *origbase); +int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); @@ -649,6 +652,7 @@ extern int32_t ASSETCHAINS_STAKED; extern uint64_t ASSETCHAINS_DECAY[]; extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; extern int32_t KOMODO_LOADINGBLOCKS; +extern int32_t ASSETCHAINS_FOUNDERS; #ifndef KOMODO_NSPV_FULLNODE #define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) diff --git a/src/miner.cpp b/src/miner.cpp index 2a8c7351413..a7b045e2832 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1117,13 +1117,10 @@ static bool ProcessBlockFound(CBlock* pblock) return true; } -int32_t komodo_baseid(char *origbase); -int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); -arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); -int32_t FOUND_BLOCK,KOMODO_MAYBEMINED; -extern int32_t KOMODO_LASTMINED,KOMODO_INSYNC; + +int32_t FOUND_BLOCK, KOMODO_MAYBEMINED; int32_t roundrobin_delay; -arith_uint256 HASHTarget,HASHTarget_POW; +arith_uint256 HASHTarget, HASHTarget_POW; // wait for peers to connect void waitForPeers(const CChainParams &chainparams) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index d2e891556c2..1241e05bb0b 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -50,12 +50,6 @@ using namespace std; #include "komodo_defs.h" -extern int32_t ASSETCHAINS_FOUNDERS; -uint64_t komodo_commission(const CBlock *pblock,int32_t height); -int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex); -arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); -int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); - /** * Return average network hashes per second based on the last 'lookup' blocks, * or over the difficulty averaging window if 'lookup' is nonpositive. diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index cd0cc42a6c5..e42628f6416 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -42,11 +42,11 @@ #include "zcash/Note.hpp" #include "zcash/NoteEncryption.hpp" +#include "rpcwallet.h" + using namespace std; using namespace libzcash; -// Function declaration for function implemented in wallet/rpcwallet.cpp -bool EnsureWalletIsAvailable(bool avoidException); /** * RPC call to generate a payment disclosure diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 31f583ee4f1..3795a7077ad 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -37,10 +37,9 @@ #include -using namespace std; +#include "rpcwallet.h" -void EnsureWalletIsUnlocked(); -bool EnsureWalletIsAvailable(bool avoidException); +using namespace std; UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys); UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e0f6123b6e9..a7a1733218b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -63,6 +63,8 @@ #include "komodo_defs.h" #include +#include "rpcwallet.h" + #include "../cc/CCfaucet.h" #include "../cc/CCrewards.h" #include "../cc/CCdice.h" diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 3e7a54d4afe..226647b1986 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -24,5 +24,6 @@ class CRPCTable; void RegisterWalletRPCCommands(CRPCTable &tableRPC); bool EnsureWalletIsAvailable(bool avoidException); +void EnsureWalletIsUnlocked(); #endif //BITCOIN_WALLET_RPCWALLET_H From e91a98720d538e3a826f00643ff8d0bca8069673 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 30 Aug 2021 14:53:53 +0300 Subject: [PATCH 094/348] lock moved up in get_chainactive --- src/miner.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index a7b045e2832..e7f8a74aa75 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1169,19 +1169,17 @@ void waitForPeers(const CChainParams &chainparams) } #ifdef ENABLE_WALLET -CBlockIndex *get_chainactive(int32_t height) +CBlockIndex* get_chainactive(int32_t height) { - if ( chainActive.LastTip() != 0 ) - { - if ( height <= chainActive.LastTip()->GetHeight() ) - { - LOCK(cs_main); - return(chainActive[height]); + LOCK(cs_main); // moved lock at the begininng as getting the vector size is unsafe in the multithread env + if (chainActive.LastTip() != 0) { + if (height <= chainActive.LastTip()->GetHeight()) { + return (chainActive[height]); } // else fprintf(stderr,"get_chainactive height %d > active.%d\n",height,chainActive.Tip()->GetHeight()); } //fprintf(stderr,"get_chainactive null chainActive.Tip() height %d\n",height); - return(0); + return (0); } /* From 6efb71e815eb8c98d08076dbf743c936967428e8 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 30 Aug 2021 15:38:47 +0300 Subject: [PATCH 095/348] added check lockstack not null in debug lockorder --- src/sync.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sync.cpp b/src/sync.cpp index 31c3301bd25..2f17a401bad 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -157,7 +157,8 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) static void pop_lock() { dd_mutex.lock(); - (*lockstack).pop_back(); + if (lockstack.get() != NULL) + (*lockstack).pop_back(); dd_mutex.unlock(); } From cf7a5817ecfa5ce435d9b09730b0d0aed08ea7ad Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 7 Sep 2021 21:21:24 +0500 Subject: [PATCH 096/348] rate limiter to check reqs/sec; added maxrecords param to nspv getutxo gettxids --- src/komodo_defs.h | 2 + src/komodo_nSPV.h | 10 +- src/komodo_nSPV_defs.h | 10 +- src/komodo_nSPV_fullnode.h | 232 +++++++++++++++++++++--------------- src/komodo_nSPV_superlite.h | 29 +++-- src/net.cpp | 2 + src/net.h | 6 +- 7 files changed, 176 insertions(+), 115 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 12e4f1553f0..a3a278037f9 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -44,6 +44,8 @@ #define ASSETCHAINS_STAKED_MIN_POW_DIFF 536900000 // 537000000 537300000 #define _COINBASE_MATURITY 100 +#define IS_KMD_CHAIN() (ASSETCHAINS_SYMBOL[0] == '\0') + #define KOMODO_ADDRESS_BUFSIZE 64 // KMD Notary Seasons diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index 8b6b74fd6c3..e8bb2d9df31 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -26,6 +26,12 @@ #ifndef KOMODO_NSPV_H #define KOMODO_NSPV_H +#include +#include "main.h" +#include "komodo_defs.h" +#include "cc/CCinclude.h" +#include "komodo_nSPV_defs.h" + int32_t iguana_rwbuf(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *buf) { if ( rwflag != 0 ) @@ -101,7 +107,7 @@ int32_t NSPV_rwutxosresp(int32_t rwflag,uint8_t *serialized,struct NSPV_utxosres len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->total),&ptr->total); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->interest),&ptr->interest); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->filter),&ptr->filter); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->maxrecords),&ptr->maxrecords); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); if ( rwflag != 0 ) @@ -159,7 +165,7 @@ int32_t NSPV_rwtxidsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidsres len += NSPV_rwtxidresp(rwflag,&serialized[len],&ptr->txids[i]); } len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->filter),&ptr->filter); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->maxrecords),&ptr->maxrecords); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); if ( rwflag != 0 ) diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 18a10338d4f..20579cf8ab3 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -17,6 +17,8 @@ #ifndef KOMODO_NSPV_DEFSH #define KOMODO_NSPV_DEFSH +#include + #define NSPV_PROTOCOL_VERSION 0x00000004 #define NSPV_POLLITERS 200 #define NSPV_POLLMICROS 50000 @@ -55,6 +57,8 @@ #define NSPV_REMOTERPC 0x14 #define NSPV_REMOTERPCRESP 0x15 +#define NSPV_MAXREQSPERSEC 15 + int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int32_t height,CTransaction &tx,uint256 &hashblock,int32_t &txheight,int32_t ¤theight,int64_t extradata,uint32_t tiptime,int64_t &rewardsum); UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); extern uint256 SIG_TXHASH; @@ -84,7 +88,7 @@ struct NSPV_utxosresp struct NSPV_utxoresp *utxos; char coinaddr[64]; int64_t total,interest; - int32_t nodeheight,skipcount,filter; + int32_t nodeheight,skipcount,maxrecords; uint16_t numutxos,CCflag; }; @@ -99,8 +103,8 @@ struct NSPV_txidsresp { struct NSPV_txidresp *txids; char coinaddr[64]; - int32_t nodeheight,skipcount,filter; - uint16_t numtxids,CCflag; + int32_t nodeheight, skipcount, maxrecords; + uint16_t numtxids, CCflag; }; struct NSPV_mempoolresp diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 2075590e41d..120d36c5d95 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -19,8 +19,17 @@ // NSPV_get... functions need to return the exact serialized length, which is the size of the structure minus size of pointers, plus size of allocated data +#include + +#include "main.h" +#include "komodo_defs.h" #include "notarisationdb.h" #include "rpc/server.h" +#include "cc/CCinclude.h" +#include "komodo_nSPV_defs.h" +#include "komodo_nSPV.h" + + static std::map nspv_remote_commands = { @@ -176,72 +185,70 @@ int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) return (-1); } -int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC,int32_t skipcount,uint32_t filter) +int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool isCC, int32_t skipcount, int32_t maxrecords) { CAmount total = 0, interest = 0; uint32_t locktime; - int32_t ind = 0, tipheight, maxlen, txheight, n = 0, len = 0; + int32_t ind = 0, tipheight, /*maxlen,*/ txheight, n = 0; - std::vector > unspentOutputs; - SetCCunspents(unspentOutputs,coinaddr,isCC); + std::vector> unspentOutputs; + SetCCunspents(unspentOutputs, coinaddr, isCC); { LOCK(cs_main); tipheight = chainActive.LastTip()->GetHeight(); } - maxlen = MAX_BLOCK_SIZE(tipheight) - 512; - maxlen /= sizeof(*ptr->utxos); - strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); + // use maxrecords + //maxlen = MAX_BLOCK_SIZE(tipheight) - 512; + //maxlen /= sizeof(*ptr->utxos); + if (maxrecords <= 0 || maxrecords >= std::numeric_limits::max()) + maxrecords >= std::numeric_limits::max(); // prevent large requests + + strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = isCC; - ptr->filter = filter; - if ( skipcount < 0 ) + ptr->maxrecords = maxrecords; + if (skipcount < 0) skipcount = 0; - if ( (ptr->numutxos= (int32_t)unspentOutputs.size()) >= 0 && ptr->numutxos < maxlen ) - { + if ((ptr->numutxos = (int32_t)unspentOutputs.size()) >= 0) { ptr->nodeheight = tipheight; - if ( skipcount >= ptr->numutxos ) - skipcount = ptr->numutxos-1; + if (skipcount >= ptr->numutxos) + skipcount = ptr->numutxos - 1; ptr->skipcount = skipcount; - if ( ptr->numutxos-skipcount > 0 ) - { - ptr->utxos = (struct NSPV_utxoresp *)calloc(ptr->numutxos-skipcount,sizeof(*ptr->utxos)); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { + if (ptr->numutxos - skipcount > 0) { + ptr->utxos = (struct NSPV_utxoresp*)calloc(ptr->numutxos - skipcount, sizeof(*ptr->utxos)); + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { // if gettxout is != null to handle mempool { - if ( n >= skipcount && myIsutxo_spentinmempool(ignoretxid,ignorevin,it->first.txhash,(int32_t)it->first.index) == 0 ) - { + if (n >= skipcount && myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index) == 0) { ptr->utxos[ind].txid = it->first.txhash; ptr->utxos[ind].vout = (int32_t)it->first.index; ptr->utxos[ind].satoshis = it->second.satoshis; ptr->utxos[ind].height = it->second.blockHeight; - if ( ASSETCHAINS_SYMBOL[0] == 0 && it->second.satoshis >= 10*COIN ) - { - ptr->utxos[n].extradata = komodo_accrued_interest(&txheight,&locktime,ptr->utxos[ind].txid,ptr->utxos[ind].vout,ptr->utxos[ind].height,ptr->utxos[ind].satoshis,tipheight); + if (IS_KMD_CHAIN() && it->second.satoshis >= 10 * COIN) { // calc interest on the kmd chain + ptr->utxos[n].extradata = komodo_accrued_interest(&txheight, &locktime, ptr->utxos[ind].txid, ptr->utxos[ind].vout, ptr->utxos[ind].height, ptr->utxos[ind].satoshis, tipheight); interest += ptr->utxos[ind].extradata; } ind++; total += it->second.satoshis; } n++; + if (ind >= maxrecords) + break; } } } ptr->numutxos = ind; - if ( len < maxlen ) - { - len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->utxos)*ptr->numutxos - sizeof(ptr->utxos)); - //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); - ptr->total = total; - ptr->interest = interest; - return(len); - } + int32_t len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->utxos) * ptr->numutxos - sizeof(ptr->utxos)); + //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); + ptr->total = total; + ptr->interest = interest; + return (len); } - if ( ptr->utxos != 0 ) + if (ptr->utxos != 0) free(ptr->utxos); - memset(ptr,0,sizeof(*ptr)); - return(0); + memset(ptr, 0, sizeof(*ptr)); + return (0); } class BaseCCChecker { @@ -373,7 +380,7 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ //} // select all appropriate utxos: - std::cerr << __func__ << " " << "searching addr=" << coinaddr << std::endl; + //std::cerr << __func__ << " " << "searching addr=" << coinaddr << std::endl; for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { if (myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index) == 0) @@ -389,7 +396,7 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ // if a checker is set for evalcode use it otherwise use the default checker: if (baseChecker && baseChecker->checkCC(it->first.txhash, tx.vout, nvout, evalcode, funcids, filtertxid) || defaultCCChecker.checkCC(it->first.txhash, tx.vout, nvout, evalcode, funcids, filtertxid)) { - std::cerr << __func__ << " " << "filtered utxo with amount=" << tx.vout[nvout].nValue << std::endl; + //std::cerr << __func__ << " " << "filtered utxo with amount=" << tx.vout[nvout].nValue << std::endl; struct CC_utxo utxo; utxo.txid = it->first.txhash; @@ -405,7 +412,6 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ } } - if (amount == 0) { // just return total value ptr->total = total; @@ -471,31 +477,34 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ } } -int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC,int32_t skipcount,uint32_t filter) +int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool isCC, int32_t skipcount, int32_t maxrecords) { - int32_t maxlen,txheight,ind=0,n = 0,len = 0; CTransaction tx; uint256 hashBlock; - std::vector > txids; - SetAddressIndexOutputs(txids,coinaddr,isCC); + int32_t txheight, ind = 0, n = 0, len = 0; + CTransaction tx; + uint256 hashBlock; + std::vector> txids; + SetAddressIndexOutputs(txids, coinaddr, isCC); ptr->nodeheight = chainActive.LastTip()->GetHeight(); - maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; - maxlen /= sizeof(*ptr->txids); - strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); + + // using maxrecords instead: + //maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; + //maxlen /= sizeof(*ptr->txids); + if (maxrecords <= 0 || maxrecords >= std::numeric_limits::max()) + maxrecords >= std::numeric_limits::max(); // prevent large requests + + strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = isCC; - ptr->filter = filter; - if ( skipcount < 0 ) + ptr->maxrecords = maxrecords; + if (skipcount < 0) skipcount = 0; - if ( (ptr->numtxids= (int32_t)txids.size()) >= 0 && ptr->numtxids < maxlen ) - { - if ( skipcount >= ptr->numtxids ) - skipcount = ptr->numtxids-1; + if ((ptr->numtxids = (int32_t)txids.size()) >= 0) { + if (skipcount >= ptr->numtxids) + skipcount = ptr->numtxids - 1; ptr->skipcount = skipcount; - if ( ptr->numtxids-skipcount > 0 ) - { - ptr->txids = (struct NSPV_txidresp *)calloc(ptr->numtxids-skipcount,sizeof(*ptr->txids)); - for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) - { - if ( n >= skipcount ) - { + if (ptr->numtxids - skipcount > 0) { + ptr->txids = (struct NSPV_txidresp*)calloc(ptr->numtxids - skipcount, sizeof(*ptr->txids)); + for (std::vector>::const_iterator it = txids.begin(); it != txids.end(); it++) { + if (n >= skipcount) { ptr->txids[ind].txid = it->first.txhash; ptr->txids[ind].vout = (int32_t)it->first.index; ptr->txids[ind].satoshis = (int64_t)it->second; @@ -503,16 +512,18 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC ind++; } n++; + if (ind >= maxrecords) + break; } } ptr->numtxids = ind; - len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); - return(len); + len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids) * ptr->numtxids - sizeof(ptr->txids)); + return (len); } - if ( ptr->txids != 0 ) + if (ptr->txids != nullptr) free(ptr->txids); - memset(ptr,0,sizeof(*ptr)); - return(0); + memset(ptr, 0, sizeof(*ptr)); + return (0); } int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector &txids,char *coinaddr,bool isCC,uint8_t funcid,uint256 txid,int32_t vout) @@ -759,7 +770,7 @@ uint8_t *NSPV_getrawtx(CTransaction &tx,uint256 &hashBlock,int32_t *txlenp,uint2 //fprintf(stderr,"error getting transaction %s\n",txid.GetHex().c_str()); return(0); } - string strHex = EncodeHexTx(tx); + std::string strHex = EncodeHexTx(tx); *txlenp = (int32_t)strHex.size() >> 1; if ( *txlenp > 0 ) { @@ -832,7 +843,7 @@ int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid, in } } if (found) { - set setTxids; + std::set setTxids; CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); setTxids.insert(txid); CMerkleBlock mb(block, setTxids); @@ -937,14 +948,25 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req int32_t len = request.size(); // rate limit no more 1 request/sec of same type from same node: - int32_t ind = request[0] >> 1; - if (ind >= sizeof(pfrom->prevtimes)/sizeof(*pfrom->prevtimes) ) - ind = (int32_t)(sizeof(pfrom->prevtimes)/sizeof(*pfrom->prevtimes)) - 1; - if (pfrom->prevtimes[ind] > timestamp) - pfrom->prevtimes[ind] = 0; - else if (timestamp == pfrom->prevtimes[ind]) { - LogPrint("nspv", "rate limit from peer %d\n", pfrom->id); - return; + int32_t nData = request[0] >> 1; + if (nData >= sizeof(pfrom->nspvdata)/sizeof(pfrom->nspvdata[0]) ) + nData = (int32_t)(sizeof(pfrom->nspvdata)/sizeof(pfrom->nspvdata[0])) - 1; + std::cerr << __func__ << "pfrom=" << (uint64_t)pfrom << " request[0]=" << (int)request[0] << " nData=" << nData << " timestamp=" << timestamp << " pfrom->nspvdata[nData].prevtime=" << pfrom->nspvdata[nData].prevtime << " pfrom->nspvdata[nData].nreqs=" << pfrom->nspvdata[nData].nreqs << " timestamp-prevtime=" << timestamp-pfrom->nspvdata[nData].prevtime << std::endl; + if (pfrom->nspvdata[nData].prevtime > timestamp) { + pfrom->nspvdata[nData].prevtime = 0; + pfrom->nspvdata[nData].nreqs = 0; + std::cerr << __func__ << " prevtime>timestamp reset to 0 pfrom->nspvdata[nData].prevtime=" << pfrom->nspvdata[nData].prevtime << std::endl; + } + else if (timestamp == pfrom->nspvdata[nData].prevtime) { + if (pfrom->nspvdata[nData].nreqs > NSPV_MAXREQSPERSEC) { + LogPrint("nspv", "rate limit from peer %d\n", pfrom->id); + return; + } + pfrom->nspvdata[nData].nreqs ++; + } + else { + pfrom->nspvdata[nData].nreqs = 0; + std::cerr << __func__ << " timestamp changed, reset nreqs=" << std::endl; } switch(request[0]) @@ -952,7 +974,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req case NSPV_INFO: // info { struct NSPV_inforesp I; - //fprintf(stderr,"check info %u vs %u, ind.%d\n",timestamp,pfrom->prevtimes[ind],ind); + //fprintf(stderr,"check info %u vs %u, ind.%d\n", timestamp, pfrom->nspvdata[ind].prevtime, ind); if (len == 1 + sizeof(reqheight)) iguana_rwnum(IGUANA_READ, &request[1], sizeof(reqheight), &reqheight); else @@ -967,7 +989,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { //fprintf(stderr,"send info resp to id %d\n",(int32_t)pfrom->id); pfrom->PushMessage("nSPV",response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; LogPrint("nspv-details", "NSPV_INFO response: version %d to node=%d\n", I.version, pfrom->id); } else @@ -983,9 +1006,9 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req struct NSPV_utxosresp U; char coinaddr[KOMODO_ADDRESS_BUFSIZE]; int32_t skipcount = 0; - uint32_t filter = 0; + int32_t maxrecords = 0; uint8_t isCC = 0; - //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->prevtimes[ind],ind,len); + //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); if (len < 2) { LogPrint("nspv", "NSPV_UTXOS bad request too short len.%d node %d\n", len, pfrom->id); @@ -1011,10 +1034,10 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { iguana_rwnum(IGUANA_READ, &request[offset], sizeof(skipcount), &skipcount); offset += sizeof(skipcount); - if (offset + sizeof(filter) <= len) + if (offset + sizeof(maxrecords) <= len) { - iguana_rwnum(IGUANA_READ, &request[offset], sizeof(filter), &filter); - offset += sizeof(filter); + iguana_rwnum(IGUANA_READ, &request[offset], sizeof(maxrecords), &maxrecords); + offset += sizeof(maxrecords); } } } @@ -1023,16 +1046,17 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req return; } - LogPrint("nspv-details", "NSPV_UTXOS address=%s isCC.%d skipcount.%d filter.%x\n", coinaddr, isCC, skipcount, filter); + LogPrint("nspv-details", "NSPV_UTXOS address=%s isCC.%d skipcount.%d maxrecords.%d\n", coinaddr, isCC, skipcount, maxrecords); memset(&U, 0, sizeof(U)); - if ((slen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, filter)) > 0) + if ((slen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, maxrecords)) > 0) { response.resize(1 + slen); response[0] = NSPV_UTXOSRESP; if ( NSPV_rwutxosresp(IGUANA_WRITE, &response[1], &U) == slen ) { pfrom->PushMessage("nSPV",response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; LogPrint("nspv-details", "NSPV_UTXOS response: numutxos=%d to node=%d\n", U.numutxos, pfrom->id); } else @@ -1049,9 +1073,9 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req struct NSPV_txidsresp T; char coinaddr[KOMODO_ADDRESS_BUFSIZE]; int32_t skipcount = 0; - uint32_t filter = 0; + int32_t maxrecords = 0; uint8_t isCC = 0; - //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->prevtimes[ind],ind,len); + //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); if (len < 2) { LogPrint("nspv", "NSPV_TXIDS bad request too short len.%d, node %d\n", len, pfrom->id); @@ -1077,10 +1101,10 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { iguana_rwnum(IGUANA_READ, &request[offset], sizeof(skipcount), &skipcount); offset += sizeof(skipcount); - if (offset + sizeof(filter) <= len) + if (offset + sizeof(maxrecords) <= len) { - iguana_rwnum(IGUANA_READ, &request[offset], sizeof(filter), &filter); - offset += sizeof(filter); + iguana_rwnum(IGUANA_READ, &request[offset], sizeof(maxrecords), &maxrecords); + offset += sizeof(maxrecords); } } } @@ -1089,10 +1113,10 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req return; } - LogPrint("nspv-details", "NSPV_TXIDS address=%s isCC.%d skipcount.%d filter.%x\n",coinaddr, isCC, skipcount, filter); + LogPrint("nspv-details", "NSPV_TXIDS address=%s isCC.%d skipcount.%d maxrecords.%x\n",coinaddr, isCC, skipcount, maxrecords); memset(&T, 0, sizeof(T)); - if ((slen = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, filter)) > 0) + if ((slen = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, maxrecords)) > 0) { //fprintf(stderr,"slen.%d\n",slen); response.resize(1 + slen); @@ -1100,7 +1124,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwtxidsresp(IGUANA_WRITE, &response[1], &T) == slen) { pfrom->PushMessage("nSPV",response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; LogPrint("nspv-details", "NSPV_TXIDS response: numtxids=%d to node=%d\n", (int)T.numtxids, pfrom->id); } else @@ -1141,7 +1166,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req response[0] = NSPV_MEMPOOLRESP; if (NSPV_rwmempoolresp(IGUANA_WRITE, &response[1], &M) == slen) { pfrom->PushMessage("nSPV", response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; LogPrint("nspv-details", "NSPV_MEMPOOL response: numtxids=%d to node=%d\n", M.numtxids, pfrom->id); } else LogPrint("nspv", "NSPV_rwmempoolresp incorrect response len.%d\n", slen); @@ -1173,7 +1199,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwntzsresp(IGUANA_WRITE, &response[1], &N) == slen) { pfrom->PushMessage("nSPV",response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; LogPrint("nspv-details", "NSPV_NTZS response: prevntz.txid=%s nextntx.txid=%s node=%d\n", N.prevntz.txid.GetHex().c_str(), N.nextntz.txid.GetHex().c_str(), pfrom->id); } else @@ -1204,7 +1231,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwntzsproofresp(IGUANA_WRITE, &response[1], &P) == slen) { pfrom->PushMessage("nSPV", response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; LogPrint("nspv-details", "NSPV_NTZSPROOF response: prevtxidht=%d nexttxidht=%d node=%d\n", P.prevtxidht, P.nexttxidht, pfrom->id); } else @@ -1240,7 +1268,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { //fprintf(stderr,"send response\n"); pfrom->PushMessage("nSPV",response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; LogPrint("nspv-details", "NSPV_TXPROOF response: txlen=%d txprooflen=%d node=%d\n", P.txlen, P.txprooflen, pfrom->id); } else @@ -1273,7 +1302,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwspentinfo(IGUANA_WRITE, &response[1], &S) == slen) { pfrom->PushMessage("nSPV",response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; LogPrint("nspv-details", "NSPV_SPENTINFO response: spent txid=%s vout=%d node=%d\n", S.txid.GetHex().c_str(), S.vout, pfrom->id); } else @@ -1307,7 +1337,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwbroadcastresp(IGUANA_WRITE, &response[1], &B) == slen) { pfrom->PushMessage("nSPV",response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; LogPrint("nspv-details", "NSPV_BROADCAST response: txid=%s vout=%d to node=%d\n", B.txid.GetHex().c_str(), pfrom->id); } else @@ -1335,7 +1366,9 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req response[0] = NSPV_REMOTERPCRESP; NSPV_rwremoterpcresp(IGUANA_WRITE, &response[1], &R, slen); pfrom->PushMessage("nSPV", response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; + std::cerr << __func__ << " set pfrom->nspvdata[" << nData << "].prevtime=" << timestamp << std::endl; LogPrint("nspv-details", "NSPV_REMOTERPCRESP response: method=%s json=%s to node=%d\n", R.method, R.json, pfrom->id); NSPV_remoterpc_purge(&R); } @@ -1354,7 +1387,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req char funcids[27]; uint256 filtertxid; bool errorFormat = false; - //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->prevtimes[ind],ind,len); + //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); if (len < 3) { LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short, node=%d\n", len, pfrom->id); @@ -1404,7 +1437,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwutxosresp(IGUANA_WRITE, &response[1], &U) == slen) { pfrom->PushMessage("nSPV", response); - pfrom->prevtimes[ind] = timestamp; + pfrom->nspvdata[nData].prevtime = timestamp; + pfrom->nspvdata[nData].nreqs ++; LogPrint("nspv-details", "NSPV_CCMODULEUTXOS returned %d utxos to node=%d\n", (int)U.numutxos, pfrom->id); } else diff --git a/src/komodo_nSPV_superlite.h b/src/komodo_nSPV_superlite.h index 0977b59ab1d..c7a20d82a94 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -17,6 +17,15 @@ #ifndef KOMODO_NSPVSUPERLITE_H #define KOMODO_NSPVSUPERLITE_H +#include + +#include "main.h" +#include "komodo_defs.h" +#include "notarisationdb.h" +#include "rpc/server.h" +#include "cc/CCinclude.h" +#include "komodo_nSPV_defs.h" +#include "komodo_nSPV.h" #include "komodo_DEX.h" // nSPV client. VERY simplistic "single threaded" networking model. for production GUI best to multithread, etc. @@ -231,17 +240,17 @@ CNode *NSPV_req(CNode *pnode,uint8_t *msg,int32_t len,uint64_t mask,int32_t ind) n = 0; BOOST_FOREACH(CNode *ptr,vNodes) { - if ( ptr->prevtimes[ind] > timestamp ) - ptr->prevtimes[ind] = 0; + if ( ptr->nspvdata[ind].prevtime > timestamp ) + ptr->nspvdata[ind].prevtime = 0; if ( ptr->hSocket == INVALID_SOCKET ) continue; - if ( (ptr->nServices & mask) == mask && timestamp > ptr->prevtimes[ind] ) + if ( (ptr->nServices & mask) == mask && timestamp > ptr->nspvdata[ind].prevtime ) { flag = 1; pnodes[n++] = ptr; if ( n == sizeof(pnodes)/sizeof(*pnodes) ) break; - } // else fprintf(stderr,"nServices %llx vs mask %llx, t%u vs %u, ind.%d\n",(long long)ptr->nServices,(long long)mask,timestamp,ptr->prevtimes[ind],ind); + } // else fprintf(stderr,"nServices %llx vs mask %llx, t%u vs %u, ind.%d\n",(long long)ptr->nServices,(long long)mask,timestamp,ptr->nspvdata[ind].prevtime,ind); } if ( n > 0 ) pnode = pnodes[rand() % n]; @@ -254,7 +263,7 @@ CNode *NSPV_req(CNode *pnode,uint8_t *msg,int32_t len,uint64_t mask,int32_t ind) if ( (0) && KOMODO_NSPV_SUPERLITE ) fprintf(stderr,"pushmessage [%d] len.%d\n",msg[0],len); pnode->PushMessage("getnSPV",request); - pnode->prevtimes[ind] = timestamp; + pnode->nspvdata[ind].prevtime = timestamp; return(pnode); } else fprintf(stderr,"no pnodes\n"); return(0); @@ -285,11 +294,11 @@ void komodo_nSPV(CNode *pto) // polling loop from SendMessages NSPV_logout(); if ( (pto->nServices & NODE_NSPV) == 0 ) return; - if ( pto->prevtimes[NSPV_INFO>>1] > timestamp ) - pto->prevtimes[NSPV_INFO>>1] = 0; + if ( pto->nspvdata[NSPV_INFO>>1].prevtime > timestamp ) + pto->nspvdata[NSPV_INFO>>1].prevtime = 0; if ( KOMODO_NSPV_SUPERLITE ) { - if ( timestamp > NSPV_lastinfo + ASSETCHAINS_BLOCKTIME/2 && timestamp > pto->prevtimes[NSPV_INFO>>1] + 2*ASSETCHAINS_BLOCKTIME/3 ) + if ( timestamp > NSPV_lastinfo + ASSETCHAINS_BLOCKTIME/2 && timestamp > pto->nspvdata[NSPV_INFO>>1].prevtime + 2*ASSETCHAINS_BLOCKTIME/3 ) { int32_t reqht; reqht = 0; @@ -412,7 +421,7 @@ UniValue NSPV_utxosresp_json(struct NSPV_utxosresp *ptr) result.push_back(Pair("balance",(double)ptr->total/COIN)); if ( ASSETCHAINS_SYMBOL[0] == 0 ) result.push_back(Pair("interest",(double)ptr->interest/COIN)); - result.push_back(Pair("filter",(int64_t)ptr->filter)); + result.push_back(Pair("maxrecords",(int64_t)ptr->maxrecords)); result.push_back(Pair("lastpeer",NSPV_lastpeer)); return(result); } @@ -443,7 +452,7 @@ UniValue NSPV_txidsresp_json(struct NSPV_txidsresp *ptr) result.push_back(Pair("isCC",ptr->CCflag)); result.push_back(Pair("height",(int64_t)ptr->nodeheight)); result.push_back(Pair("numtxids",(int64_t)ptr->numtxids)); - result.push_back(Pair("filter",(int64_t)ptr->filter)); + result.push_back(Pair("maxrecords",(int64_t)ptr->maxrecords)); result.push_back(Pair("lastpeer",NSPV_lastpeer)); return(result); } diff --git a/src/net.cpp b/src/net.cpp index 5fe1660254f..6ccf5e659e8 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2145,6 +2145,8 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa nPingUsecTime = 0; fPingQueued = false; nMinPingUsecTime = std::numeric_limits::max(); + memset(nspvdata, '\0', sizeof(nspvdata)); + std::cerr << __func__ << " nspvdata cleared" << std::endl; { LOCK(cs_nLastNodeId); diff --git a/src/net.h b/src/net.h index e1f16972b67..9ea83161f2e 100644 --- a/src/net.h +++ b/src/net.h @@ -284,7 +284,11 @@ class CNode int64_t nLastRecv; int64_t nTimeConnected; int64_t nTimeOffset; - uint32_t prevtimes[16],dexlastping; + struct { + uint32_t prevtime; + uint32_t nreqs; + } nspvdata[16]; + uint32_t dexlastping; // Address of this peer CAddress addr; // Bind address of our side of the connection From ef2f76f7b71e2286e6237cccafc041e94ca7e646 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 7 Sep 2021 23:23:06 +0500 Subject: [PATCH 097/348] fixed maxrecords numutxos init in getutxos --- src/komodo_nSPV_fullnode.h | 49 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 120d36c5d95..188696d39fd 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -202,42 +202,41 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool is // use maxrecords //maxlen = MAX_BLOCK_SIZE(tipheight) - 512; //maxlen /= sizeof(*ptr->utxos); + std::cerr << __func__ << " maxrecords in param=" << maxrecords << std::endl; if (maxrecords <= 0 || maxrecords >= std::numeric_limits::max()) - maxrecords >= std::numeric_limits::max(); // prevent large requests + maxrecords = std::numeric_limits::max(); // prevent large requests strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = isCC; ptr->maxrecords = maxrecords; if (skipcount < 0) skipcount = 0; - if ((ptr->numutxos = (int32_t)unspentOutputs.size()) >= 0) { + ptr->skipcount = skipcount; + ptr->utxos = nullptr; + + if (unspentOutputs.size() >= 0 && skipcount < unspentOutputs.size()) { ptr->nodeheight = tipheight; - if (skipcount >= ptr->numutxos) - skipcount = ptr->numutxos - 1; - ptr->skipcount = skipcount; - if (ptr->numutxos - skipcount > 0) { - ptr->utxos = (struct NSPV_utxoresp*)calloc(ptr->numutxos - skipcount, sizeof(*ptr->utxos)); - for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { - // if gettxout is != null to handle mempool - { - if (n >= skipcount && myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index) == 0) { - ptr->utxos[ind].txid = it->first.txhash; - ptr->utxos[ind].vout = (int32_t)it->first.index; - ptr->utxos[ind].satoshis = it->second.satoshis; - ptr->utxos[ind].height = it->second.blockHeight; - if (IS_KMD_CHAIN() && it->second.satoshis >= 10 * COIN) { // calc interest on the kmd chain - ptr->utxos[n].extradata = komodo_accrued_interest(&txheight, &locktime, ptr->utxos[ind].txid, ptr->utxos[ind].vout, ptr->utxos[ind].height, ptr->utxos[ind].satoshis, tipheight); - interest += ptr->utxos[ind].extradata; - } - ind++; - total += it->second.satoshis; + ptr->utxos = (struct NSPV_utxoresp*)calloc(unspentOutputs.size() - skipcount, sizeof(*ptr->utxos)); + for (std::vector>::const_iterator it = unspentOutputs.begin(); + it != unspentOutputs.end() && ind < maxrecords; it++) { + // if gettxout is != null to handle mempool + { + if (n >= skipcount && !myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index)) { + ptr->utxos[ind].txid = it->first.txhash; + ptr->utxos[ind].vout = (int32_t)it->first.index; + ptr->utxos[ind].satoshis = it->second.satoshis; + ptr->utxos[ind].height = it->second.blockHeight; + if (IS_KMD_CHAIN() && it->second.satoshis >= 10 * COIN) { // calc interest on the kmd chain + ptr->utxos[n].extradata = komodo_accrued_interest(&txheight, &locktime, ptr->utxos[ind].txid, ptr->utxos[ind].vout, ptr->utxos[ind].height, ptr->utxos[ind].satoshis, tipheight); + interest += ptr->utxos[ind].extradata; } - n++; - if (ind >= maxrecords) - break; + ind++; + total += it->second.satoshis; } + n++; } } + ptr->numutxos = ind; int32_t len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->utxos) * ptr->numutxos - sizeof(ptr->utxos)); //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); @@ -245,7 +244,7 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool is ptr->interest = interest; return (len); } - if (ptr->utxos != 0) + if (ptr->utxos != nullptr) free(ptr->utxos); memset(ptr, 0, sizeof(*ptr)); return (0); From a8e771b3a252cf0dcde451eb6a287dc122609dd8 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 7 Sep 2021 23:33:17 +0500 Subject: [PATCH 098/348] nspv getutxos always returns result --- src/komodo_nSPV_fullnode.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 188696d39fd..0e3c6a31dfd 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -187,7 +187,7 @@ int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool isCC, int32_t skipcount, int32_t maxrecords) { - CAmount total = 0, interest = 0; + CAmount total = 0LL, interest = 0LL; uint32_t locktime; int32_t ind = 0, tipheight, /*maxlen,*/ txheight, n = 0; @@ -236,18 +236,18 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool is n++; } } - - ptr->numutxos = ind; - int32_t len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->utxos) * ptr->numutxos - sizeof(ptr->utxos)); - //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); - ptr->total = total; - ptr->interest = interest; - return (len); } - if (ptr->utxos != nullptr) - free(ptr->utxos); - memset(ptr, 0, sizeof(*ptr)); - return (0); + // always return a result: + ptr->numutxos = ind; + int32_t len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->utxos) * ptr->numutxos - sizeof(ptr->utxos)); + //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); + ptr->total = total; + ptr->interest = interest; + return (len); + //if (ptr->utxos != nullptr) + // free(ptr->utxos); + //memset(ptr, 0, sizeof(*ptr)); + //return (0); } class BaseCCChecker { @@ -965,7 +965,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req } else { pfrom->nspvdata[nData].nreqs = 0; - std::cerr << __func__ << " timestamp changed, reset nreqs=" << std::endl; + std::cerr << __func__ << " timestamp changed, reset nreqs to 0" << std::endl; } switch(request[0]) @@ -1063,7 +1063,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req NSPV_utxosresp_purge(&U); } else - LogPrint("nspv", "NSPV_getaddressutxos error.%d\n", slen); + LogPrint("nspv", "NSPV_getaddressutxos error slen.%d\n", slen); } break; From 79a68876b35d2115ceadab333eb640aa35adc181 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 7 Sep 2021 23:56:25 +0500 Subject: [PATCH 099/348] set tipheight in nspv getuxtos (as client checks this) --- src/komodo_nSPV_fullnode.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 0e3c6a31dfd..f273289d379 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -213,9 +213,9 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool is skipcount = 0; ptr->skipcount = skipcount; ptr->utxos = nullptr; + ptr->nodeheight = tipheight; - if (unspentOutputs.size() >= 0 && skipcount < unspentOutputs.size()) { - ptr->nodeheight = tipheight; + if (unspentOutputs.size() >= 0 && skipcount < unspentOutputs.size()) { ptr->utxos = (struct NSPV_utxoresp*)calloc(unspentOutputs.size() - skipcount, sizeof(*ptr->utxos)); for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end() && ind < maxrecords; it++) { From bd348f377704dfdf8afa344f6aeeb8260a1df795 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 8 Sep 2021 00:26:59 +0500 Subject: [PATCH 100/348] always return result for nspv gettxids; skipcount refactor --- src/komodo_nSPV_fullnode.h | 62 +++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index f273289d379..6a484c2f485 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -216,12 +216,12 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool is ptr->nodeheight = tipheight; if (unspentOutputs.size() >= 0 && skipcount < unspentOutputs.size()) { - ptr->utxos = (struct NSPV_utxoresp*)calloc(unspentOutputs.size() - skipcount, sizeof(*ptr->utxos)); - for (std::vector>::const_iterator it = unspentOutputs.begin(); + ptr->utxos = (struct NSPV_utxoresp*)calloc(unspentOutputs.size() - skipcount, sizeof(ptr->utxos[0])); + for (std::vector>::const_iterator it = unspentOutputs.begin() + skipcount; it != unspentOutputs.end() && ind < maxrecords; it++) { // if gettxout is != null to handle mempool { - if (n >= skipcount && !myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index)) { + if (!myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index)) { ptr->utxos[ind].txid = it->first.txhash; ptr->utxos[ind].vout = (int32_t)it->first.index; ptr->utxos[ind].satoshis = it->second.satoshis; @@ -239,7 +239,7 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool is } // always return a result: ptr->numutxos = ind; - int32_t len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->utxos) * ptr->numutxos - sizeof(ptr->utxos)); + int32_t len = (int32_t)(sizeof(*ptr) + sizeof(ptr->utxos[0]) * ptr->numutxos - sizeof(ptr->utxos)); //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); ptr->total = total; ptr->interest = interest; @@ -478,51 +478,51 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool isCC, int32_t skipcount, int32_t maxrecords) { - int32_t txheight, ind = 0, n = 0, len = 0; - CTransaction tx; - uint256 hashBlock; + int32_t txheight, ind = 0, len = 0; + //CTransaction tx; + //uint256 hashBlock; std::vector> txids; SetAddressIndexOutputs(txids, coinaddr, isCC); - ptr->nodeheight = chainActive.LastTip()->GetHeight(); + { + LOCK(cs_main); + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + } // using maxrecords instead: //maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; //maxlen /= sizeof(*ptr->txids); if (maxrecords <= 0 || maxrecords >= std::numeric_limits::max()) - maxrecords >= std::numeric_limits::max(); // prevent large requests + maxrecords = std::numeric_limits::max(); // prevent large requests strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = isCC; ptr->maxrecords = maxrecords; if (skipcount < 0) skipcount = 0; - if ((ptr->numtxids = (int32_t)txids.size()) >= 0) { - if (skipcount >= ptr->numtxids) - skipcount = ptr->numtxids - 1; - ptr->skipcount = skipcount; + ptr->skipcount = skipcount; + ptr->txids = nullptr; + + if (txids.size() >= 0 && skipcount < ptr->numtxids) { if (ptr->numtxids - skipcount > 0) { - ptr->txids = (struct NSPV_txidresp*)calloc(ptr->numtxids - skipcount, sizeof(*ptr->txids)); - for (std::vector>::const_iterator it = txids.begin(); it != txids.end(); it++) { - if (n >= skipcount) { - ptr->txids[ind].txid = it->first.txhash; - ptr->txids[ind].vout = (int32_t)it->first.index; - ptr->txids[ind].satoshis = (int64_t)it->second; - ptr->txids[ind].height = (int64_t)it->first.blockHeight; - ind++; - } - n++; - if (ind >= maxrecords) - break; + ptr->txids = (struct NSPV_txidresp*)calloc(txids.size() - skipcount, sizeof(ptr->txids[0])); + for (std::vector>::const_iterator it = txids.begin() + skipcount; + it != txids.end() && ind < maxrecords; it++) { + ptr->txids[ind].txid = it->first.txhash; + ptr->txids[ind].vout = (int32_t)it->first.index; + ptr->txids[ind].satoshis = (int64_t)it->second; + ptr->txids[ind].height = (int64_t)it->first.blockHeight; + ind++; } } - ptr->numtxids = ind; - len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids) * ptr->numtxids - sizeof(ptr->txids)); - return (len); } - if (ptr->txids != nullptr) + // always return a result: + ptr->numtxids = ind; + len = (int32_t)(sizeof(*ptr) + sizeof(ptr->txids[0]) * ptr->numtxids - sizeof(ptr->txids)); + return (len); + /*if (ptr->txids != nullptr) free(ptr->txids); memset(ptr, 0, sizeof(*ptr)); - return (0); + return (0);*/ } int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector &txids,char *coinaddr,bool isCC,uint8_t funcid,uint256 txid,int32_t vout) @@ -743,7 +743,7 @@ int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n) rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id); response=rpc_result.write(); } - catch (const runtime_error& e) + catch (const std::runtime_error& e) { rpc_result = JSONRPCReplyObj(NullUniValue,JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); response=rpc_result.write(); From 492d685830a6f7bba0b2bbf94a24f2b729685b40 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 8 Sep 2021 01:01:09 +0500 Subject: [PATCH 101/348] fixed txid.size in nspv gettxids --- src/komodo_nSPV_fullnode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 6a484c2f485..104add97fa3 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -503,7 +503,7 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is ptr->txids = nullptr; if (txids.size() >= 0 && skipcount < ptr->numtxids) { - if (ptr->numtxids - skipcount > 0) { + if (txids.size() - skipcount > 0) { ptr->txids = (struct NSPV_txidresp*)calloc(txids.size() - skipcount, sizeof(ptr->txids[0])); for (std::vector>::const_iterator it = txids.begin() + skipcount; it != txids.end() && ind < maxrecords; it++) { From ae33b445ae7674e85d2189d58ad9b858f1100a59 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 8 Sep 2021 01:05:31 +0500 Subject: [PATCH 102/348] fixed txid.size use in gettxids --- src/komodo_nSPV_fullnode.h | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 104add97fa3..128790ad2b2 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -502,17 +502,15 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is ptr->skipcount = skipcount; ptr->txids = nullptr; - if (txids.size() >= 0 && skipcount < ptr->numtxids) { - if (txids.size() - skipcount > 0) { - ptr->txids = (struct NSPV_txidresp*)calloc(txids.size() - skipcount, sizeof(ptr->txids[0])); - for (std::vector>::const_iterator it = txids.begin() + skipcount; - it != txids.end() && ind < maxrecords; it++) { - ptr->txids[ind].txid = it->first.txhash; - ptr->txids[ind].vout = (int32_t)it->first.index; - ptr->txids[ind].satoshis = (int64_t)it->second; - ptr->txids[ind].height = (int64_t)it->first.blockHeight; - ind++; - } + if (txids.size() >= 0 && skipcount < txids.size()) { + ptr->txids = (struct NSPV_txidresp*)calloc(txids.size() - skipcount, sizeof(ptr->txids[0])); + for (std::vector>::const_iterator it = txids.begin() + skipcount; + it != txids.end() && ind < maxrecords; it++) { + ptr->txids[ind].txid = it->first.txhash; + ptr->txids[ind].vout = (int32_t)it->first.index; + ptr->txids[ind].satoshis = (int64_t)it->second; + ptr->txids[ind].height = (int64_t)it->first.blockHeight; + ind++; } } // always return a result: From 9784ee39e6eb4dd502ddb047b4f30234d06d9d5a Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 8 Sep 2021 12:36:50 +0500 Subject: [PATCH 103/348] removed extra nreqs++ --- src/komodo_nSPV_fullnode.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 128790ad2b2..62c5cb4f35f 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -948,7 +948,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req int32_t nData = request[0] >> 1; if (nData >= sizeof(pfrom->nspvdata)/sizeof(pfrom->nspvdata[0]) ) nData = (int32_t)(sizeof(pfrom->nspvdata)/sizeof(pfrom->nspvdata[0])) - 1; - std::cerr << __func__ << "pfrom=" << (uint64_t)pfrom << " request[0]=" << (int)request[0] << " nData=" << nData << " timestamp=" << timestamp << " pfrom->nspvdata[nData].prevtime=" << pfrom->nspvdata[nData].prevtime << " pfrom->nspvdata[nData].nreqs=" << pfrom->nspvdata[nData].nreqs << " timestamp-prevtime=" << timestamp-pfrom->nspvdata[nData].prevtime << std::endl; + std::cerr << __func__ << " pfrom=" << (uint64_t)pfrom << " request[0]=" << (int)request[0] << " nData=" << nData << " timestamp=" << timestamp << " pfrom->nspvdata[nData].prevtime=" << pfrom->nspvdata[nData].prevtime << " pfrom->nspvdata[nData].nreqs=" << pfrom->nspvdata[nData].nreqs << " timestamp-prevtime=" << timestamp-pfrom->nspvdata[nData].prevtime << std::endl; if (pfrom->nspvdata[nData].prevtime > timestamp) { pfrom->nspvdata[nData].prevtime = 0; pfrom->nspvdata[nData].nreqs = 0; @@ -956,10 +956,9 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req } else if (timestamp == pfrom->nspvdata[nData].prevtime) { if (pfrom->nspvdata[nData].nreqs > NSPV_MAXREQSPERSEC) { - LogPrint("nspv", "rate limit from peer %d\n", pfrom->id); + LogPrint("nspv", "rate limit reached from peer %d\n", pfrom->id); return; } - pfrom->nspvdata[nData].nreqs ++; } else { pfrom->nspvdata[nData].nreqs = 0; From 3227dec352c709ac1d28bcd346c1417ae2772dc9 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 8 Sep 2021 14:13:46 +0500 Subject: [PATCH 104/348] ignore height param in gettxproof, added comment to mempool_func --- src/komodo_nSPV_fullnode.h | 291 ++++++++++++++++++------------------- 1 file changed, 141 insertions(+), 150 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 62c5cb4f35f..1aa955d3655 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -523,130 +523,130 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is return (0);*/ } -int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector &txids,char *coinaddr,bool isCC,uint8_t funcid,uint256 txid,int32_t vout) +// get txids from addressindex or mempool by different criteria +// looks like as a set of ad-hoc functions and it should be rewritten +int32_t NSPV_mempoolfuncs(bits256* satoshisp, int32_t* vindexp, std::vector& txids, char* coinaddr, bool isCC, uint8_t funcid, uint256 txid, int32_t vout) { - int32_t num = 0,vini = 0,vouti = 0; uint8_t evalcode=0,func=0; std::vector vopret; char destaddr[64]; + int32_t num = 0, vini = 0, vouti = 0; + uint8_t evalcode = 0, func = 0; + std::vector vopret; + char destaddr[64]; *vindexp = -1; - memset(satoshisp,0,sizeof(*satoshisp)); - if ( funcid == NSPV_CC_TXIDS) - { - std::vector > tmp_txids; uint256 tmp_txid,hashBlock; - int32_t n=0,skipcount=vout>>16; uint8_t eval=(vout>>8)&0xFF, func=vout&0xFF; + memset(satoshisp, 0, sizeof(*satoshisp)); + if (funcid == NSPV_CC_TXIDS) { + std::vector> tmp_txids; + uint256 tmp_txid, hashBlock; + int32_t n = 0, skipcount = vout >> 16; + uint8_t eval = (vout >> 8) & 0xFF, func = vout & 0xFF; CTransaction tx; - SetAddressIndexOutputs(tmp_txids,coinaddr,isCC); - if ( skipcount < 0 ) skipcount = 0; - if ( skipcount >= tmp_txids.size() ) - skipcount = tmp_txids.size()-1; - if ( tmp_txids.size()-skipcount > 0 ) - { - for (std::vector >::const_iterator it=tmp_txids.begin(); it!=tmp_txids.end(); it++) - { - if (txid!=zeroid || func!=0) - { - myGetTransaction(it->first.txhash,tx,hashBlock); - std::vector oprets; uint256 tokenid,txid; - std::vector vopret,vOpretExtra; uint8_t *script,e,f; + SetAddressIndexOutputs(tmp_txids, coinaddr, isCC); + if (skipcount < 0) + skipcount = 0; + if (skipcount >= tmp_txids.size()) + skipcount = tmp_txids.size() - 1; + if (tmp_txids.size() - skipcount > 0) { + for (std::vector>::const_iterator it = tmp_txids.begin(); it != tmp_txids.end(); it++) { + if (txid != zeroid || func != 0) { + myGetTransaction(it->first.txhash, tx, hashBlock); + std::vector oprets; + uint256 tokenid, txid; + std::vector vopret, vOpretExtra; + uint8_t *script, e, f; std::vector pubkeys; - if (DecodeTokenOpRetV1(tx.vout[tx.vout.size()-1].scriptPubKey,tokenid,pubkeys,oprets)!=0 && GetOpReturnCCBlob(oprets, vOpretExtra) && vOpretExtra.size()>0) - { - vopret=vOpretExtra; - } - else GetOpReturnData(tx.vout[tx.vout.size()-1].scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && script[0]==eval ) - { - switch (eval) - { - case EVAL_CHANNELS:EVAL_PEGS:EVAL_ORACLES:EVAL_GAMES:EVAL_IMPORTGATEWAY:EVAL_ROGUE: - E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> tmp_txid;); - if (e!=eval || (txid!=zeroid && txid!=tmp_txid) || (func!=0 && f!=func)) continue; - break; - case EVAL_TOKENS:EVAL_DICE:EVAL_DILITHIUM:EVAL_FAUCET:EVAL_LOTO:EVAL_PAYMENTS:EVAL_REWARDS: - E_UNMARSHAL(vopret,ss >> e; ss >> f;); - if (e!=eval || (func!=0 && f!=func)) continue; - break; - default: - break; + if (DecodeTokenOpRetV1(tx.vout[tx.vout.size() - 1].scriptPubKey, tokenid, pubkeys, oprets) != 0 && GetOpReturnCCBlob(oprets, vOpretExtra) && vOpretExtra.size() > 0) { + vopret = vOpretExtra; + } else + GetOpReturnData(tx.vout[tx.vout.size() - 1].scriptPubKey, vopret); + script = (uint8_t*)vopret.data(); + if (vopret.size() > 2 && script[0] == eval) { + switch (eval) { + case EVAL_CHANNELS: + EVAL_PEGS: + EVAL_ORACLES: + EVAL_GAMES: + EVAL_IMPORTGATEWAY: + EVAL_ROGUE: + E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> tmp_txid;); + if (e != eval || (txid != zeroid && txid != tmp_txid) || (func != 0 && f != func)) + continue; + break; + case EVAL_TOKENS: + EVAL_DICE: + EVAL_DILITHIUM: + EVAL_FAUCET: + EVAL_LOTO: + EVAL_PAYMENTS: + EVAL_REWARDS: + E_UNMARSHAL(vopret, ss >> e; ss >> f;); + if (e != eval || (func != 0 && f != func)) + continue; + break; + default: + break; } - } + } } - if ( n >= skipcount ) txids.push_back(it->first.txhash); + if (n >= skipcount) + txids.push_back(it->first.txhash); n++; } - return (n-skipcount); + return (n - skipcount); } return (0); } - if ( mempool.size() == 0 ) - return(0); - if ( funcid == NSPV_MEMPOOL_CCEVALCODE ) - { + if (mempool.size() == 0) + return (0); + if (funcid == NSPV_MEMPOOL_CCEVALCODE) { isCC = true; evalcode = vout & 0xff; func = (vout >> 8) & 0xff; } LOCK(mempool.cs); - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - if ( funcid == NSPV_MEMPOOL_ALL ) - { + BOOST_FOREACH (const CTxMemPoolEntry& e, mempool.mapTx) { + const CTransaction& tx = e.GetTx(); + const uint256& hash = tx.GetHash(); + if (funcid == NSPV_MEMPOOL_ALL) { txids.push_back(hash); num++; continue; - } - else if ( funcid == NSPV_MEMPOOL_INMEMPOOL ) - { - if ( hash == txid ) - { + } else if (funcid == NSPV_MEMPOOL_INMEMPOOL) { + if (hash == txid) { txids.push_back(hash); - return(++num); + return (++num); } continue; - } - else if ( funcid == NSPV_MEMPOOL_CCEVALCODE ) - { - if ( tx.vout.size() > 1 ) - { - CScript scriptPubKey = tx.vout[tx.vout.size()-1].scriptPubKey; - if ( GetOpReturnData(scriptPubKey,vopret) != 0 ) - { - if ( vopret[0] != evalcode || (func!=0 && vopret[1] != func) ) continue; + } else if (funcid == NSPV_MEMPOOL_CCEVALCODE) { + if (tx.vout.size() > 1) { + CScript scriptPubKey = tx.vout[tx.vout.size() - 1].scriptPubKey; + if (GetOpReturnData(scriptPubKey, vopret) != 0) { + if (vopret[0] != evalcode || (func != 0 && vopret[1] != func)) + continue; txids.push_back(hash); num++; } } continue; } - if ( funcid == NSPV_MEMPOOL_ISSPENT ) - { - BOOST_FOREACH(const CTxIn &txin,tx.vin) - { + if (funcid == NSPV_MEMPOOL_ISSPENT) { + BOOST_FOREACH (const CTxIn& txin, tx.vin) { //fprintf(stderr,"%s/v%d ",uint256_str(str,txin.prevout.hash),txin.prevout.n); - if ( txin.prevout.n == vout && txin.prevout.hash == txid ) - { + if (txin.prevout.n == vout && txin.prevout.hash == txid) { txids.push_back(hash); *vindexp = vini; - return(++num); + return (++num); } vini++; } - } - else if ( funcid == NSPV_MEMPOOL_ADDRESS ) - { - BOOST_FOREACH(const CTxOut &txout,tx.vout) - { - if ( txout.scriptPubKey.IsPayToCryptoCondition() == isCC ) - { - Getscriptaddress(destaddr,txout.scriptPubKey); - if ( strcmp(destaddr,coinaddr) == 0 ) - { + } else if (funcid == NSPV_MEMPOOL_ADDRESS) { + BOOST_FOREACH (const CTxOut& txout, tx.vout) { + if (txout.scriptPubKey.IsPayToCryptoCondition() == isCC) { + Getscriptaddress(destaddr, txout.scriptPubKey); + if (strcmp(destaddr, coinaddr) == 0) { txids.push_back(hash); *vindexp = vouti; - if ( num < 4 ) + if (num < 4) satoshisp->ulongs[num] = txout.nValue; num++; } @@ -656,47 +656,45 @@ int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector txids; bits256 satoshis; uint256 tmp,tmpdest; int32_t i,len = 0; + std::vector txids; + bits256 satoshis; + uint256 tmp, tmpdest; + int32_t i, len = 0; { LOCK(cs_main); ptr->nodeheight = chainActive.LastTip()->GetHeight(); } - strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); + strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = isCC; ptr->txid = txid; ptr->vout = vout; ptr->funcid = funcid; - if ( NSPV_mempoolfuncs(&satoshis,&ptr->vindex,txids,coinaddr,isCC,funcid,txid,vout) >= 0 ) - { - if ( (ptr->numtxids= (int32_t)txids.size()) >= 0 ) - { - if ( ptr->numtxids > 0 ) - { - ptr->txids = (uint256 *)calloc(ptr->numtxids,sizeof(*ptr->txids)); - for (i=0; inumtxids; i++) - { + if (NSPV_mempoolfuncs(&satoshis, &ptr->vindex, txids, coinaddr, isCC, funcid, txid, vout) >= 0) { + if ((ptr->numtxids = (int32_t)txids.size()) >= 0) { + if (ptr->numtxids > 0) { + ptr->txids = (uint256*)calloc(ptr->numtxids, sizeof(*ptr->txids)); + for (i = 0; i < ptr->numtxids; i++) { tmp = txids[i]; - iguana_rwbignum(IGUANA_READ,(uint8_t *)&tmp,sizeof(*ptr->txids),(uint8_t *)&ptr->txids[i]); + iguana_rwbignum(IGUANA_READ, (uint8_t*)&tmp, sizeof(*ptr->txids), (uint8_t*)&ptr->txids[i]); } } - if ( funcid == NSPV_MEMPOOL_ADDRESS ) - { - memcpy(&tmp,&satoshis,sizeof(tmp)); - iguana_rwbignum(IGUANA_READ,(uint8_t *)&tmp,sizeof(ptr->txid),(uint8_t *)&ptr->txid); + if (funcid == NSPV_MEMPOOL_ADDRESS) { + memcpy(&tmp, &satoshis, sizeof(tmp)); + iguana_rwbignum(IGUANA_READ, (uint8_t*)&tmp, sizeof(ptr->txid), (uint8_t*)&ptr->txid); } - len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); - return(len); + len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids) * ptr->numtxids - sizeof(ptr->txids)); + return (len); } } - if ( ptr->txids != 0 ) + if (ptr->txids != 0) free(ptr->txids); - memset(ptr,0,sizeof(*ptr)); - return(0); + memset(ptr, 0, sizeof(*ptr)); + return (0); } int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n) @@ -808,7 +806,8 @@ int32_t NSPV_sendrawtransaction(struct NSPV_broadcastresp *ptr,uint8_t *data,int // get txproof for txid, // to get the proof object the height should be passed // otherwise only block hash alone will be returned -int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid, int32_t height) +// Note: not clear why we should have passed the height? Txid is sufficient, let's ignore height +int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid /*, int32_t height*/) { int32_t len = 0; CTransaction _tx; @@ -821,42 +820,36 @@ int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid, in ptr->txid = txid; ptr->vout = vout; ptr->hashblock = hashBlock; - if (height == 0) { + { LOCK(cs_main); ptr->height = komodo_blockheight(hashBlock); + pindex = komodo_chainactive(ptr->height); } - else { - ptr->height = height; - { - LOCK(cs_main); - pindex = komodo_chainactive(height); - } - if (pindex != nullptr && komodo_blockload(block, pindex) == 0) { - bool found = false; - BOOST_FOREACH (const CTransaction& tx, block.vtx) { - if (tx.GetHash() == txid) { - found = true; - break; - } - } - if (found) { - std::set setTxids; - CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); - setTxids.insert(txid); - CMerkleBlock mb(block, setTxids); - ssMB << mb; - std::vector proof(ssMB.begin(), ssMB.end()); - ptr->txprooflen = (int32_t)proof.size(); - LogPrint("nspv-details", "%s txid.%s found txproof.(%s) height.%d\n", __func__, txid.GetHex().c_str(), HexStr(proof).c_str(), ptr->height); - if (ptr->txprooflen > 0) { - ptr->txproof = (uint8_t*)calloc(1, ptr->txprooflen); - memcpy(ptr->txproof, &proof[0], ptr->txprooflen); - } - //fprintf(stderr,"gettxproof slen.%d\n",(int32_t)(sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen)); + if (pindex != nullptr && komodo_blockload(block, pindex) == 0) { + bool found = false; + BOOST_FOREACH (const CTransaction& tx, block.vtx) { + if (tx.GetHash() == txid) { + found = true; + break; } - else { - LogPrint("nspv-details", "%s txid=%s not found in the block of ht=%d", __func__, txid.GetHex().c_str(), ptr->height); + } + if (found) { + std::set setTxids; + CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); + setTxids.insert(txid); + CMerkleBlock mb(block, setTxids); + ssMB << mb; + std::vector proof(ssMB.begin(), ssMB.end()); + ptr->txprooflen = (int32_t)proof.size(); + LogPrint("nspv-details", "%s txid.%s found txproof.(%s) height.%d\n", __func__, txid.GetHex().c_str(), HexStr(proof).c_str(), ptr->height); + if (ptr->txprooflen > 0) { + ptr->txproof = (uint8_t*)calloc(1, ptr->txprooflen); + memcpy(ptr->txproof, &proof[0], ptr->txprooflen); } + //fprintf(stderr,"gettxproof slen.%d\n",(int32_t)(sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen)); + } + else { + LogPrint("nspv-details", "%s txid=%s not found in the block of ht=%d", __func__, txid.GetHex().c_str(), ptr->height); } } ptr->unspentvalue = CCgettxout(txid, vout, 1, 1); @@ -911,24 +904,22 @@ int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp *ptr,uint256 prevntztxid return(sizeof(*ptr) + sizeof(*ptr->common.hdrs)*ptr->common.numhdrs - sizeof(ptr->common.hdrs) - sizeof(ptr->prevntz) - sizeof(ptr->nextntz) + ptr->prevtxlen + ptr->nexttxlen); } -int32_t NSPV_getspentinfo(struct NSPV_spentinfo *ptr,uint256 txid,int32_t vout) +int32_t NSPV_getspentinfo(struct NSPV_spentinfo* ptr, uint256 txid, int32_t vout) { int32_t len = 0; ptr->txid = txid; ptr->vout = vout; ptr->spentvini = -1; len = (int32_t)(sizeof(*ptr) - sizeof(ptr->spent.tx) - sizeof(ptr->spent.txproof)); - if ( CCgetspenttxid(ptr->spent.txid,ptr->spentvini,ptr->spent.height,txid,vout) == 0 ) - { - if ( NSPV_gettxproof(&ptr->spent,0,ptr->spent.txid,ptr->spent.height) > 0 ) + if (CCgetspenttxid(ptr->spent.txid, ptr->spentvini, ptr->spent.height, txid, vout) == 0) { + if (NSPV_gettxproof(&ptr->spent, 0, ptr->spent.txid /*,ptr->spent.height*/) > 0) len += ptr->spent.txlen + ptr->spent.txprooflen; - else - { + else { NSPV_txproof_purge(&ptr->spent); - return(-1); + return (-1); } } - return(len); + return (len); } void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a request @@ -1255,7 +1246,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req iguana_rwbignum(IGUANA_READ, &request[1 + sizeof(height) + sizeof(vout)], sizeof(txid), (uint8_t*)&txid); //fprintf(stderr,"got txid %s/v%d ht.%d\n",txid.GetHex().c_str(),vout,height); memset(&P, 0, sizeof(P)); - if ((slen = NSPV_gettxproof(&P,vout,txid,height)) > 0) + if ((slen = NSPV_gettxproof(&P, vout, txid /*,height*/)) > 0) { //fprintf(stderr,"slen.%d\n",slen); response.resize(1 + slen); From dba8935d963aa3144e05a714ae2898ec04ffc265 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 9 Sep 2021 01:18:56 +0500 Subject: [PATCH 105/348] removed extra debug prints --- src/cc/CCtokenutils.cpp | 1 - src/komodo_nSPV_fullnode.h | 3 --- src/net.cpp | 1 - 3 files changed, 5 deletions(-) diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index 3cd1731a326..c01024eb330 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -417,7 +417,6 @@ CTxOut MakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount n if (!CCtoAnon(payoutCond.get())) return vout; - std::cerr << " CCtoAnon=" << cc_conditionToJSONString(payoutCond.get()) << std::endl; vout = CTxOut(nValue, CCPubKey(payoutCond.get(),true)); { diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 1aa955d3655..32b803e6767 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -939,11 +939,9 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req int32_t nData = request[0] >> 1; if (nData >= sizeof(pfrom->nspvdata)/sizeof(pfrom->nspvdata[0]) ) nData = (int32_t)(sizeof(pfrom->nspvdata)/sizeof(pfrom->nspvdata[0])) - 1; - std::cerr << __func__ << " pfrom=" << (uint64_t)pfrom << " request[0]=" << (int)request[0] << " nData=" << nData << " timestamp=" << timestamp << " pfrom->nspvdata[nData].prevtime=" << pfrom->nspvdata[nData].prevtime << " pfrom->nspvdata[nData].nreqs=" << pfrom->nspvdata[nData].nreqs << " timestamp-prevtime=" << timestamp-pfrom->nspvdata[nData].prevtime << std::endl; if (pfrom->nspvdata[nData].prevtime > timestamp) { pfrom->nspvdata[nData].prevtime = 0; pfrom->nspvdata[nData].nreqs = 0; - std::cerr << __func__ << " prevtime>timestamp reset to 0 pfrom->nspvdata[nData].prevtime=" << pfrom->nspvdata[nData].prevtime << std::endl; } else if (timestamp == pfrom->nspvdata[nData].prevtime) { if (pfrom->nspvdata[nData].nreqs > NSPV_MAXREQSPERSEC) { @@ -953,7 +951,6 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req } else { pfrom->nspvdata[nData].nreqs = 0; - std::cerr << __func__ << " timestamp changed, reset nreqs to 0" << std::endl; } switch(request[0]) diff --git a/src/net.cpp b/src/net.cpp index 6ccf5e659e8..aa60ade5966 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2146,7 +2146,6 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa fPingQueued = false; nMinPingUsecTime = std::numeric_limits::max(); memset(nspvdata, '\0', sizeof(nspvdata)); - std::cerr << __func__ << " nspvdata cleared" << std::endl; { LOCK(cs_nLastNodeId); From 92c82e79f680ff6e3a062845c8b880cde61977e5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 9 Sep 2021 01:26:02 +0500 Subject: [PATCH 106/348] removed unused test code --- src/rpc/testtransactions.cpp | 268 ----------------------------------- 1 file changed, 268 deletions(-) delete mode 100644 src/rpc/testtransactions.cpp diff --git a/src/rpc/testtransactions.cpp b/src/rpc/testtransactions.cpp deleted file mode 100644 index c41e97e1036..00000000000 --- a/src/rpc/testtransactions.cpp +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - -#include - -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "crosschain.h" -#include "base58.h" -#include "consensus/validation.h" -#include "cc/eval.h" -#include "main.h" -#include "primitives/transaction.h" -#include "rpc/server.h" -#include "streams.h" -#include "sync.h" -#include "util.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "script/standard.h" - -#include - -#include - -#include - - -#include "cc/CCinclude.h" -#include "cc/CCPrices.h" - -using namespace std; - -int32_t ensure_CCrequirements(uint8_t evalcode); - -UniValue test_ac(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 4)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_HEIR) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - std::vector pubkey1; - std::vector pubkey2; - - pubkey1 = ParseHex(params[0].get_str().c_str()); - pubkey2 = ParseHex(params[1].get_str().c_str()); - - CPubKey pk1 = pubkey2pk(pubkey1); - CPubKey pk2 = pubkey2pk(pubkey2); - - if (!pk1.IsValid() || !pk2.IsValid()) - throw runtime_error("invalid pubkey\n"); - - int64_t txfee = 10000; - int64_t amount = atoll(params[2].get_str().c_str()) * COIN; - uint256 fundingtxid = Parseuint256((char *)params[3].get_str().c_str()); - - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, txfee + amount, 60); - - if (normalInputs < txfee + amount) - throw runtime_error("not enough normals\n"); - - mtx.vout.push_back(MakeCC1of2vout(EVAL_HEIR, amount, pk1, pk2)); - - CScript opret; - fundingtxid = revuint256(fundingtxid); - - opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'A' << fundingtxid << (uint8_t)0); - - cp = CCinit(&C, EVAL_HEIR); - return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret)); -} - -UniValue test_heirmarker(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 1)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_HEIR) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - uint256 fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); - - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); - if (normalInputs < 10000) - throw runtime_error("not enough normals\n"); - - mtx.vin.push_back(CTxIn(fundingtxid, 1)); - mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, 10000, myPubkey)); - - CScript opret; - fundingtxid = revuint256(fundingtxid); - - opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'C' << fundingtxid << (uint8_t)0); - - cp = CCinit(&C, EVAL_HEIR); - return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret)); -} - -UniValue test_burntx(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 1)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_TOKENS) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str()); - - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); - if (normalInputs < 10000) - throw runtime_error("not enough normals\n"); - - CPubKey burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY)); - - mtx.vin.push_back(CTxIn(tokenid, 0)); - mtx.vin.push_back(CTxIn(tokenid, 1)); - mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, 1, burnpk)); - - std::vector voutPubkeys; - voutPubkeys.push_back(burnpk); - - cp = CCinit(&C, EVAL_TOKENS); - - std::vector vopret; - GetNonfungibleData(tokenid, vopret); - if (vopret.size() > 0) - cp->additionalTokensEvalcode2 = vopret.begin()[0]; - - uint8_t tokenpriv[33]; - char unspendableTokenAddr[64]; - CPubKey unspPk = GetUnspendable(cp, tokenpriv); - GetCCaddress(cp, unspendableTokenAddr, unspPk); - CCaddr2set(cp, EVAL_TOKENS, unspPk, tokenpriv, unspendableTokenAddr); - return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, EncodeTokenOpRet(tokenid, voutPubkeys, std::make_pair(0, vscript_t())))); -} - -UniValue test_proof(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); - std::vectorproof; - - if (fHelp || (params.size() != 2)) - throw runtime_error("incorrect params\n"); - - - proof = ParseHex(params[0].get_str()); - uint256 cointxid = Parseuint256((char *)params[1].get_str().c_str()); - - std::vector txids; - - CMerkleBlock merkleBlock; - if (!E_UNMARSHAL(proof, ss >> merkleBlock)) { - result.push_back(Pair("error", "could not unmarshal proof")); - return result; - } - uint256 merkleRoot = merkleBlock.txn.ExtractMatches(txids); - - result.push_back(Pair("source_root", merkleRoot.GetHex())); - - for (int i = 0; i < txids.size(); i++) - std::cerr << "merkle block txid=" << txids[0].GetHex() << std::endl; - - - std::vector vMatches(txids.size()); - for (auto v : vMatches) v = true; - CPartialMerkleTree verifTree(txids, vMatches); - - result.push_back(Pair("verif_root", verifTree.ExtractMatches(txids).GetHex())); - - if (std::find(txids.begin(), txids.end(), cointxid) == txids.end()) { - fprintf(stderr, "invalid proof for this cointxid\n"); - } - - std::vector vMerkleTree; - bool f; - ::BuildMerkleTree(&f, txids, vMerkleTree); - - std::vector vMerkleBranch = ::GetMerkleBranch(0, txids.size(), vMerkleTree); - - uint256 ourResult = SafeCheckMerkleBranch(zeroid, vMerkleBranch, 0); - result.push_back(Pair("SafeCheckMerkleBranch", ourResult.GetHex())); - - return result; -} - -extern CScript prices_costbasisopret(uint256 bettxid, CPubKey mypk, int32_t height, int64_t costbasis); -UniValue test_pricesmarker(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 1)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_PRICES) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - uint256 bettxid = Parseuint256((char *)params[0].get_str().c_str()); - - cp = CCinit(&C, EVAL_PRICES); - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); - if (normalInputs < 10000) - throw runtime_error("not enough normals\n"); - - mtx.vin.push_back(CTxIn(bettxid, 1)); - mtx.vout.push_back(CTxOut(1000, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG)); - - return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, prices_costbasisopret(bettxid, myPubkey, 100, 100))); -} - - -static const CRPCCommand commands[] = -{ // category name actor (function) okSafeMode - // --------------------- ------------------------ ----------------------- ---------- - - /* Not shown in help */ - { "hidden", "test_ac", &test_ac, true }, - { "hidden", "test_heirmarker", &test_heirmarker, true }, - { "hidden", "test_proof", &test_proof, true }, - { "hidden", "test_burntx", &test_burntx, true }, - { "hidden", "test_pricesmarker", &test_pricesmarker, true } -}; - -void RegisterTesttransactionsRPCCommands(CRPCTable &tableRPC) -{ - for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); -} From 069a095a7be4f45e07306a7abf440578dea0f2ed Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 9 Sep 2021 01:26:21 +0500 Subject: [PATCH 107/348] delete extra debug prints --- src/cc/CCTokelData.cpp | 1 - src/cc/CCtx.cpp | 4 ++-- src/komodo_nSPV_fullnode.h | 4 +--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index 6927d263a52..063bb1179db 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -163,7 +163,6 @@ static bool UnmarshalTokelVData(const vuint8_t &vdata, std::map 0) { - std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; + //std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; continue; } } @@ -1301,7 +1301,7 @@ CAmount AddNormalinputsRemote(CMutableTransaction& mtx, CPubKey mypk, CAmount to { LOCK(cs_main); if (CoinbaseGetBlocksToMaturity(tx, hashBlock) > 0) { - std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; + //std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; continue; } } diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 32b803e6767..9d444ae8e06 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -202,7 +202,6 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool is // use maxrecords //maxlen = MAX_BLOCK_SIZE(tipheight) - 512; //maxlen /= sizeof(*ptr->utxos); - std::cerr << __func__ << " maxrecords in param=" << maxrecords << std::endl; if (maxrecords <= 0 || maxrecords >= std::numeric_limits::max()) maxrecords = std::numeric_limits::max(); // prevent large requests @@ -319,7 +318,7 @@ class DefaultCCChecker : public BaseCCChecker { isEof = ss.eof(); ); opretTxid = revuint256(opretTxid); - std::cerr << __func__ << " " << "opretEvalcode=" << opretEvalcode << " opretFuncid=" << (char)opretFuncid << " isCreateTx=" << isCreateTx << " opretTxid=" << opretTxid.GetHex() << std::endl; + //std::cerr << __func__ << " " << "opretEvalcode=" << opretEvalcode << " opretFuncid=" << (char)opretFuncid << " isCreateTx=" << isCreateTx << " opretTxid=" << opretTxid.GetHex() << std::endl; if( parseOk /*parseOk=true if eof reached*/|| !isEof /*more data means okay*/) { if (evalcode == opretEvalcode && std::find(funcids.begin(), funcids.end(), (char)opretFuncid) != funcids.end() && @@ -1352,7 +1351,6 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req pfrom->PushMessage("nSPV", response); pfrom->nspvdata[nData].prevtime = timestamp; pfrom->nspvdata[nData].nreqs ++; - std::cerr << __func__ << " set pfrom->nspvdata[" << nData << "].prevtime=" << timestamp << std::endl; LogPrint("nspv-details", "NSPV_REMOTERPCRESP response: method=%s json=%s to node=%d\n", R.method, R.json, pfrom->id); NSPV_remoterpc_purge(&R); } From 91dfbd69fedcc7123913ccff0ec83d91c258db0f Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 11 Sep 2021 17:24:51 +0500 Subject: [PATCH 108/348] fix cs_mapRelay deadlock (when both ProcessGetData and Broadcast try to lock cs_mapRelay and cs_vSend) --- src/main.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b7dc91e2c15..60033d3752a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7446,10 +7446,18 @@ void static ProcessGetData(CNode* pfrom) // Send stream from relay memory bool pushed = false; { - LOCK(cs_mapRelay); - map::iterator mi = mapRelay.find(inv); - if (mi != mapRelay.end()) { - pfrom->PushMessage(inv.GetCommand(), (*mi).second); + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + bool found = false; + { + LOCK(cs_mapRelay); + map::iterator mi = mapRelay.find(inv); + if (mi != mapRelay.end()) { + ss = ((*mi).second); + found = true; + } + } + if (found) { + pfrom->PushMessage(inv.GetCommand(), ss); pushed = true; } } From bea44878f56502c6e8b5217f813807d6c7a92078 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 13 Sep 2021 14:57:47 +0500 Subject: [PATCH 109/348] more externs moved to komodo_defs.h --- src/cc/pegs.cpp | 2 -- src/init.cpp | 2 -- src/komodo.h | 1 - src/komodo_defs.h | 22 ++++++++++++++++++++-- src/komodo_gateway.h | 1 - src/komodo_globals.h | 6 +++--- src/komodo_nSPV_defs.h | 1 + src/komodo_utils.h | 2 +- 8 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 6de6baa4000..824bad2ce34 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -100,8 +100,6 @@ pegs CC is able to create a coin backed (by any supported coin with gateways CC #endif // PEGS_THRESHOLDS #define CC_MARKER_VALUE 10000 -extern uint64_t ASSETCHAINS_PEGSCCPARAMS[3]; - extern uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); //extern int64_t GetTokenBalance(CPubKey pk, uint256 tokenid); extern int32_t komodo_currentheight(); diff --git a/src/init.cpp b/src/init.cpp index 74c23c977fc..190b09ab5ba 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -912,8 +912,6 @@ bool AppInitServers(boost::thread_group& threadGroup) /** Initialize bitcoin. * @pre Parameters should be parsed and config file should be read. */ -extern int32_t KOMODO_REWIND; - bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) { // ********************************************************* Step 1: setup diff --git a/src/komodo.h b/src/komodo.h index 6404729fbdd..bfcfb0b789c 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -64,7 +64,6 @@ void komodo_currentheight_set(int32_t height) sp->CURRENT_HEIGHT = height; } -extern struct NSPV_inforesp NSPV_inforesult; int32_t komodo_currentheight() { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; diff --git a/src/komodo_defs.h b/src/komodo_defs.h index a3a278037f9..cda24ccb66e 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -44,6 +44,8 @@ #define ASSETCHAINS_STAKED_MIN_POW_DIFF 536900000 // 537000000 537300000 #define _COINBASE_MATURITY 100 +#define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff + #define IS_KMD_CHAIN() (ASSETCHAINS_SYMBOL[0] == '\0') #define KOMODO_ADDRESS_BUFSIZE 64 @@ -510,7 +512,10 @@ extern int32_t VERUS_MIN_STAKEAGE; extern uint32_t ASSETCHAINS_VERUSHASH, ASSETCHAINS_VERUSHASHV1_1, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB; extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; -//extern std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; +extern std::vector ASSETCHAINS_PRICES, ASSETCHAINS_STOCKS; +extern std::vector Mineropret; // opreturn data set by the data gathering code +extern uint64_t ASSETCHAINS_PEGSCCPARAMS[3]; +extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEYHASH[]; extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD; extern uint256 KOMODO_EARLYTXID; @@ -634,6 +639,7 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); int32_t komodo_baseid(char *origbase); int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); +uint64_t komodo_current_supply(uint32_t nHeight); int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); @@ -647,14 +653,26 @@ extern uint64_t KOMODO_INTERESTSUM, KOMODO_WALLETBALANCE; extern int32_t KOMODO_INSYNC, KOMODO_LASTMINED, prevKOMODO_LASTMINED; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS + 1], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS + 1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS + 1]; +extern uint64_t ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS + 1]; extern uint32_t ASSETCHAINS_MAGIC; extern uint64_t ASSETCHAINS_LINEAR, ASSETCHAINS_COMMISSION, ASSETCHAINS_SUPPLY; extern uint8_t ASSETCHAINS_PUBLIC, ASSETCHAINS_PRIVATE; extern int32_t ASSETCHAINS_STAKED; -extern uint64_t ASSETCHAINS_DECAY[]; extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; extern int32_t KOMODO_LOADINGBLOCKS; extern int32_t ASSETCHAINS_FOUNDERS; +extern char ASSETCHAINS_USERPASS[]; +extern int32_t KOMODO_REWIND; +extern uint32_t ASSETCHAINS_NUMALGOS; +extern uint32_t STAKING_MIN_DIFF; +extern uint32_t ASSETCHAINS_MINDIFF[]; +extern uint64_t ASSETCHAINS_TIMEUNLOCKFROM; +extern uint64_t ASSETCHAINS_TIMEUNLOCKTO; +extern uint32_t KOMODO_DPOWCONFS; +extern uint16_t KMD_PORT, BITCOIND_RPCPORT, DEST_PORT; +extern char KMDUSERPASS[], BTCUSERPASS[]; +extern uint32_t KOMODO_STOPAT; +extern int32_t ASSETCHAINS_CBMATURITY; #ifndef KOMODO_NSPV_FULLNODE #define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 9c804b08268..b422f9fa8c1 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1578,7 +1578,6 @@ void komodo_passport_iteration() } -extern std::vector Mineropret; // opreturn data set by the data gathering code #define PRICES_ERRORRATE (COIN / 100) // maximum acceptable change, set at 1% #define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR #define KOMODO_LOCALPRICE_CACHESIZE 13 diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 101a79e9ae8..87c94052dd7 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -64,14 +64,13 @@ int64_t MAX_MONEY = 200000000 * 100000000LL; // to be verifiable, timelocks require additional data that enables them to be validated and their ownership and // release time determined from the blockchain. to do this, every time locked output according to this // spec will use an op_return with CLTV at front and anything after |OP_RETURN|PUSH of rest|OPRETTYPE_TIMELOCK|script| -#define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff uint64_t ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF; uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0,ASSETCHAINS_CBOPRET=0; uint64_t ASSETCHAINS_LASTERA = 1; uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_PEGSCCPARAMS[3]; uint8_t ASSETCHAINS_CCDISABLES[256],ASSETCHAINS_CCZEROTXFEE[256]; -std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; +std::vector ASSETCHAINS_PRICES, ASSETCHAINS_STOCKS; #define _ASSETCHAINS_EQUIHASH 0 uint32_t ASSETCHAINS_NUMALGOS = 3; @@ -101,7 +100,8 @@ int32_t ASSETCHAINS_STAKED; uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REWARD; uint32_t KOMODO_INITDONE; -char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; +char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; +uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; uint64_t PENDING_KOMODO_TX; unsigned int MAX_BLOCK_SIGOPS = 20000; diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 20579cf8ab3..9d4fd68a12b 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -193,6 +193,7 @@ struct NSPV_remoterpcresp char *json; }; +extern struct NSPV_inforesp NSPV_inforesult; void NSPV_CCunspents(std::vector>& unspentOutputs, char* coinaddr, bool ccflag); void NSPV_CCindexOutputs(std::vector>& indexOutputs, char* coinaddr, bool ccflag); diff --git a/src/komodo_utils.h b/src/komodo_utils.h index a2468af71ce..2cd7508b45f 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -17,6 +17,7 @@ #include "util.h" #include "komodo_defs.h" #include "cc/CCinclude.h" +#include "importcoin.h" #include #ifdef _WIN32 @@ -2569,7 +2570,6 @@ int64_t komodo_get_blocktime(uint256 hashBlock) return 0; } -extern struct NSPV_inforesp NSPV_inforesult; int32_t komodo_get_current_height() { if ( KOMODO_NSPV_SUPERLITE ) From 88e631aaf52ce9ecbf0cfb69d059aba931f730b0 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 13 Sep 2021 15:16:09 +0500 Subject: [PATCH 110/348] Split renamed/refactored --- src/komodo_utils.h | 18 +++++++++--------- src/util.cpp | 24 +++++++++++------------- src/util.h | 10 +++++----- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 2cd7508b45f..6b2b70be529 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1771,10 +1771,10 @@ void komodo_args(char *argv0) ASSETCHAINS_PUBLIC = GetArg("-ac_public",0); ASSETCHAINS_PRIVATE = GetArg("-ac_private",0); KOMODO_SNAPSHOT_INTERVAL = GetArg("-ac_snapshot",0); - Split(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); + SplitIntoU64List(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); // -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height.... - Split(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), ccEnablesHeight, 0); + SplitIntoU64List(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), ccEnablesHeight, 0); // fill map with all eval codes and activation height of 0. for ( int i = 0; i < 256; i++ ) mapHeightEvalActivate[i] = 0; @@ -1848,11 +1848,11 @@ void komodo_args(char *argv0) ASSETCHAINS_TIMEUNLOCKFROM = ASSETCHAINS_TIMEUNLOCKTO = 0; } - Split(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0); - Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0); - Split(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0); - Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); - Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); + SplitIntoU64List(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0); + SplitIntoU64List(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0); + SplitIntoU64List(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0); + SplitIntoU64List(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); + SplitIntoU64List(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); for ( int i = 0; i < ASSETCHAINS_MAX_ERAS; i++ ) { @@ -1922,7 +1922,7 @@ void komodo_args(char *argv0) { uint8_t prevCCi = 0; ASSETCHAINS_CCLIB = GetArg("-ac_cclib",""); - Split(GetArg("-ac_ccenable",""), sizeof(ccenables)/sizeof(*ccenables), ccenables, 0); + SplitIntoU64List(GetArg("-ac_ccenable",""), sizeof(ccenables)/sizeof(*ccenables), ccenables, 0); for (i=nonz=0; i<0x100; i++) { if ( ccenables[i] != prevCCi && ccenables[i] != 0 ) @@ -1988,7 +1988,7 @@ void komodo_args(char *argv0) } else if ( ASSETCHAINS_SELFIMPORT == "PEGSCC") { - Split(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); + SplitIntoU64List(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); if (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_COMMISSION!=0) { fprintf(stderr,"when using import for pegsCC these must be set: -ac_end=1 -ac_perc=0\n"); diff --git a/src/util.cpp b/src/util.cpp index 65ecfe6ec7f..ae05a7702bc 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -414,36 +414,34 @@ void SplitStr(const std::string& strVal, std::vector &outVals) } } -void Split(const std::string& strVal, int32_t outsize, uint64_t *outVals, const uint64_t nDefault) +void SplitIntoU64List(const std::string& strVal, int32_t outsize, uint64_t* outVals, const uint64_t nDefault) { stringstream ss(strVal); vector vec; - uint64_t i, nLast, numVals = 0; + uint64_t val, nLast, numVals = 0; - while ( ss.peek() == ' ' ) + while (ss.peek() == ' ') ss.ignore(); - while ( ss >> i ) - { - outVals[numVals] = i; - numVals += 1; + while (ss >> val && numVals < outsize) { + outVals[numVals] = val; + numVals++; - while ( ss.peek() == ' ' ) + while (ss.peek() == ' ') ss.ignore(); - if ( ss.peek() == ',' ) + if (ss.peek() == ',') ss.ignore(); - while ( ss.peek() == ' ' ) + while (ss.peek() == ' ') ss.ignore(); } - if ( numVals > 0 ) + if (numVals > 0) nLast = outVals[numVals - 1]; else nLast = nDefault; - for ( i = numVals; i < outsize; i++ ) - { + for (int i = numVals; i < outsize; i++) { outVals[i] = nLast; } } diff --git a/src/util.h b/src/util.h index 17bf19952b0..07dcd7e8372 100644 --- a/src/util.h +++ b/src/util.h @@ -179,13 +179,13 @@ inline bool IsSwitchChar(char c) /** * Return string argument or default value * - * @param strVal string to split + * @param strVal string to split into array of uint64_t * @param outVals array of numbers from string or default - * if the string is null, nDefault is used for all array entries - * else if the string has fewer than _MAX_ERAS entries, then the last - * entry fills remaining entries + * if the strVal is null, nDefault is used for all array entries + * else if the strVal has fewer than outsize entries, then the last + * entry fills remaining entries in outVals */ -void Split(const std::string& strVal, int32_t outsize, uint64_t *outVals, uint64_t nDefault); +void SplitIntoU64List(const std::string& strVal, int32_t outsize, uint64_t *outVals, uint64_t nDefault); /** * Return string argument or default value From db523830ca705523caa343350f65c1a1298fa667 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 13 Sep 2021 16:05:52 +0500 Subject: [PATCH 111/348] removed extra def in src --- src/util.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index ae05a7702bc..7d5c3a67fc8 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -30,7 +30,7 @@ #include "sync.h" #include "utilstrencodings.h" #include "utiltime.h" -//#include "komodo_defs.h" // plz dont add this where it is not used, we have build errors for komodo-cli +#include "komodo_defs.h" // plz dont add this where it is not used, we have build errors for komodo-cli #include #include @@ -733,7 +733,6 @@ void ReadConfigFile(map& mapSettingsRet, } // If datadir is changed in .conf file: ClearDatadirCache(); - extern uint16_t BITCOIND_RPCPORT; BITCOIND_RPCPORT = GetArg("-rpcport",BaseParams().RPCPort()); } From 15e16875c90a912b2f6de5f1f2d7bf95716fec50 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 13 Sep 2021 16:06:57 +0500 Subject: [PATCH 112/348] comment fixed --- src/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.cpp b/src/util.cpp index 7d5c3a67fc8..cb32136eb58 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -30,7 +30,7 @@ #include "sync.h" #include "utilstrencodings.h" #include "utiltime.h" -#include "komodo_defs.h" // plz dont add this where it is not used, we have build errors for komodo-cli +#include "komodo_defs.h" // plz dont add this where it is not used, we have build errors for komodo-cli. Looks like it builds okay now #include #include From 17c0060758dbc7bf123932da112098e3885b95c1 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 14 Sep 2021 23:56:09 +0500 Subject: [PATCH 113/348] added a delim param to SpiltStr --- src/util.cpp | 37 ++++++++++++++++++++++++++++++++++--- src/util.h | 3 ++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index cb32136eb58..a81c7809dd7 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -394,8 +394,8 @@ void ParseParameters(int argc, const char* const argv[]) } } -// split string using by space or comma as a delimiter char -void SplitStr(const std::string& strVal, std::vector &outVals) +// split string using space, comma (default) or other char (param) as a delimiter +void SplitStr(const std::string& strVal, std::vector &outVals, const std::string &delims) { stringstream ss(strVal); @@ -406,7 +406,7 @@ void SplitStr(const std::string& strVal, std::vector &outVals) while (std::isspace(ss.peek())) ss.ignore(); - while ((c = ss.get()) != EOF && !std::isspace(c) && c != ',') + while ((c = ss.get()) != EOF && !std::isspace(c) && delims.find(c) == std::string::npos) str += c; if (!str.empty()) @@ -1037,3 +1037,34 @@ int GetNumCores() return boost::thread::physical_concurrency(); } +// add settings to args maps (to add default opts for a specific chain defined outside) +void AddSettings(std::map& mapSettingsRet, + std::map >& mapMultiSettingsRet, const std::string &strOpts) +{ + std::vector vOpts; + SplitStr(strOpts, vOpts, " "); + for (auto const &opt : vOpts) + { + std::vector namevalue; + SplitStr(opt, namevalue, "="); + if (namevalue.size() != 2) + throw std::runtime_error("Invalid option name-value format in override-settings variable"); + std::string name = namevalue[0]; + std::string value = namevalue[1]; + if (name[0] != '-') + throw std::runtime_error("Invalid option format in override-settings variable"); + + // Interpret --foo as -foo. + // If both --foo and -foo are set, the last takes effect. + if (name.length() > 1 && name[1] == '-') + name = name.substr(1); + + if (mapSettingsRet.count(name) == 0) + { + mapSettingsRet[name] = value; + // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set) + InterpretNegativeSetting(name, mapSettingsRet); + } + mapMultiSettingsRet[name].push_back(value); + } +} \ No newline at end of file diff --git a/src/util.h b/src/util.h index 07dcd7e8372..554555d0530 100644 --- a/src/util.h +++ b/src/util.h @@ -288,7 +288,8 @@ template void TraceThread(const char* name, Callable func) } // split string using by space or comma as a delimiter char -void SplitStr(const std::string& strVal, std::vector &outVals); +void SplitStr(const std::string& strVal, std::vector &outVals, const std::string &delims = ","); +void AddSettings(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet, const std::string &strOpts); #define KOMODO_ASSETCHAIN_MAXLEN 65 From ac1f92987c47d10498f4e3f8d69d373318c0eaac Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 14 Sep 2021 23:57:40 +0500 Subject: [PATCH 114/348] added configure custom chain args --- configure.ac | 35 +++++++++++++++++++ src/Makefile.am | 82 ++++++++++++++++++++++++++++++++++++++++++++- src/bitcoin-cli.cpp | 12 +++++++ src/bitcoind.cpp | 7 ++++ src/main.h | 3 +- 5 files changed, 136 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index e0629a1c56d..ac02d57af8e 100644 --- a/configure.ac +++ b/configure.ac @@ -975,6 +975,39 @@ PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP" ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no --enable-module-recovery" AC_CONFIG_SUBDIRS([src/secp256k1 src/snark src/univalue src/cryptoconditions]) +# build custom executable with customised args: + +AC_ARG_WITH([custom-bin], + [AS_HELP_STRING([--with-custom-bin], + [build custom named daemon cli (default=no)])], + [build_custom_bin=$withval], + [build_custom_bin=no]) + +# build custom executable added with an Makefile.nnn.include +AM_CONDITIONAL([BUILD_CUSTOM_BIN], [test "x$build_custom_bin" = "xyes"]) + +AC_ARG_VAR(CUSTOM_BIN_NAME, [custom executable prefix]) +if test "x${CUSTOM_BIN_NAME+set}" = "xset"; then + AC_SUBST([CUSTOM_BIN_NAME], ${CUSTOM_BIN_NAME}) +else + AC_SUBST([CUSTOM_BIN_NAME], '') +fi + +AC_ARG_VAR(CUSTOM_SERVER_ARGS, [custom daemon params]) +if test "x${CUSTOM_SERVER_ARGS+set}" = "xset"; then + AC_SUBST([CUSTOM_SERVER_ARGS], ${CUSTOM_SERVER_ARGS}) +else + AC_SUBST([CUSTOM_SERVER_ARGS], '') +fi + +AC_ARG_VAR(CUSTOM_CLIENT_ARGS, [custom cli params]) +if test "x${CUSTOM_CLIENT_ARGS+set}" = "xset"; then + AC_SUBST([CUSTOM_CLIENT_ARGS], ${CUSTOM_CLIENT_ARGS}) +else + AC_SUBST([CUSTOM_CLIENT_ARGS], '') +fi + + AC_OUTPUT dnl Taken from https://wiki.debian.org/RpathIssue @@ -1008,3 +1041,5 @@ echo " CXXFLAGS = $CXXFLAGS" echo " LDFLAGS = $LDFLAGS" echo " ARFLAGS = $ARFLAGS" echo + +echo " CUSTOM_NAME = $CUSTOM_NAME" diff --git a/src/Makefile.am b/src/Makefile.am index 8abfd389430..3c0e37cf80d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -281,7 +281,7 @@ obj/build.h: FORCE $(abs_top_srcdir) libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h -# server: zcashd +# server: komodod libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ @@ -796,3 +796,83 @@ include Makefile.kcctest.include #include Makefile.test.include #include Makefile.gtest.include endif + +# build custom executables with customised params +if BUILD_CUSTOM_BIN +# include Makefile.tokel.include + +# custom server lib compiled with -DCUSTOM_BIN_NAME -DCUSTOM_SERVER_ARGS +LIBCUSTOM_SERVER=libcustom_server.a -lcurl +libcustom_server_a_CPPFLAGS = $(libbitcoin_server_a_CPPFLAGS) +libcustom_server_a_CXXFLAGS = $(libbitcoin_server_a_CXXFLAGS) +libcustom_server_a_SOURCES = $(libbitcoin_server_a_SOURCES) + +EXTRA_LIBRARIES += $(LIBCUSTOM_SERVER) + +bin_PROGRAMS += customd + +# custom daemon binary # +customd_SOURCES = $(komodod_SOURCES) +customd_CPPFLAGS = $(komodod_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_SERVER_ARGS=\"$(CUSTOM_SERVER_ARGS)\" +customd_CXXFLAGS = $(komodod_CXXFLAGS) +customd_LDFLAGS = $(komodod_LDFLAGS) +customd_LDADD = \ + $(LIBCUSTOM_SERVER) \ + $(LIBBITCOIN_COMMON) \ + $(LIBUNIVALUE) \ + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_ZMQ) \ + $(LIBBITCOIN_PROTON) \ + $(LIBBITCOIN_CRYPTO) \ + $(LIBVERUS_CRYPTO) \ + $(LIBVERUS_PORTABLE_CRYPTO) \ + $(LIBZCASH) \ + $(LIBSNARK) \ + $(LIBLEVELDB) \ + $(LIBMEMENV) \ + $(LIBSECP256K1) \ + $(LIBCRYPTOCONDITIONS) + +customd_LDADD += \ + $(BOOST_LIBS) \ + $(BDB_LIBS) \ + $(SSL_LIBS) \ + $(CRYPTO_LIBS) \ + $(EVENT_PTHREADS_LIBS) \ + $(EVENT_LIBS) \ + $(ZMQ_LIBS) \ + $(PROTON_LIBS) \ + $(LIBBITCOIN_CRYPTO) \ + $(LIBVERUS_CRYPTO) \ + $(LIBVERUS_PORTABLE_CRYPTO) \ + $(LIBZCASH_LIBS) + +customd_LDADD += $(LIBDYNCUSTOMCONSENSUS) $(LIBSECP256K1) + +if ENABLE_PROTON +customd_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) +endif + +if ENABLE_WALLET +customd_LDADD += $(LIBBITCOIN_WALLET) +endif + +customd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(customd_CXXFLAGS) \ + $(CXXFLAGS) $(customd_LDFLAGS) $(LDFLAGS) -o $(CUSTOM_BIN_NAME)d + + +bin_PROGRAMS += custom-cli + +# custom cli binary # +custom_cli_SOURCES = $(komodo_cli_SOURCES) +custom_cli_CPPFLAGS = $(komodo_cli_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_CLIENT_ARGS=\"$(CUSTOM_CLIENT_ARGS)\" +custom_cli_CXXFLAGS = $(komodo_cli_CXXFLAGS) +custom_cli_LDFLAGS = $(komodo_cli_LDFLAGS) +custom_cli_LDADD = $(komodo_cli_LDADD) + +custom_cli_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(custom_cli_CXXFLAGS) \ + $(CXXFLAGS) $(custom_cli_LDFLAGS) $(LDFLAGS) -o $(CUSTOM_BIN_NAME)-cli + +endif \ No newline at end of file diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 544972586aa..203005dca20 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -95,6 +95,17 @@ static int AppInitRPC(int argc, char* argv[]) // Parameters // ParseParameters(argc, argv); + +#if defined(CUSTOM_CLIENT_ARGS) + // add custom chain parameters + try { + AddSettings(mapArgs, mapMultiArgs, CUSTOM_CLIENT_ARGS); + } catch (const std::exception& e) { + fprintf(stderr,"Error in custom parameters: %s\n", e.what()); + return EXIT_FAILURE; + } +#endif + std:string name; name = GetArg("-ac_name",""); if ( !name.empty() ) @@ -124,6 +135,7 @@ static int AppInitRPC(int argc, char* argv[]) fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str()); return EXIT_FAILURE; } + try { ReadConfigFile(mapArgs, mapMultiArgs); } catch (const std::exception& e) { diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 0374b2e90e1..a0dce001ddf 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -147,7 +147,14 @@ bool AppInit(int argc, char* argv[]) fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); return false; } + +#if defined(CUSTOM_SERVER_ARGS) + // add custom chain parameters + AddSettings(mapArgs, mapMultiArgs, CUSTOM_SERVER_ARGS); +#endif + void komodo_args(char *argv0); + komodo_args(argv[0]); void chainparams_commandline(); chainparams_commandline(); diff --git a/src/main.h b/src/main.h index bd03b1eb982..3122c6f134b 100644 --- a/src/main.h +++ b/src/main.h @@ -122,8 +122,7 @@ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; /** Default NSPV support enabled */ -#define DEFAULT_NSPV_TOKEL true -static const bool DEFAULT_NSPV_PROCESSING = DEFAULT_NSPV_TOKEL; +static const bool DEFAULT_NSPV_PROCESSING = false; //static const bool DEFAULT_ADDRESSINDEX = false; //static const bool DEFAULT_SPENTINDEX = false; From d9410162295b1d1e01ada238077316356d753980 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 15 Sep 2021 12:11:08 +0500 Subject: [PATCH 115/348] added CUSTOM_BIN_NAME, CUSTOM_SERVER_ARGS, CUSTOM_CLIENT_ARGS configure and Makefile vars --- configure.ac | 7 +++++++ src/Makefile.am | 6 +++--- src/bitcoin-cli.cpp | 17 +++++++++++++---- src/bitcoind.cpp | 27 ++++++++++++++++++--------- src/rpc/server.cpp | 4 ++++ 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index ac02d57af8e..37b3045011d 100644 --- a/configure.ac +++ b/configure.ac @@ -993,6 +993,13 @@ else AC_SUBST([CUSTOM_BIN_NAME], '') fi +AC_ARG_VAR(CUSTOM_BRAND_NAME, [custom brand name]) +if test "x${CUSTOM_BRAND_NAME+set}" = "xset"; then + AC_SUBST([CUSTOM_BRAND_NAME], ${CUSTOM_BRAND_NAME}) +else + AC_SUBST([CUSTOM_BRAND_NAME], '') +fi + AC_ARG_VAR(CUSTOM_SERVER_ARGS, [custom daemon params]) if test "x${CUSTOM_SERVER_ARGS+set}" = "xset"; then AC_SUBST([CUSTOM_SERVER_ARGS], ${CUSTOM_SERVER_ARGS}) diff --git a/src/Makefile.am b/src/Makefile.am index 3c0e37cf80d..113dde9cef7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -803,7 +803,7 @@ if BUILD_CUSTOM_BIN # custom server lib compiled with -DCUSTOM_BIN_NAME -DCUSTOM_SERVER_ARGS LIBCUSTOM_SERVER=libcustom_server.a -lcurl -libcustom_server_a_CPPFLAGS = $(libbitcoin_server_a_CPPFLAGS) +libcustom_server_a_CPPFLAGS = $(libbitcoin_server_a_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_BRAND_NAME=\"$(CUSTOM_BRAND_NAME)\" -DCUSTOM_SERVER_ARGS=\"$(CUSTOM_SERVER_ARGS)\" libcustom_server_a_CXXFLAGS = $(libbitcoin_server_a_CXXFLAGS) libcustom_server_a_SOURCES = $(libbitcoin_server_a_SOURCES) @@ -813,7 +813,7 @@ bin_PROGRAMS += customd # custom daemon binary # customd_SOURCES = $(komodod_SOURCES) -customd_CPPFLAGS = $(komodod_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_SERVER_ARGS=\"$(CUSTOM_SERVER_ARGS)\" +customd_CPPFLAGS = $(komodod_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_BRAND_NAME=\"$(CUSTOM_BRAND_NAME)\" -DCUSTOM_SERVER_ARGS=\"$(CUSTOM_SERVER_ARGS)\" customd_CXXFLAGS = $(komodod_CXXFLAGS) customd_LDFLAGS = $(komodod_LDFLAGS) customd_LDADD = \ @@ -866,7 +866,7 @@ bin_PROGRAMS += custom-cli # custom cli binary # custom_cli_SOURCES = $(komodo_cli_SOURCES) -custom_cli_CPPFLAGS = $(komodo_cli_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_CLIENT_ARGS=\"$(CUSTOM_CLIENT_ARGS)\" +custom_cli_CPPFLAGS = $(komodo_cli_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_BRAND_NAME=\"$(CUSTOM_BRAND_NAME)\" -DCUSTOM_CLIENT_ARGS=\"$(CUSTOM_CLIENT_ARGS)\" custom_cli_CXXFLAGS = $(komodo_cli_CXXFLAGS) custom_cli_LDFLAGS = $(komodo_cli_LDFLAGS) custom_cli_LDADD = $(komodo_cli_LDADD) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 203005dca20..e38cf348d26 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -106,18 +106,27 @@ static int AppInitRPC(int argc, char* argv[]) } #endif + std::string cliname = "komodo-cli"; + std::string brandname = "Komodo"; +#if defined(CUSTOM_BIN_NAME) + cliname = std::string(CUSTOM_BIN_NAME) + "-cli"; +#endif +#if defined(CUSTOM_BRAND_NAME) + brandname = std::string("Komodo") + " " + std::string(CUSTOM_BRAND_NAME); +#endif + std:string name; name = GetArg("-ac_name",""); if ( !name.empty() ) strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) { - std::string strUsage = _("Komodo RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); + std::string strUsage = brandname + " " + _("RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); if (!mapArgs.count("-version")) { strUsage += "\n" + _("Usage:") + "\n" + - " komodo-cli [options] [params] " + _("Send command to Komodo") + "\n" + - " komodo-cli [options] help " + _("List commands") + "\n" + - " komodo-cli [options] help " + _("Get help for a command") + "\n"; + " " + cliname + " [options] [params] " + _("Send command to ") + brandname + "\n" + + " " + cliname + " [options] help " + _("List commands") + "\n" + + " " + cliname + " [options] help " + _("Get help for a command") + "\n"; strUsage += "\n" + HelpMessageCli(); } else { diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index a0dce001ddf..9f707b8552d 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -112,7 +112,16 @@ bool AppInit(int argc, char* argv[]) CScheduler scheduler; bool fRet = false; - + std::string daemonname = "komodod"; + std::string cliname = "komodo-cli"; +#if defined(CUSTOM_BIN_NAME) + daemonname = std::string(CUSTOM_BIN_NAME) + "d"; + cliname = std::string(CUSTOM_BIN_NAME) + "-cli"; +#endif + std::string brandname = "Komodo"; +#if defined(CUSTOM_BRAND_NAME) + brandname = std::string("Komodo") + " " + std::string(CUSTOM_BRAND_NAME); +#endif // // Parameters // @@ -131,7 +140,7 @@ bool AppInit(int argc, char* argv[]) else { strUsage += "\n" + _("Usage:") + "\n" + - " komodod [options] " + _("Start Komodo Daemon") + "\n"; + " " + daemonname + " [options] " + _("Start ") + brandname + _(" Daemon") + "\n"; strUsage += "\n" + HelpMessage(HMM_BITCOIND); } @@ -171,16 +180,16 @@ bool AppInit(int argc, char* argv[]) ReadConfigFile(mapArgs, mapMultiArgs); } catch (const missing_zcash_conf& e) { fprintf(stderr, - (_("Before starting komodod, you need to create a configuration file:\n" + (_("Before starting ") + daemonname + _(", you need to create a configuration file:\n" "%s\n" "It can be completely empty! That indicates you are happy with the default\n" - "configuration of komodod. But requiring a configuration file to start ensures\n" - "that komodod won't accidentally compromise your privacy if there was a default\n" + "configuration of ") + daemonname + _(". But requiring a configuration file to start ensures\n" + "that ") + daemonname + _(" won't accidentally compromise your privacy if there was a default\n" "option you needed to change.\n" "\n" "You can look at the example configuration file for suggestions of default\n" "options that you may want to change. It should be in one of these locations,\n" - "depending on how you installed Komodo:\n") + + "depending on how you installed ") + brandname + _(":\n") + _("- Source code: %s\n" "- .deb package: %s\n")).c_str(), GetConfigFile().string().c_str(), @@ -195,12 +204,12 @@ bool AppInit(int argc, char* argv[]) // Command-line RPC bool fCommandLine = false; for (int i = 1; i < argc; i++) - if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "komodo:")) + if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "komodo:")) // Are there any "komodo:" params? fCommandLine = true; if (fCommandLine) { - fprintf(stderr, "Error: There is no RPC client functionality in komodod. Use the komodo-cli utility instead.\n"); + std::cerr << "Error: There is no RPC client functionality in " << daemonname << ". Use the " << cliname << " utility instead." << std::endl; exit(EXIT_FAILURE); } @@ -208,7 +217,7 @@ bool AppInit(int argc, char* argv[]) fDaemon = GetBoolArg("-daemon", false); if (fDaemon) { - fprintf(stdout, "Komodo %s server starting\n",ASSETCHAINS_SYMBOL); + fprintf(stdout, "Komodo %s server starting\n", ASSETCHAINS_SYMBOL); // Daemonize pid_t pid = fork(); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 57068503a5b..955cc9991bf 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -876,7 +876,11 @@ std::string HelpExampleCli(const std::string& methodname, const std::string& arg } else if ((strncmp(ASSETCHAINS_SYMBOL, "HUSH3", 5) == 0) ) { return "> hush-cli " + methodname + " " + args + "\n"; } else { +#if !defined CUSTOM_BIN_NAME return "> komodo-cli -ac_name=" + strprintf("%s", ASSETCHAINS_SYMBOL) + " " + methodname + " " + args + "\n"; +#else + return "> " + std::string(CUSTOM_BIN_NAME) + "-cli" + " " + methodname + " " + args + "\n"; +#endif } } From fe44c26d18df7ff7df31a6da984721aa57a0826a Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 15 Sep 2021 19:26:00 +0500 Subject: [PATCH 116/348] added EXEEXT to build cmd; libbitcoin_wallet moved up for custom --- src/Makefile.am | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 113dde9cef7..4fb31dc0f59 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -833,6 +833,10 @@ customd_LDADD = \ $(LIBSECP256K1) \ $(LIBCRYPTOCONDITIONS) +if ENABLE_WALLET +customd_LDADD += $(LIBBITCOIN_WALLET) +endif + customd_LDADD += \ $(BOOST_LIBS) \ $(BDB_LIBS) \ @@ -853,13 +857,9 @@ if ENABLE_PROTON customd_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) endif -if ENABLE_WALLET -customd_LDADD += $(LIBBITCOIN_WALLET) -endif - customd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(customd_CXXFLAGS) \ - $(CXXFLAGS) $(customd_LDFLAGS) $(LDFLAGS) -o $(CUSTOM_BIN_NAME)d + $(CXXFLAGS) $(customd_LDFLAGS) $(LDFLAGS) -o $(CUSTOM_BIN_NAME)d$(EXEEXT) bin_PROGRAMS += custom-cli @@ -873,6 +873,6 @@ custom_cli_LDADD = $(komodo_cli_LDADD) custom_cli_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(custom_cli_CXXFLAGS) \ - $(CXXFLAGS) $(custom_cli_LDFLAGS) $(LDFLAGS) -o $(CUSTOM_BIN_NAME)-cli + $(CXXFLAGS) $(custom_cli_LDFLAGS) $(LDFLAGS) -o $(CUSTOM_BIN_NAME)-cli$(EXEEXT) endif \ No newline at end of file From 8710a0a3eed5be95eb89ea5166929670c44b77e3 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 19 Sep 2021 13:56:09 +0500 Subject: [PATCH 117/348] added gettransactionsmany nspv rpc --- src/komodo_nSPV_fullnode.h | 2 +- src/rpc/ccutilsrpc.cpp | 92 +++++++++++++++++++++++++++++++++++++- src/rpc/tokensrpc.cpp | 53 ---------------------- 3 files changed, 91 insertions(+), 56 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 9d444ae8e06..3bf41f84ff6 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -46,7 +46,7 @@ static std::map nspv_remote_commands = { { "tokenv2ask", true }, { "tokenv2bid", true }, { "tokenv2fillask", true }, { "tokenv2fillbid", true }, { "tokenv2cancelask", true }, { "tokenv2cancelbid", true }, { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", true },{ "tokenv2create", true }, // nspv helpers - { "createtxwithnormalinputs", true }, { "tokenv2addccinputs", true }, { "tokenv2infotokel", true } + { "createtxwithnormalinputs", true }, { "tokenv2addccinputs", true }, { "tokenv2infotokel", true }, { "gettransactionsmany", true }, }; struct NSPV_ntzargs diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index c4bf88f7bd4..81f3d3c0ba3 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -90,12 +90,100 @@ UniValue listccunspents(const UniValue& params, bool fHelp, const CPubKey& mypk) } +// a helper function for nspv clients: creates a tx and add normal inputs for the requested amouny +UniValue createtxwithnormalinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || (params.size() < 1 || params.size() > 2)) + { + string msg = "createtxwithnormalinputs amount [pubkey]\n" + "\nReturns a new tx with added normal inputs and previous txns. Note that the caller must add the change output\n" + "\nArguments:\n" + //"address which utxos are added from\n" + "amount (in satoshi) which will be added as normal inputs (equal or more)\n" + "pubkey optional, if not set -pubkey used\n" + "Result: json object with created tx and added vin txns\n\n"; + throw runtime_error(msg); + } + /*std::string address = params[0].get_str(); + if (!CBitcoinAddress(address.c_str()).IsValid()) + throw runtime_error("address invalid");*/ + CAmount amount = atoll(params[0].get_str().c_str()); + if (amount <= 0) + throw runtime_error("amount invalid"); + + CPubKey usedpk = remotepk; + if (params.size() >= 2) { + CPubKey pk = pubkey2pk(ParseHex(params[1].get_str())); + if (!pk.IsValid()) + throw runtime_error("pubkey invalid"); + usedpk = pk; + } + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + std::vector vintxns; + CAmount added = AddNormalinputsRemote(mtx, usedpk, amount, CC_MAXVINS, &vintxns); + if (added < amount) + throw runtime_error("could not find normal inputs"); + + for (auto const & vin : mtx.vin) { + CTransaction tx; + uint256 hashBlock; + if (myGetTransaction(vin.prevout.hash, tx, hashBlock)) + vintxns.push_back(tx); + } + UniValue result (UniValue::VOBJ); + UniValue array (UniValue::VARR); + + result.pushKV("txhex", HexStr(E_MARSHAL(ss << mtx))); + for (auto const &vtx : vintxns) + array.push_back(HexStr(E_MARSHAL(ss << vtx))); + result.pushKV("previousTxns", array); + return result; +} + +UniValue gettransactionsmany(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() < 1 || params.size() > 0x1000) + { + string msg = "gettransactionsmany txid1 txid2 ...\n" + "\nReturns a list of confirmed transactions for the given txids.\n" + "\nArguments:\n" + "txid1 txid2... - txids to load, with max number of no more than 4096\n" + "Result: json object with txns in hex and optional list of txids that could not be loaded\n\n"; + throw runtime_error(msg); + } + + UniValue result(UniValue::VOBJ); + UniValue txns(UniValue::VARR); + UniValue notloaded(UniValue::VARR); + + for (size_t i = 0; i < params.size(); i ++) + { + uint256 txid = Parseuint256(params[i].get_str().c_str()); + if (txid.IsNull()) + throw std::runtime_error("txid invalid for i=" + std::to_string(i)); + + CTransaction tx; + uint256 hashBlock; + if (myGetTransaction(txid, tx, hashBlock) && !hashBlock.IsNull()) + txns.push_back(HexStr(E_MARSHAL(ss << tx))); + else + notloaded.push_back(txid.GetHex()); + } + result.pushKV("transactions", txns); + if (!notloaded.empty()) + result.pushKV("notloaded", notloaded); + + return result; +} static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- - // tokens & assets - { "ccutils", "listccunspents", &listccunspents, true } + // cc helpers + { "ccutils", "listccunspents", &listccunspents, true }, + { "nspv", "createtxwithnormalinputs", &createtxwithnormalinputs, true }, + { "nspv", "gettransactionsmany", &gettransactionsmany, true }, }; void RegisterCCUtilsRPCCommands(CRPCTable &tableRPC) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 3c3f2995309..0ee1178b0ca 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -1063,56 +1063,6 @@ UniValue addccv2signature(const UniValue& params, bool fHelp, const CPubKey& rem } -UniValue createtxwithnormalinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) -{ - if (fHelp || (params.size() < 1 || params.size() > 2)) - { - string msg = "createtxwithnormalinputs amount [pubkey]\n" - "\nReturns a new tx with added normal inputs and previous txns. Note that the caller must add the change output\n" - "\nArguments:\n" - //"address which utxos are added from\n" - "amount (in satoshi) which will be added as normal inputs (equal or more)\n" - "pubkey optional, if not set -pubkey used\n" - "Result: json object with created tx and added vin txns\n\n"; - throw runtime_error(msg); - } - /*std::string address = params[0].get_str(); - if (!CBitcoinAddress(address.c_str()).IsValid()) - throw runtime_error("address invalid");*/ - CAmount amount = atoll(params[0].get_str().c_str()); - if (amount <= 0) - throw runtime_error("amount invalid"); - - CPubKey usedpk = remotepk; - if (params.size() >= 2) { - CPubKey pk = pubkey2pk(ParseHex(params[1].get_str())); - if (!pk.IsValid()) - throw runtime_error("pubkey invalid"); - usedpk = pk; - } - - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - std::vector vintxns; - CAmount added = AddNormalinputsRemote(mtx, usedpk, amount, CC_MAXVINS, &vintxns); - if (added < amount) - throw runtime_error("could not find normal inputs"); - - for (auto const & vin : mtx.vin) { - CTransaction tx; - uint256 hashBlock; - if (myGetTransaction(vin.prevout.hash, tx, hashBlock)) - vintxns.push_back(tx); - } - UniValue result (UniValue::VOBJ); - UniValue array (UniValue::VARR); - - result.pushKV("txhex", HexStr(E_MARSHAL(ss << mtx))); - for (auto const &vtx : vintxns) - array.push_back(HexStr(E_MARSHAL(ss << vtx))); - result.pushKV("previousTxns", array); - return result; -} - UniValue tokenv2addccinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) { if (fHelp || params.size() != 3) @@ -1200,10 +1150,7 @@ static const CRPCCommand commands[] = { "tokens v2", "tokenv2createtokel", &tokenv2createtokel, true }, { "tokens", "tokeninfotokel", &tokeninfotokel, true }, { "tokens v2", "tokenv2infotokel", &tokenv2infotokel, true }, - { "nspv", "createtxwithnormalinputs", &createtxwithnormalinputs, true }, { "nspv", "tokenv2addccinputs", &tokenv2addccinputs, true }, - - }; void RegisterTokensRPCCommands(CRPCTable &tableRPC) From 8c1d74fa935a4cbd057d42b4eb73321ed8223286 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 19 Sep 2021 14:46:22 +0500 Subject: [PATCH 118/348] added define for unspentccindex --- src/main.cpp | 2 +- src/main.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 60033d3752a..1f141757f79 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6914,7 +6914,7 @@ bool InitBlockIndex() { pblocktree->WriteFlag("spentindex", fSpentIndex); fprintf(stderr,"fAddressIndex.%d/%d fSpentIndex.%d/%d\n",fAddressIndex,DEFAULT_ADDRESSINDEX,fSpentIndex,DEFAULT_SPENTINDEX); - fUnspentCCIndex = GetBoolArg("-unspentccindex", false); + fUnspentCCIndex = GetBoolArg("-unspentccindex", DEFAULT_UNSPENTCCINDEX); pblocktree->WriteFlag("unspentccindex", fUnspentCCIndex); fprintf(stderr, "fUnspentCCIndex.%d\n", fUnspentCCIndex); diff --git a/src/main.h b/src/main.h index 3122c6f134b..9fbde9e5ac5 100644 --- a/src/main.h +++ b/src/main.h @@ -128,6 +128,7 @@ static const bool DEFAULT_NSPV_PROCESSING = false; //static const bool DEFAULT_SPENTINDEX = false; #define DEFAULT_ADDRESSINDEX (GetArg("-ac_cc",0) != 0 || GetArg("-ac_ccactivate",0) != 0) #define DEFAULT_SPENTINDEX (GetArg("-ac_cc",0) != 0 || GetArg("-ac_ccactivate",0) != 0) +#define DEFAULT_UNSPENTCCINDEX false static const bool DEFAULT_TIMESTAMPINDEX = false; static const unsigned int DEFAULT_DB_MAX_OPEN_FILES = 1000; From c3b772a7d6ed747656cd84a729a82cd4418e403b Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 21 Sep 2021 21:47:30 +0500 Subject: [PATCH 119/348] refactored after code review: removed duplicate defs, more defs moved to komodo_defs.h, removed unused CUSTOM_NAME, replaced strprintf in server --- configure.ac | 2 - src/bitcoind.cpp | 15 +- src/cc/CCinclude.h | 5 - src/coins.cpp | 3 - src/komodo_bitcoind.h | 2 - src/komodo_defs.h | 47 ++- src/rpc/blockchain.cpp | 2 - src/rpc/mining.cpp | 1 - src/rpc/rawtransaction.cpp | 2 - src/rpc/server.cpp | 4 +- src/rpc/server.h | 698 ++++++++++++++++++------------------- src/util.cpp | 3 +- src/wallet/rpcwallet.cpp | 25 -- src/wallet/wallet.cpp | 3 - 14 files changed, 386 insertions(+), 426 deletions(-) diff --git a/configure.ac b/configure.ac index 37b3045011d..98d3b098ffc 100644 --- a/configure.ac +++ b/configure.ac @@ -1048,5 +1048,3 @@ echo " CXXFLAGS = $CXXFLAGS" echo " LDFLAGS = $LDFLAGS" echo " ARFLAGS = $ARFLAGS" echo - -echo " CUSTOM_NAME = $CUSTOM_NAME" diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 9f707b8552d..0e6492c3580 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -68,14 +68,7 @@ void WaitForShutdown(boost::thread_group* threadGroup) fprintf(stderr,"error: earlytx must be before block height %d or tx does not exist\n",KOMODO_EARLYTXID_HEIGHT); StartShutdown(); } - /*if ( ASSETCHAINS_STAKED == 0 && ASSETCHAINS_ADAPTIVEPOW == 0 && (pindex= komodo_chainactive(1)) != 0 ) - { - if ( pindex->nTime > ADAPTIVEPOW_CHANGETO_DEFAULTON ) - { - ASSETCHAINS_ADAPTIVEPOW = 1; - fprintf(stderr,"default activate adaptivepow\n"); - } else fprintf(stderr,"height1 time %u vs %u\n",pindex->nTime,ADAPTIVEPOW_CHANGETO_DEFAULTON); - } //else fprintf(stderr,"cant find height 1\n");*/ + if ( ASSETCHAINS_CBOPRET != 0 ) komodo_pricesinit(); /* @@ -99,12 +92,6 @@ void WaitForShutdown(boost::thread_group* threadGroup) // // Start // -/* -extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY; -extern uint32_t ASSETCHAIN_INIT; -extern std::string NOTARY_PUBKEY; -int32_t komodo_is_issuer(); -*/ bool AppInit(int argc, char* argv[]) { diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index e21371f5278..f2debae24e5 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -370,11 +370,6 @@ void CCclearvars(struct CCcontract_info *cp); UniValue CClib(struct CCcontract_info *cp,char *method,char *jsonstr); UniValue CClib_info(struct CCcontract_info *cp); -//CBlockIndex *komodo_blockindex(uint256 hash); //moved to komodo_def.h -//CBlockIndex *komodo_chainactive(int32_t height); //moved to komodo_def.h -//int32_t komodo_blockheight(uint256 hash); //moved to komodo_def.h -//void StartShutdown(); - static const uint256 zeroid; //!< null uint256 constant /// \cond INTERNAL diff --git a/src/coins.cpp b/src/coins.cpp index 92206b65379..77a46d38b90 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -565,9 +565,6 @@ const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const return coins->vout[input.prevout.n]; } -//uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; const CScript &CCoinsViewCache::GetSpendFor(const CCoins *coins, const CTxIn& input) { diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 34ae9e5e34f..8226a76080c 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1263,8 +1263,6 @@ uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_ return(locktime); } -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); - uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight) { uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex; diff --git a/src/komodo_defs.h b/src/komodo_defs.h index cda24ccb66e..17398cd85ac 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -22,6 +22,7 @@ #include "pubkey.h" #include "chain.h" #include "primitives/transaction.h" +#include "threadsafety.h" #include "komodo_nk.h" @@ -491,7 +492,7 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = #define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1) #endif -extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC; +extern uint8_t ASSETCHAINS_TXPOW; extern int8_t ASSETCHAINS_ADAPTIVEPOW; int32_t MAX_BLOCK_SIZE(int32_t height); extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; @@ -544,7 +545,6 @@ void komodo_netevent(std::vector payload); int32_t getacseason(uint32_t timestamp); int32_t getkmdseason(int32_t height); -#define IGUANA_MAXSCRIPTSIZE 10001 #define KOMODO_KVDURATION 1440 #define KOMODO_KVBINARY 2 #define PRICES_SMOOTHWIDTH 1 @@ -554,10 +554,8 @@ int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *bas int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); -int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); uint32_t komodo_blocktime(uint256 hash); -int32_t komodo_longestchain(); int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); int8_t komodo_segid(int32_t nocache,int32_t height); int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight); @@ -566,7 +564,6 @@ int32_t komodo_priceind(const char *symbol); int32_t komodo_pricesinit(); int64_t komodo_priceave(int64_t *tmpbuf,int64_t *correlated,int32_t cskip); int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth); -int32_t komodo_nextheight(); uint32_t komodo_heightstamp(int32_t height); int64_t komodo_pricemult_to10e8(int32_t ind); int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks); @@ -594,7 +591,6 @@ int32_t komodo_get_current_height(); struct komodo_state *komodo_stateptrget(char *base); void komodo_prefetch(FILE *fp); -uint32_t komodo_heightstamp(int32_t height); void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); void komodo_init(int32_t height); int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); @@ -629,13 +625,14 @@ int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime); void komodo_passport_iteration(); void komodo_cbopretupdate(int32_t forceflag); uint64_t komodo_interestsum(); +uint64_t komodo_interest(int32_t txheight, uint64_t nValue, uint32_t nLockTime, uint32_t tiptime); bool komodo_dailysnapshot(int32_t height); void komodo_setactivation(int32_t height); void komodo_pricesupdate(int32_t height,CBlock *pblock); void komodo_broadcast(CBlock *pblock,int32_t limit); int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); -int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); +int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main) ; arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); int32_t komodo_baseid(char *origbase); int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); @@ -651,14 +648,10 @@ void *filestr(long *allocsizep,char *_fname); extern uint64_t KOMODO_INTERESTSUM, KOMODO_WALLETBALANCE; extern int32_t KOMODO_INSYNC, KOMODO_LASTMINED, prevKOMODO_LASTMINED; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS + 1], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS + 1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS + 1]; +extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS + 1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS + 1]; extern uint64_t ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS + 1]; -extern uint32_t ASSETCHAINS_MAGIC; -extern uint64_t ASSETCHAINS_LINEAR, ASSETCHAINS_COMMISSION, ASSETCHAINS_SUPPLY; +extern uint64_t ASSETCHAINS_LINEAR, ASSETCHAINS_SUPPLY; extern uint8_t ASSETCHAINS_PUBLIC, ASSETCHAINS_PRIVATE; -extern int32_t ASSETCHAINS_STAKED; -extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; extern int32_t KOMODO_LOADINGBLOCKS; extern int32_t ASSETCHAINS_FOUNDERS; extern char ASSETCHAINS_USERPASS[]; @@ -670,7 +663,7 @@ extern uint64_t ASSETCHAINS_TIMEUNLOCKFROM; extern uint64_t ASSETCHAINS_TIMEUNLOCKTO; extern uint32_t KOMODO_DPOWCONFS; extern uint16_t KMD_PORT, BITCOIND_RPCPORT, DEST_PORT; -extern char KMDUSERPASS[], BTCUSERPASS[]; +extern char KMDUSERPASS[], BTCUSERPASS[]; extern uint32_t KOMODO_STOPAT; extern int32_t ASSETCHAINS_CBMATURITY; @@ -732,4 +725,30 @@ extern int32_t JUMBLR_PAUSE; int32_t Jumblr_depositaddradd(char *depositaddr); int32_t Jumblr_secretaddradd(char *secretaddr); + +#define KOMODO_KVPROTECTED 1 +#define KOMODO_KVBINARY 2 +#define KOMODO_KVDURATION 1440 + +uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey37[37],char *coinaddr,int32_t height,char *base,int64_t fiatoshis); +int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); +#define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" +extern int32_t KOMODO_PAX; +int32_t komodo_is_issuer(); +int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); +int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); + +int32_t komodo_pending_withdraws(char *opretstr); +void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value); +int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); +int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize); +uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen); +uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 privkey); +int32_t komodo_kvduration(uint32_t flags); +uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase); +int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig); + +uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +uint64_t _komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); + #endif diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 8e564d5b2a0..0fb2f67dce4 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1125,8 +1125,6 @@ UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk) return ret; } -int32_t komodo_pending_withdraws(char *opretstr); -int32_t pax_fiatstatus(uint64_t *available, uint64_t *deposited, uint64_t *issued, uint64_t *withdrawn, uint64_t *approved, uint64_t *redeemed, char *base); extern char CURRENCIES[][8]; UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 1241e05bb0b..bb0e475fd06 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -398,7 +398,6 @@ UniValue setgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk) } #endif -CBlockIndex *komodo_chainactive(int32_t height); arith_uint256 zawy_ctB(arith_uint256 bnTarget,uint32_t solvetime); UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index db61ae5b8c3..d20807e5331 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -132,8 +132,6 @@ UniValue TxJoinSplitToJSON(const CTransaction& tx) { return vjoinsplit; } -//uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - UniValue TxShieldedSpendsToJSON(const CTransaction& tx) { UniValue vdesc(UniValue::VARR); for (const SpendDescription& spendDesc : tx.vShieldedSpend) { diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 955cc9991bf..c8645442f4c 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -877,9 +877,9 @@ std::string HelpExampleCli(const std::string& methodname, const std::string& arg return "> hush-cli " + methodname + " " + args + "\n"; } else { #if !defined CUSTOM_BIN_NAME - return "> komodo-cli -ac_name=" + strprintf("%s", ASSETCHAINS_SYMBOL) + " " + methodname + " " + args + "\n"; + return std::string("> komodo-cli -ac_name=") + std::string(ASSETCHAINS_SYMBOL) + " " + methodname + " " + args + "\n"; #else - return "> " + std::string(CUSTOM_BIN_NAME) + "-cli" + " " + methodname + " " + args + "\n"; + return std::string("> ") + std::string(CUSTOM_BIN_NAME) + std::string("-cli") + " " + methodname + " " + args + "\n"; #endif } } diff --git a/src/rpc/server.h b/src/rpc/server.h index 2bfd1d75926..f8e27b156fb 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -183,363 +183,363 @@ extern CRPCTable tableRPC; * Utilities: convert hex-encoded Values * (throws error if not hex). */ -extern uint256 ParseHashV(const UniValue& v, std::string strName); -extern uint256 ParseHashO(const UniValue& o, std::string strKey); -extern std::vector ParseHexV(const UniValue& v, std::string strName); -extern std::vector ParseHexO(const UniValue& o, std::string strKey); +uint256 ParseHashV(const UniValue& v, std::string strName); +uint256 ParseHashO(const UniValue& o, std::string strKey); +std::vector ParseHexV(const UniValue& v, std::string strName); +std::vector ParseHexO(const UniValue& o, std::string strKey); extern int64_t nWalletUnlockTime; -extern CAmount AmountFromValue(const UniValue& value); -extern UniValue ValueFromAmount(const CAmount& amount); -extern double GetDifficulty(const CBlockIndex* blockindex = NULL); -extern double GetNetworkDifficulty(const CBlockIndex* blockindex = NULL); -extern std::string HelpRequiringPassphrase(); -extern std::string HelpExampleCli(const std::string& methodname, const std::string& args); -extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args); - -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); -extern UniValue mempoolInfoToJSON(); -extern UniValue mempoolToJSON(bool fVerbose = false); -extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -extern UniValue blockheaderToJSON(const CBlockIndex* blockindex); -extern UniValue TxJoinSplitToJSON(const CTransaction& tx); - -extern void EnsureWalletIsUnlocked(); +CAmount AmountFromValue(const UniValue& value); +UniValue ValueFromAmount(const CAmount& amount); +double GetDifficulty(const CBlockIndex* blockindex = NULL); +double GetNetworkDifficulty(const CBlockIndex* blockindex = NULL); +std::string HelpRequiringPassphrase(); +std::string HelpExampleCli(const std::string& methodname, const std::string& args); +std::string HelpExampleRpc(const std::string& methodname, const std::string& args); + +void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); +UniValue mempoolInfoToJSON(); +UniValue mempoolToJSON(bool fVerbose = false); +void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +UniValue blockheaderToJSON(const CBlockIndex* blockindex); +UniValue TxJoinSplitToJSON(const CTransaction& tx); + +void EnsureWalletIsUnlocked(); bool StartRPC(); void InterruptRPC(); void StopRPC(); std::string JSONRPCExecBatch(const UniValue& vReq); -extern std::string experimentalDisabledHelpMsg(const std::string& rpc, const std::string& enableArg); - -extern UniValue getconnectioncount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcnet.cpp -extern UniValue getaddressmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddressutxos(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddressdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddresstxids(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getsnapshot(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddressbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue checknotarization(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnotarypayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue ping(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue addnode(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue disconnectnode(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnettotals(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue setban(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue clearbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dumpwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue getgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmining.cpp -extern UniValue setgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getlocalsolps(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnetworksolps(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnetworkhashps(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getmininginfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue prioritisetransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue submitblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue estimatefee(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue estimatepriority(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heiraddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heirfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heiradd(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heirclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heirinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heirlist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oracleslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclescreate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclesfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclesregister(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclessubscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclesdata(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclessample(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclessamples(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue priceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue mypriceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paymentsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_release(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_fund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_merge(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_txidopret(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_create(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_airdrop(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_airdroptokens(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_info(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_list(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue cclibaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue cclibinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue cclib(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysdumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysbind(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayswithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayspartialsign(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayscompletesigning(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysmarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayspendingdeposits(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayspendingwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysprocessed(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelsopen(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelspayment(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelsclose(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelsrefund(const UniValue& params, bool fHelp, const CPubKey& mypk); -//extern UniValue tokenswapask(const UniValue& params, bool fHelp, const CPubKey& mypk); -//extern UniValue tokenfillswap(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue faucetfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue faucetget(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue faucetaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue faucetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardscreatefunding(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardsaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardslock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardsunlock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue diceaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dicefund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dicelist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue diceinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue diceaddfunds(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dicebet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dicefinish(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dicestatus(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue lottoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue FSMaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue FSMcreate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue FSMlist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue FSMinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue auctionaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegscreate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsget(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsredeem(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsliquidate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsexchange(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsaccounthistory(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsaccountinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsworstaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -//extern UniValue getnewaddress64(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue getaccountaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getrawchangeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddressesbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue signmessage(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue verifymessage(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getbalance64(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getunconfirmedbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue movecmd(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue addmultisigaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue createmultisig(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listaddressgroupings(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listsinceblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gettransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue backupwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue keypoolrefill(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue walletpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue walletpassphrasechange(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue walletlock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue encryptwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue decodeccopret(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getiguanajson(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnotarysendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue setstakingsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getwalletinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnetworkinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getdeprecationinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue setmocktime(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue resendwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue zc_benchmark(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue zc_raw_keygen(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue zc_raw_receive(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue jumblr_deposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_secret(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_pause(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_resume(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rcprawtransaction.cpp -extern UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue createrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue decodescript(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue fundrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gettxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue verifytxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue getblockcount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcblockchain.cpp -extern UniValue getbestblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getdifficulty(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue settxfee(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getmempoolinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getrawmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblockhashes(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblockdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getlastsegidstakes(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue verifychain(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getchaintips(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue invalidateblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue reconsiderblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getspentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue selfimport(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importdual(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewayaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaybind(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaydeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaywithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaywithdrawsign(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaymarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaypendingsignwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaysignedwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewayexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaydumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue nspv_getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_login(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_mempool(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_spentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_notarizations(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_hdrsproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_txproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_spend(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_logout(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_listccmoduleunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue DEX_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_anonsend(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_list(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_get(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_stats(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_orderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_cancel(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_publish(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_subscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_stream(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_streamsub(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_notarize(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue getblocksubsidy(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue z_exportkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_importkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_listaddresses(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_exportwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_getoperationstatus(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_getoperationresult(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmisc.cpp -extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp -extern UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp - -extern UniValue MoMoMdata(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue calc_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue height_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue assetchainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue crosschainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue scanNotarisationsDB(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getimports(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getwalletburntransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_converttoexport(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_checkburntransactionsource(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_createnotaryapprovaltransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue minerids(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue kvsearch(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxprice(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxprices(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxwithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue prices(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesbet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricessetcostbasis(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricescashout(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesrekt(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesgetorderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesrefillfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +std::string experimentalDisabledHelpMsg(const std::string& rpc, const std::string& enableArg); + +UniValue getconnectioncount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcnet.cpp +UniValue getaddressmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddressutxos(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddressdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddresstxids(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getsnapshot(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddressbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue checknotarization(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnotarypayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue ping(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue addnode(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue disconnectnode(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddednodeinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnettotals(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue setban(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue clearbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dumpwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue getgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmining.cpp +UniValue setgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getlocalsolps(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnetworksolps(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnetworkhashps(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getmininginfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue prioritisetransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue submitblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue estimatefee(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue estimatepriority(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heiraddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heirfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heiradd(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heirclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heirinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heirlist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oracleslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclescreate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclesfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclesregister(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclessubscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclesdata(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclessample(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclessamples(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue priceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue mypriceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paymentsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_release(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_fund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_merge(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_txidopret(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_create(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_airdrop(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_airdroptokens(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_info(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_list(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue cclibaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue cclibinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue cclib(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysdumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysbind(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayswithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayspartialsign(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayscompletesigning(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysmarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayspendingdeposits(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayspendingwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysprocessed(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelsopen(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelspayment(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelsclose(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelsrefund(const UniValue& params, bool fHelp, const CPubKey& mypk); +//UniValue tokenswapask(const UniValue& params, bool fHelp, const CPubKey& mypk); +//UniValue tokenfillswap(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue faucetfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue faucetget(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue faucetaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue faucetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardscreatefunding(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardsaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardslock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardsunlock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue diceaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dicefund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dicelist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue diceinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue diceaddfunds(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dicebet(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dicefinish(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dicestatus(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue lottoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue FSMaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue FSMcreate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue FSMlist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue FSMinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue auctionaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegscreate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsget(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsredeem(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsliquidate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsexchange(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsaccounthistory(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsaccountinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsworstaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +//UniValue getnewaddress64(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue getaccountaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getrawchangeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddressesbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue signmessage(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue verifymessage(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getbalance64(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getunconfirmedbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue movecmd(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue addmultisigaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue createmultisig(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listaddressgroupings(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listsinceblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gettransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue backupwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue keypoolrefill(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue walletpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue walletpassphrasechange(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue walletlock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue encryptwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue decodeccopret(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getiguanajson(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnotarysendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue setstakingsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getwalletinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnetworkinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getdeprecationinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue setmocktime(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue resendwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue zc_benchmark(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue zc_raw_keygen(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue zc_raw_receive(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue jumblr_deposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue jumblr_secret(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue jumblr_pause(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue jumblr_resume(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rcprawtransaction.cpp +UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue createrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue decodescript(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue fundrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gettxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue verifytxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue getblockcount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcblockchain.cpp +UniValue getbestblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getdifficulty(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue settxfee(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getmempoolinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getrawmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblockhashes(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblockdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getlastsegidstakes(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue verifychain(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getchaintips(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue invalidateblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue reconsiderblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getspentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue selfimport(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importdual(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewayaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaybind(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaydeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaywithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaywithdrawsign(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaymarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaypendingsignwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaysignedwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewayexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaydumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue nspv_getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_login(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_mempool(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_spentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_notarizations(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_hdrsproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_txproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_spend(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_logout(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_listccmoduleunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue DEX_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_anonsend(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_list(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_get(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_stats(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_orderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_cancel(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_publish(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_subscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_stream(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_streamsub(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_notarize(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue getblocksubsidy(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue z_exportkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_importkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_listaddresses(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_exportwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_getoperationstatus(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_getoperationresult(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmisc.cpp +UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp +UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp + +UniValue MoMoMdata(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue calc_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue height_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue assetchainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue crosschainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue scanNotarisationsDB(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getimports(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getwalletburntransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_converttoexport(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_checkburntransactionsource(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_createnotaryapprovaltransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue minerids(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue kvsearch(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paxprice(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paxprices(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paxdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paxwithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue prices(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesbet(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricessetcostbasis(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricescashout(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesrekt(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesgetorderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesrefillfund(const UniValue& params, bool fHelp, const CPubKey& mypk); diff --git a/src/util.cpp b/src/util.cpp index a81c7809dd7..bee7903d2b5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -30,8 +30,7 @@ #include "sync.h" #include "utilstrencodings.h" #include "utiltime.h" -#include "komodo_defs.h" // plz dont add this where it is not used, we have build errors for komodo-cli. Looks like it builds okay now - +#include "komodo_defs.h" #include #include #include diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a7a1733218b..c2b0480d5f6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -507,8 +507,6 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); } -int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); - UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) { uint8_t opretbuf[IGUANA_MAXSCRIPTSIZE],opretscript[IGUANA_MAXSCRIPTSIZE],*opret=0; char *oprethexstr; int32_t len,opretlen = 0; @@ -586,29 +584,6 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) return wtx.GetHash().GetHex(); } -#include "komodo_defs.h" - -#define KOMODO_KVPROTECTED 1 -#define KOMODO_KVBINARY 2 -#define KOMODO_KVDURATION 1440 -#define IGUANA_MAXSCRIPTSIZE 10001 -uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey37[37],char *coinaddr,int32_t height,char *base,int64_t fiatoshis); -int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); -#define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" -extern int32_t KOMODO_PAX; -extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; -int32_t komodo_is_issuer(); -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -int32_t komodo_isrealtime(int32_t *kmdheightp); -int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); -int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); -int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize); -uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen); -uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 privkey); -int32_t komodo_kvduration(uint32_t flags); -uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase); -int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig); - UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk) { static uint256 zeroes; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 9f9d55c9347..daee7ef67ef 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3382,9 +3382,6 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const /** * populate vCoins with vector of available COutputs. */ -uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase) const { uint64_t interest,*ptr; From e4600e1efe61494e239653b44e2c4ea8bef35ea8 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 21 Sep 2021 21:48:28 +0500 Subject: [PATCH 120/348] fixed notarization.timestamp in nspv getinfo --- src/komodo_nSPV_fullnode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 3bf41f84ff6..a5f7902d9a1 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -172,7 +172,7 @@ int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) return (-1); ptr->notarization = pair.prevntz; if ((pindex2 = komodo_chainactive(ptr->notarization.txidheight)) != 0) - ptr->notarization.timestamp = pindex->nTime; + ptr->notarization.timestamp = pindex2->nTime; //fprintf(stderr, "timestamp.%i\n", ptr->notarization.timestamp ); if (reqheight == 0) reqheight = ptr->height; From d99af250e522b7e5820231f636ce8a7db83365db Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 21 Sep 2021 21:57:17 +0500 Subject: [PATCH 121/348] enable tokenv2address nspv --- src/komodo_nSPV_fullnode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index a5f7902d9a1..54fd50c8482 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -44,7 +44,7 @@ static std::map nspv_remote_commands = { { "tokenask", false }, { "tokenbid", false }, { "tokenfillask", false }, { "tokenfillbid", false }, { "tokencancelask", false }, { "tokencancelbid", false }, { "tokenorders", false }, { "mytokenorders", false }, { "tokentransfer", false },{ "tokencreate", false }, { "tokenv2ask", true }, { "tokenv2bid", true }, { "tokenv2fillask", true }, { "tokenv2fillbid", true }, { "tokenv2cancelask", true }, { "tokenv2cancelbid", true }, - { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", true },{ "tokenv2create", true }, + { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", true },{ "tokenv2create", true }, { "tokenv2address", true }, // nspv helpers { "createtxwithnormalinputs", true }, { "tokenv2addccinputs", true }, { "tokenv2infotokel", true }, { "gettransactionsmany", true }, }; From 19a5049c6f7fdc2dcea7211ff67221828a3cc250 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 19 Sep 2021 16:37:04 +0500 Subject: [PATCH 122/348] set default nspv_msg and unspentccindex to true for tokel --- src/main.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.h b/src/main.h index 9fbde9e5ac5..99fe460e118 100644 --- a/src/main.h +++ b/src/main.h @@ -122,13 +122,13 @@ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; /** Default NSPV support enabled */ -static const bool DEFAULT_NSPV_PROCESSING = false; +static const bool DEFAULT_NSPV_PROCESSING = true; //static const bool DEFAULT_ADDRESSINDEX = false; //static const bool DEFAULT_SPENTINDEX = false; #define DEFAULT_ADDRESSINDEX (GetArg("-ac_cc",0) != 0 || GetArg("-ac_ccactivate",0) != 0) #define DEFAULT_SPENTINDEX (GetArg("-ac_cc",0) != 0 || GetArg("-ac_ccactivate",0) != 0) -#define DEFAULT_UNSPENTCCINDEX false +#define DEFAULT_UNSPENTCCINDEX true static const bool DEFAULT_TIMESTAMPINDEX = false; static const unsigned int DEFAULT_DB_MAX_OPEN_FILES = 1000; From 71573589461af6f95d458620d8deafcb4288eefb Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 19 Sep 2021 17:24:37 +0500 Subject: [PATCH 123/348] added tokel params to buildxxx.sh --- zcutil/build-mac.sh | 9 ++++++--- zcutil/build-win.sh | 14 +++++++++----- zcutil/build.sh | 7 +++++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index 5f7c1d5f7be..4e4ce740404 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -47,6 +47,7 @@ PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 +# cclib building now added to src/Makefile.am #BUILD CCLIB # WD=$PWD # cd src/cc @@ -54,11 +55,13 @@ make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 # echo Making cclib... # ./makecustom # cd $WD -# cclib building now added to src/Makefile.am ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ -./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" +./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" \ + --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ + CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ + CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' -make "$@" V=1 NO_GTEST=1 STATIC=1 +make "$@" V=1 NO_GTEST=1 STATIC=1 \ No newline at end of file diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index a445ef873b7..b89271e4833 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -13,17 +13,21 @@ cd "$(dirname "$(readlink -f "$0")")/.." cd depends/ && make HOST=$HOST V=1 NO_QT=1 cd ../ +# note: cclib building now added to src/Makefile.am #BUILD CCLIB # WD=$PWD # cd src/cc # echo $PWD # ./makecustom # cd $WD -# cclib building now added to src/Makefile.am - ./autogen.sh -CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared -sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure +CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared \ + --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ + CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ + CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' +sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure + cd src/ -CC="${CC} -g " CXX="${CXX} -g " make V=1 komodod.exe komodo-cli.exe komodo-tx.exe +# note: to build tokeld, tokel-cli it should not exist 'komodod.exe komodo-cli.exe' param here: +CC="${CC} -g " CXX="${CXX} -g " make V=1 diff --git a/zcutil/build.sh b/zcutil/build.sh index 9033ac32fbc..2c1a9c66e86 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -99,14 +99,17 @@ ld -v HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh -CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' +CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' \ + --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ + CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ + CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' +# cclib building now added to src/Makefile.am: #BUILD CCLIB #WD=$PWD #cd src/cc #echo $PWD #./makecustom #cd $WD -# cclib building now added to src/Makefile.am "$MAKE" "$@" V=1 From cf511ac095be15cb684d66d144135421ea492414 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 24 Sep 2021 15:04:03 +0500 Subject: [PATCH 124/348] added blockheader to nspv gettransactionsmany --- src/rpc/ccutilsrpc.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index 81f3d3c0ba3..72d31691234 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -165,8 +165,18 @@ UniValue gettransactionsmany(const UniValue& params, bool fHelp, const CPubKey& CTransaction tx; uint256 hashBlock; - if (myGetTransaction(txid, tx, hashBlock) && !hashBlock.IsNull()) - txns.push_back(HexStr(E_MARSHAL(ss << tx))); + if (myGetTransaction(txid, tx, hashBlock) && !hashBlock.IsNull()) { + UniValue elem(UniValue::VOBJ); + elem.pushKV("tx", HexStr(E_MARSHAL(ss << tx))); + + LOCK(cs_main); + CBlockIndex *pindex = komodo_getblockindex(hashBlock); + if (pindex) { + CNetworkBlockHeader nethdr = pindex->GetBlockHeader(); + elem.pushKV("block", HexStr(E_MARSHAL(ss << nethdr))); + } + txns.push_back(elem); + } else notloaded.push_back(txid.GetHex()); } From 7b31fdfdd7fae24b856400e5dbbc12526136c669 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 24 Sep 2021 19:09:16 +0500 Subject: [PATCH 125/348] added height hash to gettransactionsmany --- src/rpc/ccutilsrpc.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index 72d31691234..0abc20e54ff 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -173,7 +173,9 @@ UniValue gettransactionsmany(const UniValue& params, bool fHelp, const CPubKey& CBlockIndex *pindex = komodo_getblockindex(hashBlock); if (pindex) { CNetworkBlockHeader nethdr = pindex->GetBlockHeader(); - elem.pushKV("block", HexStr(E_MARSHAL(ss << nethdr))); + elem.pushKV("blockHeader", HexStr(E_MARSHAL(ss << nethdr))); + elem.pushKV("blockHeight", pindex->GetHeight()); + elem.pushKV("blockHash", hashBlock.GetHex()); } txns.push_back(elem); } From e749119b1dc8e52e77b2e62ff93825108972ac31 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 1 Oct 2021 14:15:25 +0500 Subject: [PATCH 126/348] added cryptocondition destination type with address prefixed by 'C' --- src/base58.cpp | 14 ++++++++++++++ src/base58.h | 2 ++ src/chainparams.cpp | 11 +++++++++-- src/chainparams.h | 1 + src/key_io.cpp | 15 +++++++++++++++ src/rpc/misc.cpp | 2 ++ src/script/standard.cpp | 6 +++++- src/script/standard.h | 10 +++++++++- src/wallet/wallet.cpp | 2 ++ 9 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index 383666d826b..39d64a75640 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -230,6 +230,7 @@ class CBitcoinAddressVisitor : public boost::static_visitor bool operator()(const CKeyID& id) const { return addr->Set(id); } bool operator()(const CPubKey& key) const { return addr->Set(key); } bool operator()(const CScriptID& id) const { return addr->Set(id); } + bool operator()(const CCryptoConditionID& id) const { return addr->Set(id); } bool operator()(const CNoDestination& no) const { return false; } }; @@ -254,6 +255,12 @@ bool CBitcoinAddress::Set(const CScriptID& id) return true; } +bool CBitcoinAddress::Set(const CCryptoConditionID& id) +{ + SetData(Params().Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS), &id, 20); + return true; +} + bool CBitcoinAddress::Set(const CTxDestination& dest) { return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); @@ -355,6 +362,13 @@ bool CCustomBitcoinAddress::Set(const CScriptID& id) return true; } +bool CCustomBitcoinAddress::Set(const CCryptoConditionID& id) +{ + SetData(base58Prefixes[0], &id, 20); // dimxy: CCryptoConditionID is actually CKeyID so we use base58Prefixes[0] as only two prefixes are supported in CCustomBitcoinAddress. + // TODO: check how it would work in gateways and importgateways + return true; +} + bool CCustomBitcoinAddress::Set(const CTxDestination& dest) { return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); diff --git a/src/base58.h b/src/base58.h index 8be0247e08f..a86b689d0e7 100644 --- a/src/base58.h +++ b/src/base58.h @@ -133,6 +133,7 @@ class CBitcoinAddress : public CBase58Data { virtual bool Set(const CKeyID &id); virtual bool Set(const CPubKey &key); virtual bool Set(const CScriptID &id); + virtual bool Set(const CCryptoConditionID &id); bool Set(const CTxDestination &dest); bool IsValid() const; bool IsValid(const CChainParams ¶ms) const; @@ -158,6 +159,7 @@ class CCustomBitcoinAddress : public CBitcoinAddress { bool Set(const CPubKey &key); bool Set(const CScriptID &id); bool Set(const CTxDestination &dest); + bool Set(const CCryptoConditionID &id); bool IsValid() const; CCustomBitcoinAddress() {} diff --git a/src/chainparams.cpp b/src/chainparams.cpp index fcae87cb6c4..fb2b3399f66 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -182,12 +182,13 @@ class CMainParams : public CChainParams { assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); vFixedSeeds.clear(); vSeeds.clear(); - vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); // Static contolled seeds list (Kolo) - vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); // Active seeds crawler (Kolo) + //vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); // Static contolled seeds list (Kolo) + //vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); // Active seeds crawler (Kolo) // TODO: we need more seed crawlers from other community members base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,60); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,85); base58Prefixes[SECRET_KEY] = std::vector(1,188); + base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container >(); // guarantees the first two characters, when base58 encoded, are "zc" @@ -197,6 +198,8 @@ class CMainParams : public CChainParams { // guarantees the first two characters, when base58 encoded, are "SK" base58Prefixes[ZCSPENDING_KEY] = {171,54}; + base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); + bech32HRPs[SAPLING_PAYMENT_ADDRESS] = "zs"; bech32HRPs[SAPLING_FULL_VIEWING_KEY] = "zviews"; bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivks"; @@ -307,6 +310,8 @@ class CTestNetParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,0); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,5); base58Prefixes[SECRET_KEY] = std::vector(1,128); + base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); + base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); base58Prefixes[ZCPAYMENT_ADDRRESS] = {20,81}; @@ -428,6 +433,8 @@ class CRegTestParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,60); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,85); base58Prefixes[SECRET_KEY] = std::vector(1,188); + base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); + //base58Prefixes[PUBKEY_ADDRESS] = {0x1D,0x25}; //base58Prefixes[SCRIPT_ADDRESS] = {0x1C,0xBA}; //base58Prefixes[SECRET_KEY] = {0xEF}; diff --git a/src/chainparams.h b/src/chainparams.h index daa16af8c40..23916b7ef17 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -63,6 +63,7 @@ class CChainParams ZCPAYMENT_ADDRRESS, ZCSPENDING_KEY, ZCVIEWING_KEY, + CRYPTOCONDITION_ADDRESS, MAX_BASE58_TYPES }; diff --git a/src/key_io.cpp b/src/key_io.cpp index dd4176fee12..7c515add247 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -49,6 +49,13 @@ class DestinationEncoder : public boost::static_visitor return EncodeBase58Check(data); } + std::string operator()(const CCryptoConditionID& id) const + { + std::vector data = m_params.Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS); + data.insert(data.end(), id.begin(), id.end()); + return EncodeBase58Check(data); + } + std::string operator()(const CNoDestination& no) const { return {}; } }; @@ -72,6 +79,14 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin()); return CScriptID(hash); } + + // added cc addresses decode: + const std::vector& cc_prefix = params.Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS); + if (data.size() == hash.size() + cc_prefix.size() && std::equal(cc_prefix.begin(), cc_prefix.end(), data.begin())) { + std::copy(data.begin() + cc_prefix.size(), data.end(), hash.begin()); + return CCryptoConditionID(hash); + } + } return CNoDestination(); } diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 1235f46eed0..e8b09089bb3 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -389,6 +389,8 @@ class DescribeAddressVisitor : public boost::static_visitor } return obj; } + + UniValue operator()(const CCryptoConditionID &ccID) const { return UniValue(UniValue::VOBJ); } // cryptoconditions are not recognised in the wallet yet }; #endif diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 290fb2ee7fa..f240dde79d8 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -385,7 +385,7 @@ bool ExtractDestination(const CScript& _scriptPubKey, CTxDestination& addressRet else if (IsCryptoConditionsEnabled() != 0 && whichType == TX_CRYPTOCONDITION) { - addressRet = CKeyID(uint160(vSolutions[0])); + addressRet = CCryptoConditionID(uint160(vSolutions[0])); return true; } // Multisig txns have more than one address... @@ -500,6 +500,10 @@ class CScriptVisitor : public boost::static_visitor *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL; return true; } + bool operator()(const CCryptoConditionID &dest) const { + script->clear(); + return false; // can't create a cc that simple + } }; } diff --git a/src/script/standard.h b/src/script/standard.h index 912c575d993..a3c0a995d8f 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -40,6 +40,14 @@ class CScriptID : public uint160 CScriptID(const uint160& in) : uint160(in) {} }; +class CCryptoConditionID : public uint160 +{ +public: + CCryptoConditionID() : uint160() {} + explicit CCryptoConditionID(const CCryptoConditionID& in) : uint160(Hash160(in.begin(), in.end())) {} + CCryptoConditionID(const uint160& in) : uint160(in) {} +}; + static const unsigned int MAX_OP_RETURN_RELAY = 8192; //! bytes extern unsigned nMaxDatacarrierBytes; @@ -96,7 +104,7 @@ class CNoDestination { * * CScriptID: TX_SCRIPTHASH destination * A CTxDestination is the internal data type encoded in a bitcoin address */ -typedef boost::variant CTxDestination; +typedef boost::variant CTxDestination; class COptCCParams { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index daee7ef67ef..b98cdac42b8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4825,6 +4825,8 @@ class CAffectedKeysVisitor : public boost::static_visitor { Process(script); } + void operator()(const CCryptoConditionID &none) {} // no cc in the wallet + void operator()(const CNoDestination &none) {} }; From f6c6808091ccc8da82d4105112de91e1a7223baa Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 1 Oct 2021 14:16:47 +0500 Subject: [PATCH 127/348] added initialisation of CCcontract_info with C-prefixed global addresses --- src/cc/CCcustom.cpp | 165 ++++++++++++++++++++++---------------------- src/cc/CCinclude.h | 2 +- 2 files changed, 85 insertions(+), 82 deletions(-) diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 9a460f96780..771ebd343ac 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -62,8 +62,8 @@ // Assets, aka Tokens #define FUNCNAME IsAssetsInput #define EVALCODE EVAL_ASSETS -const char *AssetsCCaddr = "RGKRjeTBw4LYFotSDLT6RWzMHbhXri6BG6"; -const char *AssetsNormaladdr = "RFYE2yL3KknWdHK6uNhvWacYsCUtwzjY3u"; +//const char *AssetsCCaddr = "RGKRjeTBw4LYFotSDLT6RWzMHbhXri6BG6"; +//const char *AssetsNormaladdr = "RFYE2yL3KknWdHK6uNhvWacYsCUtwzjY3u"; char AssetsCChexstr[67] = { "02adf84e0e075cf90868bd4e3d34a03420e034719649c41f371fc70d8e33aa2702" }; uint8_t AssetsCCpriv[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xba, 0x43, 0x83, 0x74, 0xf7, 0x63, 0x11, 0x3b, 0xf0, 0xf3, 0x50, 0x6f, 0xd9, 0x6b, 0x67, 0x85, 0xf9, 0x7a, 0xf0, 0x54, 0x4d, 0xb1, 0x30, 0x77 }; #include "CCcustom.inc" @@ -73,8 +73,8 @@ uint8_t AssetsCCpriv[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xb // Faucet #define FUNCNAME IsFaucetInput #define EVALCODE EVAL_FAUCET -const char *FaucetCCaddr = "R9zHrofhRbub7ER77B7NrVch3A63R39GuC"; -const char *FaucetNormaladdr = "RKQV4oYs4rvxAWx1J43VnT73rSTVtUeckk"; +//const char *FaucetCCaddr = "R9zHrofhRbub7ER77B7NrVch3A63R39GuC"; +//const char *FaucetNormaladdr = "RKQV4oYs4rvxAWx1J43VnT73rSTVtUeckk"; char FaucetCChexstr[67] = { "03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12" }; uint8_t FaucetCCpriv[32] = { 0xd4, 0x4f, 0xf2, 0x31, 0x71, 0x7d, 0x28, 0x02, 0x4b, 0xc7, 0xdd, 0x71, 0xa0, 0x39, 0xc4, 0xbe, 0x1a, 0xfe, 0xeb, 0xc2, 0x46, 0xda, 0x76, 0xf8, 0x07, 0x53, 0x3d, 0x96, 0xb4, 0xca, 0xa0, 0xe9 }; #include "CCcustom.inc" @@ -84,8 +84,8 @@ uint8_t FaucetCCpriv[32] = { 0xd4, 0x4f, 0xf2, 0x31, 0x71, 0x7d, 0x28, 0x02, 0x4 // Rewards #define FUNCNAME IsRewardsInput #define EVALCODE EVAL_REWARDS -const char *RewardsCCaddr = "RTsRBYL1HSvMoE3qtBJkyiswdVaWkm8YTK"; -const char *RewardsNormaladdr = "RMgye9jeczNjQx9Uzq8no8pTLiCSwuHwkz"; +//const char *RewardsCCaddr = "RTsRBYL1HSvMoE3qtBJkyiswdVaWkm8YTK"; +//const char *RewardsNormaladdr = "RMgye9jeczNjQx9Uzq8no8pTLiCSwuHwkz"; char RewardsCChexstr[67] = { "03da60379d924c2c30ac290d2a86c2ead128cb7bd571f69211cb95356e2dcc5eb9" }; uint8_t RewardsCCpriv[32] = { 0x82, 0xf5, 0xd2, 0xe7, 0xd6, 0x99, 0x33, 0x77, 0xfb, 0x80, 0x00, 0x97, 0x23, 0x3d, 0x1e, 0x6f, 0x61, 0xa9, 0xb5, 0x2e, 0x5e, 0xb4, 0x96, 0x6f, 0xbc, 0xed, 0x6b, 0xe2, 0xbb, 0x7b, 0x4b, 0xb3 }; #include "CCcustom.inc" @@ -95,8 +95,8 @@ uint8_t RewardsCCpriv[32] = { 0x82, 0xf5, 0xd2, 0xe7, 0xd6, 0x99, 0x33, 0x77, 0x // Dice #define FUNCNAME IsDiceInput #define EVALCODE EVAL_DICE -const char *DiceCCaddr = "REabWB7KjFN5C3LFMZ5odExHPenYzHLtVw"; -const char *DiceNormaladdr = "RLEe8f7Eg3TDuXii9BmNiiiaVGraHUt25c"; +//const char *DiceCCaddr = "REabWB7KjFN5C3LFMZ5odExHPenYzHLtVw"; +//const char *DiceNormaladdr = "RLEe8f7Eg3TDuXii9BmNiiiaVGraHUt25c"; char DiceCChexstr[67] = { "039d966927cfdadab3ee6c56da63c21f17ea753dde4b3dfd41487103e24b27e94e" }; uint8_t DiceCCpriv[32] = { 0x0e, 0xe8, 0xf5, 0xb4, 0x3d, 0x25, 0xcc, 0x35, 0xd1, 0xf1, 0x2f, 0x04, 0x5f, 0x01, 0x26, 0xb8, 0xd1, 0xac, 0x3a, 0x5a, 0xea, 0xe0, 0x25, 0xa2, 0x8f, 0x2a, 0x8e, 0x0e, 0xf9, 0x34, 0xfa, 0x77 }; #include "CCcustom.inc" @@ -106,8 +106,8 @@ uint8_t DiceCCpriv[32] = { 0x0e, 0xe8, 0xf5, 0xb4, 0x3d, 0x25, 0xcc, 0x35, 0xd1, // Lotto #define FUNCNAME IsLottoInput #define EVALCODE EVAL_LOTTO -const char *LottoCCaddr = "RNXZxgyWSAE6XS3qGnTaf5dVNCxnYzhPrg"; -const char *LottoNormaladdr = "RLW6hhRqBZZMBndnyPv29Yg3krh6iBYCyg"; +//const char *LottoCCaddr = "RNXZxgyWSAE6XS3qGnTaf5dVNCxnYzhPrg"; +//const char *LottoNormaladdr = "RLW6hhRqBZZMBndnyPv29Yg3krh6iBYCyg"; char LottoCChexstr[67] = { "03f72d2c4db440df1e706502b09ca5fec73ffe954ea1883e4049e98da68690d98f" }; uint8_t LottoCCpriv[32] = { 0xb4, 0xac, 0xc2, 0xd9, 0x67, 0x34, 0xd7, 0x58, 0x80, 0x4e, 0x25, 0x55, 0xc0, 0x50, 0x66, 0x84, 0xbb, 0xa2, 0xe7, 0xc0, 0x39, 0x17, 0xb4, 0xc5, 0x07, 0xb7, 0x3f, 0xca, 0x07, 0xb0, 0x9a, 0xeb }; #include "CCcustom.inc" @@ -117,8 +117,8 @@ uint8_t LottoCCpriv[32] = { 0xb4, 0xac, 0xc2, 0xd9, 0x67, 0x34, 0xd7, 0x58, 0x80 // Finite State Machine #define FUNCNAME IsFSMInput #define EVALCODE EVAL_FSM -const char *FSMCCaddr = "RUKTbLBeKgHkm3Ss4hKZP3ikuLW1xx7B2x"; -const char *FSMNormaladdr = "RWSHRbxnJYLvDjpcQ2i8MekgP6h2ctTKaj"; +//const char *FSMCCaddr = "RUKTbLBeKgHkm3Ss4hKZP3ikuLW1xx7B2x"; +//const char *FSMNormaladdr = "RWSHRbxnJYLvDjpcQ2i8MekgP6h2ctTKaj"; char FSMCChexstr[67] = { "039b52d294b413b07f3643c1a28c5467901a76562d8b39a785910ae0a0f3043810" }; uint8_t FSMCCpriv[32] = { 0x11, 0xe1, 0xea, 0x3e, 0xdb, 0x36, 0xf0, 0xa8, 0xc6, 0x34, 0xe1, 0x21, 0xb8, 0x02, 0xb9, 0x4b, 0x12, 0x37, 0x8f, 0xa0, 0x86, 0x23, 0x50, 0xb2, 0x5f, 0xe4, 0xe7, 0x36, 0x0f, 0xda, 0xae, 0xfc }; #include "CCcustom.inc" @@ -128,8 +128,8 @@ uint8_t FSMCCpriv[32] = { 0x11, 0xe1, 0xea, 0x3e, 0xdb, 0x36, 0xf0, 0xa8, 0xc6, // Auction #define FUNCNAME IsAuctionInput #define EVALCODE EVAL_AUCTION -const char *AuctionCCaddr = "RL4YPX7JYG3FnvoPqWF2pn3nQknH5NWEwx"; -const char *AuctionNormaladdr = "RFtVDNmdTZBTNZdmFRbfBgJ6LitgTghikL"; +//const char *AuctionCCaddr = "RL4YPX7JYG3FnvoPqWF2pn3nQknH5NWEwx"; +//const char *AuctionNormaladdr = "RFtVDNmdTZBTNZdmFRbfBgJ6LitgTghikL"; char AuctionCChexstr[67] = { "037eefe050c14cb60ae65d5b2f69eaa1c9006826d729bc0957bdc3024e3ca1dbe6" }; uint8_t AuctionCCpriv[32] = { 0x8c, 0x1b, 0xb7, 0x8c, 0x02, 0xa3, 0x9d, 0x21, 0x28, 0x59, 0xf5, 0xea, 0xda, 0xec, 0x0d, 0x11, 0xcd, 0x38, 0x47, 0xac, 0x0b, 0x6f, 0x19, 0xc0, 0x24, 0x36, 0xbf, 0x1c, 0x0a, 0x06, 0x31, 0xfb }; #include "CCcustom.inc" @@ -139,8 +139,8 @@ uint8_t AuctionCCpriv[32] = { 0x8c, 0x1b, 0xb7, 0x8c, 0x02, 0xa3, 0x9d, 0x21, 0x // Heir #define FUNCNAME IsHeirInput #define EVALCODE EVAL_HEIR -const char *HeirCCaddr = "RDVHcSekmXgeYBqRupNTmqo3Rn8QRXNduy"; -const char *HeirNormaladdr = "RTPwUjKYECcGn6Y4KYChLhgaht1RSU4jwf"; +//const char *HeirCCaddr = "RDVHcSekmXgeYBqRupNTmqo3Rn8QRXNduy"; +//const char *HeirNormaladdr = "RTPwUjKYECcGn6Y4KYChLhgaht1RSU4jwf"; char HeirCChexstr[67] = { "03c91bef3d7cc59c3a89286833a3446b29e52a5e773f738a1ad2b09785e5f4179e" }; uint8_t HeirCCpriv[32] = { 0x9d, 0xa1, 0xf8, 0xf7, 0xba, 0x0a, 0x91, 0x36, 0x89, 0x9a, 0x86, 0x30, 0x63, 0x20, 0xd7, 0xdf, 0xaa, 0x35, 0xe3, 0x99, 0x32, 0x2b, 0x63, 0xc0, 0x66, 0x9c, 0x93, 0xc4, 0x5e, 0x9d, 0xb9, 0xce }; #include "CCcustom.inc" @@ -150,8 +150,8 @@ uint8_t HeirCCpriv[32] = { 0x9d, 0xa1, 0xf8, 0xf7, 0xba, 0x0a, 0x91, 0x36, 0x89, // Channels #define FUNCNAME IsChannelsInput #define EVALCODE EVAL_CHANNELS -const char *ChannelsCCaddr = "RQy3rwX8sP9oDm3c39vGKA6H315cgtPLfr"; -const char *ChannelsNormaladdr = "RQUuT8zmkvDfXqECH4m3VD3SsHZAfnoh1v"; +//const char *ChannelsCCaddr = "RQy3rwX8sP9oDm3c39vGKA6H315cgtPLfr"; +//const char *ChannelsNormaladdr = "RQUuT8zmkvDfXqECH4m3VD3SsHZAfnoh1v"; char ChannelsCChexstr[67] = { "035debdb19b1c98c615259339500511d6216a3ffbeb28ff5655a7ef5790a12ab0b" }; uint8_t ChannelsCCpriv[32] = { 0xec, 0x91, 0x36, 0x15, 0x2d, 0xd4, 0x48, 0x73, 0x22, 0x36, 0x4f, 0x6a, 0x34, 0x5c, 0x61, 0x0f, 0x01, 0xb4, 0x79, 0xe8, 0x1c, 0x2f, 0xa1, 0x1d, 0x4a, 0x0a, 0x21, 0x16, 0xea, 0x82, 0x84, 0x60 }; #include "CCcustom.inc" @@ -161,8 +161,8 @@ uint8_t ChannelsCCpriv[32] = { 0xec, 0x91, 0x36, 0x15, 0x2d, 0xd4, 0x48, 0x73, 0 // Oracles #define FUNCNAME IsOraclesInput #define EVALCODE EVAL_ORACLES -const char *OraclesCCaddr = "REt2C4ZMnX8YYX1DRpffNA4hECZTFm39e3"; -const char *OraclesNormaladdr = "RHkFKzn1csxA3fWzAsxsLWohoCgBbirXb5"; +//const char *OraclesCCaddr = "REt2C4ZMnX8YYX1DRpffNA4hECZTFm39e3"; +//const char *OraclesNormaladdr = "RHkFKzn1csxA3fWzAsxsLWohoCgBbirXb5"; char OraclesCChexstr[67] = { "038c1d42db6a45a57eccb8981b078fb7857b9b496293fe299d2b8d120ac5b5691a" }; uint8_t OraclesCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0x89, 0xb1, 0xcb, 0xb9, 0xe6, 0x9c, 0x2c, 0x70, 0x85, 0x37, 0xdd, 0x00, 0x7a, 0x67, 0xff, 0x7c, 0x62, 0x1b, 0xe2, 0xfb, 0x04, 0x8f, 0x85, 0xbf }; #include "CCcustom.inc" @@ -172,8 +172,8 @@ uint8_t OraclesCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0x // Prices #define FUNCNAME IsPricesInput #define EVALCODE EVAL_PRICES -const char *PricesCCaddr = "RAL5Vh8NXmFqEKJRKrk1KjKaUckK7mM1iS"; -const char *PricesNormaladdr = "RBunXCsMHk5NPd6q8SQfmpgre3x133rSwZ"; +//const char *PricesCCaddr = "RAL5Vh8NXmFqEKJRKrk1KjKaUckK7mM1iS"; +//const char *PricesNormaladdr = "RBunXCsMHk5NPd6q8SQfmpgre3x133rSwZ"; char PricesCChexstr[67] = { "039894cb054c0032e99e65e715b03799607aa91212a16648d391b6fa2cc52ed0cf" }; uint8_t PricesCCpriv[32] = { 0x0a, 0x3b, 0xe7, 0x5d, 0xce, 0x06, 0xed, 0xb7, 0xc0, 0xb1, 0xbe, 0xe8, 0x7b, 0x5a, 0xd4, 0x99, 0xb8, 0x8d, 0xde, 0xac, 0xb2, 0x7e, 0x7a, 0x52, 0x96, 0x15, 0xd2, 0xa0, 0xc6, 0xb9, 0x89, 0x61 }; #include "CCcustom.inc" @@ -183,8 +183,8 @@ uint8_t PricesCCpriv[32] = { 0x0a, 0x3b, 0xe7, 0x5d, 0xce, 0x06, 0xed, 0xb7, 0xc // Pegs #define FUNCNAME IsPegsInput #define EVALCODE EVAL_PEGS -const char *PegsCCaddr = "RHnkVb7vHuHnjEjhkCF1bS6xxLLNZPv5fd"; -const char *PegsNormaladdr = "RMcCZtX6dHf1fz3gpLQhUEMQ8cVZ6Rzaro"; +//const char *PegsCCaddr = "RHnkVb7vHuHnjEjhkCF1bS6xxLLNZPv5fd"; +//const char *PegsNormaladdr = "RMcCZtX6dHf1fz3gpLQhUEMQ8cVZ6Rzaro"; char PegsCChexstr[67] = { "03c75c1de29a35e41606363b430c08be1c2dd93cf7a468229a082cc79c7b77eece" }; uint8_t PegsCCpriv[32] = { 0x52, 0x56, 0x4c, 0x78, 0x87, 0xf7, 0xa2, 0x39, 0xb0, 0x90, 0xb7, 0xb8, 0x62, 0x80, 0x0f, 0x83, 0x18, 0x9d, 0xf4, 0xf4, 0xbd, 0x28, 0x09, 0xa9, 0x9b, 0x85, 0x54, 0x16, 0x0f, 0x3f, 0xfb, 0x65 }; #include "CCcustom.inc" @@ -194,8 +194,8 @@ uint8_t PegsCCpriv[32] = { 0x52, 0x56, 0x4c, 0x78, 0x87, 0xf7, 0xa2, 0x39, 0xb0, // Marmara (reserved evalcode, the source moved to the marmara repo) #define FUNCNAME IsMarmaraInput #define EVALCODE EVAL_MARMARA -const char *MarmaraCCaddr = "RGLSRDnUqTB43bYtRtNVgmwSSd1sun2te8"; -const char *MarmaraNormaladdr = "RMN25Tn8NNzcyQDiQNuMp8UmwLMFd9thYc"; +//const char *MarmaraCCaddr = "RGLSRDnUqTB43bYtRtNVgmwSSd1sun2te8"; +//const char *MarmaraNormaladdr = "RMN25Tn8NNzcyQDiQNuMp8UmwLMFd9thYc"; char MarmaraCChexstr[67] = { "03afc5be570d0ff419425cfcc580cc762ab82baad88c148f5b028d7db7bfeee61d" }; uint8_t MarmaraCCpriv[32] = { 0x7c, 0x0b, 0x54, 0x9b, 0x65, 0xd4, 0x89, 0x57, 0xdf, 0x05, 0xfe, 0xa2, 0x62, 0x41, 0xa9, 0x09, 0x0f, 0x2a, 0x6b, 0x11, 0x2c, 0xbe, 0xbd, 0x06, 0x31, 0x8d, 0xc0, 0xb9, 0x96, 0x76, 0x3f, 0x24 }; #include "CCcustom.inc" @@ -205,8 +205,8 @@ uint8_t MarmaraCCpriv[32] = { 0x7c, 0x0b, 0x54, 0x9b, 0x65, 0xd4, 0x89, 0x57, 0x // Payments #define FUNCNAME IsPaymentsInput #define EVALCODE EVAL_PAYMENTS -const char *PaymentsCCaddr = "REpyKi7avsVduqZ3eimncK4uKqSArLTGGK"; -const char *PaymentsNormaladdr = "RHRX8RTMAh2STWe9DHqsvJbzS7ty6aZy3d"; +//const char *PaymentsCCaddr = "REpyKi7avsVduqZ3eimncK4uKqSArLTGGK"; +//const char *PaymentsNormaladdr = "RHRX8RTMAh2STWe9DHqsvJbzS7ty6aZy3d"; char PaymentsCChexstr[67] = { "0358f1764f82c63abc7c7455555fd1d3184905e30e819e97667e247e5792b46856" }; uint8_t PaymentsCCpriv[32] = { 0x03, 0xc9, 0x73, 0xc2, 0xb8, 0x30, 0x3d, 0xbd, 0xc8, 0xd9, 0xbf, 0x02, 0x49, 0xd9, 0x65, 0x61, 0x45, 0xed, 0x9e, 0x93, 0x51, 0xab, 0x8b, 0x2e, 0xe7, 0xc7, 0x40, 0xf1, 0xc4, 0xd2, 0xc0, 0x5b }; #include "CCcustom.inc" @@ -216,8 +216,8 @@ uint8_t PaymentsCCpriv[32] = { 0x03, 0xc9, 0x73, 0xc2, 0xb8, 0x30, 0x3d, 0xbd, 0 // Gateways #define FUNCNAME IsGatewaysInput #define EVALCODE EVAL_GATEWAYS -const char *GatewaysCCaddr = "RKWpoK6vTRtq5b9qrRBodLkCzeURHeEk33"; -const char *GatewaysNormaladdr = "RGJKV97ZN1wBfunuMt1tebiiHENNEq73Yh"; // wif UxJFYqEvLAjWPPRvn8NN1fRWscBxQZXZB5BBgc3HiapKVQBYNcmo +//const char *GatewaysCCaddr = "RKWpoK6vTRtq5b9qrRBodLkCzeURHeEk33"; +//const char *GatewaysNormaladdr = "RGJKV97ZN1wBfunuMt1tebiiHENNEq73Yh"; // wif UxJFYqEvLAjWPPRvn8NN1fRWscBxQZXZB5BBgc3HiapKVQBYNcmo char GatewaysCChexstr[67] = { "03ea9c062b9652d8eff34879b504eda0717895d27597aaeb60347d65eed96ccb40" }; uint8_t GatewaysCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0x89, 0xb1, 0xcb, 0xb9, 0xe6, 0x9c, 0x2c, 0x70, 0x85, 0x37, 0xdd, 0x00, 0x7a, 0x67, 0xff, 0x7c, 0x62, 0x1b, 0xe2, 0xfb, 0x04, 0x8f, 0x85, 0xbf }; #include "CCcustom.inc" @@ -227,8 +227,8 @@ uint8_t GatewaysCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0 // Tokens #define FUNCNAME IsTokensInput #define EVALCODE EVAL_TOKENS -const char *TokensCCaddr = "RAMvUfoyURBRxAdVeTMHxn3giJZCFWeha2"; -const char *TokensNormaladdr = "RCNgAngYAdrfzujYyPgfbjCGNVQZzCgTad"; +//const char *TokensCCaddr = "RAMvUfoyURBRxAdVeTMHxn3giJZCFWeha2"; +//const char *TokensNormaladdr = "RCNgAngYAdrfzujYyPgfbjCGNVQZzCgTad"; char TokensCChexstr[67] = { "03e6191c70c9c9a28f9fd87089b9488d0e6c02fb629df64979c9cdb6b2b4a68d95" }; uint8_t TokensCCpriv[32] = { 0x1d, 0x0d, 0x0d, 0xce, 0x2d, 0xd2, 0xe1, 0x9d, 0xf5, 0xb6, 0x26, 0xd5, 0xad, 0xa0, 0xf0, 0x0a, 0xdd, 0x7a, 0x72, 0x7d, 0x17, 0x35, 0xb5, 0xe3, 0x2c, 0x6c, 0xa9, 0xa2, 0x03, 0x16, 0x4b, 0xcf }; #include "CCcustom.inc" @@ -247,8 +247,8 @@ uint8_t CClibCCpriv[32] = { 0x57, 0xcf, 0x49, 0x71, 0x7d, 0xb4, 0x15, 0x1b, 0x4f // ImportGateway #define FUNCNAME IsImportGatewayInput #define EVALCODE EVAL_IMPORTGATEWAY -const char *ImportGatewayCCaddr = "RXJT6CRAXHFuQ2UjqdxMj7EfrayF6UJpzZ"; -const char *ImportGatewayNormaladdr = "RNFRho63Ddz1Rh2eGPETykrU4fA8r67S4Y"; +//const char *ImportGatewayCCaddr = "RXJT6CRAXHFuQ2UjqdxMj7EfrayF6UJpzZ"; +//const char *ImportGatewayNormaladdr = "RNFRho63Ddz1Rh2eGPETykrU4fA8r67S4Y"; char ImportGatewayCChexstr[67] = { "0397231cfe04ea32d5fafb2206773ec9fba6e15c5a4e86064468bca195f7542714" }; uint8_t ImportGatewayCCpriv[32] = { 0x65, 0xef, 0x27, 0xeb, 0x3d, 0xb0, 0xb4, 0xae, 0x0f, 0xbc, 0x77, 0xdb, 0xf8, 0x40, 0x48, 0x90, 0x52, 0x20, 0x9e, 0x45, 0x3b, 0x49, 0xd8, 0x97, 0x60, 0x8c, 0x27, 0x4c, 0x59, 0x46, 0xe1, 0xdf }; #include "CCcustom.inc" @@ -258,8 +258,8 @@ uint8_t ImportGatewayCCpriv[32] = { 0x65, 0xef, 0x27, 0xeb, 0x3d, 0xb0, 0xb4, 0x // Tokens v2 #define FUNCNAME IsTokensv2Input #define EVALCODE EVAL_TOKENSV2 -const char *Tokensv2CCaddr = "RSc4RycihBEWQP2GDvSYS46MvFJsTKaNVU"; -const char *Tokensv2Normaladdr = "RDVU97zvJamGmVBSUyTm7RcYZtxjriNGkj"; +//const char *Tokensv2CCaddr = "RSc4RycihBEWQP2GDvSYS46MvFJsTKaNVU"; +//const char *Tokensv2Normaladdr = "RDVU97zvJamGmVBSUyTm7RcYZtxjriNGkj"; char Tokensv2CChexstr[67] = { "032fd27f72591b02f13a7f9701246eb0296b2be7cfdad32c520e594844ec3d4801" }; uint8_t Tokensv2CCpriv[32] = { 0xb5, 0xba, 0x92, 0x7f, 0x53, 0x45, 0x4f, 0xf8, 0xa4, 0xad, 0x0d, 0x38, 0x30, 0x4f, 0xd0, 0x97, 0xd1, 0xb7, 0x94, 0x1b, 0x1f, 0x52, 0xbd, 0xae, 0xa2, 0xe7, 0x49, 0x06, 0x2e, 0xd2, 0x2d, 0xa5 }; #include "CCcustom.inc" @@ -269,8 +269,8 @@ uint8_t Tokensv2CCpriv[32] = { 0xb5, 0xba, 0x92, 0x7f, 0x53, 0x45, 0x4f, 0xf8, 0 // Assets v2 #define FUNCNAME IsAssetsv2Input #define EVALCODE EVAL_ASSETSV2 -const char *Assetsv2CCaddr = "RX99NCswvrLiM6vNE4zmpKKBWMZU9zqwAk"; -const char *Assetsv2Normaladdr = "RSB4NhRbvEShUFDkZz2KACj5EEBGDtDsV9"; +//const char *Assetsv2CCaddr = "RX99NCswvrLiM6vNE4zmpKKBWMZU9zqwAk"; +//const char *Assetsv2Normaladdr = "RSB4NhRbvEShUFDkZz2KACj5EEBGDtDsV9"; char Assetsv2CChexstr[67] = { "0345d2e7ab018619da6ed58ccc0138c5f58a7b754bd8e9a1a9d2b811c5fe72d467" }; uint8_t Assetsv2CCpriv[32] = { 0x46, 0x58, 0x3b, 0x18, 0xee, 0x16, 0x63, 0x51, 0x6f, 0x60, 0x6e, 0x09, 0xdf, 0x9d, 0x27, 0xc8, 0xa7, 0xa2, 0x72, 0xa5, 0xd4, 0x6a, 0x9b, 0xcb, 0xd5, 0x4f, 0x7d, 0x1c, 0xb1, 0x2e, 0x63, 0x21 }; #include "CCcustom.inc" @@ -333,118 +333,119 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) { // memset(cp, '\0', sizeof(*cp)); <-- it is not good to initialize objects like this. // special init func now used: - cp->init_to_zeros(); + cp->clear(); cp->evalcode = evalcode; + bool ismixed = false; switch ( evalcode ) { case EVAL_ASSETS: - strcpy(cp->unspendableCCaddr,AssetsCCaddr); - strcpy(cp->normaladdr,AssetsNormaladdr); + //strcpy(cp->unspendableCCaddr,AssetsCCaddr); + //strcpy(cp->normaladdr,AssetsNormaladdr); strcpy(cp->CChexstr,AssetsCChexstr); memcpy(cp->CCpriv,AssetsCCpriv,32); cp->validate = AssetsValidate; cp->ismyvin = IsAssetsInput; break; case EVAL_FAUCET: - strcpy(cp->unspendableCCaddr,FaucetCCaddr); - strcpy(cp->normaladdr,FaucetNormaladdr); + //strcpy(cp->unspendableCCaddr,FaucetCCaddr); + //strcpy(cp->normaladdr,FaucetNormaladdr); strcpy(cp->CChexstr,FaucetCChexstr); memcpy(cp->CCpriv,FaucetCCpriv,32); cp->validate = FaucetValidate; cp->ismyvin = IsFaucetInput; break; case EVAL_REWARDS: - strcpy(cp->unspendableCCaddr,RewardsCCaddr); - strcpy(cp->normaladdr,RewardsNormaladdr); + //strcpy(cp->unspendableCCaddr,RewardsCCaddr); + //strcpy(cp->normaladdr,RewardsNormaladdr); strcpy(cp->CChexstr,RewardsCChexstr); memcpy(cp->CCpriv,RewardsCCpriv,32); cp->validate = RewardsValidate; cp->ismyvin = IsRewardsInput; break; case EVAL_DICE: - strcpy(cp->unspendableCCaddr,DiceCCaddr); - strcpy(cp->normaladdr,DiceNormaladdr); + //strcpy(cp->unspendableCCaddr,DiceCCaddr); + //strcpy(cp->normaladdr,DiceNormaladdr); strcpy(cp->CChexstr,DiceCChexstr); memcpy(cp->CCpriv,DiceCCpriv,32); cp->validate = DiceValidate; cp->ismyvin = IsDiceInput; break; case EVAL_LOTTO: - strcpy(cp->unspendableCCaddr,LottoCCaddr); - strcpy(cp->normaladdr,LottoNormaladdr); + //strcpy(cp->unspendableCCaddr,LottoCCaddr); + //strcpy(cp->normaladdr,LottoNormaladdr); strcpy(cp->CChexstr,LottoCChexstr); memcpy(cp->CCpriv,LottoCCpriv,32); cp->validate = LottoValidate; cp->ismyvin = IsLottoInput; break; case EVAL_FSM: - strcpy(cp->unspendableCCaddr,FSMCCaddr); - strcpy(cp->normaladdr,FSMNormaladdr); + //strcpy(cp->unspendableCCaddr,FSMCCaddr); + //strcpy(cp->normaladdr,FSMNormaladdr); strcpy(cp->CChexstr,FSMCChexstr); memcpy(cp->CCpriv,FSMCCpriv,32); cp->validate = FSMValidate; cp->ismyvin = IsFSMInput; break; case EVAL_AUCTION: - strcpy(cp->unspendableCCaddr,AuctionCCaddr); - strcpy(cp->normaladdr,AuctionNormaladdr); + //strcpy(cp->unspendableCCaddr,AuctionCCaddr); + //strcpy(cp->normaladdr,AuctionNormaladdr); strcpy(cp->CChexstr,AuctionCChexstr); memcpy(cp->CCpriv,AuctionCCpriv,32); cp->validate = AuctionValidate; cp->ismyvin = IsAuctionInput; break; case EVAL_HEIR: - strcpy(cp->unspendableCCaddr,HeirCCaddr); - strcpy(cp->normaladdr,HeirNormaladdr); + //strcpy(cp->unspendableCCaddr,HeirCCaddr); + //strcpy(cp->normaladdr,HeirNormaladdr); strcpy(cp->CChexstr,HeirCChexstr); memcpy(cp->CCpriv,HeirCCpriv,32); cp->validate = HeirValidate; cp->ismyvin = IsHeirInput; break; case EVAL_CHANNELS: - strcpy(cp->unspendableCCaddr,ChannelsCCaddr); - strcpy(cp->normaladdr,ChannelsNormaladdr); + //strcpy(cp->unspendableCCaddr,ChannelsCCaddr); + //strcpy(cp->normaladdr,ChannelsNormaladdr); strcpy(cp->CChexstr,ChannelsCChexstr); memcpy(cp->CCpriv,ChannelsCCpriv,32); cp->validate = ChannelsValidate; cp->ismyvin = IsChannelsInput; break; case EVAL_ORACLES: - strcpy(cp->unspendableCCaddr,OraclesCCaddr); - strcpy(cp->normaladdr,OraclesNormaladdr); + //strcpy(cp->unspendableCCaddr,OraclesCCaddr); + //strcpy(cp->normaladdr,OraclesNormaladdr); strcpy(cp->CChexstr,OraclesCChexstr); memcpy(cp->CCpriv,OraclesCCpriv,32); cp->validate = OraclesValidate; cp->ismyvin = IsOraclesInput; break; case EVAL_PRICES: - strcpy(cp->unspendableCCaddr,PricesCCaddr); - strcpy(cp->normaladdr,PricesNormaladdr); + //strcpy(cp->unspendableCCaddr,PricesCCaddr); + //strcpy(cp->normaladdr,PricesNormaladdr); strcpy(cp->CChexstr,PricesCChexstr); memcpy(cp->CCpriv,PricesCCpriv,32); cp->validate = PricesValidate; cp->ismyvin = IsPricesInput; break; case EVAL_PEGS: - strcpy(cp->unspendableCCaddr,PegsCCaddr); - strcpy(cp->normaladdr,PegsNormaladdr); + //strcpy(cp->unspendableCCaddr,PegsCCaddr); + //strcpy(cp->normaladdr,PegsNormaladdr); strcpy(cp->CChexstr,PegsCChexstr); memcpy(cp->CCpriv,PegsCCpriv,32); cp->validate = PegsValidate; cp->ismyvin = IsPegsInput; break; case EVAL_PAYMENTS: - strcpy(cp->unspendableCCaddr,PaymentsCCaddr); - strcpy(cp->normaladdr,PaymentsNormaladdr); + //strcpy(cp->unspendableCCaddr,PaymentsCCaddr); + //strcpy(cp->normaladdr,PaymentsNormaladdr); strcpy(cp->CChexstr,PaymentsCChexstr); memcpy(cp->CCpriv,PaymentsCCpriv,32); cp->validate = PaymentsValidate; cp->ismyvin = IsPaymentsInput; break; case EVAL_GATEWAYS: - strcpy(cp->unspendableCCaddr,GatewaysCCaddr); - strcpy(cp->normaladdr,GatewaysNormaladdr); + //strcpy(cp->unspendableCCaddr,GatewaysCCaddr); + //strcpy(cp->normaladdr,GatewaysNormaladdr); strcpy(cp->CChexstr,GatewaysCChexstr); memcpy(cp->CCpriv,GatewaysCCpriv,32); cp->validate = GatewaysValidate; @@ -452,16 +453,16 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) break; case EVAL_TOKENS: - strcpy(cp->unspendableCCaddr, TokensCCaddr); - strcpy(cp->normaladdr, TokensNormaladdr); + //strcpy(cp->unspendableCCaddr, TokensCCaddr); + //strcpy(cp->normaladdr, TokensNormaladdr); strcpy(cp->CChexstr, TokensCChexstr); memcpy(cp->CCpriv, TokensCCpriv, 32); cp->validate = TokensValidate; cp->ismyvin = IsTokensInput; break; case EVAL_IMPORTGATEWAY: - strcpy(cp->unspendableCCaddr, ImportGatewayCCaddr); - strcpy(cp->normaladdr, ImportGatewayNormaladdr); + //strcpy(cp->unspendableCCaddr, ImportGatewayCCaddr); + //strcpy(cp->normaladdr, ImportGatewayNormaladdr); strcpy(cp->CChexstr, ImportGatewayCChexstr); memcpy(cp->CCpriv, ImportGatewayCCpriv, 32); cp->validate = ImportGatewayValidate; @@ -469,32 +470,34 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) break; case EVAL_TOKENSV2: - strcpy(cp->unspendableCCaddr, Tokensv2CCaddr); - strcpy(cp->normaladdr, Tokensv2Normaladdr); + //strcpy(cp->unspendableCCaddr, Tokensv2CCaddr); + //strcpy(cp->normaladdr, Tokensv2Normaladdr); strcpy(cp->CChexstr, Tokensv2CChexstr); memcpy(cp->CCpriv, Tokensv2CCpriv, 32); cp->validate = Tokensv2Validate; cp->ismyvin = IsTokensv2Input; + ismixed = true; break; case EVAL_ASSETSV2: - strcpy(cp->unspendableCCaddr,Assetsv2CCaddr); - strcpy(cp->normaladdr,Assetsv2Normaladdr); + //strcpy(cp->unspendableCCaddr,Assetsv2CCaddr); + //strcpy(cp->normaladdr,Assetsv2Normaladdr); strcpy(cp->CChexstr,Assetsv2CChexstr); memcpy(cp->CCpriv,Assetsv2CCpriv,32); cp->validate = Assetsv2Validate; cp->ismyvin = IsAssetsv2Input; - break; - - case EVAL_TOKELDATA: - cp->validate = TokelDataValidate; - cp->ismyvin = IsTokelDataInput; + ismixed = true; break; default: - if ( CClib_initcp(cp,evalcode) < 0 ) + if (CClib_initcp(cp, evalcode) < 0) return(0); break; } + // init addresses now here: + if (cp->CChexstr[0]) { + _GetCCaddress(cp->unspendableCCaddr, cp->evalcode, pubkey2pk(ParseHex(cp->CChexstr)), ismixed); + Getscriptaddress(cp->normaladdr, CScript() << ParseHex(cp->CChexstr) << OP_CHECKSIG); + } return(cp); } diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index f2debae24e5..7ad52153821 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -291,7 +291,7 @@ struct CCcontract_info std::vector< struct CCVintxProbe > CCvintxprobes; // Date: Fri, 1 Oct 2021 14:17:22 +0500 Subject: [PATCH 128/348] tokenv2indexkey added, tokenv2address not supported --- src/rpc/tokensrpc.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 0ee1178b0ca..fa032bf839f 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -61,11 +61,33 @@ UniValue tokenaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) return CCaddress(cp, "Tokens", pubkey, false); } +UniValue tokenv2indexkey(const UniValue& params, bool fHelp, const CPubKey& mypk) +{ + struct CCcontract_info *cp,C; + vuint8_t vpubkey; + + cp = CCinit(&C, EVAL_TOKENSV2); + if (fHelp || params.size() != 1) + throw runtime_error("tokenv2address pubkey\n"); + if (ensure_CCrequirements(cp->evalcode) < 0) + throw runtime_error(CC_REQUIREMENTS_MSG); + vpubkey = ParseHex(params[0].get_str().c_str()); + CPubKey pk = pubkey2pk(vpubkey); + if (!pk.IsValid()) + throw runtime_error("invalid pubkey\n"); + + char address[KOMODO_ADDRESS_BUFSIZE]; + GetCCaddress(cp, address, pk, true); + + return address; +} + UniValue tokenv2address(const UniValue& params, bool fHelp, const CPubKey& mypk) { struct CCcontract_info *cp,C; vuint8_t pubkey; + throw runtime_error("tokenv2address not supported, use tokenv2indexkey\n"); cp = CCinit(&C, EVAL_TOKENSV2); if (fHelp || params.size() > 1) throw runtime_error("tokenv2address [pubkey]\n"); @@ -1121,6 +1143,7 @@ static const CRPCCommand commands[] = { "tokens v2", "mytokenv2orders", &mytokenv2orders, true }, { "tokens", "tokenaddress", &tokenaddress, true }, { "tokens v2", "tokenv2address", &tokenv2address, true }, + { "tokens v2", "tokenv2indexkey", &tokenv2indexkey, true }, { "tokens", "tokenbalance", &tokenbalance, true }, { "tokens v2", "tokenv2balance", &tokenv2balance, true }, { "tokens", "tokencreate", &tokencreate, true }, From c12d328c62c17edcf6b1b2e48cda6bcdb4c7bc39 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 1 Oct 2021 14:17:49 +0500 Subject: [PATCH 129/348] disabled zcash seeds --- src/chainparamsseeds.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index e3dac3ca641..4a6a2248632 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -23,12 +23,15 @@ * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly. */ static SeedSpec6 pnSeed6_main[] = { - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27487}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27487}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27487} +/** + * no need in zcash seeds: + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27485}, + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27487}, + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27485}, + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27487}, + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27485}, + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27487} + */ }; static SeedSpec6 pnSeed6_test[] = { From 96f4a2d99a6b3f989fb73d9a6a979fe625a194b1 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 2 Oct 2021 15:21:05 +0500 Subject: [PATCH 130/348] fixed CCryptoConditionID removed extra constructor, fixed usage in CBitcoinAddress: Get GetIndexKey IsValid funcs --- src/base58.cpp | 10 ++++++++-- src/script/standard.h | 1 - 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index 39d64a75640..58e3fbb3847 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -275,7 +275,8 @@ bool CBitcoinAddress::IsValid(const CChainParams& params) const { bool fCorrectSize = vchData.size() == 20; bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) || - vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); + vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS) || + vchVersion == params.Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS); return fCorrectSize && fKnownVersion; } @@ -299,6 +300,8 @@ CTxDestination CBitcoinAddress::Get() const return CKeyID(id); else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) return CScriptID(id); + else if (vchVersion == Params().Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS)) + return CCryptoConditionID(id); else return CNoDestination(); } @@ -315,8 +318,11 @@ bool CBitcoinAddress::GetIndexKey(uint160& hashBytes, int& type, bool ccflag) co memcpy(&hashBytes, &vchData[0], 20); type = 2; return true; + } else if (vchVersion == Params().Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS)) { + memcpy(&hashBytes, &vchData[0], 20); + type = 3; + return true; } - return false; } diff --git a/src/script/standard.h b/src/script/standard.h index a3c0a995d8f..d9c8f512d11 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -44,7 +44,6 @@ class CCryptoConditionID : public uint160 { public: CCryptoConditionID() : uint160() {} - explicit CCryptoConditionID(const CCryptoConditionID& in) : uint160(Hash160(in.begin(), in.end())) {} CCryptoConditionID(const uint160& in) : uint160(in) {} }; From 2c5a1c3741bc6e6eac16e09067905c669d66c019 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 2 Oct 2021 15:22:53 +0500 Subject: [PATCH 131/348] removed unused global addresses in CCcustom.cpp --- src/cc/CCcustom.cpp | 81 ++------------------------------------------- 1 file changed, 2 insertions(+), 79 deletions(-) diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 771ebd343ac..2e6a1eb4eef 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -59,11 +59,9 @@ // to create a new CCaddr, add to rpcwallet the CCaddress and start with -pubkey= with the pubkey of the new address, with its wif already imported. set normaladdr and CChexstr. run CCaddress and it will print the privkey along with autocorrect the CCaddress. which should then update the CCaddr here -// Assets, aka Tokens +// Assets #define FUNCNAME IsAssetsInput #define EVALCODE EVAL_ASSETS -//const char *AssetsCCaddr = "RGKRjeTBw4LYFotSDLT6RWzMHbhXri6BG6"; -//const char *AssetsNormaladdr = "RFYE2yL3KknWdHK6uNhvWacYsCUtwzjY3u"; char AssetsCChexstr[67] = { "02adf84e0e075cf90868bd4e3d34a03420e034719649c41f371fc70d8e33aa2702" }; uint8_t AssetsCCpriv[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xba, 0x43, 0x83, 0x74, 0xf7, 0x63, 0x11, 0x3b, 0xf0, 0xf3, 0x50, 0x6f, 0xd9, 0x6b, 0x67, 0x85, 0xf9, 0x7a, 0xf0, 0x54, 0x4d, 0xb1, 0x30, 0x77 }; #include "CCcustom.inc" @@ -73,8 +71,6 @@ uint8_t AssetsCCpriv[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xb // Faucet #define FUNCNAME IsFaucetInput #define EVALCODE EVAL_FAUCET -//const char *FaucetCCaddr = "R9zHrofhRbub7ER77B7NrVch3A63R39GuC"; -//const char *FaucetNormaladdr = "RKQV4oYs4rvxAWx1J43VnT73rSTVtUeckk"; char FaucetCChexstr[67] = { "03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12" }; uint8_t FaucetCCpriv[32] = { 0xd4, 0x4f, 0xf2, 0x31, 0x71, 0x7d, 0x28, 0x02, 0x4b, 0xc7, 0xdd, 0x71, 0xa0, 0x39, 0xc4, 0xbe, 0x1a, 0xfe, 0xeb, 0xc2, 0x46, 0xda, 0x76, 0xf8, 0x07, 0x53, 0x3d, 0x96, 0xb4, 0xca, 0xa0, 0xe9 }; #include "CCcustom.inc" @@ -84,8 +80,6 @@ uint8_t FaucetCCpriv[32] = { 0xd4, 0x4f, 0xf2, 0x31, 0x71, 0x7d, 0x28, 0x02, 0x4 // Rewards #define FUNCNAME IsRewardsInput #define EVALCODE EVAL_REWARDS -//const char *RewardsCCaddr = "RTsRBYL1HSvMoE3qtBJkyiswdVaWkm8YTK"; -//const char *RewardsNormaladdr = "RMgye9jeczNjQx9Uzq8no8pTLiCSwuHwkz"; char RewardsCChexstr[67] = { "03da60379d924c2c30ac290d2a86c2ead128cb7bd571f69211cb95356e2dcc5eb9" }; uint8_t RewardsCCpriv[32] = { 0x82, 0xf5, 0xd2, 0xe7, 0xd6, 0x99, 0x33, 0x77, 0xfb, 0x80, 0x00, 0x97, 0x23, 0x3d, 0x1e, 0x6f, 0x61, 0xa9, 0xb5, 0x2e, 0x5e, 0xb4, 0x96, 0x6f, 0xbc, 0xed, 0x6b, 0xe2, 0xbb, 0x7b, 0x4b, 0xb3 }; #include "CCcustom.inc" @@ -95,8 +89,6 @@ uint8_t RewardsCCpriv[32] = { 0x82, 0xf5, 0xd2, 0xe7, 0xd6, 0x99, 0x33, 0x77, 0x // Dice #define FUNCNAME IsDiceInput #define EVALCODE EVAL_DICE -//const char *DiceCCaddr = "REabWB7KjFN5C3LFMZ5odExHPenYzHLtVw"; -//const char *DiceNormaladdr = "RLEe8f7Eg3TDuXii9BmNiiiaVGraHUt25c"; char DiceCChexstr[67] = { "039d966927cfdadab3ee6c56da63c21f17ea753dde4b3dfd41487103e24b27e94e" }; uint8_t DiceCCpriv[32] = { 0x0e, 0xe8, 0xf5, 0xb4, 0x3d, 0x25, 0xcc, 0x35, 0xd1, 0xf1, 0x2f, 0x04, 0x5f, 0x01, 0x26, 0xb8, 0xd1, 0xac, 0x3a, 0x5a, 0xea, 0xe0, 0x25, 0xa2, 0x8f, 0x2a, 0x8e, 0x0e, 0xf9, 0x34, 0xfa, 0x77 }; #include "CCcustom.inc" @@ -106,8 +98,6 @@ uint8_t DiceCCpriv[32] = { 0x0e, 0xe8, 0xf5, 0xb4, 0x3d, 0x25, 0xcc, 0x35, 0xd1, // Lotto #define FUNCNAME IsLottoInput #define EVALCODE EVAL_LOTTO -//const char *LottoCCaddr = "RNXZxgyWSAE6XS3qGnTaf5dVNCxnYzhPrg"; -//const char *LottoNormaladdr = "RLW6hhRqBZZMBndnyPv29Yg3krh6iBYCyg"; char LottoCChexstr[67] = { "03f72d2c4db440df1e706502b09ca5fec73ffe954ea1883e4049e98da68690d98f" }; uint8_t LottoCCpriv[32] = { 0xb4, 0xac, 0xc2, 0xd9, 0x67, 0x34, 0xd7, 0x58, 0x80, 0x4e, 0x25, 0x55, 0xc0, 0x50, 0x66, 0x84, 0xbb, 0xa2, 0xe7, 0xc0, 0x39, 0x17, 0xb4, 0xc5, 0x07, 0xb7, 0x3f, 0xca, 0x07, 0xb0, 0x9a, 0xeb }; #include "CCcustom.inc" @@ -117,8 +107,6 @@ uint8_t LottoCCpriv[32] = { 0xb4, 0xac, 0xc2, 0xd9, 0x67, 0x34, 0xd7, 0x58, 0x80 // Finite State Machine #define FUNCNAME IsFSMInput #define EVALCODE EVAL_FSM -//const char *FSMCCaddr = "RUKTbLBeKgHkm3Ss4hKZP3ikuLW1xx7B2x"; -//const char *FSMNormaladdr = "RWSHRbxnJYLvDjpcQ2i8MekgP6h2ctTKaj"; char FSMCChexstr[67] = { "039b52d294b413b07f3643c1a28c5467901a76562d8b39a785910ae0a0f3043810" }; uint8_t FSMCCpriv[32] = { 0x11, 0xe1, 0xea, 0x3e, 0xdb, 0x36, 0xf0, 0xa8, 0xc6, 0x34, 0xe1, 0x21, 0xb8, 0x02, 0xb9, 0x4b, 0x12, 0x37, 0x8f, 0xa0, 0x86, 0x23, 0x50, 0xb2, 0x5f, 0xe4, 0xe7, 0x36, 0x0f, 0xda, 0xae, 0xfc }; #include "CCcustom.inc" @@ -128,8 +116,6 @@ uint8_t FSMCCpriv[32] = { 0x11, 0xe1, 0xea, 0x3e, 0xdb, 0x36, 0xf0, 0xa8, 0xc6, // Auction #define FUNCNAME IsAuctionInput #define EVALCODE EVAL_AUCTION -//const char *AuctionCCaddr = "RL4YPX7JYG3FnvoPqWF2pn3nQknH5NWEwx"; -//const char *AuctionNormaladdr = "RFtVDNmdTZBTNZdmFRbfBgJ6LitgTghikL"; char AuctionCChexstr[67] = { "037eefe050c14cb60ae65d5b2f69eaa1c9006826d729bc0957bdc3024e3ca1dbe6" }; uint8_t AuctionCCpriv[32] = { 0x8c, 0x1b, 0xb7, 0x8c, 0x02, 0xa3, 0x9d, 0x21, 0x28, 0x59, 0xf5, 0xea, 0xda, 0xec, 0x0d, 0x11, 0xcd, 0x38, 0x47, 0xac, 0x0b, 0x6f, 0x19, 0xc0, 0x24, 0x36, 0xbf, 0x1c, 0x0a, 0x06, 0x31, 0xfb }; #include "CCcustom.inc" @@ -139,8 +125,6 @@ uint8_t AuctionCCpriv[32] = { 0x8c, 0x1b, 0xb7, 0x8c, 0x02, 0xa3, 0x9d, 0x21, 0x // Heir #define FUNCNAME IsHeirInput #define EVALCODE EVAL_HEIR -//const char *HeirCCaddr = "RDVHcSekmXgeYBqRupNTmqo3Rn8QRXNduy"; -//const char *HeirNormaladdr = "RTPwUjKYECcGn6Y4KYChLhgaht1RSU4jwf"; char HeirCChexstr[67] = { "03c91bef3d7cc59c3a89286833a3446b29e52a5e773f738a1ad2b09785e5f4179e" }; uint8_t HeirCCpriv[32] = { 0x9d, 0xa1, 0xf8, 0xf7, 0xba, 0x0a, 0x91, 0x36, 0x89, 0x9a, 0x86, 0x30, 0x63, 0x20, 0xd7, 0xdf, 0xaa, 0x35, 0xe3, 0x99, 0x32, 0x2b, 0x63, 0xc0, 0x66, 0x9c, 0x93, 0xc4, 0x5e, 0x9d, 0xb9, 0xce }; #include "CCcustom.inc" @@ -150,8 +134,6 @@ uint8_t HeirCCpriv[32] = { 0x9d, 0xa1, 0xf8, 0xf7, 0xba, 0x0a, 0x91, 0x36, 0x89, // Channels #define FUNCNAME IsChannelsInput #define EVALCODE EVAL_CHANNELS -//const char *ChannelsCCaddr = "RQy3rwX8sP9oDm3c39vGKA6H315cgtPLfr"; -//const char *ChannelsNormaladdr = "RQUuT8zmkvDfXqECH4m3VD3SsHZAfnoh1v"; char ChannelsCChexstr[67] = { "035debdb19b1c98c615259339500511d6216a3ffbeb28ff5655a7ef5790a12ab0b" }; uint8_t ChannelsCCpriv[32] = { 0xec, 0x91, 0x36, 0x15, 0x2d, 0xd4, 0x48, 0x73, 0x22, 0x36, 0x4f, 0x6a, 0x34, 0x5c, 0x61, 0x0f, 0x01, 0xb4, 0x79, 0xe8, 0x1c, 0x2f, 0xa1, 0x1d, 0x4a, 0x0a, 0x21, 0x16, 0xea, 0x82, 0x84, 0x60 }; #include "CCcustom.inc" @@ -172,8 +154,6 @@ uint8_t OraclesCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0x // Prices #define FUNCNAME IsPricesInput #define EVALCODE EVAL_PRICES -//const char *PricesCCaddr = "RAL5Vh8NXmFqEKJRKrk1KjKaUckK7mM1iS"; -//const char *PricesNormaladdr = "RBunXCsMHk5NPd6q8SQfmpgre3x133rSwZ"; char PricesCChexstr[67] = { "039894cb054c0032e99e65e715b03799607aa91212a16648d391b6fa2cc52ed0cf" }; uint8_t PricesCCpriv[32] = { 0x0a, 0x3b, 0xe7, 0x5d, 0xce, 0x06, 0xed, 0xb7, 0xc0, 0xb1, 0xbe, 0xe8, 0x7b, 0x5a, 0xd4, 0x99, 0xb8, 0x8d, 0xde, 0xac, 0xb2, 0x7e, 0x7a, 0x52, 0x96, 0x15, 0xd2, 0xa0, 0xc6, 0xb9, 0x89, 0x61 }; #include "CCcustom.inc" @@ -183,8 +163,6 @@ uint8_t PricesCCpriv[32] = { 0x0a, 0x3b, 0xe7, 0x5d, 0xce, 0x06, 0xed, 0xb7, 0xc // Pegs #define FUNCNAME IsPegsInput #define EVALCODE EVAL_PEGS -//const char *PegsCCaddr = "RHnkVb7vHuHnjEjhkCF1bS6xxLLNZPv5fd"; -//const char *PegsNormaladdr = "RMcCZtX6dHf1fz3gpLQhUEMQ8cVZ6Rzaro"; char PegsCChexstr[67] = { "03c75c1de29a35e41606363b430c08be1c2dd93cf7a468229a082cc79c7b77eece" }; uint8_t PegsCCpriv[32] = { 0x52, 0x56, 0x4c, 0x78, 0x87, 0xf7, 0xa2, 0x39, 0xb0, 0x90, 0xb7, 0xb8, 0x62, 0x80, 0x0f, 0x83, 0x18, 0x9d, 0xf4, 0xf4, 0xbd, 0x28, 0x09, 0xa9, 0x9b, 0x85, 0x54, 0x16, 0x0f, 0x3f, 0xfb, 0x65 }; #include "CCcustom.inc" @@ -194,8 +172,6 @@ uint8_t PegsCCpriv[32] = { 0x52, 0x56, 0x4c, 0x78, 0x87, 0xf7, 0xa2, 0x39, 0xb0, // Marmara (reserved evalcode, the source moved to the marmara repo) #define FUNCNAME IsMarmaraInput #define EVALCODE EVAL_MARMARA -//const char *MarmaraCCaddr = "RGLSRDnUqTB43bYtRtNVgmwSSd1sun2te8"; -//const char *MarmaraNormaladdr = "RMN25Tn8NNzcyQDiQNuMp8UmwLMFd9thYc"; char MarmaraCChexstr[67] = { "03afc5be570d0ff419425cfcc580cc762ab82baad88c148f5b028d7db7bfeee61d" }; uint8_t MarmaraCCpriv[32] = { 0x7c, 0x0b, 0x54, 0x9b, 0x65, 0xd4, 0x89, 0x57, 0xdf, 0x05, 0xfe, 0xa2, 0x62, 0x41, 0xa9, 0x09, 0x0f, 0x2a, 0x6b, 0x11, 0x2c, 0xbe, 0xbd, 0x06, 0x31, 0x8d, 0xc0, 0xb9, 0x96, 0x76, 0x3f, 0x24 }; #include "CCcustom.inc" @@ -205,8 +181,6 @@ uint8_t MarmaraCCpriv[32] = { 0x7c, 0x0b, 0x54, 0x9b, 0x65, 0xd4, 0x89, 0x57, 0x // Payments #define FUNCNAME IsPaymentsInput #define EVALCODE EVAL_PAYMENTS -//const char *PaymentsCCaddr = "REpyKi7avsVduqZ3eimncK4uKqSArLTGGK"; -//const char *PaymentsNormaladdr = "RHRX8RTMAh2STWe9DHqsvJbzS7ty6aZy3d"; char PaymentsCChexstr[67] = { "0358f1764f82c63abc7c7455555fd1d3184905e30e819e97667e247e5792b46856" }; uint8_t PaymentsCCpriv[32] = { 0x03, 0xc9, 0x73, 0xc2, 0xb8, 0x30, 0x3d, 0xbd, 0xc8, 0xd9, 0xbf, 0x02, 0x49, 0xd9, 0x65, 0x61, 0x45, 0xed, 0x9e, 0x93, 0x51, 0xab, 0x8b, 0x2e, 0xe7, 0xc7, 0x40, 0xf1, 0xc4, 0xd2, 0xc0, 0x5b }; #include "CCcustom.inc" @@ -216,8 +190,7 @@ uint8_t PaymentsCCpriv[32] = { 0x03, 0xc9, 0x73, 0xc2, 0xb8, 0x30, 0x3d, 0xbd, 0 // Gateways #define FUNCNAME IsGatewaysInput #define EVALCODE EVAL_GATEWAYS -//const char *GatewaysCCaddr = "RKWpoK6vTRtq5b9qrRBodLkCzeURHeEk33"; -//const char *GatewaysNormaladdr = "RGJKV97ZN1wBfunuMt1tebiiHENNEq73Yh"; // wif UxJFYqEvLAjWPPRvn8NN1fRWscBxQZXZB5BBgc3HiapKVQBYNcmo +// wif UxJFYqEvLAjWPPRvn8NN1fRWscBxQZXZB5BBgc3HiapKVQBYNcmo char GatewaysCChexstr[67] = { "03ea9c062b9652d8eff34879b504eda0717895d27597aaeb60347d65eed96ccb40" }; uint8_t GatewaysCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0x89, 0xb1, 0xcb, 0xb9, 0xe6, 0x9c, 0x2c, 0x70, 0x85, 0x37, 0xdd, 0x00, 0x7a, 0x67, 0xff, 0x7c, 0x62, 0x1b, 0xe2, 0xfb, 0x04, 0x8f, 0x85, 0xbf }; #include "CCcustom.inc" @@ -227,8 +200,6 @@ uint8_t GatewaysCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0 // Tokens #define FUNCNAME IsTokensInput #define EVALCODE EVAL_TOKENS -//const char *TokensCCaddr = "RAMvUfoyURBRxAdVeTMHxn3giJZCFWeha2"; -//const char *TokensNormaladdr = "RCNgAngYAdrfzujYyPgfbjCGNVQZzCgTad"; char TokensCChexstr[67] = { "03e6191c70c9c9a28f9fd87089b9488d0e6c02fb629df64979c9cdb6b2b4a68d95" }; uint8_t TokensCCpriv[32] = { 0x1d, 0x0d, 0x0d, 0xce, 0x2d, 0xd2, 0xe1, 0x9d, 0xf5, 0xb6, 0x26, 0xd5, 0xad, 0xa0, 0xf0, 0x0a, 0xdd, 0x7a, 0x72, 0x7d, 0x17, 0x35, 0xb5, 0xe3, 0x2c, 0x6c, 0xa9, 0xa2, 0x03, 0x16, 0x4b, 0xcf }; #include "CCcustom.inc" @@ -247,8 +218,6 @@ uint8_t CClibCCpriv[32] = { 0x57, 0xcf, 0x49, 0x71, 0x7d, 0xb4, 0x15, 0x1b, 0x4f // ImportGateway #define FUNCNAME IsImportGatewayInput #define EVALCODE EVAL_IMPORTGATEWAY -//const char *ImportGatewayCCaddr = "RXJT6CRAXHFuQ2UjqdxMj7EfrayF6UJpzZ"; -//const char *ImportGatewayNormaladdr = "RNFRho63Ddz1Rh2eGPETykrU4fA8r67S4Y"; char ImportGatewayCChexstr[67] = { "0397231cfe04ea32d5fafb2206773ec9fba6e15c5a4e86064468bca195f7542714" }; uint8_t ImportGatewayCCpriv[32] = { 0x65, 0xef, 0x27, 0xeb, 0x3d, 0xb0, 0xb4, 0xae, 0x0f, 0xbc, 0x77, 0xdb, 0xf8, 0x40, 0x48, 0x90, 0x52, 0x20, 0x9e, 0x45, 0x3b, 0x49, 0xd8, 0x97, 0x60, 0x8c, 0x27, 0x4c, 0x59, 0x46, 0xe1, 0xdf }; #include "CCcustom.inc" @@ -258,8 +227,6 @@ uint8_t ImportGatewayCCpriv[32] = { 0x65, 0xef, 0x27, 0xeb, 0x3d, 0xb0, 0xb4, 0x // Tokens v2 #define FUNCNAME IsTokensv2Input #define EVALCODE EVAL_TOKENSV2 -//const char *Tokensv2CCaddr = "RSc4RycihBEWQP2GDvSYS46MvFJsTKaNVU"; -//const char *Tokensv2Normaladdr = "RDVU97zvJamGmVBSUyTm7RcYZtxjriNGkj"; char Tokensv2CChexstr[67] = { "032fd27f72591b02f13a7f9701246eb0296b2be7cfdad32c520e594844ec3d4801" }; uint8_t Tokensv2CCpriv[32] = { 0xb5, 0xba, 0x92, 0x7f, 0x53, 0x45, 0x4f, 0xf8, 0xa4, 0xad, 0x0d, 0x38, 0x30, 0x4f, 0xd0, 0x97, 0xd1, 0xb7, 0x94, 0x1b, 0x1f, 0x52, 0xbd, 0xae, 0xa2, 0xe7, 0x49, 0x06, 0x2e, 0xd2, 0x2d, 0xa5 }; #include "CCcustom.inc" @@ -269,20 +236,12 @@ uint8_t Tokensv2CCpriv[32] = { 0xb5, 0xba, 0x92, 0x7f, 0x53, 0x45, 0x4f, 0xf8, 0 // Assets v2 #define FUNCNAME IsAssetsv2Input #define EVALCODE EVAL_ASSETSV2 -//const char *Assetsv2CCaddr = "RX99NCswvrLiM6vNE4zmpKKBWMZU9zqwAk"; -//const char *Assetsv2Normaladdr = "RSB4NhRbvEShUFDkZz2KACj5EEBGDtDsV9"; char Assetsv2CChexstr[67] = { "0345d2e7ab018619da6ed58ccc0138c5f58a7b754bd8e9a1a9d2b811c5fe72d467" }; uint8_t Assetsv2CCpriv[32] = { 0x46, 0x58, 0x3b, 0x18, 0xee, 0x16, 0x63, 0x51, 0x6f, 0x60, 0x6e, 0x09, 0xdf, 0x9d, 0x27, 0xc8, 0xa7, 0xa2, 0x72, 0xa5, 0xd4, 0x6a, 0x9b, 0xcb, 0xd5, 0x4f, 0x7d, 0x1c, 0xb1, 0x2e, 0x63, 0x21 }; #include "CCcustom.inc" #undef FUNCNAME #undef EVALCODE -// Tokel TokenData validator -#define FUNCNAME IsTokelDataInput -#define EVALCODE EVAL_TOKELDATA -#include "CCcustom.inc" -#undef FUNCNAME -#undef EVALCODE int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode) { @@ -340,112 +299,84 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) switch ( evalcode ) { case EVAL_ASSETS: - //strcpy(cp->unspendableCCaddr,AssetsCCaddr); - //strcpy(cp->normaladdr,AssetsNormaladdr); strcpy(cp->CChexstr,AssetsCChexstr); memcpy(cp->CCpriv,AssetsCCpriv,32); cp->validate = AssetsValidate; cp->ismyvin = IsAssetsInput; break; case EVAL_FAUCET: - //strcpy(cp->unspendableCCaddr,FaucetCCaddr); - //strcpy(cp->normaladdr,FaucetNormaladdr); strcpy(cp->CChexstr,FaucetCChexstr); memcpy(cp->CCpriv,FaucetCCpriv,32); cp->validate = FaucetValidate; cp->ismyvin = IsFaucetInput; break; case EVAL_REWARDS: - //strcpy(cp->unspendableCCaddr,RewardsCCaddr); - //strcpy(cp->normaladdr,RewardsNormaladdr); strcpy(cp->CChexstr,RewardsCChexstr); memcpy(cp->CCpriv,RewardsCCpriv,32); cp->validate = RewardsValidate; cp->ismyvin = IsRewardsInput; break; case EVAL_DICE: - //strcpy(cp->unspendableCCaddr,DiceCCaddr); - //strcpy(cp->normaladdr,DiceNormaladdr); strcpy(cp->CChexstr,DiceCChexstr); memcpy(cp->CCpriv,DiceCCpriv,32); cp->validate = DiceValidate; cp->ismyvin = IsDiceInput; break; case EVAL_LOTTO: - //strcpy(cp->unspendableCCaddr,LottoCCaddr); - //strcpy(cp->normaladdr,LottoNormaladdr); strcpy(cp->CChexstr,LottoCChexstr); memcpy(cp->CCpriv,LottoCCpriv,32); cp->validate = LottoValidate; cp->ismyvin = IsLottoInput; break; case EVAL_FSM: - //strcpy(cp->unspendableCCaddr,FSMCCaddr); - //strcpy(cp->normaladdr,FSMNormaladdr); strcpy(cp->CChexstr,FSMCChexstr); memcpy(cp->CCpriv,FSMCCpriv,32); cp->validate = FSMValidate; cp->ismyvin = IsFSMInput; break; case EVAL_AUCTION: - //strcpy(cp->unspendableCCaddr,AuctionCCaddr); - //strcpy(cp->normaladdr,AuctionNormaladdr); strcpy(cp->CChexstr,AuctionCChexstr); memcpy(cp->CCpriv,AuctionCCpriv,32); cp->validate = AuctionValidate; cp->ismyvin = IsAuctionInput; break; case EVAL_HEIR: - //strcpy(cp->unspendableCCaddr,HeirCCaddr); - //strcpy(cp->normaladdr,HeirNormaladdr); strcpy(cp->CChexstr,HeirCChexstr); memcpy(cp->CCpriv,HeirCCpriv,32); cp->validate = HeirValidate; cp->ismyvin = IsHeirInput; break; case EVAL_CHANNELS: - //strcpy(cp->unspendableCCaddr,ChannelsCCaddr); - //strcpy(cp->normaladdr,ChannelsNormaladdr); strcpy(cp->CChexstr,ChannelsCChexstr); memcpy(cp->CCpriv,ChannelsCCpriv,32); cp->validate = ChannelsValidate; cp->ismyvin = IsChannelsInput; break; case EVAL_ORACLES: - //strcpy(cp->unspendableCCaddr,OraclesCCaddr); - //strcpy(cp->normaladdr,OraclesNormaladdr); strcpy(cp->CChexstr,OraclesCChexstr); memcpy(cp->CCpriv,OraclesCCpriv,32); cp->validate = OraclesValidate; cp->ismyvin = IsOraclesInput; break; case EVAL_PRICES: - //strcpy(cp->unspendableCCaddr,PricesCCaddr); - //strcpy(cp->normaladdr,PricesNormaladdr); strcpy(cp->CChexstr,PricesCChexstr); memcpy(cp->CCpriv,PricesCCpriv,32); cp->validate = PricesValidate; cp->ismyvin = IsPricesInput; break; case EVAL_PEGS: - //strcpy(cp->unspendableCCaddr,PegsCCaddr); - //strcpy(cp->normaladdr,PegsNormaladdr); strcpy(cp->CChexstr,PegsCChexstr); memcpy(cp->CCpriv,PegsCCpriv,32); cp->validate = PegsValidate; cp->ismyvin = IsPegsInput; break; case EVAL_PAYMENTS: - //strcpy(cp->unspendableCCaddr,PaymentsCCaddr); - //strcpy(cp->normaladdr,PaymentsNormaladdr); strcpy(cp->CChexstr,PaymentsCChexstr); memcpy(cp->CCpriv,PaymentsCCpriv,32); cp->validate = PaymentsValidate; cp->ismyvin = IsPaymentsInput; break; case EVAL_GATEWAYS: - //strcpy(cp->unspendableCCaddr,GatewaysCCaddr); - //strcpy(cp->normaladdr,GatewaysNormaladdr); strcpy(cp->CChexstr,GatewaysCChexstr); memcpy(cp->CCpriv,GatewaysCCpriv,32); cp->validate = GatewaysValidate; @@ -453,16 +384,12 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) break; case EVAL_TOKENS: - //strcpy(cp->unspendableCCaddr, TokensCCaddr); - //strcpy(cp->normaladdr, TokensNormaladdr); strcpy(cp->CChexstr, TokensCChexstr); memcpy(cp->CCpriv, TokensCCpriv, 32); cp->validate = TokensValidate; cp->ismyvin = IsTokensInput; break; case EVAL_IMPORTGATEWAY: - //strcpy(cp->unspendableCCaddr, ImportGatewayCCaddr); - //strcpy(cp->normaladdr, ImportGatewayNormaladdr); strcpy(cp->CChexstr, ImportGatewayCChexstr); memcpy(cp->CCpriv, ImportGatewayCCpriv, 32); cp->validate = ImportGatewayValidate; @@ -470,8 +397,6 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) break; case EVAL_TOKENSV2: - //strcpy(cp->unspendableCCaddr, Tokensv2CCaddr); - //strcpy(cp->normaladdr, Tokensv2Normaladdr); strcpy(cp->CChexstr, Tokensv2CChexstr); memcpy(cp->CCpriv, Tokensv2CCpriv, 32); cp->validate = Tokensv2Validate; @@ -479,8 +404,6 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) ismixed = true; break; case EVAL_ASSETSV2: - //strcpy(cp->unspendableCCaddr,Assetsv2CCaddr); - //strcpy(cp->normaladdr,Assetsv2Normaladdr); strcpy(cp->CChexstr,Assetsv2CChexstr); memcpy(cp->CCpriv,Assetsv2CCpriv,32); cp->validate = Assetsv2Validate; From e308ee5ee6530b3a7aadcfc730d053dee44f5ef6 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 2 Oct 2021 15:23:46 +0500 Subject: [PATCH 132/348] added tokenv2allbalances rpc; disabled tokenv2indexkey --- src/rpc/tokensrpc.cpp | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index fa032bf839f..37453016db9 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -308,6 +308,39 @@ UniValue tokenv2balance(const UniValue& params, bool fHelp, const CPubKey& remot return tokenbalance("tokenv2balance", params, fHelp, remotepk); } +template +static UniValue tokenallbalances(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() > 1) + throw runtime_error(name + " [pubkey]\n"); + if (ensure_CCrequirements(V::EvalCode()) < 0) + throw runtime_error(CC_REQUIREMENTS_MSG); + + // LOCK(cs_main); + // no need to lock cs_main as we use only indexes in this rpc + // but still use lock if you need to get chainActive.Height() or something like that + + std::vector vpubkey; + if (params.size() == 1) + vpubkey = ParseHex(params[0].get_str().c_str()); + else + vpubkey = Mypubkey(); + + UniValue result = GetAllTokenBalances(pubkey2pk(vpubkey), false); + return result; +} + +UniValue tokenallbalances(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + return tokenallbalances("tokenallbalances", params, fHelp, remotepk); +} +UniValue tokenv2allbalances(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + return tokenallbalances("tokenv2allbalances", params, fHelp, remotepk); +} + + + template static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, bool fHelp, const CPubKey& remotepk) { @@ -1143,9 +1176,11 @@ static const CRPCCommand commands[] = { "tokens v2", "mytokenv2orders", &mytokenv2orders, true }, { "tokens", "tokenaddress", &tokenaddress, true }, { "tokens v2", "tokenv2address", &tokenv2address, true }, - { "tokens v2", "tokenv2indexkey", &tokenv2indexkey, true }, +// { "tokens v2", "tokenv2indexkey", &tokenv2indexkey, true }, { "tokens", "tokenbalance", &tokenbalance, true }, { "tokens v2", "tokenv2balance", &tokenv2balance, true }, + { "tokens", "tokenallbalances", &tokenallbalances, true }, + { "tokens v2", "tokenv2allbalances", &tokenv2allbalances, true }, { "tokens", "tokencreate", &tokencreate, true }, { "tokens v2", "tokenv2create", &tokenv2create, true }, { "tokens", "tokentransfer", &tokentransfer, true }, From a3fd650b16d26218cf0e4c38762d76a0fa02dd40 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 2 Oct 2021 15:24:48 +0500 Subject: [PATCH 133/348] added tokenallbalances inmplementation --- src/cc/CCtokens.cpp | 7 ++-- src/cc/CCtokens_impl.h | 81 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 6b19ee55e5c..c615b81a065 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -831,12 +831,13 @@ UniValue TokenList() }; SetCCtxids(txids, cp->normaladdr, false, cp->evalcode, 0, zeroid, 'c'); // find by old normal addr marker + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "cp->normaladdr=" << cp->normaladdr << " SetCCtxids txids.size()=" << txids.size() << std::endl); for (std::vector::const_iterator it = txids.begin(); it != txids.end(); it++) { addTokenId(*it); } SetCCunspents(unspentOutputs, cp->unspendableCCaddr, true); // find by burnable validated cc addr marker - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "cp->unspendableCCaddr=" << cp->unspendableCCaddr << " SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { addTokenId(it->first.txhash); } @@ -929,7 +930,7 @@ UniValue TokenV2List(const UniValue ¶ms) std::vector > unspentOutputs; SetCCunspentsCCIndex(unspentOutputs, cp->unspendableCCaddr, zeroid); // find by burnable validated cc addr marker - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetCCunspentsCCIndex unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " cp->unspendableCCaddr=" << cp->unspendableCCaddr << " SetCCunspentsCCIndex unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (const auto &it : unspentOutputs) { LOCK(cs_main); if (IsTxidInActiveChain(it.first.creationid)) @@ -941,7 +942,7 @@ UniValue TokenV2List(const UniValue ¶ms) std::vector > unspentOutputs; SetCCunspents(unspentOutputs, cp->unspendableCCaddr, CC_OUTPUTS_TRUE); - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " cp->unspendableCCaddr=" << cp->unspendableCCaddr << " SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (const auto &it : unspentOutputs) { CTransaction creationtx; uint256 hashBlock; diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 35a0d342874..92f0453363e 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -540,6 +540,87 @@ CAmount GetTokenBalance(CPubKey pk, uint256 tokenid, bool usemempool) return(AddTokenCCInputs(cp, mtx, pk, tokenid, 0, 0, usemempool)); } +template +UniValue GetAllTokenBalances(CPubKey pk, bool useMempool) +{ + const bool CC_INPUTS_TRUE = true; + const char *funcname = __func__; + + UniValue result(UniValue::VARR); + + struct CCcontract_info *cp, C; + cp = CCinit(&C, V::EvalCode()); + + char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; + GetTokensCCaddress(cp, tokenaddr, pk, V::IsMixed()); + + std::map mapBalances; + + // make lambda to use it for either index kind: + auto add_token_amount = [&](uint256 txhash, int32_t index, CAmount satoshis) -> void + { + CTransaction tx; + uint256 hashBlock; + + if (satoshis == 0) + return; // skip null utxos + + if (myGetTransaction(txhash, tx, hashBlock) != 0) + { + char destaddr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(destaddr, tx.vout[index].scriptPubKey); + if (strcmp(destaddr, tokenaddr) != 0) + return; + + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << "()" << " checking tx vout destaddress=" << destaddr << " amount=" << tx.vout[index].nValue << std::endl); + + uint8_t funcId = 0; + uint256 tokenIdInOpret; + CScript opret; + std::string errorStr; + + CAmount retAmount = V::CheckTokensvout(cp, NULL, tx, index, opret, tokenIdInOpret, funcId, errorStr); + + if (retAmount > 0 && !myIsutxo_spentinmempool(ignoretxid, ignorevin, txhash, index)) + { + CAmount prevAmount = result[tokenIdInOpret.GetHex()].get_int64(); + mapBalances[tokenIdInOpret] += retAmount; + } + } + }; // auto add_token_amount + + if (fUnspentCCIndex) + { + std::vector > unspentOutputs; + + SetCCunspentsCCIndex(unspentOutputs, tokenaddr); + if (useMempool) + AddCCunspentsCCIndexMempool(unspentOutputs, tokenaddr); + + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspent ccindex found unspentOutputs=" << unspentOutputs.size() << std::endl); + for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) + add_token_amount(it->first.txhash, it->first.index, it->second.satoshis); + } + else + { + std::vector > unspentOutputs; + + if (useMempool) + SetCCunspentsWithMempool(unspentOutputs, (char*)tokenaddr, CC_INPUTS_TRUE); + else + SetCCunspents(unspentOutputs, (char*)tokenaddr, CC_INPUTS_TRUE); + + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspent index found unspentOutputs=" << unspentOutputs.size() << std::endl); + for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) + add_token_amount(it->first.txhash, it->first.index, it->second.satoshis); + } + + for(auto const &m : mapBalances) + result.pushKV(m.first.GetHex(), m.second); + + return result; +} + template UniValue TokenInfo(uint256 tokenid, E parseExtraData) { From 1e196fc10c87213d5b5486d5e80a7f0a30bb68c5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 2 Oct 2021 15:26:25 +0500 Subject: [PATCH 134/348] allowed empty creationid in SetCCunspents to list all tokens); allowed default null creationid for SetCCunspentsCCindex func --- src/cc/CCinclude.h | 11 +++-------- src/cc/CCtx.cpp | 3 ++- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 7ad52153821..c2253d8b620 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -929,18 +929,13 @@ void SetCCunspentsWithMempool(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId); - -/// SetCCunspents returns a vector of unspent outputs for a cc address -/// @param[out] unspentOutputs vector of pairs of objects CAddressUnspentCCKey and CAddressUnspentCCValue -/// @param coinaddr cc address where unspent outputs are searched -void SetCCunspentsCCIndex(std::vector > &unspentOutputs, const char *coinaddr); +void SetCCunspentsCCIndex(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId = uint256()); /// Adds mempool outputs to a vector of unspent outputs for a cc address /// @param[out] unspentOutputs vector of pairs of objects CAddressUnspentCCKey and CAddressUnspentCCValue /// @param coinaddr cc address where unspent outputs are searched -/// @param creationId txid of cc instance creation tx, might be empty to return all txns on coinaddr -void AddCCunspentsCCIndexMempool(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId); +/// @param creationId txid of cc instance creation tx, can be empty to return all txns on coinaddr +void AddCCunspentsCCIndexMempool(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId = uint256()); /// SetAddressIndexOutputs searches address index for a vector of outputs on an address /// @param[out] addressIndex vector of pairs of address index key and amount diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 994912b39e0..16077cc19e9 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -850,7 +850,8 @@ void SetCCunspentsCCIndex(std::vector >::iterator it = searchKeys.begin(); it != searchKeys.end(); it++) { if (GetUnspentCCIndex((*it).first, (*it).second, unspentOutputs, -1, -1, 0) == 0) From 241aa0f03bf9851f11631688a63b5bf9fb824c59 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 3 Oct 2021 17:47:19 +0500 Subject: [PATCH 135/348] fixed init err param in cc_conditionFromJSON() to prevent decoding failure if err not inited by caller --- src/cryptoconditions/src/threshold.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 82aeca4c85e..8415ac8efa8 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -293,7 +293,7 @@ static CC *thresholdFromJSON(const cJSON *params, char *err) { for (int i=0; isize; i++) { sub = cJSON_GetArrayItem(subfulfillments_item, i); cond->subconditions[i] = cc_conditionFromJSON(sub, err); - if (err[0] || cond->subconditions[i]==NULL) + if (/*err[0] || */ cond->subconditions[i]==NULL) // it should not be any 'err' if subconditions was created okay. This 'err[0]' check caused cc_conditionFromJSON failure if err not inited by the user { if (cond) cc_free(cond); return NULL; From 0272f0a34a223f1bc34617d929606a7a5f9cccf9 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 3 Oct 2021 17:48:19 +0500 Subject: [PATCH 136/348] fixed return to void func in cryptoconditions utils.c (some compiles failed) --- src/cryptoconditions/src/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptoconditions/src/utils.c b/src/cryptoconditions/src/utils.c index 26d5f706976..0baa88da446 100644 --- a/src/cryptoconditions/src/utils.c +++ b/src/cryptoconditions/src/utils.c @@ -216,7 +216,7 @@ void hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp, uint8_t * ASN_STRUCT_FREE(*asnType, fp); if (rc.encoded < 1) { fprintf(stderr, "Encoding fingerprint failed\n"); - return 0; + return; } sha256(buf, rc.encoded, out); } From 16627bcc8b5bb0b13a5e4309ff867b895facfe8f Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 3 Oct 2021 17:48:46 +0500 Subject: [PATCH 137/348] added mempool-tx ext debug messages --- src/main.cpp | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 1f141757f79..7e7bd0051d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1815,7 +1815,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (limit > 0) { size_t n = tx.vin.size(); if (n > limit) { - LogPrint("mempool", "Dropping txid %s : too many transparent inputs %zu > limit %zu\n", tx.GetHash().ToString(), n, limit ); + LogPrint("mempool", "Dropping txid %s : too many transparent inputs %zu > limit %zu\n", tx.GetHash().ToString().c_str(), n, limit ); return state.Error("AcceptToMemoryPool: too many inputs"); } } @@ -1823,12 +1823,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa auto verifier = libzcash::ProofVerifier::Strict(); if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,chainActive.LastTip()->GetHeight()+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 ) { - fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n"); + LogPrint("mempool-tx", "%s: komodo_validate_interest failed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Error("AcceptToMemoryPool: komodo_validate_interest failed"); } if (!CheckTransaction(tiptime,tx, state, verifier, 0, 0)) { + LogPrint("mempool", "%s: CheckTransaction failed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return error("AcceptToMemoryPool: CheckTransaction failed"); // state must be already set } @@ -1836,13 +1837,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Check transaction contextually against the set of consensus rules which apply in the next block to be mined. if (!ContextualCheckTransaction(0,0,0,tx, state, nextBlockHeight, (dosLevel == -1) ? 10 : dosLevel)) { + LogPrint("mempool-tx", "%s: ContextualCheckTransaction failed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return error("AcceptToMemoryPool: ContextualCheckTransaction failed"); // state must be already set } //fprintf(stderr,"addmempool 2\n"); // Coinbase is only valid in a block, not as a loose transaction if (tx.IsCoinBase()) { - fprintf(stderr,"AcceptToMemoryPool coinbase as individual tx\n"); + LogPrint("mempool-tx", "%s: coinbase as individual tx not supported, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(100, error("AcceptToMemoryPool: coinbase as individual tx"), REJECT_INVALID, "coinbase"); } @@ -1850,7 +1852,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa string reason; if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) { - //fprintf(stderr,"AcceptToMemoryPool reject nonstandard transaction: %s\nscriptPubKey: %s\n",reason.c_str(),tx.vout[0].scriptPubKey.ToString().c_str()); + LogPrint("mempool-tx","%s reject nonstandard transaction: reason %s tx: %s\n", __func__, reason.c_str(), HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(0,error("AcceptToMemoryPool: nonstandard transaction: %s", reason), REJECT_NONSTANDARD, reason); } @@ -1859,7 +1861,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // be mined yet. if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) { - //fprintf(stderr,"AcceptToMemoryPool reject non-final\n"); + LogPrint("mempool-tx", "%s: reject non final, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(0, false, REJECT_NONSTANDARD, "non-final"); } //fprintf(stderr,"addmempool 3\n"); @@ -1867,7 +1869,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa uint256 hash = tx.GetHash(); if (pool.exists(hash)) { - //fprintf(stderr,"already in mempool\n"); + LogPrint("mempool-tx", "%s: reject already in mempool, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); } @@ -1880,6 +1882,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (pool.mapNextTx.count(outpoint)) { // Disable replacement feature for now + LogPrint("mempool-tx", "%s: transaction replacement in mempool not allowed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Error("AcceptToMemoryPool: transaction replacement in mempool not allowed"); } } @@ -1913,14 +1916,17 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (view.HaveCoins(hash)) { //fprintf(stderr,"view.HaveCoins(hash) error\n"); + LogPrint("mempool-tx", "%s: already have coins, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Invalid(false, REJECT_DUPLICATE, "already have coins"); } if (tx.IsCoinImport() || tx.IsPegsImport()) { // Inverse of normal case; if input exists, it's been spent - if (ExistsImportTombstone(tx, view)) + if (ExistsImportTombstone(tx, view)) { + LogPrint("mempool-tx", "%s: import tombstone exists, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists"); + } } else { @@ -1933,7 +1939,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { if (pfMissingInputs) *pfMissingInputs = true; - fprintf(stderr,"%s missing inputs for tx %s prevout.hash=%s\n", __func__, tx.GetHash().GetHex().c_str(), txin.prevout.hash.GetHex().c_str()); //TODO: remove + LogPrint("mempool-tx", "%s missing inputs for tx %s prevout.hash=%s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str(), txin.prevout.hash.GetHex().c_str()); return false; /* https://github.com/zcash/zcash/blob/master/src/main.cpp#L1490 @@ -1945,6 +1951,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (!view.HaveInputs(tx)) { //fprintf(stderr,"accept failure.1\n"); + LogPrint("mempool-tx", "%s inputs already spent for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); } } @@ -1966,8 +1973,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa view.SetBackend(dummy); } // Check for non-standard pay-to-script-hash in inputs - if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId)) + if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId)) { + LogPrint("mempool-tx", "%s reject nonstandard transaction input for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Error("AcceptToMemoryPool: reject nonstandard transaction input"); + } // Check that the transaction doesn't have an excessive number of // sigops, making it impossible to mine. Since the coinbase transaction @@ -1985,8 +1994,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa CAmount nValueOut = tx.GetValueOut(); CAmount nFees = nValueIn-nValueOut; double dPriority = view.GetPriority(tx, chainActive.Height()); - if ( nValueOut > 777777*COIN && KOMODO_VALUETOOBIG(nValueOut - 777777*COIN) != 0 ) // some room for blockreward and txfees + if ( nValueOut > 777777*COIN && KOMODO_VALUETOOBIG(nValueOut - 777777*COIN) != 0 ) { // some room for blockreward and txfees + LogPrint("mempool-tx", "%s GetValueOut too big for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(100, error("AcceptToMemoryPool: GetValueOut too big"),REJECT_INVALID,"tx valueout is too big"); + } // Keep track of transactions that spend a coinbase, which we re-scan // during reorgs to ensure COINBASE_MATURITY is still met. @@ -2018,7 +2029,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (fLimitFree && nFees < txMinFee) { //fprintf(stderr,"accept failure.5\n"); - return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d",hash.ToString(), nFees, txMinFee),REJECT_INSUFFICIENTFEE, "insufficient fee"); + LogPrint("mempool-tx", "%s not enough fees for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d", hash.ToString(), nFees, txMinFee),REJECT_INSUFFICIENTFEE, "insufficient fee"); } } @@ -2048,6 +2060,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000) { //fprintf(stderr,"accept failure.7\n"); + LogPrint("mempool-tx", "%s free transaction rejected by rate limiter for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(0, error("AcceptToMemoryPool: free transaction rejected by rate limiter"), REJECT_INSUFFICIENTFEE, "rate limited free transaction"); } LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize); @@ -2060,6 +2073,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa hash.ToString(), nFees, ::minRelayTxFee.GetFee(nSize) * 10000); LogPrint("mempool", errmsg.c_str()); + LogPrint("mempool-tx", "%s rejected %s for tx %s\n", __func__, errmsg.c_str(), HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Error("AcceptToMemoryPool: " + errmsg); } //fprintf(stderr,"addmempool 6\n"); @@ -2071,7 +2085,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, evalcodeChecker)) { //fprintf(stderr,"accept failure.9\n"); - return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString()); + LogPrint("mempool-tx", "%s ConnectInputs failed for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString().c_str()); } // Check again against just the consensus-critical mandatory script @@ -2099,7 +2114,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } if (!ContextualCheckOutputs(tx, state, true, txdata, evalcodeChecker)) - return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ContextualCheckOutputs failed %s", hash.ToString());; + return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ContextualCheckOutputs failed %s", hash.ToString()); if (flag != 0) KOMODO_CONNECTING = -1; From 698a15627185eec8386ab7377f42aad262758f20 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 3 Oct 2021 18:01:05 +0500 Subject: [PATCH 138/348] getindexkeyforcc util rpc added --- src/rpc/ccutilsrpc.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index 0abc20e54ff..08282211851 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -90,7 +90,7 @@ UniValue listccunspents(const UniValue& params, bool fHelp, const CPubKey& mypk) } -// a helper function for nspv clients: creates a tx and add normal inputs for the requested amouny +// a helper function for nspv clients: creates a tx and add normal inputs for the requested amount UniValue createtxwithnormalinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) { if (fHelp || (params.size() < 1 || params.size() > 2)) @@ -141,6 +141,7 @@ UniValue createtxwithnormalinputs(const UniValue& params, bool fHelp, const CPub return result; } +// helper for nspv clients, to load several txns by their txids UniValue gettransactionsmany(const UniValue& params, bool fHelp, const CPubKey& remotepk) { if (fHelp || params.size() < 1 || params.size() > 0x1000) @@ -189,11 +190,50 @@ UniValue gettransactionsmany(const UniValue& params, bool fHelp, const CPubKey& return result; } +// helper for testing, returns index key for a cryptoconditon scriptPubKey +UniValue getindexkeyforcc(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() != 2) + { + string msg = "getindexkeyforcc cc-as-json is-mixed\n" + "\nReturns indexing key (formely cc address) for scriptPubKey made from a cryptocondition\n" + "\nArguments:\n" + //"address which utxos are added from\n" + "cc-as-json cryptocondition in json\n" + "is-mixed is mixed mode, true or false" + "Result: indexing key\n\n" + "Sample:\n" + "getindexkeyforcc \'{ \"type\": \"threshold-sha-256\", \"threshold\": 2, \"subfulfillments\":" + "[{\"type\":\"eval-sha-256\",\"code\":\"9A\"}, {\"type\":\"threshold-sha-256\", \"threshold\":1," + "subfulfillments\":[{ \"type\": \"secp256k1-sha-256\", \"publicKey\": \"03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12\" }] }] }\' true\n\n" + ; + throw std::runtime_error(msg); + } + + char err[128];// = ""; + CCwrapper cc = cc_conditionFromJSONString(params[0].get_str().c_str(), err); + if (cc == nullptr) + throw std::runtime_error(std::string("could not create cryptocondition: ") + err); + bool ismixed = false; + if (params[1].get_str() == "true") + ismixed = true; + else if (params[1].get_str() == "false") + ismixed = false; + else + throw std::runtime_error(std::string("is-mixed must be true or false")); + + CScript spk = CCPubKey(cc.get(), ismixed); + char ccaddress[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(ccaddress, spk); + return ccaddress; +} + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- // cc helpers { "ccutils", "listccunspents", &listccunspents, true }, + { "ccutils", "getindexkeyforcc", &getindexkeyforcc, true }, { "nspv", "createtxwithnormalinputs", &createtxwithnormalinputs, true }, { "nspv", "gettransactionsmany", &gettransactionsmany, true }, }; From f215e9072701e0a848c0306ec8c0837569a288b3 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 3 Oct 2021 18:02:23 +0500 Subject: [PATCH 139/348] added error into SendMoney if destination scriptPubKey was not decoded (empty) --- src/wallet/rpcwallet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c2b0480d5f6..14eb173709d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -476,6 +476,8 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr // Parse Zcash address CScript scriptPubKey = GetScriptForDestination(address); + if (scriptPubKey.empty()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid destination"); // Create and send the transaction CReserveKey reservekey(pwalletMain); From d1fcb5b5ecb69e456ef9d30764502e78c0fa8ed2 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 3 Oct 2021 18:10:30 +0500 Subject: [PATCH 140/348] added build lib cryptoconditions into build...sh --- zcutil/build-mac.sh | 9 ++++++++- zcutil/build-win.sh | 7 +++++++ zcutil/build.sh | 7 +++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index 4e4ce740404..fd00a245914 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -56,9 +56,16 @@ make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 # ./makecustom # cd $WD +# build cryptoconditions +cd ./src/cryptoconditions +./autogen.sh +./configure +make +cd ../.. + ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ +CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ ./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" \ --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index b89271e4833..92ad86ab94b 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -13,6 +13,13 @@ cd "$(dirname "$(readlink -f "$0")")/.." cd depends/ && make HOST=$HOST V=1 NO_QT=1 cd ../ +# build cryptoconditions +cd ./src/cryptoconditions +./autogen.sh +./configure +make +cd ../.. + # note: cclib building now added to src/Makefile.am #BUILD CCLIB # WD=$PWD diff --git a/zcutil/build.sh b/zcutil/build.sh index 2c1a9c66e86..3a64f2d2e69 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -96,6 +96,13 @@ eval "$MAKE" --version as --version ld -v +# build cryptoconditions +cd ./src/cryptoconditions +./autogen.sh +./configure +make +cd ../.. + HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh From 121f63b3199439b13b5ac00e01109f242e5f1aaa Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 3 Oct 2021 21:27:09 +0500 Subject: [PATCH 141/348] fix cryptoconditions configure make params in build-win --- zcutil/build-win.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index 92ad86ab94b..eef4b4f27f2 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -16,8 +16,8 @@ cd ../ # build cryptoconditions cd ./src/cryptoconditions ./autogen.sh -./configure -make +./configure --host=x86_64-w64-mingw32 --enable-static --disable-shared +CC="${CC} -g " CXX="${CXX} -g " make V=1 cd ../.. # note: cclib building now added to src/Makefile.am From d07bbd09ae6689e33547faf7394fe41a2d641bdd Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 4 Oct 2021 10:30:05 +0500 Subject: [PATCH 142/348] added switch default return in cryptoconditions.c --- src/cryptoconditions/src/cryptoconditions.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index 8eab9628ec1..7d608f7449e 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -172,6 +172,7 @@ void asnCondition(const CC *cond, Condition_t *asn) { case Condition_PR_ed25519Sha256: choice = &asn->choice.ed25519Sha256; break; case Condition_PR_secp256k1Sha256: choice = &asn->choice.secp256k1Sha256; break; case Condition_PR_evalSha256: choice = &asn->choice.evalSha256; break; + default: return; }; choice->cost = cc_getCost(cond); choice->fingerprint.buf = calloc(1, 32); From d8f2ec7d59ccf4c180f0d96b7770d10766d3f459 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 4 Oct 2021 10:31:15 +0500 Subject: [PATCH 143/348] added missing include for gcc10/kali/debian10 --- src/crypto/equihash.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crypto/equihash.h b/src/crypto/equihash.h index 57c434dae96..7d1275079ce 100644 --- a/src/crypto/equihash.h +++ b/src/crypto/equihash.h @@ -13,6 +13,7 @@ #include "komodo_nk.h" #include +#include #include #include #include From bf74d0a62c2037ef99032d305c67b225567cac9a Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 4 Oct 2021 11:21:31 +0500 Subject: [PATCH 144/348] restored missed tokel validation func init --- src/cc/CCcustom.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 2e6a1eb4eef..26e28346495 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -242,6 +242,12 @@ uint8_t Assetsv2CCpriv[32] = { 0x46, 0x58, 0x3b, 0x18, 0xee, 0x16, 0x63, 0x51, 0 #undef FUNCNAME #undef EVALCODE +// Tokel TokenData validator +#define FUNCNAME IsTokelDataInput +#define EVALCODE EVAL_TOKELDATA +#include "CCcustom.inc" +#undef FUNCNAME +#undef EVALCODE int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode) { @@ -411,6 +417,12 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) ismixed = true; break; + case EVAL_TOKELDATA: + cp->validate = TokelDataValidate; + cp->ismyvin = IsTokelDataInput; + ismixed = true; + break; + default: if (CClib_initcp(cp, evalcode) < 0) return(0); From 3448aa02c3ff2445ecf8a3743d623cef33e571a9 Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Tue, 5 Oct 2021 07:59:45 +1100 Subject: [PATCH 145/348] Revert "Tokel fixes and improvements for nspv and customised build" --- configure.ac | 40 - src/Makefile.am | 82 +- src/alert.h | 2 - src/base58.cpp | 24 +- src/base58.h | 2 - src/bitcoin-cli.cpp | 29 +- src/bitcoind.cpp | 57 +- src/cc/CCImportGateway.h | 4 - src/cc/CCTokelData.cpp | 1 + src/cc/CCcustom.cpp | 93 +- src/cc/CCinclude.h | 28 +- src/cc/CCtokens.cpp | 7 +- src/cc/CCtokens_impl.h | 81 - src/cc/CCtokenutils.cpp | 1 - src/cc/CCtx.cpp | 7 +- src/cc/CCutils.cpp | 153 +- src/cc/import.cpp | 20 +- src/cc/importgateway.cpp | 2 +- src/cc/pegs.cpp | 2 + src/chainparams.cpp | 11 +- src/chainparams.h | 1 - src/chainparamsseeds.h | 15 +- src/coins.cpp | 3 + src/crosschain.cpp | 2 + src/crypto/equihash.h | 1 - src/cryptoconditions/src/cryptoconditions.c | 1 - src/cryptoconditions/src/threshold.c | 2 +- src/cryptoconditions/src/utils.c | 2 +- src/deprecation.cpp | 2 +- src/importcoin.cpp | 3 + src/importcoin.h | 3 - src/init.cpp | 15 +- src/init.h | 2 - src/key_io.cpp | 15 - src/komodo-tx.cpp | 3 +- src/komodo.h | 10 +- src/komodo_DEX.h | 56 +- src/komodo_bitcoind.h | 39 +- src/komodo_defs.h | 157 +- src/komodo_gateway.h | 5 + src/komodo_globals.h | 24 +- src/komodo_nSPV.h | 10 +- src/komodo_nSPV_defs.h | 11 +- src/komodo_nSPV_fullnode.h | 647 ++++---- src/komodo_nSPV_superlite.h | 29 +- src/komodo_nSPV_wallet.h | 5 +- src/komodo_utils.h | 179 +- src/main.cpp | 80 +- src/main.h | 4 +- src/miner.cpp | 60 +- src/net.cpp | 1 - src/net.h | 6 +- src/rest.cpp | 6 + src/rpc/blockchain.cpp | 20 +- src/rpc/ccutilsrpc.cpp | 144 +- src/rpc/mining.cpp | 7 + src/rpc/misc.cpp | 38 +- src/rpc/net.cpp | 63 + src/rpc/rawtransaction.cpp | 10 + src/rpc/server.cpp | 6 +- src/rpc/server.h | 693 ++++---- src/rpc/testtransactions.cpp | 268 +++ src/rpc/tokensrpc.cpp | 100 -- src/rpcblockchain.old | 1625 +++++++++++++++++++ src/script/standard.cpp | 6 +- src/script/standard.h | 9 +- src/sync.cpp | 3 +- src/util.cpp | 65 +- src/util.h | 13 +- src/wallet/rpcdisclosure.cpp | 4 +- src/wallet/rpcdump.cpp | 5 +- src/wallet/rpcwallet.cpp | 39 +- src/wallet/rpcwallet.h | 1 - src/wallet/wallet.cpp | 14 +- zcutil/build-mac.sh | 18 +- zcutil/build-win.sh | 21 +- zcutil/build.sh | 14 +- 77 files changed, 3260 insertions(+), 1971 deletions(-) create mode 100644 src/rpc/testtransactions.cpp create mode 100644 src/rpcblockchain.old diff --git a/configure.ac b/configure.ac index 98d3b098ffc..e0629a1c56d 100644 --- a/configure.ac +++ b/configure.ac @@ -975,46 +975,6 @@ PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP" ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no --enable-module-recovery" AC_CONFIG_SUBDIRS([src/secp256k1 src/snark src/univalue src/cryptoconditions]) -# build custom executable with customised args: - -AC_ARG_WITH([custom-bin], - [AS_HELP_STRING([--with-custom-bin], - [build custom named daemon cli (default=no)])], - [build_custom_bin=$withval], - [build_custom_bin=no]) - -# build custom executable added with an Makefile.nnn.include -AM_CONDITIONAL([BUILD_CUSTOM_BIN], [test "x$build_custom_bin" = "xyes"]) - -AC_ARG_VAR(CUSTOM_BIN_NAME, [custom executable prefix]) -if test "x${CUSTOM_BIN_NAME+set}" = "xset"; then - AC_SUBST([CUSTOM_BIN_NAME], ${CUSTOM_BIN_NAME}) -else - AC_SUBST([CUSTOM_BIN_NAME], '') -fi - -AC_ARG_VAR(CUSTOM_BRAND_NAME, [custom brand name]) -if test "x${CUSTOM_BRAND_NAME+set}" = "xset"; then - AC_SUBST([CUSTOM_BRAND_NAME], ${CUSTOM_BRAND_NAME}) -else - AC_SUBST([CUSTOM_BRAND_NAME], '') -fi - -AC_ARG_VAR(CUSTOM_SERVER_ARGS, [custom daemon params]) -if test "x${CUSTOM_SERVER_ARGS+set}" = "xset"; then - AC_SUBST([CUSTOM_SERVER_ARGS], ${CUSTOM_SERVER_ARGS}) -else - AC_SUBST([CUSTOM_SERVER_ARGS], '') -fi - -AC_ARG_VAR(CUSTOM_CLIENT_ARGS, [custom cli params]) -if test "x${CUSTOM_CLIENT_ARGS+set}" = "xset"; then - AC_SUBST([CUSTOM_CLIENT_ARGS], ${CUSTOM_CLIENT_ARGS}) -else - AC_SUBST([CUSTOM_CLIENT_ARGS], '') -fi - - AC_OUTPUT dnl Taken from https://wiki.debian.org/RpathIssue diff --git a/src/Makefile.am b/src/Makefile.am index 4fb31dc0f59..8abfd389430 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -281,7 +281,7 @@ obj/build.h: FORCE $(abs_top_srcdir) libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h -# server: komodod +# server: zcashd libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ @@ -796,83 +796,3 @@ include Makefile.kcctest.include #include Makefile.test.include #include Makefile.gtest.include endif - -# build custom executables with customised params -if BUILD_CUSTOM_BIN -# include Makefile.tokel.include - -# custom server lib compiled with -DCUSTOM_BIN_NAME -DCUSTOM_SERVER_ARGS -LIBCUSTOM_SERVER=libcustom_server.a -lcurl -libcustom_server_a_CPPFLAGS = $(libbitcoin_server_a_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_BRAND_NAME=\"$(CUSTOM_BRAND_NAME)\" -DCUSTOM_SERVER_ARGS=\"$(CUSTOM_SERVER_ARGS)\" -libcustom_server_a_CXXFLAGS = $(libbitcoin_server_a_CXXFLAGS) -libcustom_server_a_SOURCES = $(libbitcoin_server_a_SOURCES) - -EXTRA_LIBRARIES += $(LIBCUSTOM_SERVER) - -bin_PROGRAMS += customd - -# custom daemon binary # -customd_SOURCES = $(komodod_SOURCES) -customd_CPPFLAGS = $(komodod_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_BRAND_NAME=\"$(CUSTOM_BRAND_NAME)\" -DCUSTOM_SERVER_ARGS=\"$(CUSTOM_SERVER_ARGS)\" -customd_CXXFLAGS = $(komodod_CXXFLAGS) -customd_LDFLAGS = $(komodod_LDFLAGS) -customd_LDADD = \ - $(LIBCUSTOM_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_ZMQ) \ - $(LIBBITCOIN_PROTON) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBVERUS_CRYPTO) \ - $(LIBVERUS_PORTABLE_CRYPTO) \ - $(LIBZCASH) \ - $(LIBSNARK) \ - $(LIBLEVELDB) \ - $(LIBMEMENV) \ - $(LIBSECP256K1) \ - $(LIBCRYPTOCONDITIONS) - -if ENABLE_WALLET -customd_LDADD += $(LIBBITCOIN_WALLET) -endif - -customd_LDADD += \ - $(BOOST_LIBS) \ - $(BDB_LIBS) \ - $(SSL_LIBS) \ - $(CRYPTO_LIBS) \ - $(EVENT_PTHREADS_LIBS) \ - $(EVENT_LIBS) \ - $(ZMQ_LIBS) \ - $(PROTON_LIBS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBVERUS_CRYPTO) \ - $(LIBVERUS_PORTABLE_CRYPTO) \ - $(LIBZCASH_LIBS) - -customd_LDADD += $(LIBDYNCUSTOMCONSENSUS) $(LIBSECP256K1) - -if ENABLE_PROTON -customd_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) -endif - -customd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(customd_CXXFLAGS) \ - $(CXXFLAGS) $(customd_LDFLAGS) $(LDFLAGS) -o $(CUSTOM_BIN_NAME)d$(EXEEXT) - - -bin_PROGRAMS += custom-cli - -# custom cli binary # -custom_cli_SOURCES = $(komodo_cli_SOURCES) -custom_cli_CPPFLAGS = $(komodo_cli_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_BRAND_NAME=\"$(CUSTOM_BRAND_NAME)\" -DCUSTOM_CLIENT_ARGS=\"$(CUSTOM_CLIENT_ARGS)\" -custom_cli_CXXFLAGS = $(komodo_cli_CXXFLAGS) -custom_cli_LDFLAGS = $(komodo_cli_LDFLAGS) -custom_cli_LDADD = $(komodo_cli_LDADD) - -custom_cli_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(custom_cli_CXXFLAGS) \ - $(CXXFLAGS) $(custom_cli_LDFLAGS) $(LDFLAGS) -o $(CUSTOM_BIN_NAME)-cli$(EXEEXT) - -endif \ No newline at end of file diff --git a/src/alert.h b/src/alert.h index cd978c5546f..16204c9c533 100644 --- a/src/alert.h +++ b/src/alert.h @@ -124,6 +124,4 @@ class CAlert : public CUnsignedAlert static CAlert getAlertByHash(const uint256 &hash); }; -void ThreadSendAlert(); - #endif // BITCOIN_ALERT_H diff --git a/src/base58.cpp b/src/base58.cpp index 58e3fbb3847..383666d826b 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -230,7 +230,6 @@ class CBitcoinAddressVisitor : public boost::static_visitor bool operator()(const CKeyID& id) const { return addr->Set(id); } bool operator()(const CPubKey& key) const { return addr->Set(key); } bool operator()(const CScriptID& id) const { return addr->Set(id); } - bool operator()(const CCryptoConditionID& id) const { return addr->Set(id); } bool operator()(const CNoDestination& no) const { return false; } }; @@ -255,12 +254,6 @@ bool CBitcoinAddress::Set(const CScriptID& id) return true; } -bool CBitcoinAddress::Set(const CCryptoConditionID& id) -{ - SetData(Params().Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS), &id, 20); - return true; -} - bool CBitcoinAddress::Set(const CTxDestination& dest) { return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); @@ -275,8 +268,7 @@ bool CBitcoinAddress::IsValid(const CChainParams& params) const { bool fCorrectSize = vchData.size() == 20; bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) || - vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS) || - vchVersion == params.Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS); + vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); return fCorrectSize && fKnownVersion; } @@ -300,8 +292,6 @@ CTxDestination CBitcoinAddress::Get() const return CKeyID(id); else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) return CScriptID(id); - else if (vchVersion == Params().Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS)) - return CCryptoConditionID(id); else return CNoDestination(); } @@ -318,11 +308,8 @@ bool CBitcoinAddress::GetIndexKey(uint160& hashBytes, int& type, bool ccflag) co memcpy(&hashBytes, &vchData[0], 20); type = 2; return true; - } else if (vchVersion == Params().Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS)) { - memcpy(&hashBytes, &vchData[0], 20); - type = 3; - return true; } + return false; } @@ -368,13 +355,6 @@ bool CCustomBitcoinAddress::Set(const CScriptID& id) return true; } -bool CCustomBitcoinAddress::Set(const CCryptoConditionID& id) -{ - SetData(base58Prefixes[0], &id, 20); // dimxy: CCryptoConditionID is actually CKeyID so we use base58Prefixes[0] as only two prefixes are supported in CCustomBitcoinAddress. - // TODO: check how it would work in gateways and importgateways - return true; -} - bool CCustomBitcoinAddress::Set(const CTxDestination& dest) { return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); diff --git a/src/base58.h b/src/base58.h index a86b689d0e7..8be0247e08f 100644 --- a/src/base58.h +++ b/src/base58.h @@ -133,7 +133,6 @@ class CBitcoinAddress : public CBase58Data { virtual bool Set(const CKeyID &id); virtual bool Set(const CPubKey &key); virtual bool Set(const CScriptID &id); - virtual bool Set(const CCryptoConditionID &id); bool Set(const CTxDestination &dest); bool IsValid() const; bool IsValid(const CChainParams ¶ms) const; @@ -159,7 +158,6 @@ class CCustomBitcoinAddress : public CBitcoinAddress { bool Set(const CPubKey &key); bool Set(const CScriptID &id); bool Set(const CTxDestination &dest); - bool Set(const CCryptoConditionID &id); bool IsValid() const; CCustomBitcoinAddress() {} diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index e38cf348d26..544972586aa 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -95,38 +95,18 @@ static int AppInitRPC(int argc, char* argv[]) // Parameters // ParseParameters(argc, argv); - -#if defined(CUSTOM_CLIENT_ARGS) - // add custom chain parameters - try { - AddSettings(mapArgs, mapMultiArgs, CUSTOM_CLIENT_ARGS); - } catch (const std::exception& e) { - fprintf(stderr,"Error in custom parameters: %s\n", e.what()); - return EXIT_FAILURE; - } -#endif - - std::string cliname = "komodo-cli"; - std::string brandname = "Komodo"; -#if defined(CUSTOM_BIN_NAME) - cliname = std::string(CUSTOM_BIN_NAME) + "-cli"; -#endif -#if defined(CUSTOM_BRAND_NAME) - brandname = std::string("Komodo") + " " + std::string(CUSTOM_BRAND_NAME); -#endif - std:string name; name = GetArg("-ac_name",""); if ( !name.empty() ) strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) { - std::string strUsage = brandname + " " + _("RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); + std::string strUsage = _("Komodo RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); if (!mapArgs.count("-version")) { strUsage += "\n" + _("Usage:") + "\n" + - " " + cliname + " [options] [params] " + _("Send command to ") + brandname + "\n" + - " " + cliname + " [options] help " + _("List commands") + "\n" + - " " + cliname + " [options] help " + _("Get help for a command") + "\n"; + " komodo-cli [options] [params] " + _("Send command to Komodo") + "\n" + + " komodo-cli [options] help " + _("List commands") + "\n" + + " komodo-cli [options] help " + _("Get help for a command") + "\n"; strUsage += "\n" + HelpMessageCli(); } else { @@ -144,7 +124,6 @@ static int AppInitRPC(int argc, char* argv[]) fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str()); return EXIT_FAILURE; } - try { ReadConfigFile(mapArgs, mapMultiArgs); } catch (const std::exception& e) { diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 0e6492c3580..ef7b09a37f0 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -57,6 +57,15 @@ static bool fDaemon; #include "komodo_defs.h" +#define KOMODO_ASSETCHAIN_MAXLEN 65 +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +extern int32_t ASSETCHAINS_BLOCKTIME; +extern uint64_t ASSETCHAINS_CBOPRET; +void komodo_passport_iteration(); +uint64_t komodo_interestsum(); +int32_t komodo_longestchain(); +void komodo_cbopretupdate(int32_t forceflag); +CBlockIndex *komodo_chainactive(int32_t height); void WaitForShutdown(boost::thread_group* threadGroup) { @@ -68,7 +77,14 @@ void WaitForShutdown(boost::thread_group* threadGroup) fprintf(stderr,"error: earlytx must be before block height %d or tx does not exist\n",KOMODO_EARLYTXID_HEIGHT); StartShutdown(); } - + /*if ( ASSETCHAINS_STAKED == 0 && ASSETCHAINS_ADAPTIVEPOW == 0 && (pindex= komodo_chainactive(1)) != 0 ) + { + if ( pindex->nTime > ADAPTIVEPOW_CHANGETO_DEFAULTON ) + { + ASSETCHAINS_ADAPTIVEPOW = 1; + fprintf(stderr,"default activate adaptivepow\n"); + } else fprintf(stderr,"height1 time %u vs %u\n",pindex->nTime,ADAPTIVEPOW_CHANGETO_DEFAULTON); + } //else fprintf(stderr,"cant find height 1\n");*/ if ( ASSETCHAINS_CBOPRET != 0 ) komodo_pricesinit(); /* @@ -92,6 +108,11 @@ void WaitForShutdown(boost::thread_group* threadGroup) // // Start // +extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY; +extern uint32_t ASSETCHAIN_INIT; +extern std::string NOTARY_PUBKEY; +int32_t komodo_is_issuer(); +void komodo_passport_iteration(); bool AppInit(int argc, char* argv[]) { @@ -99,16 +120,7 @@ bool AppInit(int argc, char* argv[]) CScheduler scheduler; bool fRet = false; - std::string daemonname = "komodod"; - std::string cliname = "komodo-cli"; -#if defined(CUSTOM_BIN_NAME) - daemonname = std::string(CUSTOM_BIN_NAME) + "d"; - cliname = std::string(CUSTOM_BIN_NAME) + "-cli"; -#endif - std::string brandname = "Komodo"; -#if defined(CUSTOM_BRAND_NAME) - brandname = std::string("Komodo") + " " + std::string(CUSTOM_BRAND_NAME); -#endif + // // Parameters // @@ -127,7 +139,7 @@ bool AppInit(int argc, char* argv[]) else { strUsage += "\n" + _("Usage:") + "\n" + - " " + daemonname + " [options] " + _("Start ") + brandname + _(" Daemon") + "\n"; + " komodod [options] " + _("Start Komodo Daemon") + "\n"; strUsage += "\n" + HelpMessage(HMM_BITCOIND); } @@ -143,14 +155,7 @@ bool AppInit(int argc, char* argv[]) fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); return false; } - -#if defined(CUSTOM_SERVER_ARGS) - // add custom chain parameters - AddSettings(mapArgs, mapMultiArgs, CUSTOM_SERVER_ARGS); -#endif - void komodo_args(char *argv0); - komodo_args(argv[0]); void chainparams_commandline(); chainparams_commandline(); @@ -167,16 +172,16 @@ bool AppInit(int argc, char* argv[]) ReadConfigFile(mapArgs, mapMultiArgs); } catch (const missing_zcash_conf& e) { fprintf(stderr, - (_("Before starting ") + daemonname + _(", you need to create a configuration file:\n" + (_("Before starting komodod, you need to create a configuration file:\n" "%s\n" "It can be completely empty! That indicates you are happy with the default\n" - "configuration of ") + daemonname + _(". But requiring a configuration file to start ensures\n" - "that ") + daemonname + _(" won't accidentally compromise your privacy if there was a default\n" + "configuration of komodod. But requiring a configuration file to start ensures\n" + "that komodod won't accidentally compromise your privacy if there was a default\n" "option you needed to change.\n" "\n" "You can look at the example configuration file for suggestions of default\n" "options that you may want to change. It should be in one of these locations,\n" - "depending on how you installed ") + brandname + _(":\n") + + "depending on how you installed Komodo:\n") + _("- Source code: %s\n" "- .deb package: %s\n")).c_str(), GetConfigFile().string().c_str(), @@ -191,12 +196,12 @@ bool AppInit(int argc, char* argv[]) // Command-line RPC bool fCommandLine = false; for (int i = 1; i < argc; i++) - if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "komodo:")) // Are there any "komodo:" params? + if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "komodo:")) fCommandLine = true; if (fCommandLine) { - std::cerr << "Error: There is no RPC client functionality in " << daemonname << ". Use the " << cliname << " utility instead." << std::endl; + fprintf(stderr, "Error: There is no RPC client functionality in komodod. Use the komodo-cli utility instead.\n"); exit(EXIT_FAILURE); } @@ -204,7 +209,7 @@ bool AppInit(int argc, char* argv[]) fDaemon = GetBoolArg("-daemon", false); if (fDaemon) { - fprintf(stdout, "Komodo %s server starting\n", ASSETCHAINS_SYMBOL); + fprintf(stdout, "Komodo %s server starting\n",ASSETCHAINS_SYMBOL); // Daemonize pid_t pid = fork(); diff --git a/src/cc/CCImportGateway.h b/src/cc/CCImportGateway.h index a139538803e..ee741a1487e 100644 --- a/src/cc/CCImportGateway.h +++ b/src/cc/CCImportGateway.h @@ -33,8 +33,4 @@ UniValue ImportGatewayExternalAddress(uint256 bindtxid,CPubKey pubkey); UniValue ImportGatewayDumpPrivKey(uint256 bindtxid,CKey key); UniValue ImportGatewayList(); UniValue ImportGatewayInfo(uint256 bindtxid); - -int64_t ImportGatewayVerify(char *refdepositaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2); -uint8_t DecodeImportGatewayBindOpRet(char *depositaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); - #endif diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index 063bb1179db..6927d263a52 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -163,6 +163,7 @@ static bool UnmarshalTokelVData(const vuint8_t &vdata, std::mapclear(); + cp->init_to_zeros(); cp->evalcode = evalcode; - bool ismixed = false; switch ( evalcode ) { case EVAL_ASSETS: + strcpy(cp->unspendableCCaddr,AssetsCCaddr); + strcpy(cp->normaladdr,AssetsNormaladdr); strcpy(cp->CChexstr,AssetsCChexstr); memcpy(cp->CCpriv,AssetsCCpriv,32); cp->validate = AssetsValidate; cp->ismyvin = IsAssetsInput; break; case EVAL_FAUCET: + strcpy(cp->unspendableCCaddr,FaucetCCaddr); + strcpy(cp->normaladdr,FaucetNormaladdr); strcpy(cp->CChexstr,FaucetCChexstr); memcpy(cp->CCpriv,FaucetCCpriv,32); cp->validate = FaucetValidate; cp->ismyvin = IsFaucetInput; break; case EVAL_REWARDS: + strcpy(cp->unspendableCCaddr,RewardsCCaddr); + strcpy(cp->normaladdr,RewardsNormaladdr); strcpy(cp->CChexstr,RewardsCChexstr); memcpy(cp->CCpriv,RewardsCCpriv,32); cp->validate = RewardsValidate; cp->ismyvin = IsRewardsInput; break; case EVAL_DICE: + strcpy(cp->unspendableCCaddr,DiceCCaddr); + strcpy(cp->normaladdr,DiceNormaladdr); strcpy(cp->CChexstr,DiceCChexstr); memcpy(cp->CCpriv,DiceCCpriv,32); cp->validate = DiceValidate; cp->ismyvin = IsDiceInput; break; case EVAL_LOTTO: + strcpy(cp->unspendableCCaddr,LottoCCaddr); + strcpy(cp->normaladdr,LottoNormaladdr); strcpy(cp->CChexstr,LottoCChexstr); memcpy(cp->CCpriv,LottoCCpriv,32); cp->validate = LottoValidate; cp->ismyvin = IsLottoInput; break; case EVAL_FSM: + strcpy(cp->unspendableCCaddr,FSMCCaddr); + strcpy(cp->normaladdr,FSMNormaladdr); strcpy(cp->CChexstr,FSMCChexstr); memcpy(cp->CCpriv,FSMCCpriv,32); cp->validate = FSMValidate; cp->ismyvin = IsFSMInput; break; case EVAL_AUCTION: + strcpy(cp->unspendableCCaddr,AuctionCCaddr); + strcpy(cp->normaladdr,AuctionNormaladdr); strcpy(cp->CChexstr,AuctionCChexstr); memcpy(cp->CCpriv,AuctionCCpriv,32); cp->validate = AuctionValidate; cp->ismyvin = IsAuctionInput; break; case EVAL_HEIR: + strcpy(cp->unspendableCCaddr,HeirCCaddr); + strcpy(cp->normaladdr,HeirNormaladdr); strcpy(cp->CChexstr,HeirCChexstr); memcpy(cp->CCpriv,HeirCCpriv,32); cp->validate = HeirValidate; cp->ismyvin = IsHeirInput; break; case EVAL_CHANNELS: + strcpy(cp->unspendableCCaddr,ChannelsCCaddr); + strcpy(cp->normaladdr,ChannelsNormaladdr); strcpy(cp->CChexstr,ChannelsCChexstr); memcpy(cp->CCpriv,ChannelsCCpriv,32); cp->validate = ChannelsValidate; cp->ismyvin = IsChannelsInput; break; case EVAL_ORACLES: + strcpy(cp->unspendableCCaddr,OraclesCCaddr); + strcpy(cp->normaladdr,OraclesNormaladdr); strcpy(cp->CChexstr,OraclesCChexstr); memcpy(cp->CCpriv,OraclesCCpriv,32); cp->validate = OraclesValidate; cp->ismyvin = IsOraclesInput; break; case EVAL_PRICES: + strcpy(cp->unspendableCCaddr,PricesCCaddr); + strcpy(cp->normaladdr,PricesNormaladdr); strcpy(cp->CChexstr,PricesCChexstr); memcpy(cp->CCpriv,PricesCCpriv,32); cp->validate = PricesValidate; cp->ismyvin = IsPricesInput; break; case EVAL_PEGS: + strcpy(cp->unspendableCCaddr,PegsCCaddr); + strcpy(cp->normaladdr,PegsNormaladdr); strcpy(cp->CChexstr,PegsCChexstr); memcpy(cp->CCpriv,PegsCCpriv,32); cp->validate = PegsValidate; cp->ismyvin = IsPegsInput; break; case EVAL_PAYMENTS: + strcpy(cp->unspendableCCaddr,PaymentsCCaddr); + strcpy(cp->normaladdr,PaymentsNormaladdr); strcpy(cp->CChexstr,PaymentsCChexstr); memcpy(cp->CCpriv,PaymentsCCpriv,32); cp->validate = PaymentsValidate; cp->ismyvin = IsPaymentsInput; break; case EVAL_GATEWAYS: + strcpy(cp->unspendableCCaddr,GatewaysCCaddr); + strcpy(cp->normaladdr,GatewaysNormaladdr); strcpy(cp->CChexstr,GatewaysCChexstr); memcpy(cp->CCpriv,GatewaysCCpriv,32); cp->validate = GatewaysValidate; @@ -390,12 +451,16 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) break; case EVAL_TOKENS: + strcpy(cp->unspendableCCaddr, TokensCCaddr); + strcpy(cp->normaladdr, TokensNormaladdr); strcpy(cp->CChexstr, TokensCChexstr); memcpy(cp->CCpriv, TokensCCpriv, 32); cp->validate = TokensValidate; cp->ismyvin = IsTokensInput; break; case EVAL_IMPORTGATEWAY: + strcpy(cp->unspendableCCaddr, ImportGatewayCCaddr); + strcpy(cp->normaladdr, ImportGatewayNormaladdr); strcpy(cp->CChexstr, ImportGatewayCChexstr); memcpy(cp->CCpriv, ImportGatewayCCpriv, 32); cp->validate = ImportGatewayValidate; @@ -403,36 +468,32 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) break; case EVAL_TOKENSV2: + strcpy(cp->unspendableCCaddr, Tokensv2CCaddr); + strcpy(cp->normaladdr, Tokensv2Normaladdr); strcpy(cp->CChexstr, Tokensv2CChexstr); memcpy(cp->CCpriv, Tokensv2CCpriv, 32); cp->validate = Tokensv2Validate; cp->ismyvin = IsTokensv2Input; - ismixed = true; break; case EVAL_ASSETSV2: + strcpy(cp->unspendableCCaddr,Assetsv2CCaddr); + strcpy(cp->normaladdr,Assetsv2Normaladdr); strcpy(cp->CChexstr,Assetsv2CChexstr); memcpy(cp->CCpriv,Assetsv2CCpriv,32); cp->validate = Assetsv2Validate; cp->ismyvin = IsAssetsv2Input; - ismixed = true; break; case EVAL_TOKELDATA: cp->validate = TokelDataValidate; cp->ismyvin = IsTokelDataInput; - ismixed = true; break; default: - if (CClib_initcp(cp, evalcode) < 0) + if ( CClib_initcp(cp,evalcode) < 0 ) return(0); break; } - // init addresses now here: - if (cp->CChexstr[0]) { - _GetCCaddress(cp->unspendableCCaddr, cp->evalcode, pubkey2pk(ParseHex(cp->CChexstr)), ismixed); - Getscriptaddress(cp->normaladdr, CScript() << ParseHex(cp->CChexstr) << OP_CHECKSIG); - } return(cp); } diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index c2253d8b620..dff7522e2e1 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -291,7 +291,7 @@ struct CCcontract_info std::vector< struct CCVintxProbe > CCvintxprobes; // > &unspentOutputs, const char *coinaddr, uint256 creationId = uint256()); +void SetCCunspentsCCIndex(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId); + +/// SetCCunspents returns a vector of unspent outputs for a cc address +/// @param[out] unspentOutputs vector of pairs of objects CAddressUnspentCCKey and CAddressUnspentCCValue +/// @param coinaddr cc address where unspent outputs are searched +void SetCCunspentsCCIndex(std::vector > &unspentOutputs, const char *coinaddr); /// Adds mempool outputs to a vector of unspent outputs for a cc address /// @param[out] unspentOutputs vector of pairs of objects CAddressUnspentCCKey and CAddressUnspentCCValue /// @param coinaddr cc address where unspent outputs are searched -/// @param creationId txid of cc instance creation tx, can be empty to return all txns on coinaddr -void AddCCunspentsCCIndexMempool(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId = uint256()); +/// @param creationId txid of cc instance creation tx, might be empty to return all txns on coinaddr +void AddCCunspentsCCIndexMempool(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId); /// SetAddressIndexOutputs searches address index for a vector of outputs on an address /// @param[out] addressIndex vector of pairs of address index key and amount @@ -1027,6 +1037,16 @@ UniValue OracleFormat(uint8_t *data,int32_t datalen,char *format,int32_t formatl /// @private CScript GetCCDropAsOpret(const CScript &scriptPubKey); +/*! \cond INTERNAL */ +// curve25519 and sha256 +bits256 curve25519_shared(bits256 privkey,bits256 otherpub); +bits256 curve25519_basepoint9(); +bits256 curve25519(bits256 mysecret,bits256 basepoint); +void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); +bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); +// UniValue ValueFromAmount(const CAmount& amount); // defined in server.h +/*! \endcond */ + /*! \cond INTERNAL */ CAmount TotalPubkeyNormalInputs(Eval *eval, const CTransaction &tx, const CPubKey &pubkey); CAmount TotalPubkeyCCInputs(Eval *eval, const CTransaction &tx, const CPubKey &pubkey); diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index c615b81a065..6b19ee55e5c 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -831,13 +831,12 @@ UniValue TokenList() }; SetCCtxids(txids, cp->normaladdr, false, cp->evalcode, 0, zeroid, 'c'); // find by old normal addr marker - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "cp->normaladdr=" << cp->normaladdr << " SetCCtxids txids.size()=" << txids.size() << std::endl); for (std::vector::const_iterator it = txids.begin(); it != txids.end(); it++) { addTokenId(*it); } SetCCunspents(unspentOutputs, cp->unspendableCCaddr, true); // find by burnable validated cc addr marker - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "cp->unspendableCCaddr=" << cp->unspendableCCaddr << " SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { addTokenId(it->first.txhash); } @@ -930,7 +929,7 @@ UniValue TokenV2List(const UniValue ¶ms) std::vector > unspentOutputs; SetCCunspentsCCIndex(unspentOutputs, cp->unspendableCCaddr, zeroid); // find by burnable validated cc addr marker - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " cp->unspendableCCaddr=" << cp->unspendableCCaddr << " SetCCunspentsCCIndex unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetCCunspentsCCIndex unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (const auto &it : unspentOutputs) { LOCK(cs_main); if (IsTxidInActiveChain(it.first.creationid)) @@ -942,7 +941,7 @@ UniValue TokenV2List(const UniValue ¶ms) std::vector > unspentOutputs; SetCCunspents(unspentOutputs, cp->unspendableCCaddr, CC_OUTPUTS_TRUE); - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " cp->unspendableCCaddr=" << cp->unspendableCCaddr << " SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (const auto &it : unspentOutputs) { CTransaction creationtx; uint256 hashBlock; diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 92f0453363e..35a0d342874 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -540,87 +540,6 @@ CAmount GetTokenBalance(CPubKey pk, uint256 tokenid, bool usemempool) return(AddTokenCCInputs(cp, mtx, pk, tokenid, 0, 0, usemempool)); } -template -UniValue GetAllTokenBalances(CPubKey pk, bool useMempool) -{ - const bool CC_INPUTS_TRUE = true; - const char *funcname = __func__; - - UniValue result(UniValue::VARR); - - struct CCcontract_info *cp, C; - cp = CCinit(&C, V::EvalCode()); - - char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; - GetTokensCCaddress(cp, tokenaddr, pk, V::IsMixed()); - - std::map mapBalances; - - // make lambda to use it for either index kind: - auto add_token_amount = [&](uint256 txhash, int32_t index, CAmount satoshis) -> void - { - CTransaction tx; - uint256 hashBlock; - - if (satoshis == 0) - return; // skip null utxos - - if (myGetTransaction(txhash, tx, hashBlock) != 0) - { - char destaddr[KOMODO_ADDRESS_BUFSIZE]; - Getscriptaddress(destaddr, tx.vout[index].scriptPubKey); - if (strcmp(destaddr, tokenaddr) != 0) - return; - - LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << "()" << " checking tx vout destaddress=" << destaddr << " amount=" << tx.vout[index].nValue << std::endl); - - uint8_t funcId = 0; - uint256 tokenIdInOpret; - CScript opret; - std::string errorStr; - - CAmount retAmount = V::CheckTokensvout(cp, NULL, tx, index, opret, tokenIdInOpret, funcId, errorStr); - - if (retAmount > 0 && !myIsutxo_spentinmempool(ignoretxid, ignorevin, txhash, index)) - { - CAmount prevAmount = result[tokenIdInOpret.GetHex()].get_int64(); - mapBalances[tokenIdInOpret] += retAmount; - } - } - }; // auto add_token_amount - - if (fUnspentCCIndex) - { - std::vector > unspentOutputs; - - SetCCunspentsCCIndex(unspentOutputs, tokenaddr); - if (useMempool) - AddCCunspentsCCIndexMempool(unspentOutputs, tokenaddr); - - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspent ccindex found unspentOutputs=" << unspentOutputs.size() << std::endl); - for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) - add_token_amount(it->first.txhash, it->first.index, it->second.satoshis); - } - else - { - std::vector > unspentOutputs; - - if (useMempool) - SetCCunspentsWithMempool(unspentOutputs, (char*)tokenaddr, CC_INPUTS_TRUE); - else - SetCCunspents(unspentOutputs, (char*)tokenaddr, CC_INPUTS_TRUE); - - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspent index found unspentOutputs=" << unspentOutputs.size() << std::endl); - for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) - add_token_amount(it->first.txhash, it->first.index, it->second.satoshis); - } - - for(auto const &m : mapBalances) - result.pushKV(m.first.GetHex(), m.second); - - return result; -} - template UniValue TokenInfo(uint256 tokenid, E parseExtraData) { diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index c01024eb330..d1521c618f1 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -416,7 +416,6 @@ CTxOut MakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount n CCwrapper payoutCond( MakeTokensv2CCcondMofN(evalcode1, evalcode2, M, pks) ); if (!CCtoAnon(payoutCond.get())) return vout; - vout = CTxOut(nValue, CCPubKey(payoutCond.get(),true)); { diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 16077cc19e9..6851c0ba614 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -850,8 +850,7 @@ void SetCCunspentsCCIndex(std::vector >::iterator it = searchKeys.begin(); it != searchKeys.end(); it++) { if (GetUnspentCCIndex((*it).first, (*it).second, unspentOutputs, -1, -1, 0) == 0) @@ -1192,7 +1191,7 @@ CAmount AddNormalinputsLocal(CMutableTransaction& mtx, CPubKey mypk, CAmount tot { LOCK(cs_main); if (CoinbaseGetBlocksToMaturity(tx, hashBlock) > 0) { - //std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; + std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; continue; } } @@ -1302,7 +1301,7 @@ CAmount AddNormalinputsRemote(CMutableTransaction& mtx, CPubKey mypk, CAmount to { LOCK(cs_main); if (CoinbaseGetBlocksToMaturity(tx, hashBlock) > 0) { - //std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; + std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; continue; } } diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index aa28ef33e17..6721f4b7a5c 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -16,14 +16,25 @@ /* CCutils has low level functions that are universally useful for all contracts. */ -#include "key_io.h" -#include "komodo_defs.h" -#include "komodo_structs.h" + #include "CCinclude.h" #include "CCtokens.h" +#include "komodo_structs.h" +#include "komodo_defs.h" +#include "key_io.h" + thread_local CCERROR CCerror = ""; +#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; + void endiancpy(uint8_t *dest,uint8_t *src,int32_t len) { int32_t i,j=0; @@ -835,6 +846,94 @@ uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::ve return merkleBlock.txn.ExtractMatches(txids); } +int64_t komodo_get_blocktime(uint256 hashBlock) +{ + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) + { + CBlockIndex* pindex = (*mi).second; + if (chainActive.Contains(pindex)) + return pindex->GetBlockTime(); + } + return 0; +} + +extern struct NSPV_inforesp NSPV_inforesult; +int32_t komodo_get_current_height() +{ + if ( KOMODO_NSPV_SUPERLITE ) + { + return (NSPV_inforesult.height); + } + else return chainActive.LastTip()->GetHeight(); +} + +bool komodo_txnotarizedconfirmed(uint256 txid, int32_t minconfirms) +{ + char str[65]; + int32_t confirms,minimumconfirms,notarized=0,txheight=0,currentheight=0;; + CTransaction tx; + uint256 hashBlock; + CBlockIndex *pindex; + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + + if (minconfirms==0) return (true); + if ( KOMODO_NSPV_SUPERLITE ) + { + if ( NSPV_myGetTransaction(txid,tx,hashBlock,txheight,currentheight) == 0 ) + { + fprintf(stderr,"komodo_txnotarizedconfirmed cant find txid %s\n",txid.ToString().c_str()); + return(0); + } + else if (txheight<=0) + { + fprintf(stderr,"komodo_txnotarizedconfirmed no txheight.%d for txid %s\n",txheight,txid.ToString().c_str()); + return(0); + } + else if (txheight>currentheight) + { + fprintf(stderr,"komodo_txnotarizedconfirmed backwards heights for txid %s hts.(%d %d)\n",txid.ToString().c_str(),txheight,currentheight); + return(0); + } + confirms=1 + currentheight - txheight; + } + else + { + 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= komodo_blockindex(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 (minconfirms>1) minimumconfirms=minconfirms; + else minimumconfirms=MIN_NON_NOTARIZED_CONFIRMS; + 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 >= minimumconfirms) + return (true); + return (false); +} + CPubKey check_signing_pubkey(CScript scriptSig) { bool found = false; @@ -1135,6 +1234,54 @@ uint8_t *SuperNET_ciphercalc(uint8_t **ptrp,int32_t *cipherlenp,bits256 privkey, return(origptr); } +uint8_t *komodo_DEX_encrypt(uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 destpubkey,bits256 privkey) +{ + int32_t cipherlen; uint8_t *cipher; + cipher = SuperNET_ciphercalc(allocatedp,&cipherlen,privkey,destpubkey,data,*datalenp); + *datalenp = cipherlen; + return(cipher); +} + +uint8_t *komodo_DEX_decrypt(uint8_t *senderpub,uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 privkey) +{ + int32_t msglen; + *allocatedp = 0; + if ( (msglen= *datalenp) <= crypto_box_NONCEBYTES + crypto_box_ZEROBYTES + sizeof(bits256) ) + { + *datalenp = 0; + return(0); + } + if ( (data= SuperNET_deciphercalc(senderpub,allocatedp,&msglen,privkey,data,*datalenp)) == 0 ) + { + //printf("komodo_DEX_decrypt decrytion error\n"); + *datalenp = 0; + return(0); + } else *datalenp = msglen; + return(data); +} + +void komodo_DEX_privkey(bits256 &privkey) +{ + bits256 priv,hash; + Myprivkey(priv.bytes); + vcalc_sha256(0,hash.bytes,priv.bytes,32); + vcalc_sha256(0,privkey.bytes,hash.bytes,32); + memset(priv.bytes,0,sizeof(priv)); + memset(hash.bytes,0,sizeof(hash)); +} + +void komodo_DEX_pubkey(bits256 &pubkey) +{ + bits256 privkey; + komodo_DEX_privkey(privkey); + /*{ + char *bits256_str(char hexstr[65],bits256 x); + char str[65]; + fprintf(stderr,"new DEX_privkey %s\n",bits256_str(str,privkey)); + }*/ + pubkey = curve25519(privkey,curve25519_basepoint9()); + memset(privkey.bytes,0,sizeof(privkey)); +} // add probe vintx conditions for making CCSig in FinalizeCCTx void CCAddVintxCond(struct CCcontract_info *cp, const CCwrapper &condWrapped, const uint8_t *priv) diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 74344e951a4..1a8c2f4519b 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -13,16 +13,14 @@ * * ******************************************************************************/ -#include #include "cc/eval.h" #include "cc/utils.h" -#include "komodo_defs.h" #include "importcoin.h" #include "crosschain.h" #include "primitives/transaction.h" #include "cc/CCinclude.h" +#include #include "cc/CCtokens.h" -#include "cc/CCImportGateway.h" #include "key_io.h" #define CODA_BURN_ADDRESS "KPrrRoPfHOnNpZZQ6laHXdQDkSQDkVHaN0V+LizLlHxz7NaA59sBAAAA" @@ -35,6 +33,22 @@ ##### 0xffffffff is a special CCid for single chain/dual daemon imports */ +extern std::string ASSETCHAINS_SELFIMPORT; +extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT; +extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; +extern uint256 KOMODO_EARLYTXID; + +// utilities from gateways.cpp +uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::vector &txids); +uint256 GatewaysReverseScan(uint256 &txid, int32_t height, uint256 reforacletxid, uint256 batontxid); +int32_t GatewaysCointxidExists(struct CCcontract_info *cp, uint256 cointxid); +uint8_t DecodeImportGatewayBindOpRet(char *burnaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); +int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2); +char *nonportable_path(char *str); +char *portable_path(char *str); +void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); +void *filestr(long *allocsizep,char *_fname); + cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,char const *arg3,char const *arg4,char const *arg5) { char cmdstr[5000],fname[256],*jsonstr; diff --git a/src/cc/importgateway.cpp b/src/cc/importgateway.cpp index 8948ec5c731..782fcc9e6fc 100644 --- a/src/cc/importgateway.cpp +++ b/src/cc/importgateway.cpp @@ -13,9 +13,9 @@ * * ******************************************************************************/ +#include "CCImportGateway.h" #include "key_io.h" #include "../importcoin.h" -#include "CCImportGateway.h" // start of consensus code diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 824bad2ce34..6de6baa4000 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -100,6 +100,8 @@ pegs CC is able to create a coin backed (by any supported coin with gateways CC #endif // PEGS_THRESHOLDS #define CC_MARKER_VALUE 10000 +extern uint64_t ASSETCHAINS_PEGSCCPARAMS[3]; + extern uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); //extern int64_t GetTokenBalance(CPubKey pk, uint256 tokenid); extern int32_t komodo_currentheight(); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index fb2b3399f66..fcae87cb6c4 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -182,13 +182,12 @@ class CMainParams : public CChainParams { assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); vFixedSeeds.clear(); vSeeds.clear(); - //vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); // Static contolled seeds list (Kolo) - //vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); // Active seeds crawler (Kolo) + vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); // Static contolled seeds list (Kolo) + vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); // Active seeds crawler (Kolo) // TODO: we need more seed crawlers from other community members base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,60); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,85); base58Prefixes[SECRET_KEY] = std::vector(1,188); - base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container >(); // guarantees the first two characters, when base58 encoded, are "zc" @@ -198,8 +197,6 @@ class CMainParams : public CChainParams { // guarantees the first two characters, when base58 encoded, are "SK" base58Prefixes[ZCSPENDING_KEY] = {171,54}; - base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); - bech32HRPs[SAPLING_PAYMENT_ADDRESS] = "zs"; bech32HRPs[SAPLING_FULL_VIEWING_KEY] = "zviews"; bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivks"; @@ -310,8 +307,6 @@ class CTestNetParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,0); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,5); base58Prefixes[SECRET_KEY] = std::vector(1,128); - base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); base58Prefixes[ZCPAYMENT_ADDRRESS] = {20,81}; @@ -433,8 +428,6 @@ class CRegTestParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,60); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,85); base58Prefixes[SECRET_KEY] = std::vector(1,188); - base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); - //base58Prefixes[PUBKEY_ADDRESS] = {0x1D,0x25}; //base58Prefixes[SCRIPT_ADDRESS] = {0x1C,0xBA}; //base58Prefixes[SECRET_KEY] = {0xEF}; diff --git a/src/chainparams.h b/src/chainparams.h index 23916b7ef17..daa16af8c40 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -63,7 +63,6 @@ class CChainParams ZCPAYMENT_ADDRRESS, ZCSPENDING_KEY, ZCVIEWING_KEY, - CRYPTOCONDITION_ADDRESS, MAX_BASE58_TYPES }; diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index 4a6a2248632..e3dac3ca641 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -23,15 +23,12 @@ * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly. */ static SeedSpec6 pnSeed6_main[] = { -/** - * no need in zcash seeds: - * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27485}, - * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27487}, - * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27485}, - * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27487}, - * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27485}, - * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27487} - */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27485}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27487}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27485}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27487}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27485}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27487} }; static SeedSpec6 pnSeed6_test[] = { diff --git a/src/coins.cpp b/src/coins.cpp index 77a46d38b90..92206b65379 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -565,6 +565,9 @@ const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const return coins->vout[input.prevout.n]; } +//uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; const CScript &CCoinsViewCache::GetSpendFor(const CCoins *coins, const CTxIn& input) { diff --git a/src/crosschain.cpp b/src/crosschain.cpp index 375d5ac9174..0a081c0868a 100644 --- a/src/crosschain.cpp +++ b/src/crosschain.cpp @@ -43,6 +43,8 @@ int NOTARISATION_SCAN_LIMIT_BLOCKS = 1440; +CBlockIndex *komodo_getblockindex(uint256 hash); + /* On KMD */ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, diff --git a/src/crypto/equihash.h b/src/crypto/equihash.h index 7d1275079ce..57c434dae96 100644 --- a/src/crypto/equihash.h +++ b/src/crypto/equihash.h @@ -13,7 +13,6 @@ #include "komodo_nk.h" #include -#include #include #include #include diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index 7d608f7449e..8eab9628ec1 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -172,7 +172,6 @@ void asnCondition(const CC *cond, Condition_t *asn) { case Condition_PR_ed25519Sha256: choice = &asn->choice.ed25519Sha256; break; case Condition_PR_secp256k1Sha256: choice = &asn->choice.secp256k1Sha256; break; case Condition_PR_evalSha256: choice = &asn->choice.evalSha256; break; - default: return; }; choice->cost = cc_getCost(cond); choice->fingerprint.buf = calloc(1, 32); diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 8415ac8efa8..82aeca4c85e 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -293,7 +293,7 @@ static CC *thresholdFromJSON(const cJSON *params, char *err) { for (int i=0; isize; i++) { sub = cJSON_GetArrayItem(subfulfillments_item, i); cond->subconditions[i] = cc_conditionFromJSON(sub, err); - if (/*err[0] || */ cond->subconditions[i]==NULL) // it should not be any 'err' if subconditions was created okay. This 'err[0]' check caused cc_conditionFromJSON failure if err not inited by the user + if (err[0] || cond->subconditions[i]==NULL) { if (cond) cc_free(cond); return NULL; diff --git a/src/cryptoconditions/src/utils.c b/src/cryptoconditions/src/utils.c index 0baa88da446..26d5f706976 100644 --- a/src/cryptoconditions/src/utils.c +++ b/src/cryptoconditions/src/utils.c @@ -216,7 +216,7 @@ void hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp, uint8_t * ASN_STRUCT_FREE(*asnType, fp); if (rc.encoded < 1) { fprintf(stderr, "Encoding fingerprint failed\n"); - return; + return 0; } sha256(buf, rc.encoded, out); } diff --git a/src/deprecation.cpp b/src/deprecation.cpp index 9d84fab0761..6005918ec66 100644 --- a/src/deprecation.cpp +++ b/src/deprecation.cpp @@ -25,9 +25,9 @@ #include "ui_interface.h" #include "util.h" #include "chainparams.h" -#include "komodo_defs.h" static const std::string CLIENT_VERSION_STR = FormatVersion(CLIENT_VERSION); +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; void EnforceNodeDeprecation(int nHeight, bool forceLogging, bool fThread) { diff --git a/src/importcoin.cpp b/src/importcoin.cpp index 1b0224685a5..db1346f286c 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -28,6 +28,9 @@ #include "cc/CCtokens.h" #include "cc/CCtokens_impl.h" + +//int32_t komodo_nextheight(); + // makes import tx for either coins or tokens CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride) { diff --git a/src/importcoin.h b/src/importcoin.h index 16dc49150d1..0f7c52aa520 100644 --- a/src/importcoin.h +++ b/src/importcoin.h @@ -122,7 +122,4 @@ bool CheckVinPubKey(const CTransaction &sourcetx, int32_t i, uint8_t pubkey33[33 CMutableTransaction MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount); int32_t GetSelfimportProof(const CMutableTransaction sourceMtx, CMutableTransaction &templateMtx, ImportProof &proofNull); -extern std::string ASSETCHAINS_SELFIMPORT; -extern uint16_t ASSETCHAINS_CODAPORT, ASSETCHAINS_BEAMPORT; - #endif /* IMPORTCOIN_H */ \ No newline at end of file diff --git a/src/init.cpp b/src/init.cpp index 190b09ab5ba..fdbb56fd765 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -23,7 +23,6 @@ #endif #include "init.h" -#include "alert.h" #include "crypto/common.h" #include "primitives/block.h" #include "addrman.h" @@ -94,6 +93,14 @@ using namespace std; #include "komodo_defs.h" +extern void ThreadSendAlert(); +extern bool komodo_dailysnapshot(int32_t height); +extern int32_t KOMODO_LOADINGBLOCKS; +extern bool VERUS_MINTBLOCKS; +extern char ASSETCHAINS_SYMBOL[]; +extern int32_t KOMODO_SNAPSHOT_INTERVAL; + +extern void komodo_init(int32_t height); ZCJoinSplit* pzcashParams = NULL; @@ -747,6 +754,10 @@ void ThreadNotifyRecentlyAdded() } } +/* declarations needed for ThreadUpdateKomodoInternals */ +void komodo_passport_iteration(); +void komodo_cbopretupdate(int32_t forceflag); + void ThreadUpdateKomodoInternals() { RenameThread("int-updater"); @@ -912,6 +923,8 @@ bool AppInitServers(boost::thread_group& threadGroup) /** Initialize bitcoin. * @pre Parameters should be parsed and config file should be read. */ +extern int32_t KOMODO_REWIND; + bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) { // ********************************************************* Step 1: setup diff --git a/src/init.h b/src/init.h index 7bef5d37836..108339865be 100644 --- a/src/init.h +++ b/src/init.h @@ -51,6 +51,4 @@ enum HelpMessageMode { /** Help for options shared between UI and daemon (for -help) */ std::string HelpMessage(HelpMessageMode mode); -extern std::atomic fRequestShutdown; - #endif // BITCOIN_INIT_H diff --git a/src/key_io.cpp b/src/key_io.cpp index 7c515add247..dd4176fee12 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -49,13 +49,6 @@ class DestinationEncoder : public boost::static_visitor return EncodeBase58Check(data); } - std::string operator()(const CCryptoConditionID& id) const - { - std::vector data = m_params.Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS); - data.insert(data.end(), id.begin(), id.end()); - return EncodeBase58Check(data); - } - std::string operator()(const CNoDestination& no) const { return {}; } }; @@ -79,14 +72,6 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin()); return CScriptID(hash); } - - // added cc addresses decode: - const std::vector& cc_prefix = params.Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS); - if (data.size() == hash.size() + cc_prefix.size() && std::equal(cc_prefix.begin(), cc_prefix.end(), data.begin())) { - std::copy(data.begin() + cc_prefix.size(), data.end(), hash.begin()); - return CCryptoConditionID(hash); - } - } return CNoDestination(); } diff --git a/src/komodo-tx.cpp b/src/komodo-tx.cpp index d25cbc8af42..21752778454 100644 --- a/src/komodo-tx.cpp +++ b/src/komodo-tx.cpp @@ -41,10 +41,9 @@ using namespace std; #include "uint256.h" #include "arith_uint256.h" -#include "komodo_defs.h" #include "komodo_structs.h" #include "komodo_globals.h" - +#include "komodo_defs.h" #include "komodo_interest.h" diff --git a/src/komodo.h b/src/komodo.h index bfcfb0b789c..88e741df7f7 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -37,7 +37,10 @@ uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID; #include "uthash.h" #include "utlist.h" -//bool check_pprevnotarizedht(); +int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); +void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); +int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); +bool check_pprevnotarizedht(); #include "komodo_structs.h" #include "komodo_globals.h" @@ -64,6 +67,7 @@ void komodo_currentheight_set(int32_t height) sp->CURRENT_HEIGHT = height; } +extern struct NSPV_inforesp NSPV_inforesult; int32_t komodo_currentheight() { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; @@ -788,7 +792,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar // if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed // OP_RETURN: 'D' -> deposit, 'W' -> withdraw -//int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); +int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]) { @@ -816,8 +820,6 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash; int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count; - - AssertLockHeld(cs_main); if ( pindex == 0 ) { fprintf(stderr,"komodo_connectblock null pindex\n"); diff --git a/src/komodo_DEX.h b/src/komodo_DEX.h index c2711f0af57..4eb4c9ef524 100644 --- a/src/komodo_DEX.h +++ b/src/komodo_DEX.h @@ -60,6 +60,11 @@ detect evil peer: 'Q' is directly protected by txpow, G is a fixed size, so it cant be very big and invalid request can be detected. 'P' message will lead to 'G' queries that cannot be answered, 'R' needs to have high priority */ +uint8_t *komodo_DEX_encrypt(uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 pubkey,bits256 privkey); +uint8_t *komodo_DEX_decrypt(uint8_t *senderpub,uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 privkey); +void komodo_DEX_pubkey(bits256 &pub0); +void komodo_DEX_privkey(bits256 &priv0); +int32_t komodo_DEX_request(int32_t priority,uint32_t shorthash,uint32_t timestamp,char *tagA,char *tagB); #define KOMODO_DEX_PURGELIST 0 @@ -166,29 +171,6 @@ static struct DEX_globals FILE *fp; } *G; -void komodo_DEX_privkey(bits256 &privkey) -{ - bits256 priv,hash; - Myprivkey(priv.bytes); - vcalc_sha256(0,hash.bytes,priv.bytes,32); - vcalc_sha256(0,privkey.bytes,hash.bytes,32); - memset(priv.bytes,0,sizeof(priv)); - memset(hash.bytes,0,sizeof(hash)); -} - -void komodo_DEX_pubkey(bits256 &pubkey) -{ - bits256 privkey; - komodo_DEX_privkey(privkey); - /*{ - char *bits256_str(char hexstr[65],bits256 x); - char str[65]; - fprintf(stderr,"new DEX_privkey %s\n",bits256_str(str,privkey)); - }*/ - pubkey = curve25519(privkey,curve25519_basepoint9()); - memset(privkey.bytes,0,sizeof(privkey)); -} - void komodo_DEX_pubkeyupdate() { komodo_DEX_pubkey(DEX_pubkey); @@ -271,34 +253,6 @@ uint32_t komodo_DEXquotehash(bits256 &hash,uint8_t *msg,int32_t len) return(_komodo_DEXquotehash(hash,len)); } -uint8_t *komodo_DEX_encrypt(uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 destpubkey,bits256 privkey) -{ - int32_t cipherlen; uint8_t *cipher; - cipher = SuperNET_ciphercalc(allocatedp,&cipherlen,privkey,destpubkey,data,*datalenp); - *datalenp = cipherlen; - return(cipher); -} - -uint8_t *komodo_DEX_decrypt(uint8_t *senderpub,uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 privkey) -{ - int32_t msglen; - *allocatedp = 0; - if ( (msglen= *datalenp) <= crypto_box_NONCEBYTES + crypto_box_ZEROBYTES + sizeof(bits256) ) - { - *datalenp = 0; - return(0); - } - if ( (data= SuperNET_deciphercalc(senderpub,allocatedp,&msglen,privkey,data,*datalenp)) == 0 ) - { - //printf("komodo_DEX_decrypt decrytion error\n"); - *datalenp = 0; - return(0); - } else *datalenp = msglen; - return(data); -} - - - uint16_t _komodo_DEXpeerpos(uint32_t timestamp,int32_t peerid) { // this needs to maintain the bitposition from epoch to epoch, to preserve the accuracy of the GETBIT() diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 8226a76080c..15ab79f0e68 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -19,14 +19,22 @@ #include #include "primitives/nonce.h" #include "consensus/params.h" -#include "script/standard.h" -#include "init.h" -#include "main.h" #include "komodo_defs.h" +#include "script/standard.h" #include "cc/CCinclude.h" const char *LOG_KOMODOBITCOIND = "komodostaking"; +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); +int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); +int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp); +unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); +bool EnsureWalletIsAvailable(bool avoidException); +extern bool fRequestShutdown; +extern CScript KOMODO_EARLYTXID_SCRIPTPUB; + +uint32_t komodo_heightstamp(int32_t height); + //#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr)) struct MemoryStruct { char *memory; size_t size; }; @@ -934,7 +942,6 @@ int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) uint32_t komodo_chainactive_timestamp() { - AssertLockHeld(cs_main); if ( chainActive.LastTip() != 0 ) return((uint32_t)chainActive.LastTip()->GetBlockTime()); else return(0); @@ -942,7 +949,6 @@ uint32_t komodo_chainactive_timestamp() CBlockIndex *komodo_chainactive(int32_t height) { - AssertLockHeld(cs_main); if ( chainActive.LastTip() != 0 ) { if ( height <= chainActive.LastTip()->GetHeight() ) @@ -955,7 +961,6 @@ CBlockIndex *komodo_chainactive(int32_t height) uint32_t komodo_heightstamp(int32_t height) { - AssertLockHeld(cs_main); CBlockIndex *ptr; if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 ) return(ptr->nTime); @@ -1263,11 +1268,11 @@ uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_ return(locktime); } +uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); + uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight) { uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex; - AssertLockHeld(cs_main); - if ( (pindex= chainActive[tipheight]) != 0 ) tiptime = (uint32_t)pindex->nTime; else fprintf(stderr,"cant find height[%d]\n",tipheight); @@ -1283,25 +1288,15 @@ uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 int32_t komodo_nextheight() { - CBlockIndex* pindex; - int32_t ht; - - { - LOCK(cs_main); // dimxy added to protect chainActive concurrent use. - pindex = chainActive.LastTip(); - } - - if (pindex != nullptr && (ht = pindex->GetHeight()) > 0) - return (ht + 1); - else - return (komodo_longestchain() + 1); + CBlockIndex *pindex; int32_t ht; + if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->GetHeight()) > 0 ) + return(ht+1); + else return(komodo_longestchain() + 1); } int32_t komodo_isrealtime(int32_t *kmdheightp) { struct komodo_state *sp; CBlockIndex *pindex; - - AssertLockHeld(cs_main); if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) *kmdheightp = sp->CURRENT_HEIGHT; else *kmdheightp = 0; diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 17398cd85ac..6c2f7967d54 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -18,12 +18,7 @@ #include #include "arith_uint256.h" -#include "script/script.h" -#include "pubkey.h" #include "chain.h" -#include "primitives/transaction.h" -#include "threadsafety.h" - #include "komodo_nk.h" #define KOMODO_EARLYTXID_HEIGHT 100 @@ -45,10 +40,6 @@ #define ASSETCHAINS_STAKED_MIN_POW_DIFF 536900000 // 537000000 537300000 #define _COINBASE_MATURITY 100 -#define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff - -#define IS_KMD_CHAIN() (ASSETCHAINS_SYMBOL[0] == '\0') - #define KOMODO_ADDRESS_BUFSIZE 64 // KMD Notary Seasons @@ -492,7 +483,7 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = #define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1) #endif -extern uint8_t ASSETCHAINS_TXPOW; +extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC; extern int8_t ASSETCHAINS_ADAPTIVEPOW; int32_t MAX_BLOCK_SIZE(int32_t height); extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; @@ -513,10 +504,7 @@ extern int32_t VERUS_MIN_STAKEAGE; extern uint32_t ASSETCHAINS_VERUSHASH, ASSETCHAINS_VERUSHASHV1_1, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB; extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; -extern std::vector ASSETCHAINS_PRICES, ASSETCHAINS_STOCKS; -extern std::vector Mineropret; // opreturn data set by the data gathering code -extern uint64_t ASSETCHAINS_PEGSCCPARAMS[3]; -extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEYHASH[]; +//extern std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD; extern uint256 KOMODO_EARLYTXID; @@ -545,6 +533,7 @@ void komodo_netevent(std::vector payload); int32_t getacseason(uint32_t timestamp); int32_t getkmdseason(int32_t height); +#define IGUANA_MAXSCRIPTSIZE 10001 #define KOMODO_KVDURATION 1440 #define KOMODO_KVBINARY 2 #define PRICES_SMOOTHWIDTH 1 @@ -554,8 +543,10 @@ int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *bas int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); +int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); uint32_t komodo_blocktime(uint256 hash); +int32_t komodo_longestchain(); int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); int8_t komodo_segid(int32_t nocache,int32_t height); int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight); @@ -564,6 +555,7 @@ int32_t komodo_priceind(const char *symbol); int32_t komodo_pricesinit(); int64_t komodo_priceave(int64_t *tmpbuf,int64_t *correlated,int32_t cskip); int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth); +int32_t komodo_nextheight(); uint32_t komodo_heightstamp(int32_t height); int64_t komodo_pricemult_to10e8(int32_t ind); int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks); @@ -588,84 +580,6 @@ int32_t komodo_blockload(CBlock& block, CBlockIndex *pindex); uint32_t komodo_chainactive_timestamp(); uint32_t GetLatestTimestamp(int32_t height); int32_t komodo_get_current_height(); -struct komodo_state *komodo_stateptrget(char *base); - -void komodo_prefetch(FILE *fp); -void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); -void komodo_init(int32_t height); -int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); -int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); -char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); -int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); -int32_t komodo_isrealtime(int32_t *kmdheightp); -uint64_t komodo_paxtotal(); -int32_t komodo_longestchain(); -uint64_t komodo_maxallowed(int32_t baseid); -int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); -int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); -int64_t komodo_block_unlocktime(uint32_t nHeight); -int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void *pTr); -uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); -CScript komodo_mineropret(int32_t nHeight); -bool komodo_appendACscriptpub(); -uint64_t komodo_commission(const CBlock *pblock,int32_t height); -int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); -uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); -int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk); -int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len); -int32_t komodo_is_notarytx(const CTransaction& tx); -int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag); -uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len); -CScript komodo_makeopret(CBlock *pblock, bool fNew); -int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); -int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); -int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); -int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime); -void komodo_passport_iteration(); -void komodo_cbopretupdate(int32_t forceflag); -uint64_t komodo_interestsum(); -uint64_t komodo_interest(int32_t txheight, uint64_t nValue, uint32_t nLockTime, uint32_t tiptime); -bool komodo_dailysnapshot(int32_t height); -void komodo_setactivation(int32_t height); -void komodo_pricesupdate(int32_t height,CBlock *pblock); -void komodo_broadcast(CBlock *pblock,int32_t limit); -int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); -void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); -int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main) ; -arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); -int32_t komodo_baseid(char *origbase); -int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); -uint64_t komodo_current_supply(uint32_t nHeight); - -int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); -bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); - -char *nonportable_path(char *str); -char *portable_path(char *str); -void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); -void *filestr(long *allocsizep,char *_fname); - -extern uint64_t KOMODO_INTERESTSUM, KOMODO_WALLETBALANCE; -extern int32_t KOMODO_INSYNC, KOMODO_LASTMINED, prevKOMODO_LASTMINED; -extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS + 1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS + 1]; -extern uint64_t ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS + 1]; -extern uint64_t ASSETCHAINS_LINEAR, ASSETCHAINS_SUPPLY; -extern uint8_t ASSETCHAINS_PUBLIC, ASSETCHAINS_PRIVATE; -extern int32_t KOMODO_LOADINGBLOCKS; -extern int32_t ASSETCHAINS_FOUNDERS; -extern char ASSETCHAINS_USERPASS[]; -extern int32_t KOMODO_REWIND; -extern uint32_t ASSETCHAINS_NUMALGOS; -extern uint32_t STAKING_MIN_DIFF; -extern uint32_t ASSETCHAINS_MINDIFF[]; -extern uint64_t ASSETCHAINS_TIMEUNLOCKFROM; -extern uint64_t ASSETCHAINS_TIMEUNLOCKTO; -extern uint32_t KOMODO_DPOWCONFS; -extern uint16_t KMD_PORT, BITCOIND_RPCPORT, DEST_PORT; -extern char KMDUSERPASS[], BTCUSERPASS[]; -extern uint32_t KOMODO_STOPAT; -extern int32_t ASSETCHAINS_CBMATURITY; #ifndef KOMODO_NSPV_FULLNODE #define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) @@ -688,67 +602,8 @@ struct komodo_staking *komodo_addutxo(struct komodo_staking *array, int32_t *num void komodo_createminerstransactions(); uint32_t komodo_segid32(char *coinaddr); -int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp); - - // #ifndef _WIN32 void OS_randombytes(unsigned char *x, long xlen); // this func impl exists for win too // #endif -// curve25519 and sha256 -#ifndef _BITS256 -#define _BITS256 - union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; - typedef union _bits256 bits256; -#endif - -bits256 curve25519_shared(bits256 privkey,bits256 otherpub); -bits256 curve25519_basepoint9(); -bits256 curve25519(bits256 mysecret,bits256 basepoint); -void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); -bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); - -// supernet cipher -int32_t _SuperNET_cipher(uint8_t nonce[crypto_box_NONCEBYTES],uint8_t *cipher,uint8_t *message,int32_t len,bits256 destpub,bits256 srcpriv,uint8_t *buf); -uint8_t *_SuperNET_decipher(uint8_t nonce[crypto_box_NONCEBYTES],uint8_t *cipher,uint8_t *message,int32_t len,bits256 srcpub,bits256 mypriv); -uint8_t *SuperNET_deciphercalc(uint8_t *senderpub,uint8_t **ptrp,int32_t *msglenp,bits256 privkey,uint8_t *cipher,int32_t cipherlen); -uint8_t *SuperNET_ciphercalc(uint8_t **ptrp,int32_t *cipherlenp,bits256 privkey,bits256 destpubkey,uint8_t *data,int32_t datalen); - -#ifdef TESTMODE - #define MIN_NON_NOTARIZED_CONFIRMS 2 -#else - #define MIN_NON_NOTARIZED_CONFIRMS 101 -#endif // TESTMODE - - -extern int32_t JUMBLR_PAUSE; -int32_t Jumblr_depositaddradd(char *depositaddr); -int32_t Jumblr_secretaddradd(char *secretaddr); - - -#define KOMODO_KVPROTECTED 1 -#define KOMODO_KVBINARY 2 -#define KOMODO_KVDURATION 1440 - -uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey37[37],char *coinaddr,int32_t height,char *base,int64_t fiatoshis); -int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); -#define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" -extern int32_t KOMODO_PAX; -int32_t komodo_is_issuer(); -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); - -int32_t komodo_pending_withdraws(char *opretstr); -void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value); -int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); -int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize); -uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen); -uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 privkey); -int32_t komodo_kvduration(uint32_t flags); -uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase); -int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig); - -uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); -uint64_t _komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); - #endif diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index b422f9fa8c1..de72ab0d30f 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -682,6 +682,8 @@ int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max) return(i); } +void komodo_passport_iteration(); + int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime) // verify above block is valid pax pricing { static uint256 array[64]; static int32_t numbanned,indallvouts; @@ -1424,6 +1426,8 @@ int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,ch return(-1); } +uint64_t komodo_interestsum(); + void komodo_passport_iteration() { static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest; @@ -1578,6 +1582,7 @@ void komodo_passport_iteration() } +extern std::vector Mineropret; // opreturn data set by the data gathering code #define PRICES_ERRORRATE (COIN / 100) // maximum acceptable change, set at 1% #define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR #define KOMODO_LOCALPRICE_CACHESIZE 13 diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 87c94052dd7..ab3ed76f3a9 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -14,7 +14,22 @@ ******************************************************************************/ #include "komodo_defs.h" -#include "komodo_structs.h" + +void komodo_prefetch(FILE *fp); +uint32_t komodo_heightstamp(int32_t height); +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); +void komodo_init(int32_t height); +int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); +int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); +char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); +void komodo_init(int32_t height); +int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); +int32_t komodo_isrealtime(int32_t *kmdheightp); +uint64_t komodo_paxtotal(); +int32_t komodo_longestchain(); +uint64_t komodo_maxallowed(int32_t baseid); +int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); +int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); pthread_mutex_t komodo_mutex,staked_mutex; @@ -64,13 +79,14 @@ int64_t MAX_MONEY = 200000000 * 100000000LL; // to be verifiable, timelocks require additional data that enables them to be validated and their ownership and // release time determined from the blockchain. to do this, every time locked output according to this // spec will use an op_return with CLTV at front and anything after |OP_RETURN|PUSH of rest|OPRETTYPE_TIMELOCK|script| +#define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff uint64_t ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF; uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0,ASSETCHAINS_CBOPRET=0; uint64_t ASSETCHAINS_LASTERA = 1; uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_PEGSCCPARAMS[3]; uint8_t ASSETCHAINS_CCDISABLES[256],ASSETCHAINS_CCZEROTXFEE[256]; -std::vector ASSETCHAINS_PRICES, ASSETCHAINS_STOCKS; +std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; #define _ASSETCHAINS_EQUIHASH 0 uint32_t ASSETCHAINS_NUMALGOS = 3; @@ -100,9 +116,9 @@ int32_t ASSETCHAINS_STAKED; uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REWARD; uint32_t KOMODO_INITDONE; -char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; -uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; +char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; uint64_t PENDING_KOMODO_TX; +extern int32_t KOMODO_LOADINGBLOCKS; unsigned int MAX_BLOCK_SIGOPS = 20000; int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL; diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index e8bb2d9df31..8b6b74fd6c3 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -26,12 +26,6 @@ #ifndef KOMODO_NSPV_H #define KOMODO_NSPV_H -#include -#include "main.h" -#include "komodo_defs.h" -#include "cc/CCinclude.h" -#include "komodo_nSPV_defs.h" - int32_t iguana_rwbuf(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *buf) { if ( rwflag != 0 ) @@ -107,7 +101,7 @@ int32_t NSPV_rwutxosresp(int32_t rwflag,uint8_t *serialized,struct NSPV_utxosres len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->total),&ptr->total); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->interest),&ptr->interest); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->maxrecords),&ptr->maxrecords); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->filter),&ptr->filter); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); if ( rwflag != 0 ) @@ -165,7 +159,7 @@ int32_t NSPV_rwtxidsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidsres len += NSPV_rwtxidresp(rwflag,&serialized[len],&ptr->txids[i]); } len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->maxrecords),&ptr->maxrecords); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->filter),&ptr->filter); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); if ( rwflag != 0 ) diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 9d4fd68a12b..18a10338d4f 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -17,8 +17,6 @@ #ifndef KOMODO_NSPV_DEFSH #define KOMODO_NSPV_DEFSH -#include - #define NSPV_PROTOCOL_VERSION 0x00000004 #define NSPV_POLLITERS 200 #define NSPV_POLLMICROS 50000 @@ -57,8 +55,6 @@ #define NSPV_REMOTERPC 0x14 #define NSPV_REMOTERPCRESP 0x15 -#define NSPV_MAXREQSPERSEC 15 - int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int32_t height,CTransaction &tx,uint256 &hashblock,int32_t &txheight,int32_t ¤theight,int64_t extradata,uint32_t tiptime,int64_t &rewardsum); UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); extern uint256 SIG_TXHASH; @@ -88,7 +84,7 @@ struct NSPV_utxosresp struct NSPV_utxoresp *utxos; char coinaddr[64]; int64_t total,interest; - int32_t nodeheight,skipcount,maxrecords; + int32_t nodeheight,skipcount,filter; uint16_t numutxos,CCflag; }; @@ -103,8 +99,8 @@ struct NSPV_txidsresp { struct NSPV_txidresp *txids; char coinaddr[64]; - int32_t nodeheight, skipcount, maxrecords; - uint16_t numtxids, CCflag; + int32_t nodeheight,skipcount,filter; + uint16_t numtxids,CCflag; }; struct NSPV_mempoolresp @@ -193,7 +189,6 @@ struct NSPV_remoterpcresp char *json; }; -extern struct NSPV_inforesp NSPV_inforesult; void NSPV_CCunspents(std::vector>& unspentOutputs, char* coinaddr, bool ccflag); void NSPV_CCindexOutputs(std::vector>& indexOutputs, char* coinaddr, bool ccflag); diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 54fd50c8482..bd306331f20 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -19,17 +19,8 @@ // NSPV_get... functions need to return the exact serialized length, which is the size of the structure minus size of pointers, plus size of allocated data -#include - -#include "main.h" -#include "komodo_defs.h" #include "notarisationdb.h" #include "rpc/server.h" -#include "cc/CCinclude.h" -#include "komodo_nSPV_defs.h" -#include "komodo_nSPV.h" - - static std::map nspv_remote_commands = { @@ -44,9 +35,7 @@ static std::map nspv_remote_commands = { { "tokenask", false }, { "tokenbid", false }, { "tokenfillask", false }, { "tokenfillbid", false }, { "tokencancelask", false }, { "tokencancelbid", false }, { "tokenorders", false }, { "mytokenorders", false }, { "tokentransfer", false },{ "tokencreate", false }, { "tokenv2ask", true }, { "tokenv2bid", true }, { "tokenv2fillask", true }, { "tokenv2fillbid", true }, { "tokenv2cancelask", true }, { "tokenv2cancelbid", true }, - { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", true },{ "tokenv2create", true }, { "tokenv2address", true }, - // nspv helpers - { "createtxwithnormalinputs", true }, { "tokenv2addccinputs", true }, { "tokenv2infotokel", true }, { "gettransactionsmany", true }, + { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", true },{ "tokenv2create", true } }; struct NSPV_ntzargs @@ -98,8 +87,6 @@ int32_t NSPV_notarized_bracket(struct NSPV_ntzargs *prev,struct NSPV_ntzargs *ne int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint256 desttxid,int32_t ntzheight) { CBlockIndex *pindex; - - LOCK(cs_main); ptr->blockhash = *chainActive[ntzheight]->phashBlock; ptr->height = ntzheight; ptr->txidheight = txidht; @@ -113,11 +100,8 @@ int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint int32_t NSPV_getntzsresp(struct NSPV_ntzsresp *ptr,int32_t origreqheight) { struct NSPV_ntzargs prev,next; int32_t reqheight = origreqheight; - { - LOCK(cs_main); - if ( reqheight < chainActive.LastTip()->GetHeight() ) - reqheight++; - } + if ( reqheight < chainActive.LastTip()->GetHeight() ) + reqheight++; if ( NSPV_notarized_bracket(&prev,&next,reqheight) == 0 ) { if ( prev.ntzheight != 0 ) @@ -138,8 +122,6 @@ int32_t NSPV_getntzsresp(struct NSPV_ntzsresp *ptr,int32_t origreqheight) int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) { CBlockIndex *pindex; - LOCK(cs_main); - if ( (pindex= komodo_chainactive(height)) != 0 ) { hdr->nVersion = pindex->nVersion; @@ -159,94 +141,86 @@ int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) { - int32_t prevMoMheight, len = 0; - CBlockIndex *pindex, *pindex2; - struct NSPV_ntzsresp pair; - LOCK(cs_main); - - if ((pindex = chainActive.LastTip()) != 0) { + int32_t prevMoMheight,len = 0; CBlockIndex *pindex, *pindex2; struct NSPV_ntzsresp pair; + if ( (pindex= chainActive.LastTip()) != 0 ) + { ptr->height = pindex->GetHeight(); ptr->blockhash = pindex->GetBlockHash(); - memset(&pair, 0, sizeof(pair)); - if (NSPV_getntzsresp(&pair, ptr->height - 1) < 0) - return (-1); + memset(&pair,0,sizeof(pair)); + if ( NSPV_getntzsresp(&pair,ptr->height-1) < 0 ) + return(-1); ptr->notarization = pair.prevntz; - if ((pindex2 = komodo_chainactive(ptr->notarization.txidheight)) != 0) - ptr->notarization.timestamp = pindex2->nTime; + if ( (pindex2= komodo_chainactive(ptr->notarization.txidheight)) != 0 ) + ptr->notarization.timestamp = pindex->nTime; //fprintf(stderr, "timestamp.%i\n", ptr->notarization.timestamp ); - if (reqheight == 0) + if ( reqheight == 0 ) reqheight = ptr->height; ptr->hdrheight = reqheight; ptr->version = NSPV_PROTOCOL_VERSION; - if (NSPV_setequihdr(&ptr->H, reqheight) < 0) - return (-1); - return (sizeof(*ptr)); - } else - return (-1); + if ( NSPV_setequihdr(&ptr->H,reqheight) < 0 ) + return(-1); + return(sizeof(*ptr)); + } else return(-1); } -int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool isCC, int32_t skipcount, int32_t maxrecords) +int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC,int32_t skipcount,uint32_t filter) { - CAmount total = 0LL, interest = 0LL; - uint32_t locktime; - int32_t ind = 0, tipheight, /*maxlen,*/ txheight, n = 0; - - std::vector> unspentOutputs; - SetCCunspents(unspentOutputs, coinaddr, isCC); - - { - LOCK(cs_main); - tipheight = chainActive.LastTip()->GetHeight(); - } - - // use maxrecords - //maxlen = MAX_BLOCK_SIZE(tipheight) - 512; - //maxlen /= sizeof(*ptr->utxos); - if (maxrecords <= 0 || maxrecords >= std::numeric_limits::max()) - maxrecords = std::numeric_limits::max(); // prevent large requests - - strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); + int64_t total = 0,interest=0; uint32_t locktime; int32_t ind=0,tipheight,maxlen,txheight,n = 0,len = 0; + std::vector > unspentOutputs; + SetCCunspents(unspentOutputs,coinaddr,isCC); + maxlen = MAX_BLOCK_SIZE(tipheight) - 512; + maxlen /= sizeof(*ptr->utxos); + strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); ptr->CCflag = isCC; - ptr->maxrecords = maxrecords; - if (skipcount < 0) + ptr->filter = filter; + if ( skipcount < 0 ) skipcount = 0; - ptr->skipcount = skipcount; - ptr->utxos = nullptr; - ptr->nodeheight = tipheight; - - if (unspentOutputs.size() >= 0 && skipcount < unspentOutputs.size()) { - ptr->utxos = (struct NSPV_utxoresp*)calloc(unspentOutputs.size() - skipcount, sizeof(ptr->utxos[0])); - for (std::vector>::const_iterator it = unspentOutputs.begin() + skipcount; - it != unspentOutputs.end() && ind < maxrecords; it++) { - // if gettxout is != null to handle mempool + if ( (ptr->numutxos= (int32_t)unspentOutputs.size()) >= 0 && ptr->numutxos < maxlen ) + { + tipheight = chainActive.LastTip()->GetHeight(); + ptr->nodeheight = tipheight; + if ( skipcount >= ptr->numutxos ) + skipcount = ptr->numutxos-1; + ptr->skipcount = skipcount; + if ( ptr->numutxos-skipcount > 0 ) + { + ptr->utxos = (struct NSPV_utxoresp *)calloc(ptr->numutxos-skipcount,sizeof(*ptr->utxos)); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { - if (!myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index)) { - ptr->utxos[ind].txid = it->first.txhash; - ptr->utxos[ind].vout = (int32_t)it->first.index; - ptr->utxos[ind].satoshis = it->second.satoshis; - ptr->utxos[ind].height = it->second.blockHeight; - if (IS_KMD_CHAIN() && it->second.satoshis >= 10 * COIN) { // calc interest on the kmd chain - ptr->utxos[n].extradata = komodo_accrued_interest(&txheight, &locktime, ptr->utxos[ind].txid, ptr->utxos[ind].vout, ptr->utxos[ind].height, ptr->utxos[ind].satoshis, tipheight); - interest += ptr->utxos[ind].extradata; + // if gettxout is != null to handle mempool + { + if ( n >= skipcount && myIsutxo_spentinmempool(ignoretxid,ignorevin,it->first.txhash,(int32_t)it->first.index) == 0 ) + { + ptr->utxos[ind].txid = it->first.txhash; + ptr->utxos[ind].vout = (int32_t)it->first.index; + ptr->utxos[ind].satoshis = it->second.satoshis; + ptr->utxos[ind].height = it->second.blockHeight; + if ( ASSETCHAINS_SYMBOL[0] == 0 && it->second.satoshis >= 10*COIN ) + { + ptr->utxos[n].extradata = komodo_accrued_interest(&txheight,&locktime,ptr->utxos[ind].txid,ptr->utxos[ind].vout,ptr->utxos[ind].height,ptr->utxos[ind].satoshis,tipheight); + interest += ptr->utxos[ind].extradata; + } + ind++; + total += it->second.satoshis; } - ind++; - total += it->second.satoshis; + n++; } - n++; } } + ptr->numutxos = ind; + if ( len < maxlen ) + { + len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->utxos)*ptr->numutxos - sizeof(ptr->utxos)); + //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); + ptr->total = total; + ptr->interest = interest; + return(len); + } } - // always return a result: - ptr->numutxos = ind; - int32_t len = (int32_t)(sizeof(*ptr) + sizeof(ptr->utxos[0]) * ptr->numutxos - sizeof(ptr->utxos)); - //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); - ptr->total = total; - ptr->interest = interest; - return (len); - //if (ptr->utxos != nullptr) - // free(ptr->utxos); - //memset(ptr, 0, sizeof(*ptr)); - //return (0); + if ( ptr->utxos != 0 ) + free(ptr->utxos); + memset(ptr,0,sizeof(*ptr)); + return(0); } class BaseCCChecker { @@ -318,7 +292,7 @@ class DefaultCCChecker : public BaseCCChecker { isEof = ss.eof(); ); opretTxid = revuint256(opretTxid); - //std::cerr << __func__ << " " << "opretEvalcode=" << opretEvalcode << " opretFuncid=" << (char)opretFuncid << " isCreateTx=" << isCreateTx << " opretTxid=" << opretTxid.GetHex() << std::endl; + std::cerr << __func__ << " " << "opretEvalcode=" << opretEvalcode << " opretFuncid=" << (char)opretFuncid << " isCreateTx=" << isCreateTx << " opretTxid=" << opretTxid.GetHex() << std::endl; if( parseOk /*parseOk=true if eof reached*/|| !isEof /*more data means okay*/) { if (evalcode == opretEvalcode && std::find(funcids.begin(), funcids.end(), (char)opretFuncid) != funcids.end() && @@ -359,10 +333,6 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ std::vector > unspentOutputs; SetCCunspents(unspentOutputs, coinaddr, true); - { - LOCK(cs_main); - tipheight = chainActive.LastTip()->GetHeight(); - } maxlen = MAX_BLOCK_SIZE(tipheight) - 512; //maxlen /= sizeof(*ptr->utxos); // TODO why was this? we need maxlen in bytes, don't we? @@ -373,12 +343,12 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ ptr->numutxos = 0; strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = 1; - + tipheight = chainActive.LastTip()->GetHeight(); ptr->nodeheight = tipheight; // will be checked in libnspv //} // select all appropriate utxos: - //std::cerr << __func__ << " " << "searching addr=" << coinaddr << std::endl; + std::cerr << __func__ << " " << "searching addr=" << coinaddr << std::endl; for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { if (myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index) == 0) @@ -394,7 +364,7 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ // if a checker is set for evalcode use it otherwise use the default checker: if (baseChecker && baseChecker->checkCC(it->first.txhash, tx.vout, nvout, evalcode, funcids, filtertxid) || defaultCCChecker.checkCC(it->first.txhash, tx.vout, nvout, evalcode, funcids, filtertxid)) { - //std::cerr << __func__ << " " << "filtered utxo with amount=" << tx.vout[nvout].nValue << std::endl; + std::cerr << __func__ << " " << "filtered utxo with amount=" << tx.vout[nvout].nValue << std::endl; struct CC_utxo utxo; utxo.txid = it->first.txhash; @@ -410,6 +380,7 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ } } + if (amount == 0) { // just return total value ptr->total = total; @@ -475,177 +446,174 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ } } -int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool isCC, int32_t skipcount, int32_t maxrecords) +int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC,int32_t skipcount,uint32_t filter) { - int32_t txheight, ind = 0, len = 0; - //CTransaction tx; - //uint256 hashBlock; - std::vector> txids; - SetAddressIndexOutputs(txids, coinaddr, isCC); - { - LOCK(cs_main); - ptr->nodeheight = chainActive.LastTip()->GetHeight(); - } - - // using maxrecords instead: - //maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; - //maxlen /= sizeof(*ptr->txids); - if (maxrecords <= 0 || maxrecords >= std::numeric_limits::max()) - maxrecords = std::numeric_limits::max(); // prevent large requests - - strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); + int32_t maxlen,txheight,ind=0,n = 0,len = 0; CTransaction tx; uint256 hashBlock; + std::vector > txids; + SetAddressIndexOutputs(txids,coinaddr,isCC); + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; + maxlen /= sizeof(*ptr->txids); + strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); ptr->CCflag = isCC; - ptr->maxrecords = maxrecords; - if (skipcount < 0) + ptr->filter = filter; + if ( skipcount < 0 ) skipcount = 0; - ptr->skipcount = skipcount; - ptr->txids = nullptr; - - if (txids.size() >= 0 && skipcount < txids.size()) { - ptr->txids = (struct NSPV_txidresp*)calloc(txids.size() - skipcount, sizeof(ptr->txids[0])); - for (std::vector>::const_iterator it = txids.begin() + skipcount; - it != txids.end() && ind < maxrecords; it++) { - ptr->txids[ind].txid = it->first.txhash; - ptr->txids[ind].vout = (int32_t)it->first.index; - ptr->txids[ind].satoshis = (int64_t)it->second; - ptr->txids[ind].height = (int64_t)it->first.blockHeight; - ind++; + if ( (ptr->numtxids= (int32_t)txids.size()) >= 0 && ptr->numtxids < maxlen ) + { + if ( skipcount >= ptr->numtxids ) + skipcount = ptr->numtxids-1; + ptr->skipcount = skipcount; + if ( ptr->numtxids-skipcount > 0 ) + { + ptr->txids = (struct NSPV_txidresp *)calloc(ptr->numtxids-skipcount,sizeof(*ptr->txids)); + for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + { + if ( n >= skipcount ) + { + ptr->txids[ind].txid = it->first.txhash; + ptr->txids[ind].vout = (int32_t)it->first.index; + ptr->txids[ind].satoshis = (int64_t)it->second; + ptr->txids[ind].height = (int64_t)it->first.blockHeight; + ind++; + } + n++; + } } + ptr->numtxids = ind; + len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); + return(len); } - // always return a result: - ptr->numtxids = ind; - len = (int32_t)(sizeof(*ptr) + sizeof(ptr->txids[0]) * ptr->numtxids - sizeof(ptr->txids)); - return (len); - /*if (ptr->txids != nullptr) + if ( ptr->txids != 0 ) free(ptr->txids); - memset(ptr, 0, sizeof(*ptr)); - return (0);*/ + memset(ptr,0,sizeof(*ptr)); + return(0); } -// get txids from addressindex or mempool by different criteria -// looks like as a set of ad-hoc functions and it should be rewritten -int32_t NSPV_mempoolfuncs(bits256* satoshisp, int32_t* vindexp, std::vector& txids, char* coinaddr, bool isCC, uint8_t funcid, uint256 txid, int32_t vout) +int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector &txids,char *coinaddr,bool isCC,uint8_t funcid,uint256 txid,int32_t vout) { - int32_t num = 0, vini = 0, vouti = 0; - uint8_t evalcode = 0, func = 0; - std::vector vopret; - char destaddr[64]; + int32_t num = 0,vini = 0,vouti = 0; uint8_t evalcode=0,func=0; std::vector vopret; char destaddr[64]; *vindexp = -1; - memset(satoshisp, 0, sizeof(*satoshisp)); - if (funcid == NSPV_CC_TXIDS) { - std::vector> tmp_txids; - uint256 tmp_txid, hashBlock; - int32_t n = 0, skipcount = vout >> 16; - uint8_t eval = (vout >> 8) & 0xFF, func = vout & 0xFF; + memset(satoshisp,0,sizeof(*satoshisp)); + if ( funcid == NSPV_CC_TXIDS) + { + std::vector > tmp_txids; uint256 tmp_txid,hashBlock; + int32_t n=0,skipcount=vout>>16; uint8_t eval=(vout>>8)&0xFF, func=vout&0xFF; CTransaction tx; - SetAddressIndexOutputs(tmp_txids, coinaddr, isCC); - if (skipcount < 0) - skipcount = 0; - if (skipcount >= tmp_txids.size()) - skipcount = tmp_txids.size() - 1; - if (tmp_txids.size() - skipcount > 0) { - for (std::vector>::const_iterator it = tmp_txids.begin(); it != tmp_txids.end(); it++) { - if (txid != zeroid || func != 0) { - myGetTransaction(it->first.txhash, tx, hashBlock); - std::vector oprets; - uint256 tokenid, txid; - std::vector vopret, vOpretExtra; - uint8_t *script, e, f; + SetAddressIndexOutputs(tmp_txids,coinaddr,isCC); + if ( skipcount < 0 ) skipcount = 0; + if ( skipcount >= tmp_txids.size() ) + skipcount = tmp_txids.size()-1; + if ( tmp_txids.size()-skipcount > 0 ) + { + for (std::vector >::const_iterator it=tmp_txids.begin(); it!=tmp_txids.end(); it++) + { + if (txid!=zeroid || func!=0) + { + myGetTransaction(it->first.txhash,tx,hashBlock); + std::vector oprets; uint256 tokenid,txid; + std::vector vopret,vOpretExtra; uint8_t *script,e,f; std::vector pubkeys; - if (DecodeTokenOpRetV1(tx.vout[tx.vout.size() - 1].scriptPubKey, tokenid, pubkeys, oprets) != 0 && GetOpReturnCCBlob(oprets, vOpretExtra) && vOpretExtra.size() > 0) { - vopret = vOpretExtra; - } else - GetOpReturnData(tx.vout[tx.vout.size() - 1].scriptPubKey, vopret); - script = (uint8_t*)vopret.data(); - if (vopret.size() > 2 && script[0] == eval) { - switch (eval) { - case EVAL_CHANNELS: - EVAL_PEGS: - EVAL_ORACLES: - EVAL_GAMES: - EVAL_IMPORTGATEWAY: - EVAL_ROGUE: - E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> tmp_txid;); - if (e != eval || (txid != zeroid && txid != tmp_txid) || (func != 0 && f != func)) - continue; - break; - case EVAL_TOKENS: - EVAL_DICE: - EVAL_DILITHIUM: - EVAL_FAUCET: - EVAL_LOTO: - EVAL_PAYMENTS: - EVAL_REWARDS: - E_UNMARSHAL(vopret, ss >> e; ss >> f;); - if (e != eval || (func != 0 && f != func)) - continue; - break; - default: - break; - } + if (DecodeTokenOpRetV1(tx.vout[tx.vout.size()-1].scriptPubKey,tokenid,pubkeys,oprets)!=0 && GetOpReturnCCBlob(oprets, vOpretExtra) && vOpretExtra.size()>0) + { + vopret=vOpretExtra; } + else GetOpReturnData(tx.vout[tx.vout.size()-1].scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && script[0]==eval ) + { + switch (eval) + { + case EVAL_CHANNELS:EVAL_PEGS:EVAL_ORACLES:EVAL_GAMES:EVAL_IMPORTGATEWAY:EVAL_ROGUE: + E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> tmp_txid;); + if (e!=eval || (txid!=zeroid && txid!=tmp_txid) || (func!=0 && f!=func)) continue; + break; + case EVAL_TOKENS:EVAL_DICE:EVAL_DILITHIUM:EVAL_FAUCET:EVAL_LOTO:EVAL_PAYMENTS:EVAL_REWARDS: + E_UNMARSHAL(vopret,ss >> e; ss >> f;); + if (e!=eval || (func!=0 && f!=func)) continue; + break; + default: + break; + } + } } - if (n >= skipcount) - txids.push_back(it->first.txhash); + if ( n >= skipcount ) txids.push_back(it->first.txhash); n++; } - return (n - skipcount); + return (n-skipcount); } return (0); } - if (mempool.size() == 0) - return (0); - if (funcid == NSPV_MEMPOOL_CCEVALCODE) { + if ( mempool.size() == 0 ) + return(0); + if ( funcid == NSPV_MEMPOOL_CCEVALCODE ) + { isCC = true; evalcode = vout & 0xff; func = (vout >> 8) & 0xff; } LOCK(mempool.cs); - BOOST_FOREACH (const CTxMemPoolEntry& e, mempool.mapTx) { - const CTransaction& tx = e.GetTx(); - const uint256& hash = tx.GetHash(); - if (funcid == NSPV_MEMPOOL_ALL) { + BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) + { + const CTransaction &tx = e.GetTx(); + const uint256 &hash = tx.GetHash(); + if ( funcid == NSPV_MEMPOOL_ALL ) + { txids.push_back(hash); num++; continue; - } else if (funcid == NSPV_MEMPOOL_INMEMPOOL) { - if (hash == txid) { + } + else if ( funcid == NSPV_MEMPOOL_INMEMPOOL ) + { + if ( hash == txid ) + { txids.push_back(hash); - return (++num); + return(++num); } continue; - } else if (funcid == NSPV_MEMPOOL_CCEVALCODE) { - if (tx.vout.size() > 1) { - CScript scriptPubKey = tx.vout[tx.vout.size() - 1].scriptPubKey; - if (GetOpReturnData(scriptPubKey, vopret) != 0) { - if (vopret[0] != evalcode || (func != 0 && vopret[1] != func)) - continue; + } + else if ( funcid == NSPV_MEMPOOL_CCEVALCODE ) + { + if ( tx.vout.size() > 1 ) + { + CScript scriptPubKey = tx.vout[tx.vout.size()-1].scriptPubKey; + if ( GetOpReturnData(scriptPubKey,vopret) != 0 ) + { + if ( vopret[0] != evalcode || (func!=0 && vopret[1] != func) ) continue; txids.push_back(hash); num++; } } continue; } - if (funcid == NSPV_MEMPOOL_ISSPENT) { - BOOST_FOREACH (const CTxIn& txin, tx.vin) { + if ( funcid == NSPV_MEMPOOL_ISSPENT ) + { + BOOST_FOREACH(const CTxIn &txin,tx.vin) + { //fprintf(stderr,"%s/v%d ",uint256_str(str,txin.prevout.hash),txin.prevout.n); - if (txin.prevout.n == vout && txin.prevout.hash == txid) { + if ( txin.prevout.n == vout && txin.prevout.hash == txid ) + { txids.push_back(hash); *vindexp = vini; - return (++num); + return(++num); } vini++; } - } else if (funcid == NSPV_MEMPOOL_ADDRESS) { - BOOST_FOREACH (const CTxOut& txout, tx.vout) { - if (txout.scriptPubKey.IsPayToCryptoCondition() == isCC) { - Getscriptaddress(destaddr, txout.scriptPubKey); - if (strcmp(destaddr, coinaddr) == 0) { + } + else if ( funcid == NSPV_MEMPOOL_ADDRESS ) + { + BOOST_FOREACH(const CTxOut &txout,tx.vout) + { + if ( txout.scriptPubKey.IsPayToCryptoCondition() == isCC ) + { + Getscriptaddress(destaddr,txout.scriptPubKey); + if ( strcmp(destaddr,coinaddr) == 0 ) + { txids.push_back(hash); *vindexp = vouti; - if (num < 4) + if ( num < 4 ) satoshisp->ulongs[num] = txout.nValue; num++; } @@ -655,45 +623,44 @@ int32_t NSPV_mempoolfuncs(bits256* satoshisp, int32_t* vindexp, std::vector txids; - bits256 satoshis; - uint256 tmp, tmpdest; - int32_t i, len = 0; - { - LOCK(cs_main); - ptr->nodeheight = chainActive.LastTip()->GetHeight(); - } - strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); + std::vector txids; bits256 satoshis; uint256 tmp,tmpdest; int32_t i,len = 0; + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); ptr->CCflag = isCC; ptr->txid = txid; ptr->vout = vout; ptr->funcid = funcid; - if (NSPV_mempoolfuncs(&satoshis, &ptr->vindex, txids, coinaddr, isCC, funcid, txid, vout) >= 0) { - if ((ptr->numtxids = (int32_t)txids.size()) >= 0) { - if (ptr->numtxids > 0) { - ptr->txids = (uint256*)calloc(ptr->numtxids, sizeof(*ptr->txids)); - for (i = 0; i < ptr->numtxids; i++) { + if ( NSPV_mempoolfuncs(&satoshis,&ptr->vindex,txids,coinaddr,isCC,funcid,txid,vout) >= 0 ) + { + if ( (ptr->numtxids= (int32_t)txids.size()) >= 0 ) + { + if ( ptr->numtxids > 0 ) + { + ptr->txids = (uint256 *)calloc(ptr->numtxids,sizeof(*ptr->txids)); + for (i=0; inumtxids; i++) + { tmp = txids[i]; - iguana_rwbignum(IGUANA_READ, (uint8_t*)&tmp, sizeof(*ptr->txids), (uint8_t*)&ptr->txids[i]); + iguana_rwbignum(IGUANA_READ,(uint8_t *)&tmp,sizeof(*ptr->txids),(uint8_t *)&ptr->txids[i]); } } - if (funcid == NSPV_MEMPOOL_ADDRESS) { - memcpy(&tmp, &satoshis, sizeof(tmp)); - iguana_rwbignum(IGUANA_READ, (uint8_t*)&tmp, sizeof(ptr->txid), (uint8_t*)&ptr->txid); + if ( funcid == NSPV_MEMPOOL_ADDRESS ) + { + memcpy(&tmp,&satoshis,sizeof(tmp)); + iguana_rwbignum(IGUANA_READ,(uint8_t *)&tmp,sizeof(ptr->txid),(uint8_t *)&ptr->txid); } - len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids) * ptr->numtxids - sizeof(ptr->txids)); - return (len); + len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); + return(len); } } - if (ptr->txids != 0) + if ( ptr->txids != 0 ) free(ptr->txids); - memset(ptr, 0, sizeof(*ptr)); - return (0); + memset(ptr,0,sizeof(*ptr)); + return(0); } int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n) @@ -738,7 +705,7 @@ int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n) rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id); response=rpc_result.write(); } - catch (const std::runtime_error& e) + catch (const runtime_error& e) { rpc_result = JSONRPCReplyObj(NullUniValue,JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); response=rpc_result.write(); @@ -764,7 +731,7 @@ uint8_t *NSPV_getrawtx(CTransaction &tx,uint256 &hashBlock,int32_t *txlenp,uint2 //fprintf(stderr,"error getting transaction %s\n",txid.GetHex().c_str()); return(0); } - std::string strHex = EncodeHexTx(tx); + string strHex = EncodeHexTx(tx); *txlenp = (int32_t)strHex.size() >> 1; if ( *txlenp > 0 ) { @@ -784,7 +751,7 @@ int32_t NSPV_sendrawtransaction(struct NSPV_broadcastresp *ptr,uint8_t *data,int //LOCK(cs_main); ptr->txid = tx.GetHash(); //fprintf(stderr,"try to addmempool transaction %s\n",ptr->txid.GetHex().c_str()); - if (myAddtomempool(tx) != 0) + if ( myAddtomempool(tx) != 0 ) { ptr->retcode = 1; //int32_t i; @@ -792,63 +759,54 @@ int32_t NSPV_sendrawtransaction(struct NSPV_broadcastresp *ptr,uint8_t *data,int // fprintf(stderr,"%02x",data[i]); fprintf(stderr," relay transaction %s retcode.%d\n",ptr->txid.GetHex().c_str(),ptr->retcode); RelayTransaction(tx); - } - else - ptr->retcode = -3; + } else ptr->retcode = -3; - } - else - ptr->retcode = -1; + } else ptr->retcode = -1; return(sizeof(*ptr)); } // get txproof for txid, // to get the proof object the height should be passed // otherwise only block hash alone will be returned -// Note: not clear why we should have passed the height? Txid is sufficient, let's ignore height -int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid /*, int32_t height*/) +int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid, int32_t height) { - int32_t len = 0; + int32_t flag = 0, len = 0; CTransaction _tx; uint256 hashBlock; CBlock block; CBlockIndex* pindex; ptr->height = -1; - if ((ptr->tx = NSPV_getrawtx(_tx, hashBlock, &ptr->txlen, txid)) != nullptr) { + if ((ptr->tx = NSPV_getrawtx(_tx, hashBlock, &ptr->txlen, txid)) != 0) { ptr->txid = txid; ptr->vout = vout; ptr->hashblock = hashBlock; - { - LOCK(cs_main); + if (height == 0) ptr->height = komodo_blockheight(hashBlock); - pindex = komodo_chainactive(ptr->height); - } - if (pindex != nullptr && komodo_blockload(block, pindex) == 0) { - bool found = false; - BOOST_FOREACH (const CTransaction& tx, block.vtx) { - if (tx.GetHash() == txid) { - found = true; - break; + else { + ptr->height = height; + if ((pindex = komodo_chainactive(height)) != 0 && komodo_blockload(block, pindex) == 0) { + BOOST_FOREACH (const CTransaction& tx, block.vtx) { + if (tx.GetHash() == txid) { + flag = 1; + break; + } } - } - if (found) { - std::set setTxids; - CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); - setTxids.insert(txid); - CMerkleBlock mb(block, setTxids); - ssMB << mb; - std::vector proof(ssMB.begin(), ssMB.end()); - ptr->txprooflen = (int32_t)proof.size(); - LogPrint("nspv-details", "%s txid.%s found txproof.(%s) height.%d\n", __func__, txid.GetHex().c_str(), HexStr(proof).c_str(), ptr->height); - if (ptr->txprooflen > 0) { - ptr->txproof = (uint8_t*)calloc(1, ptr->txprooflen); - memcpy(ptr->txproof, &proof[0], ptr->txprooflen); + if (flag != 0) { + set setTxids; + CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); + setTxids.insert(txid); + CMerkleBlock mb(block, setTxids); + ssMB << mb; + std::vector proof(ssMB.begin(), ssMB.end()); + ptr->txprooflen = (int32_t)proof.size(); + LogPrint("nspv-details", "%s txid.%s found txproof.(%s) height.%d\n", __func__, txid.GetHex().c_str(), HexStr(proof).c_str(), ptr->height); + if (ptr->txprooflen > 0) { + ptr->txproof = (uint8_t*)calloc(1, ptr->txprooflen); + memcpy(ptr->txproof, &proof[0], ptr->txprooflen); + } + //fprintf(stderr,"gettxproof slen.%d\n",(int32_t)(sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen)); } - //fprintf(stderr,"gettxproof slen.%d\n",(int32_t)(sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen)); - } - else { - LogPrint("nspv-details", "%s txid=%s not found in the block of ht=%d", __func__, txid.GetHex().c_str(), ptr->height); } } ptr->unspentvalue = CCgettxout(txid, vout, 1, 1); @@ -859,9 +817,6 @@ int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid /*, int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp *ptr,uint256 prevntztxid,uint256 nextntztxid) { int32_t i; uint256 hashBlock,bhash0,bhash1,desttxid0,desttxid1; CTransaction tx; - - LOCK(cs_main); - ptr->prevtxid = prevntztxid; ptr->prevntz = NSPV_getrawtx(tx,hashBlock,&ptr->prevtxlen,ptr->prevtxid); ptr->prevtxidht = komodo_blockheight(hashBlock); @@ -872,7 +827,7 @@ int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp *ptr,uint256 prevntztxid ptr->nexttxid = nextntztxid; ptr->nextntz = NSPV_getrawtx(tx,hashBlock,&ptr->nexttxlen,ptr->nexttxid); - ptr->nexttxidht = ptr->prevtxidht; // komodo_blockheight(hashBlock); + ptr->nexttxidht = komodo_blockheight(hashBlock); if ( NSPV_notarizationextract(0,&ptr->common.nextht,&bhash1,&desttxid1,tx) < 0 ) return(-5); else if ( komodo_blockheight(bhash1) != ptr->common.nextht ) @@ -903,22 +858,24 @@ int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp *ptr,uint256 prevntztxid return(sizeof(*ptr) + sizeof(*ptr->common.hdrs)*ptr->common.numhdrs - sizeof(ptr->common.hdrs) - sizeof(ptr->prevntz) - sizeof(ptr->nextntz) + ptr->prevtxlen + ptr->nexttxlen); } -int32_t NSPV_getspentinfo(struct NSPV_spentinfo* ptr, uint256 txid, int32_t vout) +int32_t NSPV_getspentinfo(struct NSPV_spentinfo *ptr,uint256 txid,int32_t vout) { int32_t len = 0; ptr->txid = txid; ptr->vout = vout; ptr->spentvini = -1; len = (int32_t)(sizeof(*ptr) - sizeof(ptr->spent.tx) - sizeof(ptr->spent.txproof)); - if (CCgetspenttxid(ptr->spent.txid, ptr->spentvini, ptr->spent.height, txid, vout) == 0) { - if (NSPV_gettxproof(&ptr->spent, 0, ptr->spent.txid /*,ptr->spent.height*/) > 0) + if ( CCgetspenttxid(ptr->spent.txid,ptr->spentvini,ptr->spent.height,txid,vout) == 0 ) + { + if ( NSPV_gettxproof(&ptr->spent,0,ptr->spent.txid,ptr->spent.height) > 0 ) len += ptr->spent.txlen + ptr->spent.txprooflen; - else { + else + { NSPV_txproof_purge(&ptr->spent); - return (-1); + return(-1); } } - return (len); + return(len); } void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a request @@ -935,21 +892,14 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req int32_t len = request.size(); // rate limit no more 1 request/sec of same type from same node: - int32_t nData = request[0] >> 1; - if (nData >= sizeof(pfrom->nspvdata)/sizeof(pfrom->nspvdata[0]) ) - nData = (int32_t)(sizeof(pfrom->nspvdata)/sizeof(pfrom->nspvdata[0])) - 1; - if (pfrom->nspvdata[nData].prevtime > timestamp) { - pfrom->nspvdata[nData].prevtime = 0; - pfrom->nspvdata[nData].nreqs = 0; - } - else if (timestamp == pfrom->nspvdata[nData].prevtime) { - if (pfrom->nspvdata[nData].nreqs > NSPV_MAXREQSPERSEC) { - LogPrint("nspv", "rate limit reached from peer %d\n", pfrom->id); - return; - } - } - else { - pfrom->nspvdata[nData].nreqs = 0; + int32_t ind = request[0] >> 1; + if (ind >= sizeof(pfrom->prevtimes)/sizeof(*pfrom->prevtimes) ) + ind = (int32_t)(sizeof(pfrom->prevtimes)/sizeof(*pfrom->prevtimes)) - 1; + if (pfrom->prevtimes[ind] > timestamp) + pfrom->prevtimes[ind] = 0; + else if (timestamp == pfrom->prevtimes[ind]) { + LogPrint("nspv", "rate limit from peer %d\n", pfrom->id); + return; } switch(request[0]) @@ -957,7 +907,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req case NSPV_INFO: // info { struct NSPV_inforesp I; - //fprintf(stderr,"check info %u vs %u, ind.%d\n", timestamp, pfrom->nspvdata[ind].prevtime, ind); + //fprintf(stderr,"check info %u vs %u, ind.%d\n",timestamp,pfrom->prevtimes[ind],ind); if (len == 1 + sizeof(reqheight)) iguana_rwnum(IGUANA_READ, &request[1], sizeof(reqheight), &reqheight); else @@ -972,8 +922,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { //fprintf(stderr,"send info resp to id %d\n",(int32_t)pfrom->id); pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_INFO response: version %d to node=%d\n", I.version, pfrom->id); } else @@ -989,9 +938,9 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req struct NSPV_utxosresp U; char coinaddr[KOMODO_ADDRESS_BUFSIZE]; int32_t skipcount = 0; - int32_t maxrecords = 0; + uint32_t filter = 0; uint8_t isCC = 0; - //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); + //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->prevtimes[ind],ind,len); if (len < 2) { LogPrint("nspv", "NSPV_UTXOS bad request too short len.%d node %d\n", len, pfrom->id); @@ -1017,10 +966,10 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { iguana_rwnum(IGUANA_READ, &request[offset], sizeof(skipcount), &skipcount); offset += sizeof(skipcount); - if (offset + sizeof(maxrecords) <= len) + if (offset + sizeof(filter) <= len) { - iguana_rwnum(IGUANA_READ, &request[offset], sizeof(maxrecords), &maxrecords); - offset += sizeof(maxrecords); + iguana_rwnum(IGUANA_READ, &request[offset], sizeof(filter), &filter); + offset += sizeof(filter); } } } @@ -1029,17 +978,16 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req return; } - LogPrint("nspv-details", "NSPV_UTXOS address=%s isCC.%d skipcount.%d maxrecords.%d\n", coinaddr, isCC, skipcount, maxrecords); + LogPrint("nspv-details", "NSPV_UTXOS address=%s isCC.%d skipcount.%d filter.%x\n", coinaddr, isCC, skipcount, filter); memset(&U, 0, sizeof(U)); - if ((slen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, maxrecords)) > 0) + if ((slen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, filter)) > 0) { response.resize(1 + slen); response[0] = NSPV_UTXOSRESP; if ( NSPV_rwutxosresp(IGUANA_WRITE, &response[1], &U) == slen ) { pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_UTXOS response: numutxos=%d to node=%d\n", U.numutxos, pfrom->id); } else @@ -1047,7 +995,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req NSPV_utxosresp_purge(&U); } else - LogPrint("nspv", "NSPV_getaddressutxos error slen.%d\n", slen); + LogPrint("nspv", "NSPV_getaddressutxos error.%d\n", slen); } break; @@ -1056,9 +1004,9 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req struct NSPV_txidsresp T; char coinaddr[KOMODO_ADDRESS_BUFSIZE]; int32_t skipcount = 0; - int32_t maxrecords = 0; + uint32_t filter = 0; uint8_t isCC = 0; - //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); + //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->prevtimes[ind],ind,len); if (len < 2) { LogPrint("nspv", "NSPV_TXIDS bad request too short len.%d, node %d\n", len, pfrom->id); @@ -1084,10 +1032,10 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { iguana_rwnum(IGUANA_READ, &request[offset], sizeof(skipcount), &skipcount); offset += sizeof(skipcount); - if (offset + sizeof(maxrecords) <= len) + if (offset + sizeof(filter) <= len) { - iguana_rwnum(IGUANA_READ, &request[offset], sizeof(maxrecords), &maxrecords); - offset += sizeof(maxrecords); + iguana_rwnum(IGUANA_READ, &request[offset], sizeof(filter), &filter); + offset += sizeof(filter); } } } @@ -1096,10 +1044,10 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req return; } - LogPrint("nspv-details", "NSPV_TXIDS address=%s isCC.%d skipcount.%d maxrecords.%x\n",coinaddr, isCC, skipcount, maxrecords); + LogPrint("nspv-details", "NSPV_TXIDS address=%s isCC.%d skipcount.%d filter.%x\n",coinaddr, isCC, skipcount, filter); memset(&T, 0, sizeof(T)); - if ((slen = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, maxrecords)) > 0) + if ((slen = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, filter)) > 0) { //fprintf(stderr,"slen.%d\n",slen); response.resize(1 + slen); @@ -1107,8 +1055,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwtxidsresp(IGUANA_WRITE, &response[1], &T) == slen) { pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_TXIDS response: numtxids=%d to node=%d\n", (int)T.numtxids, pfrom->id); } else @@ -1149,8 +1096,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req response[0] = NSPV_MEMPOOLRESP; if (NSPV_rwmempoolresp(IGUANA_WRITE, &response[1], &M) == slen) { pfrom->PushMessage("nSPV", response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_MEMPOOL response: numtxids=%d to node=%d\n", M.numtxids, pfrom->id); } else LogPrint("nspv", "NSPV_rwmempoolresp incorrect response len.%d\n", slen); @@ -1182,8 +1128,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwntzsresp(IGUANA_WRITE, &response[1], &N) == slen) { pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_NTZS response: prevntz.txid=%s nextntx.txid=%s node=%d\n", N.prevntz.txid.GetHex().c_str(), N.nextntz.txid.GetHex().c_str(), pfrom->id); } else @@ -1214,8 +1159,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwntzsproofresp(IGUANA_WRITE, &response[1], &P) == slen) { pfrom->PushMessage("nSPV", response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_NTZSPROOF response: prevtxidht=%d nexttxidht=%d node=%d\n", P.prevtxidht, P.nexttxidht, pfrom->id); } else @@ -1242,7 +1186,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req iguana_rwbignum(IGUANA_READ, &request[1 + sizeof(height) + sizeof(vout)], sizeof(txid), (uint8_t*)&txid); //fprintf(stderr,"got txid %s/v%d ht.%d\n",txid.GetHex().c_str(),vout,height); memset(&P, 0, sizeof(P)); - if ((slen = NSPV_gettxproof(&P, vout, txid /*,height*/)) > 0) + if ((slen = NSPV_gettxproof(&P,vout,txid,height)) > 0) { //fprintf(stderr,"slen.%d\n",slen); response.resize(1 + slen); @@ -1251,8 +1195,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { //fprintf(stderr,"send response\n"); pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_TXPROOF response: txlen=%d txprooflen=%d node=%d\n", P.txlen, P.txprooflen, pfrom->id); } else @@ -1285,8 +1228,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwspentinfo(IGUANA_WRITE, &response[1], &S) == slen) { pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_SPENTINFO response: spent txid=%s vout=%d node=%d\n", S.txid.GetHex().c_str(), S.vout, pfrom->id); } else @@ -1320,8 +1262,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwbroadcastresp(IGUANA_WRITE, &response[1], &B) == slen) { pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_BROADCAST response: txid=%s vout=%d to node=%d\n", B.txid.GetHex().c_str(), pfrom->id); } else @@ -1349,8 +1290,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req response[0] = NSPV_REMOTERPCRESP; NSPV_rwremoterpcresp(IGUANA_WRITE, &response[1], &R, slen); pfrom->PushMessage("nSPV", response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_REMOTERPCRESP response: method=%s json=%s to node=%d\n", R.method, R.json, pfrom->id); NSPV_remoterpc_purge(&R); } @@ -1369,7 +1309,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req char funcids[27]; uint256 filtertxid; bool errorFormat = false; - //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); + //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->prevtimes[ind],ind,len); if (len < 3) { LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short, node=%d\n", len, pfrom->id); @@ -1419,8 +1359,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if (NSPV_rwutxosresp(IGUANA_WRITE, &response[1], &U) == slen) { pfrom->PushMessage("nSPV", response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->prevtimes[ind] = timestamp; LogPrint("nspv-details", "NSPV_CCMODULEUTXOS returned %d utxos to node=%d\n", (int)U.numutxos, pfrom->id); } else diff --git a/src/komodo_nSPV_superlite.h b/src/komodo_nSPV_superlite.h index c7a20d82a94..0977b59ab1d 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -17,15 +17,6 @@ #ifndef KOMODO_NSPVSUPERLITE_H #define KOMODO_NSPVSUPERLITE_H -#include - -#include "main.h" -#include "komodo_defs.h" -#include "notarisationdb.h" -#include "rpc/server.h" -#include "cc/CCinclude.h" -#include "komodo_nSPV_defs.h" -#include "komodo_nSPV.h" #include "komodo_DEX.h" // nSPV client. VERY simplistic "single threaded" networking model. for production GUI best to multithread, etc. @@ -240,17 +231,17 @@ CNode *NSPV_req(CNode *pnode,uint8_t *msg,int32_t len,uint64_t mask,int32_t ind) n = 0; BOOST_FOREACH(CNode *ptr,vNodes) { - if ( ptr->nspvdata[ind].prevtime > timestamp ) - ptr->nspvdata[ind].prevtime = 0; + if ( ptr->prevtimes[ind] > timestamp ) + ptr->prevtimes[ind] = 0; if ( ptr->hSocket == INVALID_SOCKET ) continue; - if ( (ptr->nServices & mask) == mask && timestamp > ptr->nspvdata[ind].prevtime ) + if ( (ptr->nServices & mask) == mask && timestamp > ptr->prevtimes[ind] ) { flag = 1; pnodes[n++] = ptr; if ( n == sizeof(pnodes)/sizeof(*pnodes) ) break; - } // else fprintf(stderr,"nServices %llx vs mask %llx, t%u vs %u, ind.%d\n",(long long)ptr->nServices,(long long)mask,timestamp,ptr->nspvdata[ind].prevtime,ind); + } // else fprintf(stderr,"nServices %llx vs mask %llx, t%u vs %u, ind.%d\n",(long long)ptr->nServices,(long long)mask,timestamp,ptr->prevtimes[ind],ind); } if ( n > 0 ) pnode = pnodes[rand() % n]; @@ -263,7 +254,7 @@ CNode *NSPV_req(CNode *pnode,uint8_t *msg,int32_t len,uint64_t mask,int32_t ind) if ( (0) && KOMODO_NSPV_SUPERLITE ) fprintf(stderr,"pushmessage [%d] len.%d\n",msg[0],len); pnode->PushMessage("getnSPV",request); - pnode->nspvdata[ind].prevtime = timestamp; + pnode->prevtimes[ind] = timestamp; return(pnode); } else fprintf(stderr,"no pnodes\n"); return(0); @@ -294,11 +285,11 @@ void komodo_nSPV(CNode *pto) // polling loop from SendMessages NSPV_logout(); if ( (pto->nServices & NODE_NSPV) == 0 ) return; - if ( pto->nspvdata[NSPV_INFO>>1].prevtime > timestamp ) - pto->nspvdata[NSPV_INFO>>1].prevtime = 0; + if ( pto->prevtimes[NSPV_INFO>>1] > timestamp ) + pto->prevtimes[NSPV_INFO>>1] = 0; if ( KOMODO_NSPV_SUPERLITE ) { - if ( timestamp > NSPV_lastinfo + ASSETCHAINS_BLOCKTIME/2 && timestamp > pto->nspvdata[NSPV_INFO>>1].prevtime + 2*ASSETCHAINS_BLOCKTIME/3 ) + if ( timestamp > NSPV_lastinfo + ASSETCHAINS_BLOCKTIME/2 && timestamp > pto->prevtimes[NSPV_INFO>>1] + 2*ASSETCHAINS_BLOCKTIME/3 ) { int32_t reqht; reqht = 0; @@ -421,7 +412,7 @@ UniValue NSPV_utxosresp_json(struct NSPV_utxosresp *ptr) result.push_back(Pair("balance",(double)ptr->total/COIN)); if ( ASSETCHAINS_SYMBOL[0] == 0 ) result.push_back(Pair("interest",(double)ptr->interest/COIN)); - result.push_back(Pair("maxrecords",(int64_t)ptr->maxrecords)); + result.push_back(Pair("filter",(int64_t)ptr->filter)); result.push_back(Pair("lastpeer",NSPV_lastpeer)); return(result); } @@ -452,7 +443,7 @@ UniValue NSPV_txidsresp_json(struct NSPV_txidsresp *ptr) result.push_back(Pair("isCC",ptr->CCflag)); result.push_back(Pair("height",(int64_t)ptr->nodeheight)); result.push_back(Pair("numtxids",(int64_t)ptr->numtxids)); - result.push_back(Pair("maxrecords",(int64_t)ptr->maxrecords)); + result.push_back(Pair("filter",(int64_t)ptr->filter)); result.push_back(Pair("lastpeer",NSPV_lastpeer)); return(result); } diff --git a/src/komodo_nSPV_wallet.h b/src/komodo_nSPV_wallet.h index e50ace003c5..658d782c976 100644 --- a/src/komodo_nSPV_wallet.h +++ b/src/komodo_nSPV_wallet.h @@ -17,10 +17,8 @@ #ifndef KOMODO_NSPVWALLET_H #define KOMODO_NSPVWALLET_H -#include "rpc/server.h" - // nSPV wallet uses superlite functions (and some komodod built in functions) to implement nSPV_spend -//extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); int32_t NSPV_validatehdrs(struct NSPV_ntzsproofresp *ptr) { @@ -391,7 +389,6 @@ UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis) // what its a mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; mtx.nVersion = SAPLING_TX_VERSION; if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - LOCK(cs_main); if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) mtx.nLockTime = (uint32_t)time(NULL) - 777; else diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 6b2b70be529..e3a9e58dbd7 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -12,12 +12,9 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ -#include "key_io.h" -#include "net.h" -#include "util.h" #include "komodo_defs.h" +#include "key_io.h" #include "cc/CCinclude.h" -#include "importcoin.h" #include #ifdef _WIN32 @@ -1672,6 +1669,10 @@ uint64_t komodo_ac_block_subsidy(int nHeight) return(subsidy); } +extern int64_t MAX_MONEY; +void komodo_cbopretupdate(int32_t forceflag); +void SplitStr(const std::string& strVal, std::vector &outVals); + int8_t equihash_params_possible(uint64_t n, uint64_t k) { /* To add more of these you also need to edit: @@ -1771,10 +1772,10 @@ void komodo_args(char *argv0) ASSETCHAINS_PUBLIC = GetArg("-ac_public",0); ASSETCHAINS_PRIVATE = GetArg("-ac_private",0); KOMODO_SNAPSHOT_INTERVAL = GetArg("-ac_snapshot",0); - SplitIntoU64List(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); + Split(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); // -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height.... - SplitIntoU64List(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), ccEnablesHeight, 0); + Split(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), ccEnablesHeight, 0); // fill map with all eval codes and activation height of 0. for ( int i = 0; i < 256; i++ ) mapHeightEvalActivate[i] = 0; @@ -1848,11 +1849,11 @@ void komodo_args(char *argv0) ASSETCHAINS_TIMEUNLOCKFROM = ASSETCHAINS_TIMEUNLOCKTO = 0; } - SplitIntoU64List(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0); - SplitIntoU64List(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0); - SplitIntoU64List(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0); - SplitIntoU64List(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); - SplitIntoU64List(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); + Split(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0); + Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0); + Split(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0); + Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); + Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); for ( int i = 0; i < ASSETCHAINS_MAX_ERAS; i++ ) { @@ -1922,7 +1923,7 @@ void komodo_args(char *argv0) { uint8_t prevCCi = 0; ASSETCHAINS_CCLIB = GetArg("-ac_cclib",""); - SplitIntoU64List(GetArg("-ac_ccenable",""), sizeof(ccenables)/sizeof(*ccenables), ccenables, 0); + Split(GetArg("-ac_ccenable",""), sizeof(ccenables)/sizeof(*ccenables), ccenables, 0); for (i=nonz=0; i<0x100; i++) { if ( ccenables[i] != prevCCi && ccenables[i] != 0 ) @@ -1988,7 +1989,7 @@ void komodo_args(char *argv0) } else if ( ASSETCHAINS_SELFIMPORT == "PEGSCC") { - SplitIntoU64List(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); + Split(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); if (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_COMMISSION!=0) { fprintf(stderr,"when using import for pegsCC these must be set: -ac_end=1 -ac_perc=0\n"); @@ -2493,154 +2494,4 @@ void komodo_prefetch(FILE *fp) /* bool komodo_Is2021JuneHFActive() { return GetLatestTimestamp(komodo_currentheight()) > JUNE2021_NNELECTION_HARDFORK; -} */ - -int32_t KOMODO_LONGESTCHAIN; -int32_t komodo_longestchain() -{ - static int32_t depth; - int32_t ht,n=0,num=0,maxheight=0,height = 0; - if ( depth < 0 ) - depth = 0; - if ( depth == 0 ) - { - - /** - * Seems here we need to try to lock cs_main, to avoid wrong order of lock (cs_main, cs_vNodes), - * implementation of getting max(nStartingHeight, nSyncHeight, nCommonHeight) from CNodeStateStats - * and loop here is similar to getpeerinfo RPC and there we have LOCK(cs_main). If we'll not able - * to acquire lock on cs_main komodo_longestchain() will return previous saved value of - * KOMODO_LONGESTCHAIN, anyway, on next call it will be updated, when lock will success. - */ - - TRY_LOCK(cs_main, lockMain); // Acquire cs_main - if (!lockMain) { - return(KOMODO_LONGESTCHAIN); - } - - depth++; - vector vstats; - { - //LOCK(cs_main); - CopyNodeStats(vstats); - } - BOOST_FOREACH(const CNodeStats& stats, vstats) - { - //fprintf(stderr,"komodo_longestchain iter.%d\n",n); - CNodeStateStats statestats; - bool fStateStats = GetNodeStateStats(stats.nodeid,statestats); - if ( statestats.nSyncHeight < 0 ) - continue; - ht = 0; - if ( stats.nStartingHeight > ht ) - ht = stats.nStartingHeight; - if ( statestats.nSyncHeight > ht ) - ht = statestats.nSyncHeight; - if ( statestats.nCommonHeight > ht ) - ht = statestats.nCommonHeight; - if ( maxheight == 0 || ht > maxheight*1.01 ) - maxheight = ht, num = 1; - else if ( ht > maxheight*0.99 ) - num++; - if ( ht > height ) - height = ht; - } - depth--; - if ( num > (n >> 1) ) - { - if ( 0 && height != KOMODO_LONGESTCHAIN ) - fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",ASSETCHAINS_SYMBOL,height); - KOMODO_LONGESTCHAIN = height; - return(height); - } - KOMODO_LONGESTCHAIN = 0; - } - return(KOMODO_LONGESTCHAIN); -} - -int64_t komodo_get_blocktime(uint256 hashBlock) -{ - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi != mapBlockIndex.end() && (*mi).second) - { - CBlockIndex* pindex = (*mi).second; - if (chainActive.Contains(pindex)) - return pindex->GetBlockTime(); - } - return 0; -} - -int32_t komodo_get_current_height() -{ - if ( KOMODO_NSPV_SUPERLITE ) - { - return (NSPV_inforesult.height); - } - else return chainActive.LastTip()->GetHeight(); -} - -bool komodo_txnotarizedconfirmed(uint256 txid, int32_t minconfirms) -{ - char str[65]; - int32_t confirms,minimumconfirms,notarized=0,txheight=0,currentheight=0;; - CTransaction tx; - uint256 hashBlock; - CBlockIndex *pindex; - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - - if (minconfirms==0) return (true); - if ( KOMODO_NSPV_SUPERLITE ) - { - if ( NSPV_myGetTransaction(txid,tx,hashBlock,txheight,currentheight) == 0 ) - { - fprintf(stderr,"komodo_txnotarizedconfirmed cant find txid %s\n",txid.ToString().c_str()); - return(0); - } - else if (txheight<=0) - { - fprintf(stderr,"komodo_txnotarizedconfirmed no txheight.%d for txid %s\n",txheight,txid.ToString().c_str()); - return(0); - } - else if (txheight>currentheight) - { - fprintf(stderr,"komodo_txnotarizedconfirmed backwards heights for txid %s hts.(%d %d)\n",txid.ToString().c_str(),txheight,currentheight); - return(0); - } - confirms=1 + currentheight - txheight; - } - else - { - 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= komodo_blockindex(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 (minconfirms>1) minimumconfirms=minconfirms; - else minimumconfirms=MIN_NON_NOTARIZED_CONFIRMS; - 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 >= minimumconfirms) - return (true); - return (false); -} +} */ \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 7e7bd0051d2..572e137390d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -80,14 +80,14 @@ using namespace std; #define TMPFILE_START 100000000 CCriticalSection cs_main; -//extern uint8_t NOTARY_PUBKEY33[33]; -//extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI; +extern uint8_t NOTARY_PUBKEY33[33]; +extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI; int32_t KOMODO_NEWBLOCKS; -//int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); +int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); //void komodo_broadcast(CBlock *pblock,int32_t limit); -//bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); -//void komodo_setactivation(int32_t height); -//void komodo_pricesupdate(int32_t height,CBlock *pblock); +bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); +void komodo_setactivation(int32_t height); +void komodo_pricesupdate(int32_t height,CBlock *pblock); BlockMap mapBlockIndex; CChain chainActive; @@ -649,7 +649,6 @@ CBlockTreeDB *pblocktree = NULL; // Komodo globals #define KOMODO_ZCASH -#include "komodo_defs.h" #include "komodo.h" UniValue komodo_snapshot(int top) @@ -1454,7 +1453,7 @@ int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime) // from ac_private return(0); } -//int32_t komodo_acpublic(uint32_t tiptime); +int32_t komodo_acpublic(uint32_t tiptime); bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransaction& tx, CValidationState &state) { @@ -1815,7 +1814,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (limit > 0) { size_t n = tx.vin.size(); if (n > limit) { - LogPrint("mempool", "Dropping txid %s : too many transparent inputs %zu > limit %zu\n", tx.GetHash().ToString().c_str(), n, limit ); + LogPrint("mempool", "Dropping txid %s : too many transparent inputs %zu > limit %zu\n", tx.GetHash().ToString(), n, limit ); return state.Error("AcceptToMemoryPool: too many inputs"); } } @@ -1823,13 +1822,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa auto verifier = libzcash::ProofVerifier::Strict(); if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,chainActive.LastTip()->GetHeight()+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 ) { - LogPrint("mempool-tx", "%s: komodo_validate_interest failed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n"); return state.Error("AcceptToMemoryPool: komodo_validate_interest failed"); } if (!CheckTransaction(tiptime,tx, state, verifier, 0, 0)) { - LogPrint("mempool", "%s: CheckTransaction failed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return error("AcceptToMemoryPool: CheckTransaction failed"); // state must be already set } @@ -1837,14 +1835,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Check transaction contextually against the set of consensus rules which apply in the next block to be mined. if (!ContextualCheckTransaction(0,0,0,tx, state, nextBlockHeight, (dosLevel == -1) ? 10 : dosLevel)) { - LogPrint("mempool-tx", "%s: ContextualCheckTransaction failed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return error("AcceptToMemoryPool: ContextualCheckTransaction failed"); // state must be already set } //fprintf(stderr,"addmempool 2\n"); // Coinbase is only valid in a block, not as a loose transaction if (tx.IsCoinBase()) { - LogPrint("mempool-tx", "%s: coinbase as individual tx not supported, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + fprintf(stderr,"AcceptToMemoryPool coinbase as individual tx\n"); return state.DoS(100, error("AcceptToMemoryPool: coinbase as individual tx"), REJECT_INVALID, "coinbase"); } @@ -1852,7 +1849,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa string reason; if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) { - LogPrint("mempool-tx","%s reject nonstandard transaction: reason %s tx: %s\n", __func__, reason.c_str(), HexStr(E_MARSHAL(ss << tx)).c_str()); + //fprintf(stderr,"AcceptToMemoryPool reject nonstandard transaction: %s\nscriptPubKey: %s\n",reason.c_str(),tx.vout[0].scriptPubKey.ToString().c_str()); return state.DoS(0,error("AcceptToMemoryPool: nonstandard transaction: %s", reason), REJECT_NONSTANDARD, reason); } @@ -1861,7 +1858,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // be mined yet. if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) { - LogPrint("mempool-tx", "%s: reject non final, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + //fprintf(stderr,"AcceptToMemoryPool reject non-final\n"); return state.DoS(0, false, REJECT_NONSTANDARD, "non-final"); } //fprintf(stderr,"addmempool 3\n"); @@ -1869,7 +1866,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa uint256 hash = tx.GetHash(); if (pool.exists(hash)) { - LogPrint("mempool-tx", "%s: reject already in mempool, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + //fprintf(stderr,"already in mempool\n"); return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); } @@ -1882,7 +1879,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (pool.mapNextTx.count(outpoint)) { // Disable replacement feature for now - LogPrint("mempool-tx", "%s: transaction replacement in mempool not allowed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Error("AcceptToMemoryPool: transaction replacement in mempool not allowed"); } } @@ -1916,17 +1912,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (view.HaveCoins(hash)) { //fprintf(stderr,"view.HaveCoins(hash) error\n"); - LogPrint("mempool-tx", "%s: already have coins, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Invalid(false, REJECT_DUPLICATE, "already have coins"); } if (tx.IsCoinImport() || tx.IsPegsImport()) { // Inverse of normal case; if input exists, it's been spent - if (ExistsImportTombstone(tx, view)) { - LogPrint("mempool-tx", "%s: import tombstone exists, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + if (ExistsImportTombstone(tx, view)) return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists"); - } } else { @@ -1939,7 +1932,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { if (pfMissingInputs) *pfMissingInputs = true; - LogPrint("mempool-tx", "%s missing inputs for tx %s prevout.hash=%s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str(), txin.prevout.hash.GetHex().c_str()); + fprintf(stderr,"%s missing inputs for tx %s prevout.hash=%s\n", __func__, tx.GetHash().GetHex().c_str(), txin.prevout.hash.GetHex().c_str()); //TODO: remove return false; /* https://github.com/zcash/zcash/blob/master/src/main.cpp#L1490 @@ -1951,7 +1944,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (!view.HaveInputs(tx)) { //fprintf(stderr,"accept failure.1\n"); - LogPrint("mempool-tx", "%s inputs already spent for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); } } @@ -1973,10 +1965,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa view.SetBackend(dummy); } // Check for non-standard pay-to-script-hash in inputs - if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId)) { - LogPrint("mempool-tx", "%s reject nonstandard transaction input for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId)) return state.Error("AcceptToMemoryPool: reject nonstandard transaction input"); - } // Check that the transaction doesn't have an excessive number of // sigops, making it impossible to mine. Since the coinbase transaction @@ -1994,10 +1984,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa CAmount nValueOut = tx.GetValueOut(); CAmount nFees = nValueIn-nValueOut; double dPriority = view.GetPriority(tx, chainActive.Height()); - if ( nValueOut > 777777*COIN && KOMODO_VALUETOOBIG(nValueOut - 777777*COIN) != 0 ) { // some room for blockreward and txfees - LogPrint("mempool-tx", "%s GetValueOut too big for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + if ( nValueOut > 777777*COIN && KOMODO_VALUETOOBIG(nValueOut - 777777*COIN) != 0 ) // some room for blockreward and txfees return state.DoS(100, error("AcceptToMemoryPool: GetValueOut too big"),REJECT_INVALID,"tx valueout is too big"); - } // Keep track of transactions that spend a coinbase, which we re-scan // during reorgs to ensure COINBASE_MATURITY is still met. @@ -2029,8 +2017,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (fLimitFree && nFees < txMinFee) { //fprintf(stderr,"accept failure.5\n"); - LogPrint("mempool-tx", "%s not enough fees for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); - return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d", hash.ToString(), nFees, txMinFee),REJECT_INSUFFICIENTFEE, "insufficient fee"); + return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d",hash.ToString(), nFees, txMinFee),REJECT_INSUFFICIENTFEE, "insufficient fee"); } } @@ -2060,7 +2047,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000) { //fprintf(stderr,"accept failure.7\n"); - LogPrint("mempool-tx", "%s free transaction rejected by rate limiter for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(0, error("AcceptToMemoryPool: free transaction rejected by rate limiter"), REJECT_INSUFFICIENTFEE, "rate limited free transaction"); } LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize); @@ -2073,7 +2059,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa hash.ToString(), nFees, ::minRelayTxFee.GetFee(nSize) * 10000); LogPrint("mempool", errmsg.c_str()); - LogPrint("mempool-tx", "%s rejected %s for tx %s\n", __func__, errmsg.c_str(), HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Error("AcceptToMemoryPool: " + errmsg); } //fprintf(stderr,"addmempool 6\n"); @@ -2085,8 +2070,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, evalcodeChecker)) { //fprintf(stderr,"accept failure.9\n"); - LogPrint("mempool-tx", "%s ConnectInputs failed for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); - return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString().c_str()); + return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString()); } // Check again against just the consensus-critical mandatory script @@ -2114,7 +2098,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } if (!ContextualCheckOutputs(tx, state, true, txdata, evalcodeChecker)) - return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ContextualCheckOutputs failed %s", hash.ToString()); + return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ContextualCheckOutputs failed %s", hash.ToString());; if (flag != 0) KOMODO_CONNECTING = -1; @@ -2483,6 +2467,12 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW) } //uint64_t komodo_moneysupply(int32_t height); +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1]; +extern uint32_t ASSETCHAINS_MAGIC; +extern uint64_t ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; +extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; +extern int32_t ASSETCHAINS_STAKED; CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) { @@ -6929,7 +6919,7 @@ bool InitBlockIndex() { pblocktree->WriteFlag("spentindex", fSpentIndex); fprintf(stderr,"fAddressIndex.%d/%d fSpentIndex.%d/%d\n",fAddressIndex,DEFAULT_ADDRESSINDEX,fSpentIndex,DEFAULT_SPENTINDEX); - fUnspentCCIndex = GetBoolArg("-unspentccindex", DEFAULT_UNSPENTCCINDEX); + fUnspentCCIndex = GetBoolArg("-unspentccindex", false); pblocktree->WriteFlag("unspentccindex", fUnspentCCIndex); fprintf(stderr, "fUnspentCCIndex.%d\n", fUnspentCCIndex); @@ -7461,18 +7451,10 @@ void static ProcessGetData(CNode* pfrom) // Send stream from relay memory bool pushed = false; { - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - bool found = false; - { - LOCK(cs_mapRelay); - map::iterator mi = mapRelay.find(inv); - if (mi != mapRelay.end()) { - ss = ((*mi).second); - found = true; - } - } - if (found) { - pfrom->PushMessage(inv.GetCommand(), ss); + LOCK(cs_mapRelay); + map::iterator mi = mapRelay.find(inv); + if (mi != mapRelay.end()) { + pfrom->PushMessage(inv.GetCommand(), (*mi).second); pushed = true; } } diff --git a/src/main.h b/src/main.h index 99fe460e118..bd03b1eb982 100644 --- a/src/main.h +++ b/src/main.h @@ -122,13 +122,13 @@ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; /** Default NSPV support enabled */ -static const bool DEFAULT_NSPV_PROCESSING = true; +#define DEFAULT_NSPV_TOKEL true +static const bool DEFAULT_NSPV_PROCESSING = DEFAULT_NSPV_TOKEL; //static const bool DEFAULT_ADDRESSINDEX = false; //static const bool DEFAULT_SPENTINDEX = false; #define DEFAULT_ADDRESSINDEX (GetArg("-ac_cc",0) != 0 || GetArg("-ac_ccactivate",0) != 0) #define DEFAULT_SPENTINDEX (GetArg("-ac_cc",0) != 0 || GetArg("-ac_ccactivate",0) != 0) -#define DEFAULT_UNSPENTCCINDEX true static const bool DEFAULT_TIMESTAMPINDEX = false; static const unsigned int DEFAULT_DB_MAX_OPEN_FILES = 1000; diff --git a/src/miner.cpp b/src/miner.cpp index e7f8a74aa75..7e44511d49f 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -64,9 +64,6 @@ #endif #include -#include "komodo_defs.h" -#include "cc/CCinclude.h" - using namespace std; ////////////////////////////////////////////////////////////////////////////// @@ -74,12 +71,6 @@ using namespace std; // BitcoinMiner // - -extern CCriticalSection cs_metrics; - -uint32_t Mining_start,Mining_height; -int32_t My_notaryid = -1; - // // Unconfirmed transactions in the memory pool often depend on other // transactions in the memory pool. When we select transactions from the @@ -142,6 +133,34 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); } } +#include "komodo_defs.h" +#include "cc/CCinclude.h" + +extern CCriticalSection cs_metrics; +void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); + +uint32_t Mining_start,Mining_height; +int32_t My_notaryid = -1; +int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); +int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize); +int32_t komodo_baseid(char *origbase); +int32_t komodo_longestchain(); +int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); +int64_t komodo_block_unlocktime(uint32_t nHeight); +uint64_t komodo_commission(const CBlock *block,int32_t height); +int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); +int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk); +uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); +int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); +int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void* ptr); +int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); +int32_t komodo_is_notarytx(const CTransaction& tx); +uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len); +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); +int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len); +CScript komodo_mineropret(int32_t nHeight); +bool komodo_appendACscriptpub(); +CScript komodo_makeopret(CBlock *pblock, bool fNew); int32_t komodo_waituntilelegible(uint32_t blocktime, int32_t stakeHeight, uint32_t delay) { @@ -1117,10 +1136,13 @@ static bool ProcessBlockFound(CBlock* pblock) return true; } - -int32_t FOUND_BLOCK, KOMODO_MAYBEMINED; +int32_t komodo_baseid(char *origbase); +int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); +arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); +int32_t FOUND_BLOCK,KOMODO_MAYBEMINED; +extern int32_t KOMODO_LASTMINED,KOMODO_INSYNC; int32_t roundrobin_delay; -arith_uint256 HASHTarget, HASHTarget_POW; +arith_uint256 HASHTarget,HASHTarget_POW; // wait for peers to connect void waitForPeers(const CChainParams &chainparams) @@ -1169,17 +1191,19 @@ void waitForPeers(const CChainParams &chainparams) } #ifdef ENABLE_WALLET -CBlockIndex* get_chainactive(int32_t height) +CBlockIndex *get_chainactive(int32_t height) { - LOCK(cs_main); // moved lock at the begininng as getting the vector size is unsafe in the multithread env - if (chainActive.LastTip() != 0) { - if (height <= chainActive.LastTip()->GetHeight()) { - return (chainActive[height]); + if ( chainActive.LastTip() != 0 ) + { + if ( height <= chainActive.LastTip()->GetHeight() ) + { + LOCK(cs_main); + return(chainActive[height]); } // else fprintf(stderr,"get_chainactive height %d > active.%d\n",height,chainActive.Tip()->GetHeight()); } //fprintf(stderr,"get_chainactive null chainActive.Tip() height %d\n",height); - return (0); + return(0); } /* diff --git a/src/net.cpp b/src/net.cpp index aa60ade5966..5fe1660254f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2145,7 +2145,6 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa nPingUsecTime = 0; fPingQueued = false; nMinPingUsecTime = std::numeric_limits::max(); - memset(nspvdata, '\0', sizeof(nspvdata)); { LOCK(cs_nLastNodeId); diff --git a/src/net.h b/src/net.h index 9ea83161f2e..e1f16972b67 100644 --- a/src/net.h +++ b/src/net.h @@ -284,11 +284,7 @@ class CNode int64_t nLastRecv; int64_t nTimeConnected; int64_t nTimeOffset; - struct { - uint32_t prevtime; - uint32_t nreqs; - } nspvdata[16]; - uint32_t dexlastping; + uint32_t prevtimes[16],dexlastping; // Address of this peer CAddress addr; // Bind address of our side of the connection diff --git a/src/rest.cpp b/src/rest.cpp index 63de162c8fb..3fb87f8f386 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -71,6 +71,12 @@ struct CCoin { } }; +extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); +extern UniValue mempoolInfoToJSON(); +extern UniValue mempoolToJSON(bool fVerbose = false); +extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +extern UniValue blockheaderToJSON(const CBlockIndex* blockindex); static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, string message) { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 0fb2f67dce4..565a5bfb92d 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -46,16 +46,14 @@ #include "cc/CCinclude.h" #include "cc/CCPrices.h" -#include "komodo_defs.h" -#include "komodo_structs.h" - using namespace std; -//extern int32_t KOMODO_INSYNC; -//extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -//void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -//int32_t komodo_notarized_height(int32_t *prevMoMheightp, uint256 *hashp, uint256 *txidp); - +extern int32_t KOMODO_INSYNC; +extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +int32_t komodo_notarized_height(int32_t *prevMoMheightp, uint256 *hashp, uint256 *txidp); +#include "komodo_defs.h" +#include "komodo_structs.h" double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) { @@ -290,7 +288,7 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) return result; } -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails) +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) { UniValue result(UniValue::VOBJ); uint256 notarized_hash, notarized_desttxid; int32_t prevMoMheight, notarized_height; @@ -453,7 +451,7 @@ bool mytxid_inmempool(uint256 txid) return(false); } -UniValue mempoolToJSON(bool fVerbose) +UniValue mempoolToJSON(bool fVerbose = false) { if (fVerbose) { @@ -1125,6 +1123,8 @@ UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk) return ret; } +int32_t komodo_pending_withdraws(char *opretstr); +int32_t pax_fiatstatus(uint64_t *available, uint64_t *deposited, uint64_t *issued, uint64_t *withdrawn, uint64_t *approved, uint64_t *redeemed, char *base); extern char CURRENCIES[][8]; UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk) diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index 08282211851..c4bf88f7bd4 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -90,152 +90,12 @@ UniValue listccunspents(const UniValue& params, bool fHelp, const CPubKey& mypk) } -// a helper function for nspv clients: creates a tx and add normal inputs for the requested amount -UniValue createtxwithnormalinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) -{ - if (fHelp || (params.size() < 1 || params.size() > 2)) - { - string msg = "createtxwithnormalinputs amount [pubkey]\n" - "\nReturns a new tx with added normal inputs and previous txns. Note that the caller must add the change output\n" - "\nArguments:\n" - //"address which utxos are added from\n" - "amount (in satoshi) which will be added as normal inputs (equal or more)\n" - "pubkey optional, if not set -pubkey used\n" - "Result: json object with created tx and added vin txns\n\n"; - throw runtime_error(msg); - } - /*std::string address = params[0].get_str(); - if (!CBitcoinAddress(address.c_str()).IsValid()) - throw runtime_error("address invalid");*/ - CAmount amount = atoll(params[0].get_str().c_str()); - if (amount <= 0) - throw runtime_error("amount invalid"); - - CPubKey usedpk = remotepk; - if (params.size() >= 2) { - CPubKey pk = pubkey2pk(ParseHex(params[1].get_str())); - if (!pk.IsValid()) - throw runtime_error("pubkey invalid"); - usedpk = pk; - } - - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - std::vector vintxns; - CAmount added = AddNormalinputsRemote(mtx, usedpk, amount, CC_MAXVINS, &vintxns); - if (added < amount) - throw runtime_error("could not find normal inputs"); - - for (auto const & vin : mtx.vin) { - CTransaction tx; - uint256 hashBlock; - if (myGetTransaction(vin.prevout.hash, tx, hashBlock)) - vintxns.push_back(tx); - } - UniValue result (UniValue::VOBJ); - UniValue array (UniValue::VARR); - - result.pushKV("txhex", HexStr(E_MARSHAL(ss << mtx))); - for (auto const &vtx : vintxns) - array.push_back(HexStr(E_MARSHAL(ss << vtx))); - result.pushKV("previousTxns", array); - return result; -} - -// helper for nspv clients, to load several txns by their txids -UniValue gettransactionsmany(const UniValue& params, bool fHelp, const CPubKey& remotepk) -{ - if (fHelp || params.size() < 1 || params.size() > 0x1000) - { - string msg = "gettransactionsmany txid1 txid2 ...\n" - "\nReturns a list of confirmed transactions for the given txids.\n" - "\nArguments:\n" - "txid1 txid2... - txids to load, with max number of no more than 4096\n" - "Result: json object with txns in hex and optional list of txids that could not be loaded\n\n"; - throw runtime_error(msg); - } - - UniValue result(UniValue::VOBJ); - UniValue txns(UniValue::VARR); - UniValue notloaded(UniValue::VARR); - - for (size_t i = 0; i < params.size(); i ++) - { - uint256 txid = Parseuint256(params[i].get_str().c_str()); - if (txid.IsNull()) - throw std::runtime_error("txid invalid for i=" + std::to_string(i)); - - CTransaction tx; - uint256 hashBlock; - if (myGetTransaction(txid, tx, hashBlock) && !hashBlock.IsNull()) { - UniValue elem(UniValue::VOBJ); - elem.pushKV("tx", HexStr(E_MARSHAL(ss << tx))); - - LOCK(cs_main); - CBlockIndex *pindex = komodo_getblockindex(hashBlock); - if (pindex) { - CNetworkBlockHeader nethdr = pindex->GetBlockHeader(); - elem.pushKV("blockHeader", HexStr(E_MARSHAL(ss << nethdr))); - elem.pushKV("blockHeight", pindex->GetHeight()); - elem.pushKV("blockHash", hashBlock.GetHex()); - } - txns.push_back(elem); - } - else - notloaded.push_back(txid.GetHex()); - } - result.pushKV("transactions", txns); - if (!notloaded.empty()) - result.pushKV("notloaded", notloaded); - - return result; -} - -// helper for testing, returns index key for a cryptoconditon scriptPubKey -UniValue getindexkeyforcc(const UniValue& params, bool fHelp, const CPubKey& remotepk) -{ - if (fHelp || params.size() != 2) - { - string msg = "getindexkeyforcc cc-as-json is-mixed\n" - "\nReturns indexing key (formely cc address) for scriptPubKey made from a cryptocondition\n" - "\nArguments:\n" - //"address which utxos are added from\n" - "cc-as-json cryptocondition in json\n" - "is-mixed is mixed mode, true or false" - "Result: indexing key\n\n" - "Sample:\n" - "getindexkeyforcc \'{ \"type\": \"threshold-sha-256\", \"threshold\": 2, \"subfulfillments\":" - "[{\"type\":\"eval-sha-256\",\"code\":\"9A\"}, {\"type\":\"threshold-sha-256\", \"threshold\":1," - "subfulfillments\":[{ \"type\": \"secp256k1-sha-256\", \"publicKey\": \"03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12\" }] }] }\' true\n\n" - ; - throw std::runtime_error(msg); - } - - char err[128];// = ""; - CCwrapper cc = cc_conditionFromJSONString(params[0].get_str().c_str(), err); - if (cc == nullptr) - throw std::runtime_error(std::string("could not create cryptocondition: ") + err); - bool ismixed = false; - if (params[1].get_str() == "true") - ismixed = true; - else if (params[1].get_str() == "false") - ismixed = false; - else - throw std::runtime_error(std::string("is-mixed must be true or false")); - - CScript spk = CCPubKey(cc.get(), ismixed); - char ccaddress[KOMODO_ADDRESS_BUFSIZE]; - Getscriptaddress(ccaddress, spk); - return ccaddress; -} static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- - // cc helpers - { "ccutils", "listccunspents", &listccunspents, true }, - { "ccutils", "getindexkeyforcc", &getindexkeyforcc, true }, - { "nspv", "createtxwithnormalinputs", &createtxwithnormalinputs, true }, - { "nspv", "gettransactionsmany", &gettransactionsmany, true }, + // tokens & assets + { "ccutils", "listccunspents", &listccunspents, true } }; void RegisterCCUtilsRPCCommands(CRPCTable &tableRPC) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index bb0e475fd06..d2e891556c2 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -50,6 +50,12 @@ using namespace std; #include "komodo_defs.h" +extern int32_t ASSETCHAINS_FOUNDERS; +uint64_t komodo_commission(const CBlock *pblock,int32_t height); +int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex); +arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); +int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); + /** * Return average network hashes per second based on the last 'lookup' blocks, * or over the difficulty averaging window if 'lookup' is nonpositive. @@ -398,6 +404,7 @@ UniValue setgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk) } #endif +CBlockIndex *komodo_chainactive(int32_t height); arith_uint256 zawy_ctB(arith_uint256 bnTarget,uint32_t solvetime); UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index e8b09089bb3..56b3a515b77 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -28,7 +28,6 @@ #include "txmempool.h" #include "util.h" #include "notaries_staked.h" -#include "komodo_defs.h" #include "cc/eval.h" #include "cc/CCinclude.h" #ifdef ENABLE_WALLET @@ -60,8 +59,33 @@ using namespace std; * Or alternatively, create a specific query method for the information. **/ +int32_t Jumblr_depositaddradd(char *depositaddr); +int32_t Jumblr_secretaddradd(char *secretaddr); +uint64_t komodo_interestsum(); +int32_t komodo_longestchain(); +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); +//bool komodo_txnotarizedconfirmed(uint256 txid); +uint32_t komodo_chainactive_timestamp(); +int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); +extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; +extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN,IS_STAKED_NOTARY,IS_KOMODO_NOTARY,STAKED_ERA,KOMODO_INSYNC; +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +uint32_t komodo_segid32(char *coinaddr); +int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); +int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); +int8_t StakedNotaryID(std::string ¬aryname, char *Raddress); +uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); + #define KOMODO_VERSION "0.6.1" #define VERUS_VERSION "0.4.0g" +extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; +extern uint32_t ASSETCHAINS_CC; +extern uint32_t ASSETCHAINS_MAGIC,ASSETCHAINS_ALGO; +extern uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; +extern int32_t ASSETCHAINS_LWMAPOS,ASSETCHAINS_SAPLING,ASSETCHAINS_STAKED; +extern uint64_t ASSETCHAINS_ENDSUBSIDY[],ASSETCHAINS_REWARD[],ASSETCHAINS_HALVING[],ASSETCHAINS_DECAY[],ASSETCHAINS_NOTARY_PAY[]; +extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS; extern uint8_t NOTARY_PUBKEY33[]; int32_t getera(int timestamp) { @@ -197,11 +221,11 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) + HelpExampleCli("getinfo", "") + HelpExampleRpc("getinfo", "") ); - #ifdef ENABLE_WALLET - LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); - #else - LOCK(cs_main); - #endif + //#ifdef ENABLE_WALLET + // LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); + //#else + LOCK(cs_main); + //#endif proxyType proxy; GetProxy(NET_IPV4, proxy); @@ -389,8 +413,6 @@ class DescribeAddressVisitor : public boost::static_visitor } return obj; } - - UniValue operator()(const CCryptoConditionID &ccID) const { return UniValue(UniValue::VOBJ); } // cryptoconditions are not recognised in the wallet yet }; #endif diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 68a5c915063..f87d953eaf1 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -171,6 +171,69 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) return ret; } +int32_t KOMODO_LONGESTCHAIN; +int32_t komodo_longestchain() +{ + static int32_t depth; + int32_t ht,n=0,num=0,maxheight=0,height = 0; + if ( depth < 0 ) + depth = 0; + if ( depth == 0 ) + { + + /** + * Seems here we need to try to lock cs_main, to avoid wrong order of lock (cs_main, cs_vNodes), + * implementation of getting max(nStartingHeight, nSyncHeight, nCommonHeight) from CNodeStateStats + * and loop here is similar to getpeerinfo RPC and there we have LOCK(cs_main). If we'll not able + * to acquire lock on cs_main komodo_longestchain() will return previous saved value of + * KOMODO_LONGESTCHAIN, anyway, on next call it will be updated, when lock will success. + */ + + TRY_LOCK(cs_main, lockMain); // Acquire cs_main + if (!lockMain) { + return(KOMODO_LONGESTCHAIN); + } + + depth++; + vector vstats; + { + //LOCK(cs_main); + CopyNodeStats(vstats); + } + BOOST_FOREACH(const CNodeStats& stats, vstats) + { + //fprintf(stderr,"komodo_longestchain iter.%d\n",n); + CNodeStateStats statestats; + bool fStateStats = GetNodeStateStats(stats.nodeid,statestats); + if ( statestats.nSyncHeight < 0 ) + continue; + ht = 0; + if ( stats.nStartingHeight > ht ) + ht = stats.nStartingHeight; + if ( statestats.nSyncHeight > ht ) + ht = statestats.nSyncHeight; + if ( statestats.nCommonHeight > ht ) + ht = statestats.nCommonHeight; + if ( maxheight == 0 || ht > maxheight*1.01 ) + maxheight = ht, num = 1; + else if ( ht > maxheight*0.99 ) + num++; + if ( ht > height ) + height = ht; + } + depth--; + if ( num > (n >> 1) ) + { + if ( 0 && height != KOMODO_LONGESTCHAIN ) + fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",ASSETCHAINS_SYMBOL,height); + KOMODO_LONGESTCHAIN = height; + return(height); + } + KOMODO_LONGESTCHAIN = 0; + } + return(KOMODO_LONGESTCHAIN); +} + UniValue addnode(const UniValue& params, bool fHelp, const CPubKey& mypk) { string strCommand; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d20807e5331..eaf1ec002c5 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -41,12 +41,20 @@ #endif #include "komodo_defs.h" + #include + #include + #include +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); + using namespace std; +extern char ASSETCHAINS_SYMBOL[]; +int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); + void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex) { txnouttype type; @@ -132,6 +140,8 @@ UniValue TxJoinSplitToJSON(const CTransaction& tx) { return vjoinsplit; } +uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); + UniValue TxShieldedSpendsToJSON(const CTransaction& tx) { UniValue vdesc(UniValue::VARR); for (const SpendDescription& spendDesc : tx.vShieldedSpend) { diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index c8645442f4c..57068503a5b 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -876,11 +876,7 @@ std::string HelpExampleCli(const std::string& methodname, const std::string& arg } else if ((strncmp(ASSETCHAINS_SYMBOL, "HUSH3", 5) == 0) ) { return "> hush-cli " + methodname + " " + args + "\n"; } else { -#if !defined CUSTOM_BIN_NAME - return std::string("> komodo-cli -ac_name=") + std::string(ASSETCHAINS_SYMBOL) + " " + methodname + " " + args + "\n"; -#else - return std::string("> ") + std::string(CUSTOM_BIN_NAME) + std::string("-cli") + " " + methodname + " " + args + "\n"; -#endif + return "> komodo-cli -ac_name=" + strprintf("%s", ASSETCHAINS_SYMBOL) + " " + methodname + " " + args + "\n"; } } diff --git a/src/rpc/server.h b/src/rpc/server.h index f8e27b156fb..5975e0e1d8b 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -35,9 +35,6 @@ #include #include -#include "primitives/block.h" -#include "primitives/transaction.h" -#include "script/script.h" class AsyncRPCQueue; class CRPCCommand; @@ -183,363 +180,355 @@ extern CRPCTable tableRPC; * Utilities: convert hex-encoded Values * (throws error if not hex). */ -uint256 ParseHashV(const UniValue& v, std::string strName); -uint256 ParseHashO(const UniValue& o, std::string strKey); -std::vector ParseHexV(const UniValue& v, std::string strName); -std::vector ParseHexO(const UniValue& o, std::string strKey); +extern uint256 ParseHashV(const UniValue& v, std::string strName); +extern uint256 ParseHashO(const UniValue& o, std::string strKey); +extern std::vector ParseHexV(const UniValue& v, std::string strName); +extern std::vector ParseHexO(const UniValue& o, std::string strKey); extern int64_t nWalletUnlockTime; -CAmount AmountFromValue(const UniValue& value); -UniValue ValueFromAmount(const CAmount& amount); -double GetDifficulty(const CBlockIndex* blockindex = NULL); -double GetNetworkDifficulty(const CBlockIndex* blockindex = NULL); -std::string HelpRequiringPassphrase(); -std::string HelpExampleCli(const std::string& methodname, const std::string& args); -std::string HelpExampleRpc(const std::string& methodname, const std::string& args); - -void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); -UniValue mempoolInfoToJSON(); -UniValue mempoolToJSON(bool fVerbose = false); -void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -UniValue blockheaderToJSON(const CBlockIndex* blockindex); -UniValue TxJoinSplitToJSON(const CTransaction& tx); - -void EnsureWalletIsUnlocked(); +extern CAmount AmountFromValue(const UniValue& value); +extern UniValue ValueFromAmount(const CAmount& amount); +extern double GetDifficulty(const CBlockIndex* blockindex = NULL); +extern double GetNetworkDifficulty(const CBlockIndex* blockindex = NULL); +extern std::string HelpRequiringPassphrase(); +extern std::string HelpExampleCli(const std::string& methodname, const std::string& args); +extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args); + +extern void EnsureWalletIsUnlocked(); bool StartRPC(); void InterruptRPC(); void StopRPC(); std::string JSONRPCExecBatch(const UniValue& vReq); -std::string experimentalDisabledHelpMsg(const std::string& rpc, const std::string& enableArg); - -UniValue getconnectioncount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcnet.cpp -UniValue getaddressmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getaddressutxos(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getaddressdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getaddresstxids(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getsnapshot(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getaddressbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue checknotarization(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getnotarypayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue ping(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue addnode(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue disconnectnode(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getaddednodeinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getnettotals(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue setban(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue listbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue clearbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue dumpwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue getgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmining.cpp -UniValue setgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getlocalsolps(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getnetworksolps(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getnetworkhashps(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getmininginfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue prioritisetransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue submitblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue estimatefee(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue estimatepriority(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue heiraddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue heirfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue heiradd(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue heirclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue heirinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue heirlist(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue channelsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue oraclesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue oracleslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue oraclesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue oraclescreate(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue oraclesfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue oraclesregister(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue oraclessubscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue oraclesdata(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue oraclessample(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue oraclessamples(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pricesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue priceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue mypriceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pricesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue paymentsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue payments_release(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue payments_fund(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue payments_merge(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue payments_txidopret(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue payments_create(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue payments_airdrop(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue payments_airdroptokens(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue payments_info(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue payments_list(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue cclibaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue cclibinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue cclib(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewaysaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewayslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewaysinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewaysdumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewaysexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewaysbind(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewaysdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewaysclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewayswithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewayspartialsign(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewayscompletesigning(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewaysmarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewayspendingdeposits(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewayspendingwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gatewaysprocessed(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue channelslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue channelsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue channelsopen(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue channelspayment(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue channelsclose(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue channelsrefund(const UniValue& params, bool fHelp, const CPubKey& mypk); -//UniValue tokenswapask(const UniValue& params, bool fHelp, const CPubKey& mypk); -//UniValue tokenfillswap(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue faucetfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue faucetget(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue faucetaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue faucetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue rewardsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue rewardslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue rewardsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue rewardscreatefunding(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue rewardsaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue rewardslock(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue rewardsunlock(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue diceaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue dicefund(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue dicelist(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue diceinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue diceaddfunds(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue dicebet(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue dicefinish(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue dicestatus(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue lottoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue FSMaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue FSMcreate(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue FSMlist(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue FSMinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue auctionaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegscreate(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegsfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegsget(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegsredeem(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegsliquidate(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegsexchange(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegsaccounthistory(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegsaccountinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegsworstaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pegsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -//UniValue getnewaddress64(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue getaccountaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getrawchangeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getaddressesbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue signmessage(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue verifymessage(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getbalance64(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getunconfirmedbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue movecmd(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue addmultisigaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue createmultisig(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue listreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue listaddressgroupings(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue listaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue listsinceblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gettransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue backupwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue keypoolrefill(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue walletpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue walletpassphrasechange(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue walletlock(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue encryptwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue decodeccopret(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getiguanajson(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getnotarysendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue setstakingsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getwalletinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getnetworkinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getdeprecationinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue setmocktime(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue resendwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue zc_benchmark(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue zc_raw_keygen(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue zc_raw_receive(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue jumblr_deposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue jumblr_secret(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue jumblr_pause(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue jumblr_resume(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rcprawtransaction.cpp -UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue createrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue decodescript(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue fundrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gettxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue verifytxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue getblockcount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcblockchain.cpp -UniValue getbestblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getdifficulty(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue settxfee(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getmempoolinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getrawmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getblockhashes(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getblockdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getlastsegidstakes(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue verifychain(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getchaintips(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue invalidateblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue reconsiderblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getspentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue selfimport(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importdual(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewayaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewaybind(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewaydeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewaywithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewaywithdrawsign(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewaymarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewaypendingsignwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewaysignedwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewayexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue importgatewaydumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue nspv_getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_login(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_mempool(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_spentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_notarizations(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_hdrsproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_txproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_spend(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_logout(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue nspv_listccmoduleunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue DEX_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_anonsend(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_list(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_get(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_stats(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_orderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_cancel(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_publish(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_subscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_stream(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_streamsub(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue DEX_notarize(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue getblocksubsidy(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue z_exportkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -UniValue z_importkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_listaddresses(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_exportwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -UniValue z_importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_getoperationstatus(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_getoperationresult(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmisc.cpp -UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp -UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp - -UniValue MoMoMdata(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue calc_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue height_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue assetchainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue crosschainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue scanNotarisationsDB(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getimports(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue getwalletburntransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue migrate_converttoexport(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue migrate_checkburntransactionsource(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue migrate_createnotaryapprovaltransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue minerids(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue kvsearch(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue paxprice(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue paxprices(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue paxdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue paxwithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); - -UniValue prices(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pricesbet(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pricessetcostbasis(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pricescashout(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pricesrekt(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pricesaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pricesgetorderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); -UniValue pricesrefillfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern std::string experimentalDisabledHelpMsg(const std::string& rpc, const std::string& enableArg); + +extern UniValue getconnectioncount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcnet.cpp +extern UniValue getaddressmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getaddressutxos(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getaddressdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getaddresstxids(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getsnapshot(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getaddressbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue checknotarization(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getnotarypayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue ping(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue addnode(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue disconnectnode(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getnettotals(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue setban(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue listbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue clearbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +extern UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue dumpwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue getgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmining.cpp +extern UniValue setgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getlocalsolps(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getnetworksolps(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getnetworkhashps(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getmininginfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue prioritisetransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue submitblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue estimatefee(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue estimatepriority(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue heiraddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue heirfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue heiradd(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue heirclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue heirinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue heirlist(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue channelsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue oraclesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue oracleslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue oraclesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue oraclescreate(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue oraclesfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue oraclesregister(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue oraclessubscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue oraclesdata(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue oraclessample(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue oraclessamples(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pricesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue priceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue mypriceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pricesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue paymentsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue payments_release(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue payments_fund(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue payments_merge(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue payments_txidopret(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue payments_create(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue payments_airdrop(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue payments_airdroptokens(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue payments_info(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue payments_list(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue cclibaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue cclibinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue cclib(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewaysaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewayslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewaysinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewaysdumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewaysexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewaysbind(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewaysdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewaysclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewayswithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewayspartialsign(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewayscompletesigning(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewaysmarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewayspendingdeposits(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewayspendingwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gatewaysprocessed(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue channelslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue channelsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue channelsopen(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue channelspayment(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue channelsclose(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue channelsrefund(const UniValue& params, bool fHelp, const CPubKey& mypk); +//extern UniValue tokenswapask(const UniValue& params, bool fHelp, const CPubKey& mypk); +//extern UniValue tokenfillswap(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue faucetfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue faucetget(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue faucetaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue faucetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue rewardsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue rewardslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue rewardsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue rewardscreatefunding(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue rewardsaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue rewardslock(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue rewardsunlock(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue diceaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue dicefund(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue dicelist(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue diceinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue diceaddfunds(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue dicebet(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue dicefinish(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue dicestatus(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue lottoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue FSMaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue FSMcreate(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue FSMlist(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue FSMinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue auctionaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegscreate(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegsfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegsget(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegsredeem(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegsliquidate(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegsexchange(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegsaccounthistory(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegsaccountinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegsworstaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pegsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +//extern UniValue getnewaddress64(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue getaccountaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getrawchangeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getaddressesbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue signmessage(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue verifymessage(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getbalance64(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getunconfirmedbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue movecmd(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue addmultisigaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue createmultisig(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue listreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue listaddressgroupings(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue listaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue listsinceblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gettransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue backupwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue keypoolrefill(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue walletpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue walletpassphrasechange(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue walletlock(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue encryptwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue decodeccopret(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getiguanajson(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getnotarysendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue setstakingsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getwalletinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getnetworkinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getdeprecationinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue setmocktime(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue resendwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue zc_benchmark(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue zc_raw_keygen(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue zc_raw_receive(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue jumblr_deposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue jumblr_secret(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue jumblr_pause(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue jumblr_resume(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rcprawtransaction.cpp +extern UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue createrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue decodescript(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue fundrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gettxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue verifytxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue getblockcount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcblockchain.cpp +extern UniValue getbestblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getdifficulty(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue settxfee(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getmempoolinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getrawmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getblockhashes(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getblockdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getlastsegidstakes(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue verifychain(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getchaintips(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue invalidateblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue reconsiderblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getspentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue selfimport(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importdual(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewayaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewaybind(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewaydeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewaywithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewaywithdrawsign(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewaymarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewaypendingsignwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewaysignedwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewayexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue importgatewaydumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue nspv_getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_login(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_mempool(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_spentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_notarizations(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_hdrsproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_txproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_spend(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_logout(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue nspv_listccmoduleunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue DEX_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_anonsend(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_list(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_get(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_stats(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_orderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_cancel(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_publish(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_subscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_stream(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_streamsub(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue DEX_notarize(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue getblocksubsidy(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue z_exportkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +extern UniValue z_importkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +extern UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +extern UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +extern UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_listaddresses(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_exportwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +extern UniValue z_importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +extern UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_getoperationstatus(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_getoperationresult(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmisc.cpp +extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp +extern UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp + +extern UniValue MoMoMdata(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue calc_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue height_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue assetchainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue crosschainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue scanNotarisationsDB(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getimports(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getwalletburntransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue migrate_converttoexport(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue migrate_checkburntransactionsource(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue migrate_createnotaryapprovaltransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue minerids(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue kvsearch(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue paxprice(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue paxprices(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue paxdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue paxwithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); + +extern UniValue prices(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pricesbet(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pricessetcostbasis(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pricescashout(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pricesrekt(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pricesaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pricesgetorderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue pricesrefillfund(const UniValue& params, bool fHelp, const CPubKey& mypk); diff --git a/src/rpc/testtransactions.cpp b/src/rpc/testtransactions.cpp new file mode 100644 index 00000000000..c41e97e1036 --- /dev/null +++ b/src/rpc/testtransactions.cpp @@ -0,0 +1,268 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/****************************************************************************** + * 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. * + * * + ******************************************************************************/ + +#include + +#include "amount.h" +#include "chain.h" +#include "chainparams.h" +#include "checkpoints.h" +#include "crosschain.h" +#include "base58.h" +#include "consensus/validation.h" +#include "cc/eval.h" +#include "main.h" +#include "primitives/transaction.h" +#include "rpc/server.h" +#include "streams.h" +#include "sync.h" +#include "util.h" +#include "script/script.h" +#include "script/script_error.h" +#include "script/sign.h" +#include "script/standard.h" + +#include + +#include + +#include + + +#include "cc/CCinclude.h" +#include "cc/CCPrices.h" + +using namespace std; + +int32_t ensure_CCrequirements(uint8_t evalcode); + +UniValue test_ac(const UniValue& params, bool fHelp, const CPubKey& mypk) +{ + // make fake token tx: + struct CCcontract_info *cp, C; + + if (fHelp || (params.size() != 4)) + throw runtime_error("incorrect params\n"); + if (ensure_CCrequirements(EVAL_HEIR) < 0) + throw runtime_error(CC_REQUIREMENTS_MSG); + + std::vector pubkey1; + std::vector pubkey2; + + pubkey1 = ParseHex(params[0].get_str().c_str()); + pubkey2 = ParseHex(params[1].get_str().c_str()); + + CPubKey pk1 = pubkey2pk(pubkey1); + CPubKey pk2 = pubkey2pk(pubkey2); + + if (!pk1.IsValid() || !pk2.IsValid()) + throw runtime_error("invalid pubkey\n"); + + int64_t txfee = 10000; + int64_t amount = atoll(params[2].get_str().c_str()) * COIN; + uint256 fundingtxid = Parseuint256((char *)params[3].get_str().c_str()); + + CPubKey myPubkey = pubkey2pk(Mypubkey()); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + int64_t normalInputs = AddNormalinputs(mtx, myPubkey, txfee + amount, 60); + + if (normalInputs < txfee + amount) + throw runtime_error("not enough normals\n"); + + mtx.vout.push_back(MakeCC1of2vout(EVAL_HEIR, amount, pk1, pk2)); + + CScript opret; + fundingtxid = revuint256(fundingtxid); + + opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'A' << fundingtxid << (uint8_t)0); + + cp = CCinit(&C, EVAL_HEIR); + return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret)); +} + +UniValue test_heirmarker(const UniValue& params, bool fHelp, const CPubKey& mypk) +{ + // make fake token tx: + struct CCcontract_info *cp, C; + + if (fHelp || (params.size() != 1)) + throw runtime_error("incorrect params\n"); + if (ensure_CCrequirements(EVAL_HEIR) < 0) + throw runtime_error(CC_REQUIREMENTS_MSG); + + uint256 fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); + + CPubKey myPubkey = pubkey2pk(Mypubkey()); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); + if (normalInputs < 10000) + throw runtime_error("not enough normals\n"); + + mtx.vin.push_back(CTxIn(fundingtxid, 1)); + mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, 10000, myPubkey)); + + CScript opret; + fundingtxid = revuint256(fundingtxid); + + opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'C' << fundingtxid << (uint8_t)0); + + cp = CCinit(&C, EVAL_HEIR); + return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret)); +} + +UniValue test_burntx(const UniValue& params, bool fHelp, const CPubKey& mypk) +{ + // make fake token tx: + struct CCcontract_info *cp, C; + + if (fHelp || (params.size() != 1)) + throw runtime_error("incorrect params\n"); + if (ensure_CCrequirements(EVAL_TOKENS) < 0) + throw runtime_error(CC_REQUIREMENTS_MSG); + + uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str()); + + CPubKey myPubkey = pubkey2pk(Mypubkey()); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); + if (normalInputs < 10000) + throw runtime_error("not enough normals\n"); + + CPubKey burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY)); + + mtx.vin.push_back(CTxIn(tokenid, 0)); + mtx.vin.push_back(CTxIn(tokenid, 1)); + mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, 1, burnpk)); + + std::vector voutPubkeys; + voutPubkeys.push_back(burnpk); + + cp = CCinit(&C, EVAL_TOKENS); + + std::vector vopret; + GetNonfungibleData(tokenid, vopret); + if (vopret.size() > 0) + cp->additionalTokensEvalcode2 = vopret.begin()[0]; + + uint8_t tokenpriv[33]; + char unspendableTokenAddr[64]; + CPubKey unspPk = GetUnspendable(cp, tokenpriv); + GetCCaddress(cp, unspendableTokenAddr, unspPk); + CCaddr2set(cp, EVAL_TOKENS, unspPk, tokenpriv, unspendableTokenAddr); + return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, EncodeTokenOpRet(tokenid, voutPubkeys, std::make_pair(0, vscript_t())))); +} + +UniValue test_proof(const UniValue& params, bool fHelp, const CPubKey& mypk) +{ + UniValue result(UniValue::VOBJ); + std::vectorproof; + + if (fHelp || (params.size() != 2)) + throw runtime_error("incorrect params\n"); + + + proof = ParseHex(params[0].get_str()); + uint256 cointxid = Parseuint256((char *)params[1].get_str().c_str()); + + std::vector txids; + + CMerkleBlock merkleBlock; + if (!E_UNMARSHAL(proof, ss >> merkleBlock)) { + result.push_back(Pair("error", "could not unmarshal proof")); + return result; + } + uint256 merkleRoot = merkleBlock.txn.ExtractMatches(txids); + + result.push_back(Pair("source_root", merkleRoot.GetHex())); + + for (int i = 0; i < txids.size(); i++) + std::cerr << "merkle block txid=" << txids[0].GetHex() << std::endl; + + + std::vector vMatches(txids.size()); + for (auto v : vMatches) v = true; + CPartialMerkleTree verifTree(txids, vMatches); + + result.push_back(Pair("verif_root", verifTree.ExtractMatches(txids).GetHex())); + + if (std::find(txids.begin(), txids.end(), cointxid) == txids.end()) { + fprintf(stderr, "invalid proof for this cointxid\n"); + } + + std::vector vMerkleTree; + bool f; + ::BuildMerkleTree(&f, txids, vMerkleTree); + + std::vector vMerkleBranch = ::GetMerkleBranch(0, txids.size(), vMerkleTree); + + uint256 ourResult = SafeCheckMerkleBranch(zeroid, vMerkleBranch, 0); + result.push_back(Pair("SafeCheckMerkleBranch", ourResult.GetHex())); + + return result; +} + +extern CScript prices_costbasisopret(uint256 bettxid, CPubKey mypk, int32_t height, int64_t costbasis); +UniValue test_pricesmarker(const UniValue& params, bool fHelp, const CPubKey& mypk) +{ + // make fake token tx: + struct CCcontract_info *cp, C; + + if (fHelp || (params.size() != 1)) + throw runtime_error("incorrect params\n"); + if (ensure_CCrequirements(EVAL_PRICES) < 0) + throw runtime_error(CC_REQUIREMENTS_MSG); + + uint256 bettxid = Parseuint256((char *)params[0].get_str().c_str()); + + cp = CCinit(&C, EVAL_PRICES); + CPubKey myPubkey = pubkey2pk(Mypubkey()); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); + if (normalInputs < 10000) + throw runtime_error("not enough normals\n"); + + mtx.vin.push_back(CTxIn(bettxid, 1)); + mtx.vout.push_back(CTxOut(1000, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG)); + + return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, prices_costbasisopret(bettxid, myPubkey, 100, 100))); +} + + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + + /* Not shown in help */ + { "hidden", "test_ac", &test_ac, true }, + { "hidden", "test_heirmarker", &test_heirmarker, true }, + { "hidden", "test_proof", &test_proof, true }, + { "hidden", "test_burntx", &test_burntx, true }, + { "hidden", "test_pricesmarker", &test_pricesmarker, true } +}; + +void RegisterTesttransactionsRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 37453016db9..6bd4903b34b 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -61,33 +61,11 @@ UniValue tokenaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) return CCaddress(cp, "Tokens", pubkey, false); } -UniValue tokenv2indexkey(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - struct CCcontract_info *cp,C; - vuint8_t vpubkey; - - cp = CCinit(&C, EVAL_TOKENSV2); - if (fHelp || params.size() != 1) - throw runtime_error("tokenv2address pubkey\n"); - if (ensure_CCrequirements(cp->evalcode) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - vpubkey = ParseHex(params[0].get_str().c_str()); - CPubKey pk = pubkey2pk(vpubkey); - if (!pk.IsValid()) - throw runtime_error("invalid pubkey\n"); - - char address[KOMODO_ADDRESS_BUFSIZE]; - GetCCaddress(cp, address, pk, true); - - return address; -} - UniValue tokenv2address(const UniValue& params, bool fHelp, const CPubKey& mypk) { struct CCcontract_info *cp,C; vuint8_t pubkey; - throw runtime_error("tokenv2address not supported, use tokenv2indexkey\n"); cp = CCinit(&C, EVAL_TOKENSV2); if (fHelp || params.size() > 1) throw runtime_error("tokenv2address [pubkey]\n"); @@ -308,39 +286,6 @@ UniValue tokenv2balance(const UniValue& params, bool fHelp, const CPubKey& remot return tokenbalance("tokenv2balance", params, fHelp, remotepk); } -template -static UniValue tokenallbalances(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) -{ - if (fHelp || params.size() > 1) - throw runtime_error(name + " [pubkey]\n"); - if (ensure_CCrequirements(V::EvalCode()) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - // LOCK(cs_main); - // no need to lock cs_main as we use only indexes in this rpc - // but still use lock if you need to get chainActive.Height() or something like that - - std::vector vpubkey; - if (params.size() == 1) - vpubkey = ParseHex(params[0].get_str().c_str()); - else - vpubkey = Mypubkey(); - - UniValue result = GetAllTokenBalances(pubkey2pk(vpubkey), false); - return result; -} - -UniValue tokenallbalances(const UniValue& params, bool fHelp, const CPubKey& remotepk) -{ - return tokenallbalances("tokenallbalances", params, fHelp, remotepk); -} -UniValue tokenv2allbalances(const UniValue& params, bool fHelp, const CPubKey& remotepk) -{ - return tokenallbalances("tokenv2allbalances", params, fHelp, remotepk); -} - - - template static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, bool fHelp, const CPubKey& remotepk) { @@ -1118,47 +1063,6 @@ UniValue addccv2signature(const UniValue& params, bool fHelp, const CPubKey& rem } -UniValue tokenv2addccinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) -{ - if (fHelp || params.size() != 3) - { - string msg = "tokenv2addccinputs tokenid pubkey amount\n" - "\nReturns a new tx with added token inputs and the matching previous txns. Note that the caller must add the change output\n" - "\nArguments:\n" - //"address which utxos are added from\n" - "amount (in satoshi) which will be added as normal inputs (equal or more)\n" - "Result: json object with created tx and added vin txns\n\n"; - throw runtime_error(msg); - } - - uint256 tokenid = Parseuint256(params[0].get_str().c_str()); - CPubKey pk = pubkey2pk( ParseHex(params[1].get_str().c_str()) ); - CAmount amount = atoll(params[2].get_str().c_str()); - if (amount <= 0) - throw runtime_error("amount invalid"); - - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cp, C; - cp = CCinit(&C, EVAL_TOKENSV2); - - CAmount added = AddTokenCCInputs(cp, mtx, pk, tokenid, amount, CC_MAXVINS, false); - if (added < amount) - throw runtime_error("could not find token cc inputs"); - - UniValue result (UniValue::VOBJ); - UniValue array (UniValue::VARR); - - result.pushKV("txhex", HexStr(E_MARSHAL(ss << mtx))); - for (auto const &vin : mtx.vin) { - CTransaction vintx; - uint256 hashBlock; - if (myGetTransaction(vin.prevout.hash, vintx, hashBlock)) - array.push_back(HexStr(E_MARSHAL(ss << vintx))); - } - result.pushKV("previousTxns", array); - return result; -} - static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- @@ -1176,11 +1080,8 @@ static const CRPCCommand commands[] = { "tokens v2", "mytokenv2orders", &mytokenv2orders, true }, { "tokens", "tokenaddress", &tokenaddress, true }, { "tokens v2", "tokenv2address", &tokenv2address, true }, -// { "tokens v2", "tokenv2indexkey", &tokenv2indexkey, true }, { "tokens", "tokenbalance", &tokenbalance, true }, { "tokens v2", "tokenv2balance", &tokenv2balance, true }, - { "tokens", "tokenallbalances", &tokenallbalances, true }, - { "tokens v2", "tokenv2allbalances", &tokenv2allbalances, true }, { "tokens", "tokencreate", &tokencreate, true }, { "tokens v2", "tokenv2create", &tokenv2create, true }, { "tokens", "tokentransfer", &tokentransfer, true }, @@ -1208,7 +1109,6 @@ static const CRPCCommand commands[] = { "tokens v2", "tokenv2createtokel", &tokenv2createtokel, true }, { "tokens", "tokeninfotokel", &tokeninfotokel, true }, { "tokens v2", "tokenv2infotokel", &tokenv2infotokel, true }, - { "nspv", "tokenv2addccinputs", &tokenv2addccinputs, true }, }; void RegisterTokensRPCCommands(CRPCTable &tableRPC) diff --git a/src/rpcblockchain.old b/src/rpcblockchain.old new file mode 100644 index 00000000000..a91f73a6364 --- /dev/null +++ b/src/rpcblockchain.old @@ -0,0 +1,1625 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "amount.h" +#include "chain.h" +#include "chainparams.h" +#include "checkpoints.h" +#include "crosschain.h" +#include "base58.h" +#include "consensus/validation.h" +#include "cc/eval.h" +#include "main.h" +#include "primitives/transaction.h" +#include "rpcserver.h" +#include "sync.h" +#include "util.h" +#include "script/script.h" +#include "script/script_error.h" +#include "script/sign.h" +#include "script/standard.h" + +#include + +#include + +#include + +using namespace std; + +extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +int32_t komodo_longestchain(); +int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); +<<<<<<< HEAD:src/rpcblockchain.old +extern int32_t KOMODO_LONGESTCHAIN; +======= +>>>>>>> master:src/rpcblockchain.cpp + +double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) +{ + // Floating point number that is a multiple of the minimum difficulty, + // minimum difficulty = 1.0. + if (blockindex == NULL) + { + if (chainActive.LastTip() == NULL) + return 1.0; + else + blockindex = chainActive.LastTip(); + } + + uint32_t bits; + if (networkDifficulty) { + bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus()); + } else { + bits = blockindex->nBits; + } + + uint32_t powLimit = + UintToArith256(Params().GetConsensus().powLimit).GetCompact(); + int nShift = (bits >> 24) & 0xff; + int nShiftAmount = (powLimit >> 24) & 0xff; + + double dDiff = + (double)(powLimit & 0x00ffffff) / + (double)(bits & 0x00ffffff); + + while (nShift < nShiftAmount) + { + dDiff *= 256.0; + nShift++; + } + while (nShift > nShiftAmount) + { + dDiff /= 256.0; + nShift--; + } + + return dDiff; +} + +double GetDifficulty(const CBlockIndex* blockindex) +{ + return GetDifficultyINTERNAL(blockindex, false); +} + +double GetNetworkDifficulty(const CBlockIndex* blockindex) +{ + return GetDifficultyINTERNAL(blockindex, true); +} + +static UniValue ValuePoolDesc( + const std::string &name, + const boost::optional chainValue, + const boost::optional valueDelta) +{ + UniValue rv(UniValue::VOBJ); + rv.push_back(Pair("id", name)); + rv.push_back(Pair("monitored", (bool)chainValue)); + if (chainValue) { + rv.push_back(Pair("chainValue", ValueFromAmount(*chainValue))); + rv.push_back(Pair("chainValueZat", *chainValue)); + } + if (valueDelta) { + rv.push_back(Pair("valueDelta", ValueFromAmount(*valueDelta))); + rv.push_back(Pair("valueDeltaZat", *valueDelta)); + } + return rv; +} + +UniValue blockheaderToJSON(const CBlockIndex* blockindex) +{ + UniValue result(UniValue::VOBJ); + if ( blockindex == 0 ) + { + result.push_back(Pair("error", "null blockhash")); + return(result); + } + result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); + int confirmations = -1; + // Only report confirmations if the block is on the main chain + if (chainActive.Contains(blockindex)) + confirmations = chainActive.Height() - blockindex->nHeight + 1; + result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); + result.push_back(Pair("rawconfirmations", confirmations)); + result.push_back(Pair("height", blockindex->nHeight)); + result.push_back(Pair("version", blockindex->nVersion)); + result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex())); + result.push_back(Pair("time", (int64_t)blockindex->nTime)); + result.push_back(Pair("nonce", blockindex->nNonce.GetHex())); + result.push_back(Pair("solution", HexStr(blockindex->nSolution))); + result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); + result.push_back(Pair("difficulty", GetDifficulty(blockindex))); + result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); + result.push_back(Pair("segid", (int64_t)blockindex->segid)); + + if (blockindex->pprev) + result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); + CBlockIndex *pnext = chainActive.Next(blockindex); + if (pnext) + result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); + return result; +} + +UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("hash", block.GetHash().GetHex())); + int confirmations = -1; + // Only report confirmations if the block is on the main chain + if (chainActive.Contains(blockindex)) { + confirmations = chainActive.Height() - blockindex->nHeight + 1; + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block is an orphan"); + } + result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); + result.push_back(Pair("rawconfirmations", confirmations)); + result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); + result.push_back(Pair("height", blockindex->nHeight)); + result.push_back(Pair("version", block.nVersion)); + result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); + result.push_back(Pair("segid", (int64_t)blockindex->segid)); + + UniValue deltas(UniValue::VARR); + + for (unsigned int i = 0; i < block.vtx.size(); i++) { + const CTransaction &tx = block.vtx[i]; + const uint256 txhash = tx.GetHash(); + + UniValue entry(UniValue::VOBJ); + entry.push_back(Pair("txid", txhash.GetHex())); + entry.push_back(Pair("index", (int)i)); + + UniValue inputs(UniValue::VARR); + + if (!tx.IsCoinBase()) { + + for (size_t j = 0; j < tx.vin.size(); j++) { + const CTxIn input = tx.vin[j]; + + UniValue delta(UniValue::VOBJ); + + CSpentIndexValue spentInfo; + CSpentIndexKey spentKey(input.prevout.hash, input.prevout.n); + + if (GetSpentIndex(spentKey, spentInfo)) { + if (spentInfo.addressType == 1) { + delta.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); + } + else if (spentInfo.addressType == 2) { + delta.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); + } + else { + continue; + } + delta.push_back(Pair("satoshis", -1 * spentInfo.satoshis)); + delta.push_back(Pair("index", (int)j)); + delta.push_back(Pair("prevtxid", input.prevout.hash.GetHex())); + delta.push_back(Pair("prevout", (int)input.prevout.n)); + + inputs.push_back(delta); + } else { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Spent information not available"); + } + + } + } + + entry.push_back(Pair("inputs", inputs)); + + UniValue outputs(UniValue::VARR); + + for (unsigned int k = 0; k < tx.vout.size(); k++) { + const CTxOut &out = tx.vout[k]; + + UniValue delta(UniValue::VOBJ); + + if (out.scriptPubKey.IsPayToScriptHash()) { + vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); + delta.push_back(Pair("address", CBitcoinAddress(CScriptID(uint160(hashBytes))).ToString())); + + } + else if (out.scriptPubKey.IsPayToPublicKeyHash()) { + vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); + delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); + } + else if (out.scriptPubKey.IsPayToPublicKey() || out.scriptPubKey.IsPayToCryptoCondition()) { + CTxDestination address; + if (ExtractDestination(out.scriptPubKey, address)) + { + //vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); + //xxx delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); + delta.push_back(Pair("address", CBitcoinAddress(address).ToString())); + } + } + else { + continue; + } + + delta.push_back(Pair("satoshis", out.nValue)); + delta.push_back(Pair("index", (int)k)); + + outputs.push_back(delta); + } + + entry.push_back(Pair("outputs", outputs)); + deltas.push_back(entry); + + } + result.push_back(Pair("deltas", deltas)); + result.push_back(Pair("time", block.GetBlockTime())); + result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast())); + result.push_back(Pair("nonce", block.nNonce.GetHex())); + result.push_back(Pair("bits", strprintf("%08x", block.nBits))); + result.push_back(Pair("difficulty", GetDifficulty(blockindex))); + result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); + + if (blockindex->pprev) + result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); + CBlockIndex *pnext = chainActive.Next(blockindex); + if (pnext) + result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); + return result; +} + +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("hash", block.GetHash().GetHex())); + int confirmations = -1; + // Only report confirmations if the block is on the main chain + if (chainActive.Contains(blockindex)) + confirmations = chainActive.Height() - blockindex->nHeight + 1; + result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); + result.push_back(Pair("rawconfirmations", confirmations)); + result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); + result.push_back(Pair("height", blockindex->nHeight)); + result.push_back(Pair("version", block.nVersion)); + result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); + result.push_back(Pair("segid", (int64_t)blockindex->segid)); + UniValue txs(UniValue::VARR); + BOOST_FOREACH(const CTransaction&tx, block.vtx) + { + if(txDetails) + { + UniValue objTx(UniValue::VOBJ); + TxToJSON(tx, uint256(), objTx); + txs.push_back(objTx); + } + else + txs.push_back(tx.GetHash().GetHex()); + } + result.push_back(Pair("tx", txs)); + result.push_back(Pair("time", block.GetBlockTime())); + result.push_back(Pair("nonce", block.nNonce.GetHex())); + result.push_back(Pair("solution", HexStr(block.nSolution))); + result.push_back(Pair("bits", strprintf("%08x", block.nBits))); + result.push_back(Pair("difficulty", GetDifficulty(blockindex))); + result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); + result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex())); + + UniValue valuePools(UniValue::VARR); + valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue)); + result.push_back(Pair("valuePools", valuePools)); + + if (blockindex->pprev) + result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); + CBlockIndex *pnext = chainActive.Next(blockindex); + if (pnext) + result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); + return result; +} + +UniValue getblockcount(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getblockcount\n" + "\nReturns the number of blocks in the best valid block chain.\n" + "\nResult:\n" + "n (numeric) The current block count\n" + "\nExamples:\n" + + HelpExampleCli("getblockcount", "") + + HelpExampleRpc("getblockcount", "") + ); + + LOCK(cs_main); + return chainActive.Height(); +} + +UniValue getbestblockhash(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getbestblockhash\n" + "\nReturns the hash of the best (tip) block in the longest block chain.\n" + "\nResult\n" + "\"hex\" (string) the block hash hex encoded\n" + "\nExamples\n" + + HelpExampleCli("getbestblockhash", "") + + HelpExampleRpc("getbestblockhash", "") + ); + + LOCK(cs_main); + return chainActive.LastTip()->GetBlockHash().GetHex(); +} + +UniValue getdifficulty(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getdifficulty\n" + "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n" + "\nResult:\n" + "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n" + "\nExamples:\n" + + HelpExampleCli("getdifficulty", "") + + HelpExampleRpc("getdifficulty", "") + ); + + LOCK(cs_main); + return GetNetworkDifficulty(); +} + +bool myIsutxo_spentinmempool(uint256 txid,int32_t vout) +{ + //char *uint256_str(char *str,uint256); char str[65]; + //LOCK(mempool.cs); + BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) + { + const CTransaction &tx = e.GetTx(); + const uint256 &hash = tx.GetHash(); + BOOST_FOREACH(const CTxIn &txin,tx.vin) + { + //fprintf(stderr,"%s/v%d ",uint256_str(str,txin.prevout.hash),txin.prevout.n); + if ( txin.prevout.n == vout && txin.prevout.hash == txid ) + return(true); + } + //fprintf(stderr,"are vins for %s\n",uint256_str(str,hash)); + } + return(false); +} + +bool mytxid_inmempool(uint256 txid) +{ + BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) + { + const CTransaction &tx = e.GetTx(); + const uint256 &hash = tx.GetHash(); + if ( txid == hash ) + return(true); + } + return(false); +} + +UniValue mempoolToJSON(bool fVerbose = false) +{ + if (fVerbose) + { + LOCK(mempool.cs); + UniValue o(UniValue::VOBJ); + BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) + { + const uint256& hash = e.GetTx().GetHash(); + UniValue info(UniValue::VOBJ); + info.push_back(Pair("size", (int)e.GetTxSize())); + info.push_back(Pair("fee", ValueFromAmount(e.GetFee()))); + info.push_back(Pair("time", e.GetTime())); + info.push_back(Pair("height", (int)e.GetHeight())); + info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight()))); + info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height()))); + const CTransaction& tx = e.GetTx(); + set setDepends; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + if (mempool.exists(txin.prevout.hash)) + setDepends.insert(txin.prevout.hash.ToString()); + } + + UniValue depends(UniValue::VARR); + BOOST_FOREACH(const string& dep, setDepends) + { + depends.push_back(dep); + } + + info.push_back(Pair("depends", depends)); + o.push_back(Pair(hash.ToString(), info)); + } + return o; + } + else + { + vector vtxid; + mempool.queryHashes(vtxid); + + UniValue a(UniValue::VARR); + BOOST_FOREACH(const uint256& hash, vtxid) + a.push_back(hash.ToString()); + + return a; + } +} + +UniValue getrawmempool(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "getrawmempool ( verbose )\n" + "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" + "\nArguments:\n" + "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" + "\nResult: (for verbose = false):\n" + "[ (json array of string)\n" + " \"transactionid\" (string) The transaction id\n" + " ,...\n" + "]\n" + "\nResult: (for verbose = true):\n" + "{ (json object)\n" + " \"transactionid\" : { (json object)\n" + " \"size\" : n, (numeric) transaction size in bytes\n" + " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" + " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" + " \"height\" : n, (numeric) block height when transaction entered pool\n" + " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n" + " \"currentpriority\" : n, (numeric) transaction priority now\n" + " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" + " \"transactionid\", (string) parent transaction id\n" + " ... ]\n" + " }, ...\n" + "}\n" + "\nExamples\n" + + HelpExampleCli("getrawmempool", "true") + + HelpExampleRpc("getrawmempool", "true") + ); + + LOCK(cs_main); + + bool fVerbose = false; + if (params.size() > 0) + fVerbose = params[0].get_bool(); + + return mempoolToJSON(fVerbose); +} + +UniValue getblockdeltas(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error(""); + + std::string strHash = params[0].get_str(); + uint256 hash(uint256S(strHash)); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + + if(!ReadBlockFromDisk(block, pblockindex,1)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + + return blockToDeltasJSON(block, pblockindex); +} + +UniValue getblockhashes(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 2) + throw runtime_error( + "getblockhashes timestamp\n" + "\nReturns array of hashes of blocks within the timestamp range provided.\n" + "\nArguments:\n" + "1. high (numeric, required) The newer block timestamp\n" + "2. low (numeric, required) The older block timestamp\n" + "3. options (string, required) A json object\n" + " {\n" + " \"noOrphans\":true (boolean) will only include blocks on the main chain\n" + " \"logicalTimes\":true (boolean) will include logical timestamps with hashes\n" + " }\n" + "\nResult:\n" + "[\n" + " \"hash\" (string) The block hash\n" + "]\n" + "[\n" + " {\n" + " \"blockhash\": (string) The block hash\n" + " \"logicalts\": (numeric) The logical timestamp\n" + " }\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getblockhashes", "1231614698 1231024505") + + HelpExampleRpc("getblockhashes", "1231614698, 1231024505") + + HelpExampleCli("getblockhashes", "1231614698 1231024505 '{\"noOrphans\":false, \"logicalTimes\":true}'") + ); + + unsigned int high = params[0].get_int(); + unsigned int low = params[1].get_int(); + bool fActiveOnly = false; + bool fLogicalTS = false; + + if (params.size() > 2) { + if (params[2].isObject()) { + UniValue noOrphans = find_value(params[2].get_obj(), "noOrphans"); + UniValue returnLogical = find_value(params[2].get_obj(), "logicalTimes"); + + if (noOrphans.isBool()) + fActiveOnly = noOrphans.get_bool(); + + if (returnLogical.isBool()) + fLogicalTS = returnLogical.get_bool(); + } + } + + std::vector > blockHashes; + + if (fActiveOnly) + LOCK(cs_main); + + if (!GetTimestampIndex(high, low, fActiveOnly, blockHashes)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for block hashes"); + } + + UniValue result(UniValue::VARR); + + for (std::vector >::const_iterator it=blockHashes.begin(); it!=blockHashes.end(); it++) { + if (fLogicalTS) { + UniValue item(UniValue::VOBJ); + item.push_back(Pair("blockhash", it->first.GetHex())); + item.push_back(Pair("logicalts", (int)it->second)); + result.push_back(item); + } else { + result.push_back(it->first.GetHex()); + } + } + + return result; +} + +UniValue getblockhash(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getblockhash index\n" + "\nReturns hash of block in best-block-chain at index provided.\n" + "\nArguments:\n" + "1. index (numeric, required) The block index\n" + "\nResult:\n" + "\"hash\" (string) The block hash\n" + "\nExamples:\n" + + HelpExampleCli("getblockhash", "1000") + + HelpExampleRpc("getblockhash", "1000") + ); + + LOCK(cs_main); + + int nHeight = params[0].get_int(); + if (nHeight < 0 || nHeight > chainActive.Height()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); + + CBlockIndex* pblockindex = chainActive[nHeight]; + return pblockindex->GetBlockHash().GetHex(); +} + +/*uint256 _komodo_getblockhash(int32_t nHeight) +{ + uint256 hash; + LOCK(cs_main); + if ( nHeight >= 0 && nHeight <= chainActive.Height() ) + { + CBlockIndex* pblockindex = chainActive[nHeight]; + hash = pblockindex->GetBlockHash(); + int32_t i; + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&hash)[i]); + printf(" blockhash.%d\n",nHeight); + } else memset(&hash,0,sizeof(hash)); + return(hash); +}*/ + +UniValue getblockheader(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getblockheader \"hash\" ( verbose )\n" + "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" + "If verbose is true, returns an Object with information about blockheader .\n" + "\nArguments:\n" + "1. \"hash\" (string, required) The block hash\n" + "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" + "\nResult (for verbose = true):\n" + "{\n" + " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" + " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" + " \"height\" : n, (numeric) The block height or index\n" + " \"version\" : n, (numeric) The block version\n" + " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" + " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"nonce\" : n, (numeric) The nonce\n" + " \"bits\" : \"1d00ffff\", (string) The bits\n" + " \"difficulty\" : x.xxx, (numeric) The difficulty\n" + " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" + " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" + "}\n" + "\nResult (for verbose=false):\n" + "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" + "\nExamples:\n" + + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + ); + + LOCK(cs_main); + + std::string strHash = params[0].get_str(); + uint256 hash(uint256S(strHash)); + + bool fVerbose = true; + if (params.size() > 1) + fVerbose = params[1].get_bool(); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (!fVerbose) + { + CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); + ssBlock << pblockindex->GetBlockHeader(); + std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); + return strHex; + } + + return blockheaderToJSON(pblockindex); +} + +UniValue getblock(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getblock \"hash|height\" ( verbose )\n" + "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash|height'.\n" + "If verbose is true, returns an Object with information about block .\n" + "\nArguments:\n" + "1. \"hash|height\" (string, required) The block hash or height\n" + "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" + "\nResult (for verbose = true):\n" + "{\n" + " \"hash\" : \"hash\", (string) the block hash (same as provided hash)\n" + " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" + " \"size\" : n, (numeric) The block size\n" + " \"height\" : n, (numeric) The block height or index (same as provided height)\n" + " \"version\" : n, (numeric) The block version\n" + " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" + " \"tx\" : [ (array of string) The transaction ids\n" + " \"transactionid\" (string) The transaction id\n" + " ,...\n" + " ],\n" + " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"nonce\" : n, (numeric) The nonce\n" + " \"bits\" : \"1d00ffff\", (string) The bits\n" + " \"difficulty\" : x.xxx, (numeric) The difficulty\n" + " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" + " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" + "}\n" + "\nResult (for verbose=false):\n" + "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" + "\nExamples:\n" + + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + + HelpExampleCli("getblock", "12800") + + HelpExampleRpc("getblock", "12800") + ); + + LOCK(cs_main); + + std::string strHash = params[0].get_str(); + + // If height is supplied, find the hash + if (strHash.size() < (2 * sizeof(uint256))) { + // std::stoi allows characters, whereas we want to be strict + regex r("[[:digit:]]+"); + if (!regex_match(strHash, r)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); + } + + int nHeight = -1; + try { + nHeight = std::stoi(strHash); + } + catch (const std::exception &e) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); + } + + if (nHeight < 0 || nHeight > chainActive.Height()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); + } + strHash = chainActive[nHeight]->GetBlockHash().GetHex(); + } + + uint256 hash(uint256S(strHash)); + + bool fVerbose = true; + if (params.size() > 1) + fVerbose = params[1].get_bool(); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + + if(!ReadBlockFromDisk(block, pblockindex,1)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + + if (!fVerbose) + { + CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); + ssBlock << block; + std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); + return strHex; + } + + return blockToJSON(block, pblockindex); +} + +UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "gettxoutsetinfo\n" + "\nReturns statistics about the unspent transaction output set.\n" + "Note this call may take some time.\n" + "\nResult:\n" + "{\n" + " \"height\":n, (numeric) The current block height (index)\n" + " \"bestblock\": \"hex\", (string) the best block hash hex\n" + " \"transactions\": n, (numeric) The number of transactions\n" + " \"txouts\": n, (numeric) The number of output transactions\n" + " \"bytes_serialized\": n, (numeric) The serialized size\n" + " \"hash_serialized\": \"hash\", (string) The serialized hash\n" + " \"total_amount\": x.xxx (numeric) The total amount\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("gettxoutsetinfo", "") + + HelpExampleRpc("gettxoutsetinfo", "") + ); + + UniValue ret(UniValue::VOBJ); + + CCoinsStats stats; + FlushStateToDisk(); + if (pcoinsTip->GetStats(stats)) { + ret.push_back(Pair("height", (int64_t)stats.nHeight)); + ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); + ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); + ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs)); + ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize)); + ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex())); + ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount))); + } + return ret; +} + +#include "komodo_defs.h" +#include "komodo_structs.h" + +#define IGUANA_MAXSCRIPTSIZE 10001 +#define KOMODO_KVDURATION 1440 +#define KOMODO_KVBINARY 2 +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume); +int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); +char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); +int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); +int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); + +UniValue kvsearch(const UniValue& params, bool fHelp) +{ + UniValue ret(UniValue::VOBJ); uint32_t flags; uint8_t value[IGUANA_MAXSCRIPTSIZE*8],key[IGUANA_MAXSCRIPTSIZE*8]; int32_t duration,j,height,valuesize,keylen; uint256 refpubkey; static uint256 zeroes; + if (fHelp || params.size() != 1 ) + throw runtime_error( + "kvsearch key\n" + "\nSearch for a key stored via the kvupdate command. This feature is only available for asset chains.\n" + "\nArguments:\n" + "1. key (string, required) search the chain for this key\n" + "\nResult:\n" + "{\n" + " \"coin\": \"xxxxx\", (string) chain the key is stored on\n" + " \"currentheight\": xxxxx, (numeric) current height of the chain\n" + " \"key\": \"xxxxx\", (string) key\n" + " \"keylen\": xxxxx, (string) length of the key \n" + " \"owner\": \"xxxxx\" (string) hex string representing the owner of the key \n" + " \"height\": xxxxx, (numeric) height the key was stored at\n" + " \"expiration\": xxxxx, (numeric) height the key will expire\n" + " \"flags\": x (numeric) 1 if the key was created with a password; 0 otherwise.\n" + " \"value\": \"xxxxx\", (string) stored value\n" + " \"valuesize\": xxxxx (string) amount of characters stored\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("kvsearch", "examplekey") + + HelpExampleRpc("kvsearch", "\"examplekey\"") + ); + LOCK(cs_main); + if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 ) + { + ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); + ret.push_back(Pair("currentheight", (int64_t)chainActive.LastTip()->nHeight)); + ret.push_back(Pair("key",params[0].get_str())); + ret.push_back(Pair("keylen",keylen)); + if ( keylen < sizeof(key) ) + { + memcpy(key,params[0].get_str().c_str(),keylen); + if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&flags,&height,value,key,keylen)) >= 0 ) + { + std::string val; char *valuestr; + val.resize(valuesize); + valuestr = (char *)val.data(); + memcpy(valuestr,value,valuesize); + if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) + ret.push_back(Pair("owner",refpubkey.GetHex())); + ret.push_back(Pair("height",height)); + duration = ((flags >> 2) + 1) * KOMODO_KVDURATION; + ret.push_back(Pair("expiration", (int64_t)(height+duration))); + ret.push_back(Pair("flags",(int64_t)flags)); + ret.push_back(Pair("value",val)); + ret.push_back(Pair("valuesize",valuesize)); + } else ret.push_back(Pair("error",(char *)"cant find key")); + } else ret.push_back(Pair("error",(char *)"key too big")); + } else ret.push_back(Pair("error",(char *)"null key")); + return ret; +} + +UniValue minerids(const UniValue& params, bool fHelp) +{ + uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); uint8_t minerids[2000],pubkeys[65][33]; int32_t i,j,n,numnotaries,tally[129]; + if ( fHelp || params.size() != 1 ) + throw runtime_error("minerids needs height\n"); + LOCK(cs_main); + int32_t height = atoi(params[0].get_str().c_str()); + if ( height <= 0 ) + height = chainActive.LastTip()->nHeight; + else + { + CBlockIndex *pblockindex = chainActive[height]; + if ( pblockindex != 0 ) + timestamp = pblockindex->GetBlockTime(); + } + if ( (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 ) + { + memset(tally,0,sizeof(tally)); + numnotaries = komodo_notaries(pubkeys,height,timestamp); + if ( numnotaries > 0 ) + { + for (i=0; i= numnotaries ) + tally[128]++; + else tally[minerids[i]]++; + } + for (i=0; i<64; i++) + { + UniValue item(UniValue::VOBJ); std::string hex,kmdaddress; char *hexstr,kmdaddr[64],*ptr; int32_t m; + hex.resize(66); + hexstr = (char *)hex.data(); + for (j=0; j<33; j++) + sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]); + item.push_back(Pair("notaryid", i)); + + bitcoin_address(kmdaddr,60,pubkeys[i],33); + m = (int32_t)strlen(kmdaddr); + kmdaddress.resize(m); + ptr = (char *)kmdaddress.data(); + memcpy(ptr,kmdaddr,m); + item.push_back(Pair("KMDaddress", kmdaddress)); + + item.push_back(Pair("pubkey", hex)); + item.push_back(Pair("blocks", tally[i])); + a.push_back(item); + } + UniValue item(UniValue::VOBJ); + item.push_back(Pair("pubkey", (char *)"external miners")); + item.push_back(Pair("blocks", tally[128])); + a.push_back(item); + } + ret.push_back(Pair("mined", a)); + ret.push_back(Pair("numnotaries", numnotaries)); + } else ret.push_back(Pair("error", (char *)"couldnt extract minerids")); + return ret; +} + +UniValue notaries(const UniValue& params, bool fHelp) +{ + UniValue a(UniValue::VARR); uint32_t timestamp=0; UniValue ret(UniValue::VOBJ); int32_t i,j,n,m; char *hexstr; uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr; + if ( fHelp || (params.size() != 1 && params.size() != 2) ) + throw runtime_error("notaries height timestamp\n"); + LOCK(cs_main); + int32_t height = atoi(params[0].get_str().c_str()); + if ( params.size() == 2 ) + timestamp = (uint32_t)atol(params[1].get_str().c_str()); + else timestamp = (uint32_t)time(NULL); + if ( height < 0 ) + { + height = chainActive.LastTip()->nHeight; + timestamp = chainActive.LastTip()->GetBlockTime(); + } + else if ( params.size() < 2 ) + { + CBlockIndex *pblockindex = chainActive[height]; + if ( pblockindex != 0 ) + timestamp = pblockindex->GetBlockTime(); + } + if ( (n= komodo_notaries(pubkeys,height,timestamp)) > 0 ) + { + for (i=0; i 0 ) + ret.push_back(Pair("withdraws", opretbuf)); + else ret.push_back(Pair("withdraws", (char *)"")); + for (baseid=0; baseid<32; baseid++) + { + UniValue item(UniValue::VOBJ); UniValue obj(UniValue::VOBJ); + if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 ) + { + if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 ) + { + item.push_back(Pair("available", ValueFromAmount(available))); + item.push_back(Pair("deposited", ValueFromAmount(deposited))); + item.push_back(Pair("issued", ValueFromAmount(issued))); + item.push_back(Pair("withdrawn", ValueFromAmount(withdrawn))); + item.push_back(Pair("approved", ValueFromAmount(approved))); + item.push_back(Pair("redeemed", ValueFromAmount(redeemed))); + obj.push_back(Pair(CURRENCIES[baseid],item)); + a.push_back(obj); + } + } + } + ret.push_back(Pair("fiatstatus", a)); + return ret; +} + +UniValue paxprice(const UniValue& params, bool fHelp) +{ + if ( fHelp || params.size() > 4 || params.size() < 2 ) + throw runtime_error("paxprice \"base\" \"rel\" height\n"); + LOCK(cs_main); + UniValue ret(UniValue::VOBJ); uint64_t basevolume=0,relvolume,seed; + std::string base = params[0].get_str(); + std::string rel = params[1].get_str(); + int32_t height; + if ( params.size() == 2 ) + height = chainActive.LastTip()->nHeight; + else height = atoi(params[2].get_str().c_str()); + //if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 ) + basevolume = 100000; + relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume); + ret.push_back(Pair("base", base)); + ret.push_back(Pair("rel", rel)); + ret.push_back(Pair("height", height)); + char seedstr[32]; + sprintf(seedstr,"%llu",(long long)seed); + ret.push_back(Pair("seed", seedstr)); + if ( height < 0 || height > chainActive.Height() ) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); + else + { + CBlockIndex *pblockindex = chainActive[height]; + if ( pblockindex != 0 ) + ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime)); + if ( basevolume != 0 && relvolume != 0 ) + { + ret.push_back(Pair("price",((double)relvolume / (double)basevolume))); + ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume))); + ret.push_back(Pair("basevolume",ValueFromAmount(basevolume))); + ret.push_back(Pair("relvolume",ValueFromAmount(relvolume))); + } else ret.push_back(Pair("error", "overflow or error in one or more of parameters")); + } + return ret; +} + +UniValue paxprices(const UniValue& params, bool fHelp) +{ + if ( fHelp || params.size() != 3 ) + throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n"); + LOCK(cs_main); + UniValue ret(UniValue::VOBJ); uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)]; + std::string base = params[0].get_str(); + std::string rel = params[1].get_str(); + int32_t maxsamples = atoi(params[2].get_str().c_str()); + if ( maxsamples < 1 ) + maxsamples = 1; + else if ( maxsamples > sizeof(heights)/sizeof(*heights) ) + maxsamples = sizeof(heights)/sizeof(*heights); + ret.push_back(Pair("base", base)); + ret.push_back(Pair("rel", rel)); + n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str()); + UniValue a(UniValue::VARR); + for (i=0; i chainActive.Height() ) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); + else + { + CBlockIndex *pblockindex = chainActive[heights[i]]; + + item.push_back(Pair("t", (int64_t)pblockindex->nTime)); + item.push_back(Pair("p", (double)prices[i] / COIN)); + a.push_back(item); + } + } + ret.push_back(Pair("array", a)); + return ret; +} + +uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); + +UniValue gettxout(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 2 || params.size() > 3) + throw runtime_error( + "gettxout \"txid\" n ( includemempool )\n" + "\nReturns details about an unspent transaction output.\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id\n" + "2. n (numeric, required) vout value\n" + "3. includemempool (boolean, optional) Whether to include the mempool\n" + "\nResult:\n" + "{\n" + " \"bestblock\" : \"hash\", (string) the block hash\n" + " \"confirmations\" : n, (numeric) The number of confirmations\n" + " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" + " \"scriptPubKey\" : { (json object)\n" + " \"asm\" : \"code\", (string) \n" + " \"hex\" : \"hex\", (string) \n" + " \"reqSigs\" : n, (numeric) Number of required signatures\n" + " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" + " \"addresses\" : [ (array of string) array of Komodo addresses\n" + " \"komodoaddress\" (string) Komodo address\n" + " ,...\n" + " ]\n" + " },\n" + " \"version\" : n, (numeric) The version\n" + " \"coinbase\" : true|false (boolean) Coinbase or not\n" + "}\n" + + "\nExamples:\n" + "\nGet unspent transactions\n" + + HelpExampleCli("listunspent", "") + + "\nView the details\n" + + HelpExampleCli("gettxout", "\"txid\" 1") + + "\nAs a json rpc call\n" + + HelpExampleRpc("gettxout", "\"txid\", 1") + ); + + LOCK(cs_main); + + UniValue ret(UniValue::VOBJ); + + std::string strHash = params[0].get_str(); + uint256 hash(uint256S(strHash)); + int n = params[1].get_int(); + bool fMempool = true; + if (params.size() > 2) + fMempool = params[2].get_bool(); + + CCoins coins; + if (fMempool) { + LOCK(mempool.cs); + CCoinsViewMemPool view(pcoinsTip, mempool); + if (!view.GetCoins(hash, coins)) + return NullUniValue; + mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool + } else { + if (!pcoinsTip->GetCoins(hash, coins)) + return NullUniValue; + } + if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull()) + return NullUniValue; + + BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); + CBlockIndex *pindex = it->second; + ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex())); + if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT) + ret.push_back(Pair("confirmations", 0)); + else + { + ret.push_back(Pair("confirmations", komodo_dpowconfs(coins.nHeight,pindex->nHeight - coins.nHeight + 1))); + ret.push_back(Pair("rawconfirmations", pindex->nHeight - coins.nHeight + 1)); + } + ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue))); + uint64_t interest; int32_t txheight; uint32_t locktime; + if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue,(int32_t)pindex->nHeight)) != 0 ) + ret.push_back(Pair("interest", ValueFromAmount(interest))); + UniValue o(UniValue::VOBJ); + ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true); + ret.push_back(Pair("scriptPubKey", o)); + ret.push_back(Pair("version", coins.nVersion)); + ret.push_back(Pair("coinbase", coins.fCoinBase)); + + return ret; +} + +UniValue verifychain(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() > 2) + throw runtime_error( + "verifychain ( checklevel numblocks )\n" + "\nVerifies blockchain database.\n" + "\nArguments:\n" + "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n" + "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n" + "\nResult:\n" + "true|false (boolean) Verified or not\n" + "\nExamples:\n" + + HelpExampleCli("verifychain", "") + + HelpExampleRpc("verifychain", "") + ); + + LOCK(cs_main); + + int nCheckLevel = GetArg("-checklevel", 3); + int nCheckDepth = GetArg("-checkblocks", 288); + if (params.size() > 0) + nCheckLevel = params[0].get_int(); + if (params.size() > 1) + nCheckDepth = params[1].get_int(); + + return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth); +} + +/** Implementation of IsSuperMajority with better feedback */ +static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams) +{ + int nFound = 0; + CBlockIndex* pstart = pindex; + for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++) + { + if (pstart->nVersion >= minVersion) + ++nFound; + pstart = pstart->pprev; + } + + UniValue rv(UniValue::VOBJ); + rv.push_back(Pair("status", nFound >= nRequired)); + rv.push_back(Pair("found", nFound)); + rv.push_back(Pair("required", nRequired)); + rv.push_back(Pair("window", consensusParams.nMajorityWindow)); + return rv; +} + +static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) +{ + UniValue rv(UniValue::VOBJ); + rv.push_back(Pair("id", name)); + rv.push_back(Pair("version", version)); + rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))); + rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams))); + return rv; +} + +static UniValue NetworkUpgradeDesc(const Consensus::Params& consensusParams, Consensus::UpgradeIndex idx, int height) +{ + UniValue rv(UniValue::VOBJ); + auto upgrade = NetworkUpgradeInfo[idx]; + rv.push_back(Pair("name", upgrade.strName)); + rv.push_back(Pair("activationheight", consensusParams.vUpgrades[idx].nActivationHeight)); + switch (NetworkUpgradeState(height, consensusParams, idx)) { + case UPGRADE_DISABLED: rv.push_back(Pair("status", "disabled")); break; + case UPGRADE_PENDING: rv.push_back(Pair("status", "pending")); break; + case UPGRADE_ACTIVE: rv.push_back(Pair("status", "active")); break; + } + rv.push_back(Pair("info", upgrade.strInfo)); + return rv; +} + +void NetworkUpgradeDescPushBack( + UniValue& networkUpgrades, + const Consensus::Params& consensusParams, + Consensus::UpgradeIndex idx, + int height) +{ + // Network upgrades with an activation height of NO_ACTIVATION_HEIGHT are + // hidden. This is used when network upgrade implementations are merged + // without specifying the activation height. + if (consensusParams.vUpgrades[idx].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) { + networkUpgrades.push_back(Pair( + HexInt(NetworkUpgradeInfo[idx].nBranchId), + NetworkUpgradeDesc(consensusParams, idx, height))); + } +} + + +UniValue getblockchaininfo(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getblockchaininfo\n" + "Returns an object containing various state info regarding block chain processing.\n" + "\nNote that when the chain tip is at the last block before a network upgrade activation,\n" + "consensus.chaintip != consensus.nextblock.\n" + "\nResult:\n" + "{\n" + " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" + " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" + " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" + " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" + " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" + " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" + " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" + " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" + " \"commitments\": xxxxxx, (numeric) the current number of note commitments in the commitment tree\n" + " \"softforks\": [ (array) status of softforks in progress\n" + " {\n" + " \"id\": \"xxxx\", (string) name of softfork\n" + " \"version\": xx, (numeric) block version\n" + " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n" + " \"status\": xx, (boolean) true if threshold reached\n" + " \"found\": xx, (numeric) number of blocks with the new version found\n" + " \"required\": xx, (numeric) number of blocks required to trigger\n" + " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n" + " },\n" + " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" + " }, ...\n" + " ],\n" + " \"upgrades\": { (object) status of network upgrades\n" + " \"xxxx\" : { (string) branch ID of the upgrade\n" + " \"name\": \"xxxx\", (string) name of upgrade\n" + " \"activationheight\": xxxxxx, (numeric) block height of activation\n" + " \"status\": \"xxxx\", (string) status of upgrade\n" + " \"info\": \"xxxx\", (string) additional information about upgrade\n" + " }, ...\n" + " },\n" + " \"consensus\": { (object) branch IDs of the current and upcoming consensus rules\n" + " \"chaintip\": \"xxxxxxxx\", (string) branch ID used to validate the current chain tip\n" + " \"nextblock\": \"xxxxxxxx\" (string) branch ID that the next block will be validated under\n" + " }\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getblockchaininfo", "") + + HelpExampleRpc("getblockchaininfo", "") + ); + + LOCK(cs_main); + double progress; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) { + progress = Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.LastTip()); + } else { + int32_t longestchain = KOMODO_LONGESTCHAIN;//komodo_longestchain(); + progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0; + } + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("chain", Params().NetworkIDString())); + obj.push_back(Pair("blocks", (int)chainActive.Height())); + obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1)); + obj.push_back(Pair("bestblockhash", chainActive.LastTip()->GetBlockHash().GetHex())); + obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); + obj.push_back(Pair("verificationprogress", progress)); + obj.push_back(Pair("chainwork", chainActive.LastTip()->nChainWork.GetHex())); + obj.push_back(Pair("pruned", fPruneMode)); + obj.push_back(Pair("size_on_disk", CalculateCurrentUsage())); + + ZCIncrementalMerkleTree tree; + pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree); + #ifdef __APPLE__ + obj.push_back(Pair("commitments", (uint64_t)tree.size())); + #else + obj.push_back(Pair("commitments", tree.size())); + #endif + + CBlockIndex* tip = chainActive.LastTip(); + UniValue valuePools(UniValue::VARR); + valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none)); + obj.push_back(Pair("valuePools", valuePools)); + + const Consensus::Params& consensusParams = Params().GetConsensus(); + UniValue softforks(UniValue::VARR); + softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); + softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); + softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); + obj.push_back(Pair("softforks", softforks)); + + UniValue upgrades(UniValue::VOBJ); + for (int i = Consensus::UPGRADE_OVERWINTER; i < Consensus::MAX_NETWORK_UPGRADES; i++) { + NetworkUpgradeDescPushBack(upgrades, consensusParams, Consensus::UpgradeIndex(i), tip->nHeight); + } + obj.push_back(Pair("upgrades", upgrades)); + + UniValue consensus(UniValue::VOBJ); + consensus.push_back(Pair("chaintip", HexInt(CurrentEpochBranchId(tip->nHeight, consensusParams)))); + consensus.push_back(Pair("nextblock", HexInt(CurrentEpochBranchId(tip->nHeight + 1, consensusParams)))); + obj.push_back(Pair("consensus", consensus)); + + if (fPruneMode) + { + CBlockIndex *block = chainActive.LastTip(); + while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) + block = block->pprev; + + obj.push_back(Pair("pruneheight", block->nHeight)); + } + return obj; +} + +/** Comparison function for sorting the getchaintips heads. */ +struct CompareBlocksByHeight +{ + bool operator()(const CBlockIndex* a, const CBlockIndex* b) const + { + /* Make sure that unequal blocks with the same height do not compare + equal. Use the pointers themselves to make a distinction. */ + + if (a->nHeight != b->nHeight) + return (a->nHeight > b->nHeight); + + return a < b; + } +}; + +#include + +UniValue getchaintips(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getchaintips\n" + "Return information about all known tips in the block tree," + " including the main chain as well as orphaned branches.\n" + "\nResult:\n" + "[\n" + " {\n" + " \"height\": xxxx, (numeric) height of the chain tip\n" + " \"hash\": \"xxxx\", (string) block hash of the tip\n" + " \"branchlen\": 0 (numeric) zero for main chain\n" + " \"status\": \"active\" (string) \"active\" for the main chain\n" + " },\n" + " {\n" + " \"height\": xxxx,\n" + " \"hash\": \"xxxx\",\n" + " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" + " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" + " }\n" + "]\n" + "Possible values for status:\n" + "1. \"invalid\" This branch contains at least one invalid block\n" + "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" + "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" + "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" + "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" + "\nExamples:\n" + + HelpExampleCli("getchaintips", "") + + HelpExampleRpc("getchaintips", "") + ); + + LOCK(cs_main); + + /* Build up a list of chain tips. We start with the list of all + known blocks, and successively remove blocks that appear as pprev + of another block. */ + /*static pthread_mutex_t mutex; static int32_t didinit; + if ( didinit == 0 ) + { + pthread_mutex_init(&mutex,NULL); + didinit = 1; + } + pthread_mutex_lock(&mutex);*/ + std::set setTips; + int32_t n = 0; + BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) + { + n++; + setTips.insert(item.second); + } + fprintf(stderr,"iterations getchaintips %d\n",n); + n = 0; + BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) + { + const CBlockIndex* pprev=0; + n++; + if ( item.second != 0 ) + pprev = item.second->pprev; + if (pprev) + setTips.erase(pprev); + } + fprintf(stderr,"iterations getchaintips %d\n",n); + //pthread_mutex_unlock(&mutex); + + // Always report the currently active tip. + setTips.insert(chainActive.LastTip()); + + /* Construct the output array. */ + UniValue res(UniValue::VARR); const CBlockIndex *forked; + BOOST_FOREACH(const CBlockIndex* block, setTips) + BOOST_FOREACH(const CBlockIndex* block, setTips) + { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("height", block->nHeight)); + obj.push_back(Pair("hash", block->phashBlock->GetHex())); + forked = chainActive.FindFork(block); + if ( forked != 0 ) + { + const int branchLen = block->nHeight - forked->nHeight; + obj.push_back(Pair("branchlen", branchLen)); + + string status; + if (chainActive.Contains(block)) { + // This block is part of the currently active chain. + status = "active"; + } else if (block->nStatus & BLOCK_FAILED_MASK) { + // This block or one of its ancestors is invalid. + status = "invalid"; + } else if (block->nChainTx == 0) { + // This block cannot be connected because full block data for it or one of its parents is missing. + status = "headers-only"; + } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) { + // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized. + status = "valid-fork"; + } else if (block->IsValid(BLOCK_VALID_TREE)) { + // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain. + status = "valid-headers"; + } else { + // No clue. + status = "unknown"; + } + obj.push_back(Pair("status", status)); + } + res.push_back(obj); + } + + return res; +} + +UniValue mempoolInfoToJSON() +{ + UniValue ret(UniValue::VOBJ); + ret.push_back(Pair("size", (int64_t) mempool.size())); + ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize())); + ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); + + return ret; +} + +UniValue getmempoolinfo(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getmempoolinfo\n" + "\nReturns details on the active state of the TX memory pool.\n" + "\nResult:\n" + "{\n" + " \"size\": xxxxx (numeric) Current tx count\n" + " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n" + " \"usage\": xxxxx (numeric) Total memory usage for the mempool\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getmempoolinfo", "") + + HelpExampleRpc("getmempoolinfo", "") + ); + + return mempoolInfoToJSON(); +} + +UniValue invalidateblock(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "invalidateblock \"hash\"\n" + "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the block to mark as invalid\n" + "\nResult:\n" + "\nExamples:\n" + + HelpExampleCli("invalidateblock", "\"blockhash\"") + + HelpExampleRpc("invalidateblock", "\"blockhash\"") + ); + + std::string strHash = params[0].get_str(); + uint256 hash(uint256S(strHash)); + CValidationState state; + + { + LOCK(cs_main); + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlockIndex* pblockindex = mapBlockIndex[hash]; + InvalidateBlock(state, pblockindex); + } + + if (state.IsValid()) { + ActivateBestChain(state); + } + + if (!state.IsValid()) { + throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); + } + + return NullUniValue; +} + +UniValue reconsiderblock(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "reconsiderblock \"hash\"\n" + "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" + "This can be used to undo the effects of invalidateblock.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the block to reconsider\n" + "\nResult:\n" + "\nExamples:\n" + + HelpExampleCli("reconsiderblock", "\"blockhash\"") + + HelpExampleRpc("reconsiderblock", "\"blockhash\"") + ); + + std::string strHash = params[0].get_str(); + uint256 hash(uint256S(strHash)); + CValidationState state; + + { + LOCK(cs_main); + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlockIndex* pblockindex = mapBlockIndex[hash]; + ReconsiderBlock(state, pblockindex); + } + + if (state.IsValid()) { + ActivateBestChain(state); + } + + if (!state.IsValid()) { + throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); + } + + return NullUniValue; +} diff --git a/src/script/standard.cpp b/src/script/standard.cpp index f240dde79d8..290fb2ee7fa 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -385,7 +385,7 @@ bool ExtractDestination(const CScript& _scriptPubKey, CTxDestination& addressRet else if (IsCryptoConditionsEnabled() != 0 && whichType == TX_CRYPTOCONDITION) { - addressRet = CCryptoConditionID(uint160(vSolutions[0])); + addressRet = CKeyID(uint160(vSolutions[0])); return true; } // Multisig txns have more than one address... @@ -500,10 +500,6 @@ class CScriptVisitor : public boost::static_visitor *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL; return true; } - bool operator()(const CCryptoConditionID &dest) const { - script->clear(); - return false; // can't create a cc that simple - } }; } diff --git a/src/script/standard.h b/src/script/standard.h index d9c8f512d11..912c575d993 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -40,13 +40,6 @@ class CScriptID : public uint160 CScriptID(const uint160& in) : uint160(in) {} }; -class CCryptoConditionID : public uint160 -{ -public: - CCryptoConditionID() : uint160() {} - CCryptoConditionID(const uint160& in) : uint160(in) {} -}; - static const unsigned int MAX_OP_RETURN_RELAY = 8192; //! bytes extern unsigned nMaxDatacarrierBytes; @@ -103,7 +96,7 @@ class CNoDestination { * * CScriptID: TX_SCRIPTHASH destination * A CTxDestination is the internal data type encoded in a bitcoin address */ -typedef boost::variant CTxDestination; +typedef boost::variant CTxDestination; class COptCCParams { diff --git a/src/sync.cpp b/src/sync.cpp index 2f17a401bad..31c3301bd25 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -157,8 +157,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) static void pop_lock() { dd_mutex.lock(); - if (lockstack.get() != NULL) - (*lockstack).pop_back(); + (*lockstack).pop_back(); dd_mutex.unlock(); } diff --git a/src/util.cpp b/src/util.cpp index bee7903d2b5..65ecfe6ec7f 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -30,7 +30,8 @@ #include "sync.h" #include "utilstrencodings.h" #include "utiltime.h" -#include "komodo_defs.h" +//#include "komodo_defs.h" // plz dont add this where it is not used, we have build errors for komodo-cli + #include #include #include @@ -393,8 +394,8 @@ void ParseParameters(int argc, const char* const argv[]) } } -// split string using space, comma (default) or other char (param) as a delimiter -void SplitStr(const std::string& strVal, std::vector &outVals, const std::string &delims) +// split string using by space or comma as a delimiter char +void SplitStr(const std::string& strVal, std::vector &outVals) { stringstream ss(strVal); @@ -405,7 +406,7 @@ void SplitStr(const std::string& strVal, std::vector &outVals, cons while (std::isspace(ss.peek())) ss.ignore(); - while ((c = ss.get()) != EOF && !std::isspace(c) && delims.find(c) == std::string::npos) + while ((c = ss.get()) != EOF && !std::isspace(c) && c != ',') str += c; if (!str.empty()) @@ -413,34 +414,36 @@ void SplitStr(const std::string& strVal, std::vector &outVals, cons } } -void SplitIntoU64List(const std::string& strVal, int32_t outsize, uint64_t* outVals, const uint64_t nDefault) +void Split(const std::string& strVal, int32_t outsize, uint64_t *outVals, const uint64_t nDefault) { stringstream ss(strVal); vector vec; - uint64_t val, nLast, numVals = 0; + uint64_t i, nLast, numVals = 0; - while (ss.peek() == ' ') + while ( ss.peek() == ' ' ) ss.ignore(); - while (ss >> val && numVals < outsize) { - outVals[numVals] = val; - numVals++; + while ( ss >> i ) + { + outVals[numVals] = i; + numVals += 1; - while (ss.peek() == ' ') + while ( ss.peek() == ' ' ) ss.ignore(); - if (ss.peek() == ',') + if ( ss.peek() == ',' ) ss.ignore(); - while (ss.peek() == ' ') + while ( ss.peek() == ' ' ) ss.ignore(); } - if (numVals > 0) + if ( numVals > 0 ) nLast = outVals[numVals - 1]; else nLast = nDefault; - for (int i = numVals; i < outsize; i++) { + for ( i = numVals; i < outsize; i++ ) + { outVals[i] = nLast; } } @@ -732,6 +735,7 @@ void ReadConfigFile(map& mapSettingsRet, } // If datadir is changed in .conf file: ClearDatadirCache(); + extern uint16_t BITCOIND_RPCPORT; BITCOIND_RPCPORT = GetArg("-rpcport",BaseParams().RPCPort()); } @@ -1036,34 +1040,3 @@ int GetNumCores() return boost::thread::physical_concurrency(); } -// add settings to args maps (to add default opts for a specific chain defined outside) -void AddSettings(std::map& mapSettingsRet, - std::map >& mapMultiSettingsRet, const std::string &strOpts) -{ - std::vector vOpts; - SplitStr(strOpts, vOpts, " "); - for (auto const &opt : vOpts) - { - std::vector namevalue; - SplitStr(opt, namevalue, "="); - if (namevalue.size() != 2) - throw std::runtime_error("Invalid option name-value format in override-settings variable"); - std::string name = namevalue[0]; - std::string value = namevalue[1]; - if (name[0] != '-') - throw std::runtime_error("Invalid option format in override-settings variable"); - - // Interpret --foo as -foo. - // If both --foo and -foo are set, the last takes effect. - if (name.length() > 1 && name[1] == '-') - name = name.substr(1); - - if (mapSettingsRet.count(name) == 0) - { - mapSettingsRet[name] = value; - // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set) - InterpretNegativeSetting(name, mapSettingsRet); - } - mapMultiSettingsRet[name].push_back(value); - } -} \ No newline at end of file diff --git a/src/util.h b/src/util.h index 554555d0530..17bf19952b0 100644 --- a/src/util.h +++ b/src/util.h @@ -179,13 +179,13 @@ inline bool IsSwitchChar(char c) /** * Return string argument or default value * - * @param strVal string to split into array of uint64_t + * @param strVal string to split * @param outVals array of numbers from string or default - * if the strVal is null, nDefault is used for all array entries - * else if the strVal has fewer than outsize entries, then the last - * entry fills remaining entries in outVals + * if the string is null, nDefault is used for all array entries + * else if the string has fewer than _MAX_ERAS entries, then the last + * entry fills remaining entries */ -void SplitIntoU64List(const std::string& strVal, int32_t outsize, uint64_t *outVals, uint64_t nDefault); +void Split(const std::string& strVal, int32_t outsize, uint64_t *outVals, uint64_t nDefault); /** * Return string argument or default value @@ -288,8 +288,7 @@ template void TraceThread(const char* name, Callable func) } // split string using by space or comma as a delimiter char -void SplitStr(const std::string& strVal, std::vector &outVals, const std::string &delims = ","); -void AddSettings(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet, const std::string &strOpts); +void SplitStr(const std::string& strVal, std::vector &outVals); #define KOMODO_ASSETCHAIN_MAXLEN 65 diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index e42628f6416..cd0cc42a6c5 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -42,11 +42,11 @@ #include "zcash/Note.hpp" #include "zcash/NoteEncryption.hpp" -#include "rpcwallet.h" - using namespace std; using namespace libzcash; +// Function declaration for function implemented in wallet/rpcwallet.cpp +bool EnsureWalletIsAvailable(bool avoidException); /** * RPC call to generate a payment disclosure diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 3795a7077ad..31f583ee4f1 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -37,10 +37,11 @@ #include -#include "rpcwallet.h" - using namespace std; +void EnsureWalletIsUnlocked(); +bool EnsureWalletIsAvailable(bool avoidException); + UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys); UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 14eb173709d..fa5dce4eb89 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -63,8 +63,6 @@ #include "komodo_defs.h" #include -#include "rpcwallet.h" - #include "../cc/CCfaucet.h" #include "../cc/CCrewards.h" #include "../cc/CCdice.h" @@ -83,8 +81,16 @@ using namespace std; using namespace libzcash; +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; const std::string ADDR_TYPE_SPROUT = "sprout"; const std::string ADDR_TYPE_SAPLING = "sapling"; +extern UniValue TxJoinSplitToJSON(const CTransaction& tx); +extern int32_t KOMODO_INSYNC; +uint32_t komodo_segid32(char *coinaddr); +int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); +int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime); // from ac_private chains only +CBlockIndex *komodo_getblockindex(uint256 hash); int64_t nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; @@ -96,6 +102,8 @@ UniValue z_getoperationstatus_IMPL(const UniValue&, bool); #define VALID_PLAN_NAME(x) (strlen(x) <= PLAN_NAME_MAX) #define THROW_IF_SYNCING(INSYNC) if (INSYNC == 0) { throw runtime_error(strprintf("%s: Chain still syncing at height %d, aborting to prevent linkability analysis!",__FUNCTION__,chainActive.Tip()->GetHeight())); } +int tx_height( const uint256 &hash ); + std::string HelpRequiringPassphrase() { return pwalletMain && pwalletMain->IsCrypted() @@ -476,8 +484,6 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr // Parse Zcash address CScript scriptPubKey = GetScriptForDestination(address); - if (scriptPubKey.empty()) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid destination"); // Create and send the transaction CReserveKey reservekey(pwalletMain); @@ -509,6 +515,8 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); } +int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); + UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) { uint8_t opretbuf[IGUANA_MAXSCRIPTSIZE],opretscript[IGUANA_MAXSCRIPTSIZE],*opret=0; char *oprethexstr; int32_t len,opretlen = 0; @@ -586,6 +594,29 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) return wtx.GetHash().GetHex(); } +#include "komodo_defs.h" + +#define KOMODO_KVPROTECTED 1 +#define KOMODO_KVBINARY 2 +#define KOMODO_KVDURATION 1440 +#define IGUANA_MAXSCRIPTSIZE 10001 +uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey37[37],char *coinaddr,int32_t height,char *base,int64_t fiatoshis); +int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); +#define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" +extern int32_t KOMODO_PAX; +extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; +int32_t komodo_is_issuer(); +int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); +int32_t komodo_isrealtime(int32_t *kmdheightp); +int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); +int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); +int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize); +uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen); +uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 privkey); +int32_t komodo_kvduration(uint32_t flags); +uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase); +int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig); + UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk) { static uint256 zeroes; diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 226647b1986..3e7a54d4afe 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -24,6 +24,5 @@ class CRPCTable; void RegisterWalletRPCCommands(CRPCTable &tableRPC); bool EnsureWalletIsAvailable(bool avoidException); -void EnsureWalletIsUnlocked(); #endif //BITCOIN_WALLET_RPCWALLET_H diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b98cdac42b8..db66de052c4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -38,8 +38,6 @@ #include "crypter.h" #include "coins.h" #include "zcash/zip32.h" - -#include "komodo_defs.h" #include "cc/CCinclude.h" #include @@ -60,7 +58,12 @@ unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; bool bSpendZeroConfChange = true; bool fSendFreeTransactions = false; bool fPayAtLeastCustomFee = true; +#include "komodo_defs.h" +CBlockIndex *komodo_chainactive(int32_t height); +extern std::string DONATION_PUBKEY; +int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); +int tx_height( const uint256 &hash ); /** * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) @@ -3382,6 +3385,9 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const /** * populate vCoins with vector of available COutputs. */ +uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); + void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase) const { uint64_t interest,*ptr; @@ -4216,7 +4222,7 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge } -//void komodo_prefetch(FILE *fp); +void komodo_prefetch(FILE *fp); DBErrors CWallet::LoadWallet(bool& fFirstRunRet) { @@ -4825,8 +4831,6 @@ class CAffectedKeysVisitor : public boost::static_visitor { Process(script); } - void operator()(const CCryptoConditionID &none) {} // no cc in the wallet - void operator()(const CNoDestination &none) {} }; diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index fd00a245914..5f7c1d5f7be 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -47,7 +47,6 @@ PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 -# cclib building now added to src/Makefile.am #BUILD CCLIB # WD=$PWD # cd src/cc @@ -55,20 +54,11 @@ make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 # echo Making cclib... # ./makecustom # cd $WD - -# build cryptoconditions -cd ./src/cryptoconditions -./autogen.sh -./configure -make -cd ../.. +# cclib building now added to src/Makefile.am ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ -./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" \ - --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ - CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ - CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' +CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ +./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" -make "$@" V=1 NO_GTEST=1 STATIC=1 \ No newline at end of file +make "$@" V=1 NO_GTEST=1 STATIC=1 diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index eef4b4f27f2..a445ef873b7 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -13,28 +13,17 @@ cd "$(dirname "$(readlink -f "$0")")/.." cd depends/ && make HOST=$HOST V=1 NO_QT=1 cd ../ -# build cryptoconditions -cd ./src/cryptoconditions -./autogen.sh -./configure --host=x86_64-w64-mingw32 --enable-static --disable-shared -CC="${CC} -g " CXX="${CXX} -g " make V=1 -cd ../.. - -# note: cclib building now added to src/Makefile.am #BUILD CCLIB # WD=$PWD # cd src/cc # echo $PWD # ./makecustom # cd $WD +# cclib building now added to src/Makefile.am + ./autogen.sh -CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared \ - --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ - CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ - CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' -sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure - +CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared +sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure cd src/ -# note: to build tokeld, tokel-cli it should not exist 'komodod.exe komodo-cli.exe' param here: -CC="${CC} -g " CXX="${CXX} -g " make V=1 +CC="${CC} -g " CXX="${CXX} -g " make V=1 komodod.exe komodo-cli.exe komodo-tx.exe diff --git a/zcutil/build.sh b/zcutil/build.sh index 3a64f2d2e69..9033ac32fbc 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -96,27 +96,17 @@ eval "$MAKE" --version as --version ld -v -# build cryptoconditions -cd ./src/cryptoconditions -./autogen.sh -./configure -make -cd ../.. - HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh -CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' \ - --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ - CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ - CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' +CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' -# cclib building now added to src/Makefile.am: #BUILD CCLIB #WD=$PWD #cd src/cc #echo $PWD #./makecustom #cd $WD +# cclib building now added to src/Makefile.am "$MAKE" "$@" V=1 From 6941b48b31438dc6719f277397ce043e6aa77dbd Mon Sep 17 00:00:00 2001 From: Daria Date: Tue, 5 Oct 2021 15:58:24 +0800 Subject: [PATCH 146/348] Create tokel_chain_flow.md --- tokel_chain_flow.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tokel_chain_flow.md diff --git a/tokel_chain_flow.md b/tokel_chain_flow.md new file mode 100644 index 00000000000..d2697a9f95b --- /dev/null +++ b/tokel_chain_flow.md @@ -0,0 +1,21 @@ +# Tokel blockchain code commit process/flow + +## The Process + +Feature development -> Team/Community testing -> PR to the `tokel` branch + +## Feature development + +1. Fork this repository and make a new feature branch. +2. Once done make a PR to TokelPlatform/komodo ‘tkltest’. +3. Reach out to someone to review your code. + +## Team/community testing + +After getting you PR reviewed and merge to `tkltest` Team/community performs through testing. + +## Accepted/tested code + +If all the tests have gone well, the resulting code is PRd into these repositories: +1. `TokelPlatform/Komodo` `tokel` branch +2. `KomodoPlatform/Komodo` `tokel` branch From 226e234226bca274e30e9ad9ac398e5d47623fff Mon Sep 17 00:00:00 2001 From: Daria Date: Thu, 7 Oct 2021 10:26:41 +0800 Subject: [PATCH 147/348] Update README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f3179378402..79277506513 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,11 @@ This is the `tokel` branch of Komodo's sourcecode repository. This branch is required to run and use the main Tokel blockchain and hosts Tokel specific developments. -To run Tokel's test chain, please use the repository below instead. -- https://github.com/TokelPlatform/komodo/ +Instructions to run komodo based chains are to be found at +- https://github.com/KomodoPlatform/komodo#getting-started + +To run Tokel's test chain, please use the tkltest branch of this repository. +- https://github.com/TokelPlatform/komodo/tree/tkltest ## What is the Tokel Platform? From 53d4577129e80d39f7cde8f01ece97e804ee9932 Mon Sep 17 00:00:00 2001 From: Daria Date: Thu, 7 Oct 2021 14:40:46 +0800 Subject: [PATCH 148/348] Update tokel_chain_flow.md --- tokel_chain_flow.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/tokel_chain_flow.md b/tokel_chain_flow.md index d2697a9f95b..a8d6604b604 100644 --- a/tokel_chain_flow.md +++ b/tokel_chain_flow.md @@ -1,6 +1,32 @@ # Tokel blockchain code commit process/flow -## The Process +## Repository overview + +### TokelPlatform/komodo + +#### Tkltest branch + +https://github.com/TokelPlatform/komodo/tree/tkltest + +Used to test blockchain code in a community environment using the TKLTEST (test net) blockchains. + +#### Tokel branch + +https://github.com/TokelPlatform/komodo/tree/tokel + +This is the Tokel ‘master’ branch. The Tokel chain runs off this branch. + +This branch is to be kept identical to the KomodoPlatform/Komodo ‘tokel’ branch. + +### KomodoPlatform/Komodo + +#### Tokel branch + +https://github.com/KomodoPlatform/komodo/tree/tokel + +This branch is used by Komodo Notary Nodes. This branch is a ‘gateway’ between the Komodo & Tokel branches. All Tokel development is pushed through here, and vice versa for Komodo development/updates. + +## The Process - working on the Tokel Blockchain features Feature development -> Team/Community testing -> PR to the `tokel` branch @@ -19,3 +45,10 @@ After getting you PR reviewed and merge to `tkltest` Team/community performs thr If all the tests have gone well, the resulting code is PRd into these repositories: 1. `TokelPlatform/Komodo` `tokel` branch 2. `KomodoPlatform/Komodo` `tokel` branch + +## Updates coming from Komodo side + +1. PR from a branch in Komodo repository + + +## Updates coming from Komodo side From 10b892c844eaeb0875fbe22fc17726bcd3f909bc Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 7 Oct 2021 15:42:55 +0500 Subject: [PATCH 149/348] comment added to mark Tokel defaults for nspv_msg and unspentccindex --- src/main.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.h b/src/main.h index 99fe460e118..c1df8670ede 100644 --- a/src/main.h +++ b/src/main.h @@ -121,14 +121,14 @@ static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60; static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; -/** Default NSPV support enabled */ +/** Default NSPV support enabled for Tokel */ static const bool DEFAULT_NSPV_PROCESSING = true; -//static const bool DEFAULT_ADDRESSINDEX = false; -//static const bool DEFAULT_SPENTINDEX = false; #define DEFAULT_ADDRESSINDEX (GetArg("-ac_cc",0) != 0 || GetArg("-ac_ccactivate",0) != 0) #define DEFAULT_SPENTINDEX (GetArg("-ac_cc",0) != 0 || GetArg("-ac_ccactivate",0) != 0) -#define DEFAULT_UNSPENTCCINDEX true + +/** Default unspent cc enabled for Tokel */ +static const bool DEFAULT_UNSPENTCCINDEX = true; static const bool DEFAULT_TIMESTAMPINDEX = false; static const unsigned int DEFAULT_DB_MAX_OPEN_FILES = 1000; From 3cb9ac84eba07a6da9e59bd10a220a6744efd89d Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Fri, 8 Oct 2021 21:07:37 +1100 Subject: [PATCH 150/348] Updated README Added our documentation links and updated wording --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 79277506513..fb38a79c0a1 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,17 @@ ![Tokel Header](https://github.com/TokelPlatform/tokel_app/blob/development/assets/tokel-header.png "Tokel Header") -## Komodo's 'Tokel' Branch +## The Tokel blockchain repository -This is the `tokel` branch of Komodo's sourcecode repository. This branch is required to run and use the main Tokel blockchain and hosts Tokel specific developments. +This is the official repository of the Tokel Platform's blockchain source code. Tokel uses the komodo daemon to run our independent blockchain. -Instructions to run komodo based chains are to be found at -- https://github.com/KomodoPlatform/komodo#getting-started +The 'tokel' branch is required to run and use the main Tokel blockchain and hosts numerous Tokel specific developments you will not find in the master Komodo repository. -To run Tokel's test chain, please use the tkltest branch of this repository. +Instructions to run the Tokel blockchain can be found at: +- https://docs.tokel.io/guides/LaunchTheChain/ + +To run Tokel's test chain (TKLTEST), please use the 'tkltest' branch of this repository. You can find instructions here: +- https://docs.tokel.io/guides/LaunchTKLTESTchain/ - https://github.com/TokelPlatform/komodo/tree/tkltest @@ -42,7 +45,7 @@ Tokel is a dedicated token platform. This platform will provide a solid foundati The all-in-one Tokel application is an open-sourced application that will be the one stop shop for all Tokel related features. This application is built using nSPV superlite wallet technology that has been developed by the Komodo platform, for an incredibly fast and reliable experience. This application accesses all of the features offered on the Tokel blockchain whilst keeping users funds in their own wallets (completely non-custodial). This application is in development. You can keep up with progress on the github, or find out more by having a chat in our discord. -https://github.com/TokelPlatform/tokel_app +https://github.com/TokelPlatform/tokel_dapp #### Application features include: - A TKL coin wallet From 74c90a26c242841cbd2364e986715ca054c7febd Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Oct 2021 14:38:01 +0500 Subject: [PATCH 151/348] NSPV_notarizationextract logging improved --- src/komodo_nSPV.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index e8bb2d9df31..a9ea5c9545a 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -584,6 +584,8 @@ uint256 NSPV_opretextract(int32_t *heightp,uint256 *blockhashp,char *symbol,std: int32_t NSPV_notarizationextract(int32_t verifyntz,int32_t *ntzheightp,uint256 *blockhashp,uint256 *desttxidp,CTransaction tx) { int32_t numsigs=0; uint8_t elected[64][33]; char *symbol; std::vector opret; uint32_t nTime; + AssertLockHeld(cs_main); + if ( tx.vout.size() >= 2 ) { symbol = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; @@ -596,16 +598,19 @@ int32_t NSPV_notarizationextract(int32_t verifyntz,int32_t *ntzheightp,uint256 * komodo_notaries(elected,*ntzheightp,nTime); if ( verifyntz != 0 && (numsigs= NSPV_fastnotariescount(tx,elected,nTime)) < 12 ) { - fprintf(stderr,"numsigs.%d error\n",numsigs); + LogPrintf("%s error numsigs.%d less than 12\n", __func__, numsigs); return(-3); } return(0); } else { - fprintf(stderr,"opretsize.%d error\n",(int32_t)opret.size()); + LogPrintf("%s opretsize.%d error\n", __func__, (int32_t)opret.size()); return(-2); } - } else return(-1); + } else { + LogPrintf("%s tx.vout.size().%d error\n", __func__, (int32_t)tx.vout.size()); + return(-1); + } } #endif // KOMODO_NSPV_H From 8b43f7ab19f87978b70e972c010559860dc3efdb Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Oct 2021 14:38:48 +0500 Subject: [PATCH 152/348] more #include for better IDE error check --- src/komodo_nSPV_wallet.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/komodo_nSPV_wallet.h b/src/komodo_nSPV_wallet.h index e50ace003c5..fc7793e8694 100644 --- a/src/komodo_nSPV_wallet.h +++ b/src/komodo_nSPV_wallet.h @@ -18,6 +18,10 @@ #define KOMODO_NSPVWALLET_H #include "rpc/server.h" +#include "komodo_nSPV_defs.h" +#include "komodo_nSPV.h" +#include "komodo_nSPV_superlite.h" + // nSPV wallet uses superlite functions (and some komodod built in functions) to implement nSPV_spend //extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); From 8ab8c64c97a42e1e586034757fb6396ff4364b08 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Oct 2021 14:39:31 +0500 Subject: [PATCH 153/348] NSPV_getntzsproofresp fixed returned nexttxidht --- src/komodo_nSPV_fullnode.h | 67 ++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 54fd50c8482..afda5ffbda9 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -856,51 +856,56 @@ int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid /*, return (sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen); } -int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp *ptr,uint256 prevntztxid,uint256 nextntztxid) +// get notarisation bracket txns and headers between them +int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp* ptr, uint256 prevntztxid, uint256 nextntztxid) { - int32_t i; uint256 hashBlock,bhash0,bhash1,desttxid0,desttxid1; CTransaction tx; + int32_t i; + uint256 prevHashBlock, nextHashBlock, bhash0, bhash1, desttxid0, desttxid1; + CTransaction tx; LOCK(cs_main); ptr->prevtxid = prevntztxid; - ptr->prevntz = NSPV_getrawtx(tx,hashBlock,&ptr->prevtxlen,ptr->prevtxid); - ptr->prevtxidht = komodo_blockheight(hashBlock); - if ( NSPV_notarizationextract(0,&ptr->common.prevht,&bhash0,&desttxid0,tx) < 0 ) - return(-2); - else if ( komodo_blockheight(bhash0) != ptr->common.prevht ) - return(-3); - + ptr->prevntz = NSPV_getrawtx(tx, prevHashBlock, &ptr->prevtxlen, ptr->prevtxid); + ptr->prevtxidht = komodo_blockheight(prevHashBlock); + if (NSPV_notarizationextract(0, &ptr->common.prevht, &bhash0, &desttxid0, tx) < 0) { + LogPrintf("%s error: cant decode notarization opreturn ptr->common.prevht.%d bhash0 %s\n", __func__, ptr->common.prevht, bhash0.ToString()); + return (-2); + } else if (komodo_blockheight(bhash0) != ptr->common.prevht) { + LogPrintf("%s error: bhash0 ht.%d not equal to prevht.%d\n", __func__, komodo_blockheight(bhash0), ptr->common.prevht); + return (-3); + } + ptr->nexttxid = nextntztxid; - ptr->nextntz = NSPV_getrawtx(tx,hashBlock,&ptr->nexttxlen,ptr->nexttxid); - ptr->nexttxidht = ptr->prevtxidht; // komodo_blockheight(hashBlock); - if ( NSPV_notarizationextract(0,&ptr->common.nextht,&bhash1,&desttxid1,tx) < 0 ) - return(-5); - else if ( komodo_blockheight(bhash1) != ptr->common.nextht ) - return(-6); - - else if ( ptr->common.prevht > ptr->common.nextht || (ptr->common.nextht - ptr->common.prevht) > 1440 ) - { - fprintf(stderr,"illegal prevht.%d nextht.%d\n",ptr->common.prevht,ptr->common.nextht); - return(-7); + ptr->nextntz = NSPV_getrawtx(tx, nextHashBlock, &ptr->nexttxlen, ptr->nexttxid); + ptr->nexttxidht = komodo_blockheight(nextHashBlock); + if (NSPV_notarizationextract(0, &ptr->common.nextht, &bhash1, &desttxid1, tx) < 0) { + LogPrintf("%s error: cant decode notarization opreturn ptr->common.nextht.%d bhash1 %s\n", __func__, ptr->common.nextht, bhash1.ToString()); + return (-5); + } else if (komodo_blockheight(bhash1) != ptr->common.nextht) { + LogPrintf("%s error: bhash1 ht.%d not equal to nextht.%d\n", __func__, komodo_blockheight(bhash1), ptr->common.nextht); + return (-6); } - //fprintf(stderr,"%s -> prevht.%d, %s -> nexht.%d\n",ptr->prevtxid.GetHex().c_str(),ptr->common.prevht,ptr->nexttxid.GetHex().c_str(),ptr->common.nextht); + else if (ptr->common.prevht > ptr->common.nextht || (ptr->common.nextht - ptr->common.prevht) > 1440) { + LogPrintf("%s error illegal prevht.%d nextht.%d\n", __func__, ptr->common.prevht, ptr->common.nextht); + return (-7); + } + //fprintf(stderr, "%s -> prevht.%d, %s -> nexht.%d\n", ptr->prevtxid.GetHex().c_str(), ptr->common.prevht, ptr->nexttxid.GetHex().c_str(), ptr->common.nextht); ptr->common.numhdrs = (ptr->common.nextht - ptr->common.prevht + 1); - ptr->common.hdrs = (struct NSPV_equihdr *)calloc(ptr->common.numhdrs,sizeof(*ptr->common.hdrs)); - //fprintf(stderr,"prev.%d next.%d allocate numhdrs.%d\n",prevht,nextht,ptr->common.numhdrs); - for (i=0; icommon.numhdrs; i++) - { + ptr->common.hdrs = (struct NSPV_equihdr*)calloc(ptr->common.numhdrs, sizeof(*ptr->common.hdrs)); + //fprintf(stderr, "prev.%d next.%d allocate numhdrs.%d\n", ptr->common.prevht, ptr->common.nextht, ptr->common.numhdrs); + for (i = 0; i < ptr->common.numhdrs; i++) { //hashBlock = NSPV_hdrhash(&ptr->common.hdrs[i]); //fprintf(stderr,"hdr[%d] %s\n",prevht+i,hashBlock.GetHex().c_str()); - if ( NSPV_setequihdr(&ptr->common.hdrs[i],ptr->common.prevht+i) < 0 ) - { - fprintf(stderr,"error setting hdr.%d\n",ptr->common.prevht+i); + if (NSPV_setequihdr(&ptr->common.hdrs[i], ptr->common.prevht + i) < 0) { + LogPrintf("%s error setting hdr.%d\n", __func__, ptr->common.prevht + i); free(ptr->common.hdrs); ptr->common.hdrs = 0; - return(-1); + return (-1); } } - //fprintf(stderr,"sizeof ptr %ld, common.%ld lens.%d %d\n",sizeof(*ptr),sizeof(ptr->common),ptr->prevtxlen,ptr->nexttxlen); - return(sizeof(*ptr) + sizeof(*ptr->common.hdrs)*ptr->common.numhdrs - sizeof(ptr->common.hdrs) - sizeof(ptr->prevntz) - sizeof(ptr->nextntz) + ptr->prevtxlen + ptr->nexttxlen); + //fprintf(stderr, "sizeof ptr %ld, common.%ld lens.%d %d\n", sizeof(*ptr), sizeof(ptr->common), ptr->prevtxlen, ptr->nexttxlen); + return (sizeof(*ptr) + sizeof(*ptr->common.hdrs) * ptr->common.numhdrs - sizeof(ptr->common.hdrs) - sizeof(ptr->prevntz) - sizeof(ptr->nextntz) + ptr->prevtxlen + ptr->nexttxlen); } int32_t NSPV_getspentinfo(struct NSPV_spentinfo* ptr, uint256 txid, int32_t vout) From e43ac9ea21eba2babaa63a065702b4f7af0ac268 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Oct 2021 14:59:36 +0500 Subject: [PATCH 154/348] requestId 4b returned back in response was added to NSPV messages --- src/komodo_nSPV_fullnode.h | 542 +++++++++++++++++-------------------- 1 file changed, 250 insertions(+), 292 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index afda5ffbda9..e84ae73bfce 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -926,203 +926,195 @@ int32_t NSPV_getspentinfo(struct NSPV_spentinfo* ptr, uint256 txid, int32_t vout return (len); } -void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a request +// processing nspv requests +void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a request { - int32_t slen, reqheight; - std::vector response; + int32_t slen, reqheight; + std::vector response; uint32_t timestamp = (uint32_t)time(NULL); + const int nspvHeaderSize = 1 + 4; - if (request.size() == 0) { - LogPrint("nspv", "empty request from peer %d\n", pfrom->id); + if (request.size() < nspvHeaderSize) { + LogPrint("nspv", "request too small from peer %d\n", pfrom->id); return; } - - int32_t len = request.size(); + + uint8_t requestType = request[0]; + uint8_t requestId[4]; + memcpy(requestId, &request[1], sizeof(requestId)); + uint8_t *requestData = &request[nspvHeaderSize]; + int32_t requestDataLen = request.size() - nspvHeaderSize; // rate limit no more 1 request/sec of same type from same node: - int32_t nData = request[0] >> 1; - if (nData >= sizeof(pfrom->nspvdata)/sizeof(pfrom->nspvdata[0]) ) - nData = (int32_t)(sizeof(pfrom->nspvdata)/sizeof(pfrom->nspvdata[0])) - 1; - if (pfrom->nspvdata[nData].prevtime > timestamp) { - pfrom->nspvdata[nData].prevtime = 0; - pfrom->nspvdata[nData].nreqs = 0; - } - else if (timestamp == pfrom->nspvdata[nData].prevtime) { - if (pfrom->nspvdata[nData].nreqs > NSPV_MAXREQSPERSEC) { + int32_t idata = requestData[0] >> 1; + if (idata >= sizeof(pfrom->nspvdata) / sizeof(pfrom->nspvdata[0])) + idata = (int32_t)(sizeof(pfrom->nspvdata) / sizeof(pfrom->nspvdata[0])) - 1; + if (pfrom->nspvdata[idata].prevtime > timestamp) { + pfrom->nspvdata[idata].prevtime = 0; + pfrom->nspvdata[idata].nreqs = 0; + } else if (timestamp == pfrom->nspvdata[idata].prevtime) { + if (pfrom->nspvdata[idata].nreqs > NSPV_MAXREQSPERSEC) { LogPrint("nspv", "rate limit reached from peer %d\n", pfrom->id); return; } - } - else { - pfrom->nspvdata[nData].nreqs = 0; + } else { + pfrom->nspvdata[idata].nreqs = 0; } - switch(request[0]) - { + switch (requestType) { case NSPV_INFO: // info { struct NSPV_inforesp I; - //fprintf(stderr,"check info %u vs %u, ind.%d\n", timestamp, pfrom->nspvdata[ind].prevtime, ind); - if (len == 1 + sizeof(reqheight)) - iguana_rwnum(IGUANA_READ, &request[1], sizeof(reqheight), &reqheight); + //fprintf(stderr,"check info %u vs %u, ind.%d\n", timestamp, pfrom->nspvdata[ind].prevtime, ind); + if (requestDataLen == sizeof(reqheight)) + iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(reqheight), &reqheight); else reqheight = 0; //fprintf(stderr,"request height.%d\n",reqheight); memset(&I, 0, sizeof(I)); if ((slen = NSPV_getinfo(&I, reqheight)) > 0) { - response.resize(1 + slen); + response.resize(nspvHeaderSize + slen); response[0] = NSPV_INFORESP; + memcpy(&response[1], requestId, sizeof(requestId)); //fprintf(stderr,"slen.%d version.%d\n",slen,I.version); - if (NSPV_rwinforesp(IGUANA_WRITE, &response[1], &I) == slen) - { + if (NSPV_rwinforesp(IGUANA_WRITE, &response[nspvHeaderSize], &I) == slen) { //fprintf(stderr,"send info resp to id %d\n",(int32_t)pfrom->id); - pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->PushMessage("nSPV", response); + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_INFO response: version %d to node=%d\n", I.version, pfrom->id); - } - else - LogPrint("nspv", "NSPV_rwinforesp incorrect response len.%d\n", slen); + } else + LogPrint("nspv", "NSPV_rwinforesp incorrect response len.%d\n", slen); NSPV_inforesp_purge(&I); } else LogPrint("nspv", "NSPV_getinfo error.%d\n", slen); - } + } break; - case NSPV_UTXOS: + case NSPV_UTXOS: { struct NSPV_utxosresp U; - char coinaddr[KOMODO_ADDRESS_BUFSIZE]; - int32_t skipcount = 0; - int32_t maxrecords = 0; + char coinaddr[KOMODO_ADDRESS_BUFSIZE]; + int32_t skipcount = 0; + int32_t maxrecords = 0; uint8_t isCC = 0; //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); - - if (len < 2) { - LogPrint("nspv", "NSPV_UTXOS bad request too short len.%d node %d\n", len, pfrom->id); + + if (requestDataLen < 1) { + LogPrint("nspv", "NSPV_UTXOS bad request too short len.%d node %d\n", requestDataLen, pfrom->id); return; } - - int32_t offset = sizeof(request[0]) + sizeof(request[1]); - int32_t addrlen = request[1]; - if (offset + addrlen > len || addrlen > sizeof(coinaddr)-1) // out of bounds + + int32_t addrlen = requestData[0]; + int32_t offset = 1; + if (offset + addrlen > requestDataLen || addrlen > sizeof(coinaddr) - 1) // out of bounds { - LogPrint("nspv", "NSPV_UTXOS bad request len.%d too short or addrlen.%d out of bounds, node=%d\n", len, addrlen, pfrom->id); + LogPrint("nspv", "NSPV_UTXOS bad request len.%d too short or addrlen.%d out of bounds, node=%d\n", requestDataLen, addrlen, pfrom->id); return; } - memcpy(coinaddr, &request[offset], addrlen); + memcpy(coinaddr, &requestData[offset], addrlen); coinaddr[addrlen] = 0; offset += addrlen; - if (offset + sizeof(isCC) <= len) // TODO: a bit different from others format - allows omitted params, maybe better have fixed + if (offset + sizeof(isCC) <= requestDataLen) // TODO: a bit different from others format - allows omitted params, maybe better have fixed { - isCC = (request[offset] != 0); + isCC = (requestData[offset] != 0); offset += sizeof(isCC); - if (offset + sizeof(skipcount) <= len) - { - iguana_rwnum(IGUANA_READ, &request[offset], sizeof(skipcount), &skipcount); + if (offset + sizeof(skipcount) <= requestDataLen) { + iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(skipcount), &skipcount); offset += sizeof(skipcount); - if (offset + sizeof(maxrecords) <= len) - { - iguana_rwnum(IGUANA_READ, &request[offset], sizeof(maxrecords), &maxrecords); + if (offset + sizeof(maxrecords) <= requestDataLen) { + iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(maxrecords), &maxrecords); offset += sizeof(maxrecords); } } } - if (offset != len) { - LogPrint("nspv", "NSPV_UTXOS bad request parameters format: len.%d, offset.%d, addrlen.%d, node=%d\n", len, offset, addrlen, pfrom->id); + if (offset != requestDataLen) { + LogPrint("nspv", "NSPV_UTXOS bad request parameters format: len.%d, offset.%d, addrlen.%d, node=%d\n", requestDataLen, offset, addrlen, pfrom->id); return; } LogPrint("nspv-details", "NSPV_UTXOS address=%s isCC.%d skipcount.%d maxrecords.%d\n", coinaddr, isCC, skipcount, maxrecords); memset(&U, 0, sizeof(U)); - if ((slen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, maxrecords)) > 0) - { - response.resize(1 + slen); + if ((slen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, maxrecords)) > 0) { + response.resize(nspvHeaderSize + slen); response[0] = NSPV_UTXOSRESP; - if ( NSPV_rwutxosresp(IGUANA_WRITE, &response[1], &U) == slen ) - { - pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + memcpy(&response[1], requestId, sizeof(requestId)); + if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) == slen) { + pfrom->PushMessage("nSPV", response); + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_UTXOS response: numutxos=%d to node=%d\n", U.numutxos, pfrom->id); - } - else - LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", slen); + } else + LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", slen); NSPV_utxosresp_purge(&U); - } - else + } else LogPrint("nspv", "NSPV_getaddressutxos error slen.%d\n", slen); - } + } break; - case NSPV_TXIDS: + case NSPV_TXIDS: { struct NSPV_txidsresp T; - char coinaddr[KOMODO_ADDRESS_BUFSIZE]; - int32_t skipcount = 0; - int32_t maxrecords = 0; + char coinaddr[KOMODO_ADDRESS_BUFSIZE]; + int32_t skipcount = 0; + int32_t maxrecords = 0; uint8_t isCC = 0; //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); - - if (len < 2) { - LogPrint("nspv", "NSPV_TXIDS bad request too short len.%d, node %d\n", len, pfrom->id); + + if (requestDataLen < 1) { + LogPrint("nspv", "NSPV_TXIDS bad request too short len.%d, node %d\n", requestDataLen, pfrom->id); return; } - - int32_t offset = sizeof(request[0]) + sizeof(request[1]); - int32_t addrlen = request[1]; - if (offset + addrlen > len || addrlen > sizeof(coinaddr)-1) // out of bounds + + int32_t addrlen = requestData[0]; + int32_t offset = 1; + if (offset + addrlen > requestDataLen || addrlen > sizeof(coinaddr) - 1) // out of bounds { - LogPrint("nspv", "NSPV_TXIDS bad request len.%d too short or addrlen.%d out of bounds, node=%d\n", len, addrlen, pfrom->id); + LogPrint("nspv", "NSPV_TXIDS bad request len.%d too short or addrlen.%d out of bounds, node=%d\n", requestDataLen, addrlen, pfrom->id); return; } - memcpy(coinaddr, &request[offset], addrlen); + memcpy(coinaddr, &requestData[offset], addrlen); coinaddr[addrlen] = 0; offset += addrlen; - if (offset + sizeof(isCC) <= len) // TODO: a bit different from others format - allows omitted params, maybe better have fixed + if (offset + sizeof(isCC) <= requestDataLen) // TODO: a bit different from others format - allows omitted params, maybe better have fixed { - isCC = (request[offset] != 0); + isCC = (requestData[offset] != 0); offset += sizeof(isCC); - if (offset + sizeof(skipcount) <= len) - { - iguana_rwnum(IGUANA_READ, &request[offset], sizeof(skipcount), &skipcount); + if (offset + sizeof(skipcount) <= requestDataLen) { + iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(skipcount), &skipcount); offset += sizeof(skipcount); - if (offset + sizeof(maxrecords) <= len) - { - iguana_rwnum(IGUANA_READ, &request[offset], sizeof(maxrecords), &maxrecords); + if (offset + sizeof(maxrecords) <= requestDataLen) { + iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(maxrecords), &maxrecords); offset += sizeof(maxrecords); } } } - if (offset != len) { - LogPrint("nspv", "NSPV_TXIDS bad request parameters format: len.%d, offset.%d, addrlen.%d, node=%d\n", len, offset, addrlen, pfrom->id); + if (offset != requestDataLen) { + LogPrint("nspv", "NSPV_TXIDS bad request parameters format: len.%d, offset.%d, addrlen.%d, node=%d\n", requestDataLen, offset, addrlen, pfrom->id); return; } - LogPrint("nspv-details", "NSPV_TXIDS address=%s isCC.%d skipcount.%d maxrecords.%x\n",coinaddr, isCC, skipcount, maxrecords); + LogPrint("nspv-details", "NSPV_TXIDS address=%s isCC.%d skipcount.%d maxrecords.%x\n", coinaddr, isCC, skipcount, maxrecords); memset(&T, 0, sizeof(T)); - if ((slen = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, maxrecords)) > 0) - { + if ((slen = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, maxrecords)) > 0) { //fprintf(stderr,"slen.%d\n",slen); - response.resize(1 + slen); + response.resize(nspvHeaderSize + slen); response[0] = NSPV_TXIDSRESP; - if (NSPV_rwtxidsresp(IGUANA_WRITE, &response[1], &T) == slen) - { - pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + memcpy(&response[1], requestId, sizeof(requestId)); + if (NSPV_rwtxidsresp(IGUANA_WRITE, &response[nspvHeaderSize], &T) == slen) { + pfrom->PushMessage("nSPV", response); + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_TXIDS response: numtxids=%d to node=%d\n", (int)T.numtxids, pfrom->id); - } - else - LogPrint("nspv", "NSPV_rwtxidsresp incorrect response len.%d\n", slen); + } else + LogPrint("nspv", "NSPV_rwtxidsresp incorrect response len.%d\n", slen); NSPV_txidsresp_purge(&T); - } - else + } else LogPrint("nspv", "NSPV_getaddresstxids error.%d\n", slen); - } + } break; case NSPV_MEMPOOL: @@ -1133,238 +1125,209 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req uint256 txid; uint8_t funcid, isCC = 0; int8_t addrlen; - if (len > 1 + sizeof(isCC) + sizeof(funcid) + sizeof(vout) + sizeof(txid) + sizeof(addrlen)) - { - uint32_t offset = 1; - offset += iguana_rwnum(IGUANA_READ, &request[offset], sizeof(isCC), &isCC); - offset += iguana_rwnum(IGUANA_READ, &request[offset], sizeof(funcid), &funcid); - offset += iguana_rwnum(IGUANA_READ, &request[offset], sizeof(vout), &vout); - offset += iguana_rwbignum(IGUANA_READ, &request[offset], sizeof(txid), (uint8_t*)&txid); - addrlen = request[offset++]; - if (addrlen < sizeof(coinaddr) && offset + addrlen == len) - { - memcpy(coinaddr, &request[offset], addrlen); + if (requestDataLen > sizeof(isCC) + sizeof(funcid) + sizeof(vout) + sizeof(txid) + sizeof(addrlen)) { + uint32_t offset = 0; + offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(isCC), &isCC); + offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(funcid), &funcid); + offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(vout), &vout); + offset += iguana_rwbignum(IGUANA_READ, &requestData[offset], sizeof(txid), (uint8_t*)&txid); + addrlen = requestData[offset++]; + if (addrlen < sizeof(coinaddr) && offset + addrlen == requestDataLen) { + memcpy(coinaddr, &requestData[offset], addrlen); coinaddr[addrlen] = 0; offset += addrlen; - LogPrint("nspv-details", "address (%s) isCC.%d funcid.%d %s/v%d len.%d slen.%d\n", coinaddr, isCC, funcid, txid.GetHex().c_str(), vout, len, addrlen); + LogPrint("nspv-details", "address (%s) isCC.%d funcid.%d %s/v%d len.%d slen.%d\n", coinaddr, isCC, funcid, txid.GetHex().c_str(), vout, requestDataLen, addrlen); memset(&M, 0, sizeof(M)); if ((slen = NSPV_mempooltxids(&M, coinaddr, isCC, funcid, txid, vout)) > 0) { //fprintf(stderr,"NSPV_mempooltxids slen.%d\n",slen); - response.resize(1 + slen); + response.resize(nspvHeaderSize + slen); response[0] = NSPV_MEMPOOLRESP; - if (NSPV_rwmempoolresp(IGUANA_WRITE, &response[1], &M) == slen) { + memcpy(&response[1], requestId, sizeof(requestId)); + if (NSPV_rwmempoolresp(IGUANA_WRITE, &response[nspvHeaderSize], &M) == slen) { pfrom->PushMessage("nSPV", response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_MEMPOOL response: numtxids=%d to node=%d\n", M.numtxids, pfrom->id); } else LogPrint("nspv", "NSPV_rwmempoolresp incorrect response len.%d\n", slen); NSPV_mempoolresp_purge(&M); - } - else + } else LogPrint("nspv", "NSPV_mempooltxids err.%d\n", slen); - } - else - LogPrint("nspv", "NSPV_MEMPOOL incorrect addrlen.%d offset.%d len.%d\n", addrlen, offset, len); - } - else - LogPrint("nspv", "NSPV_MEMPOOL incorrect len.%d too short, node %d\n", len, pfrom->id); + } else + LogPrint("nspv", "NSPV_MEMPOOL incorrect addrlen.%d offset.%d len.%d\n", addrlen, offset, requestDataLen); + } else + LogPrint("nspv", "NSPV_MEMPOOL incorrect len.%d too short, node %d\n", requestDataLen, pfrom->id); } break; - case NSPV_NTZS: + case NSPV_NTZS: { - struct NSPV_ntzsresp N; + struct NSPV_ntzsresp N; int32_t height; - if (len == 1 + sizeof(height)) - { - iguana_rwnum(IGUANA_READ, &request[1], sizeof(height), &height); + if (requestDataLen == sizeof(height)) { + iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(height), &height); memset(&N, 0, sizeof(N)); - if ((slen = NSPV_getntzsresp(&N, height)) > 0) - { - response.resize(1 + slen); + if ((slen = NSPV_getntzsresp(&N, height)) > 0) { + response.resize(nspvHeaderSize + slen); response[0] = NSPV_NTZSRESP; - if (NSPV_rwntzsresp(IGUANA_WRITE, &response[1], &N) == slen) - { - pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + memcpy(&response[1], requestId, sizeof(requestId)); + if (NSPV_rwntzsresp(IGUANA_WRITE, &response[nspvHeaderSize], &N) == slen) { + pfrom->PushMessage("nSPV", response); + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_NTZS response: prevntz.txid=%s nextntx.txid=%s node=%d\n", N.prevntz.txid.GetHex().c_str(), N.nextntz.txid.GetHex().c_str(), pfrom->id); - } - else + } else LogPrint("nspv", "NSPV_rwntzsresp incorrect response len.%d\n", slen); NSPV_ntzsresp_purge(&N); - } - else + } else LogPrint("nspv", "NSPV_rwntzsresp err.%d\n", slen); } else - LogPrint("nspv","NSPV_NTZS bad request len.%d node %d\n", len, pfrom->id); - } + LogPrint("nspv", "NSPV_NTZS bad request len.%d node %d\n", requestDataLen, pfrom->id); + } break; - case NSPV_NTZSPROOF: + case NSPV_NTZSPROOF: { - struct NSPV_ntzsproofresp P; + struct NSPV_ntzsproofresp P; uint256 prevntz, nextntz; - if (len == 1 + sizeof(prevntz) + sizeof(nextntz)) - { - iguana_rwbignum(IGUANA_READ, &request[1], sizeof(prevntz), (uint8_t*)&prevntz); - iguana_rwbignum(IGUANA_READ, &request[1 + sizeof(prevntz)], sizeof(nextntz), (uint8_t*)&nextntz); + if (requestDataLen == sizeof(prevntz) + sizeof(nextntz)) { + iguana_rwbignum(IGUANA_READ, &requestData[0], sizeof(prevntz), (uint8_t*)&prevntz); + iguana_rwbignum(IGUANA_READ, &requestData[sizeof(prevntz)], sizeof(nextntz), (uint8_t*)&nextntz); memset(&P, 0, sizeof(P)); - if ((slen = NSPV_getntzsproofresp(&P, prevntz, nextntz)) > 0) - { + if ((slen = NSPV_getntzsproofresp(&P, prevntz, nextntz)) > 0) { // fprintf(stderr,"slen.%d msg prev.%s next.%s\n",slen,prevntz.GetHex().c_str(),nextntz.GetHex().c_str()); - response.resize(1 + slen); + response.resize(nspvHeaderSize + slen); response[0] = NSPV_NTZSPROOFRESP; - if (NSPV_rwntzsproofresp(IGUANA_WRITE, &response[1], &P) == slen) - { + memcpy(&response[1], requestId, sizeof(requestId)); + if (NSPV_rwntzsproofresp(IGUANA_WRITE, &response[nspvHeaderSize], &P) == slen) { pfrom->PushMessage("nSPV", response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_NTZSPROOF response: prevtxidht=%d nexttxidht=%d node=%d\n", P.prevtxidht, P.nexttxidht, pfrom->id); - } - else + } else LogPrint("nspv", "NSPV_rwntzsproofresp incorrect response len.%d\n", slen); NSPV_ntzsproofresp_purge(&P); - } - else + } else LogPrint("nspv", "NSPV_NTZSPROOF err.%d\n", slen); - } - else - LogPrint("nspv","NSPV_NTZSPROOF bad request len.%d node %d\n", len, pfrom->id); - } + } else + LogPrint("nspv", "NSPV_NTZSPROOF bad request len.%d node %d\n", requestDataLen, pfrom->id); + } break; case NSPV_TXPROOF: { - struct NSPV_txproof P; - uint256 txid; + struct NSPV_txproof P; + uint256 txid; int32_t height, vout; - if (len == 1 + sizeof(txid) + sizeof(height) + sizeof(vout)) - { - iguana_rwnum(IGUANA_READ, &request[1], sizeof(height), &height); - iguana_rwnum(IGUANA_READ, &request[1 + sizeof(height)], sizeof(vout), &vout); - iguana_rwbignum(IGUANA_READ, &request[1 + sizeof(height) + sizeof(vout)], sizeof(txid), (uint8_t*)&txid); + if (requestDataLen == sizeof(txid) + sizeof(height) + sizeof(vout)) { + iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(height), &height); + iguana_rwnum(IGUANA_READ, &requestData[sizeof(height)], sizeof(vout), &vout); + iguana_rwbignum(IGUANA_READ, &requestData[sizeof(height) + sizeof(vout)], sizeof(txid), (uint8_t*)&txid); //fprintf(stderr,"got txid %s/v%d ht.%d\n",txid.GetHex().c_str(),vout,height); memset(&P, 0, sizeof(P)); - if ((slen = NSPV_gettxproof(&P, vout, txid /*,height*/)) > 0) - { + if ((slen = NSPV_gettxproof(&P, vout, txid /*,height*/)) > 0) { //fprintf(stderr,"slen.%d\n",slen); - response.resize(1 + slen); + response.resize(nspvHeaderSize + slen); response[0] = NSPV_TXPROOFRESP; - if (NSPV_rwtxproof(IGUANA_WRITE, &response[1], &P) == slen) - { + memcpy(&response[1], requestId, sizeof(requestId)); + if (NSPV_rwtxproof(IGUANA_WRITE, &response[nspvHeaderSize], &P) == slen) { //fprintf(stderr,"send response\n"); - pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->PushMessage("nSPV", response); + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_TXPROOF response: txlen=%d txprooflen=%d node=%d\n", P.txlen, P.txprooflen, pfrom->id); - } - else + } else LogPrint("nspv", "NSPV_rwtxproof incorrect response len.%d\n", slen); NSPV_txproof_purge(&P); - } - else + } else LogPrint("nspv", "gettxproof error.%d\n", slen); - } - else - LogPrint("nspv","txproof bad request len.%d node %d\n", len, pfrom->id); - } + } else + LogPrint("nspv", "txproof bad request len.%d node %d\n", requestDataLen, pfrom->id); + } break; - case NSPV_SPENTINFO: + case NSPV_SPENTINFO: { - struct NSPV_spentinfo S; - int32_t vout; + struct NSPV_spentinfo S; + int32_t vout; uint256 txid; - if (len == 1 + sizeof(txid) + sizeof(vout)) - { - iguana_rwnum(IGUANA_READ, &request[1], sizeof(vout), &vout); - iguana_rwbignum(IGUANA_READ, &request[1 + sizeof(vout)], sizeof(txid), (uint8_t*)&txid); + if (requestDataLen == sizeof(txid) + sizeof(vout)) { + iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(vout), &vout); + iguana_rwbignum(IGUANA_READ, &requestData[sizeof(vout)], sizeof(txid), (uint8_t*)&txid); memset(&S, 0, sizeof(S)); - if ((slen = NSPV_getspentinfo(&S, txid, vout)) > 0) - { - response.resize(1 + slen); + if ((slen = NSPV_getspentinfo(&S, txid, vout)) > 0) { + response.resize(nspvHeaderSize + slen); response[0] = NSPV_SPENTINFORESP; - if (NSPV_rwspentinfo(IGUANA_WRITE, &response[1], &S) == slen) - { - pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + memcpy(&response[1], requestId, sizeof(requestId)); + if (NSPV_rwspentinfo(IGUANA_WRITE, &response[nspvHeaderSize], &S) == slen) { + pfrom->PushMessage("nSPV", response); + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_SPENTINFO response: spent txid=%s vout=%d node=%d\n", S.txid.GetHex().c_str(), S.vout, pfrom->id); - } - else + } else LogPrint("nspv", "NSPV_rwspentinfo incorrect response len.%d\n", slen); NSPV_spentinfo_purge(&S); - } - else + } else LogPrint("nspv", "NSPV_getspentinfo error.%d node=%d\n", slen, pfrom->id); - } - else - LogPrint("nspv", "NSPV_SPENTINFO bad request len.%d node=%d\n", len, pfrom->id); - } + } else + LogPrint("nspv", "NSPV_SPENTINFO bad request len.%d node=%d\n", requestDataLen, pfrom->id); + } break; - case NSPV_BROADCAST: + case NSPV_BROADCAST: { - struct NSPV_broadcastresp B; + struct NSPV_broadcastresp B; uint256 txid; int32_t txlen; - if (len > 1 + sizeof(txid) + sizeof(txlen)) - { - int32_t offset = 1; + if (requestDataLen > sizeof(txid) + sizeof(txlen)) { + int32_t offset = 0; - offset += iguana_rwbignum(IGUANA_READ, &request[offset], sizeof(txid), (uint8_t*)&txid); - offset += iguana_rwnum(IGUANA_READ, &request[offset], sizeof(txlen), &txlen); + offset += iguana_rwbignum(IGUANA_READ, &requestData[offset], sizeof(txid), (uint8_t*)&txid); + offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(txlen), &txlen); memset(&B, 0, sizeof(B)); - if (txlen < MAX_TX_SIZE_AFTER_SAPLING && request.size() == offset + txlen && (slen = NSPV_sendrawtransaction(&B, &request[offset], txlen)) > 0) - { - response.resize(1 + slen); + if (txlen < MAX_TX_SIZE_AFTER_SAPLING && requestDataLen == offset + txlen && (slen = NSPV_sendrawtransaction(&B, &requestData[offset], txlen)) > 0) { + response.resize(nspvHeaderSize + slen); response[0] = NSPV_BROADCASTRESP; - if (NSPV_rwbroadcastresp(IGUANA_WRITE, &response[1], &B) == slen) - { - pfrom->PushMessage("nSPV",response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + memcpy(&response[1], requestId, sizeof(requestId)); + if (NSPV_rwbroadcastresp(IGUANA_WRITE, &response[nspvHeaderSize], &B) == slen) { + pfrom->PushMessage("nSPV", response); + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_BROADCAST response: txid=%s vout=%d to node=%d\n", B.txid.GetHex().c_str(), pfrom->id); - } - else + } else LogPrint("nspv", "NSPV_rwbroadcastresp incorrect response len.%d\n", slen); NSPV_broadcast_purge(&B); - } - else + } else LogPrint("nspv", "NSPV_BROADCAST either wrong tx len.%d or NSPV_sendrawtransaction error.%d, node=%d\n", txlen, slen, pfrom->id); - } - else - LogPrint("nspv", "NSPV_BROADCAST bad request len.%d node %d\n", len, pfrom->id); + } else + LogPrint("nspv", "NSPV_BROADCAST bad request len.%d node %d\n", requestDataLen, pfrom->id); - } + } break; - case NSPV_REMOTERPC: + case NSPV_REMOTERPC: { - struct NSPV_remoterpcresp R; - int32_t offset = 1; - offset += iguana_rwnum(IGUANA_READ, &request[offset], sizeof(slen), &slen); + struct NSPV_remoterpcresp R; + int32_t offset = 0; + offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(slen), &slen); memset(&R, 0, sizeof(R)); - if (len == (offset + slen) && (slen = NSPV_remoterpc(&R,(char *)&request[offset],slen))>0 ) - { - response.resize(1 + slen); + if (requestDataLen == (offset + slen) && (slen = NSPV_remoterpc(&R, (char*)&requestData[offset], slen)) > 0) { + response.resize(nspvHeaderSize + slen); response[0] = NSPV_REMOTERPCRESP; - NSPV_rwremoterpcresp(IGUANA_WRITE, &response[1], &R, slen); + memcpy(&response[1], requestId, sizeof(requestId)); + NSPV_rwremoterpcresp(IGUANA_WRITE, &response[nspvHeaderSize], &R, slen); pfrom->PushMessage("nSPV", response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_REMOTERPCRESP response: method=%s json=%s to node=%d\n", R.method, R.json, pfrom->id); NSPV_remoterpc_purge(&R); - } - else - LogPrint("nspv", "NSPV_REMOTERPC bad request len.%d node %d\n", len, pfrom->id); - } + } else + LogPrint("nspv", "NSPV_REMOTERPC bad request len.%d node %d\n", requestDataLen, pfrom->id); + } break; - - case NSPV_CCMODULEUTXOS: // get cc module utxos from coinaddr for the requested amount, evalcode, funcid list and txid + + case NSPV_CCMODULEUTXOS: // get cc module utxos from coinaddr for the requested amount, evalcode, funcid list and txid { struct NSPV_utxosresp U; char coinaddr[64]; @@ -1375,66 +1338,61 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req uint256 filtertxid; bool errorFormat = false; //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); - - if (len < 3) { - LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short, node=%d\n", len, pfrom->id); + + if (requestDataLen < sizeof(int32_t)) { + LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short, node=%d\n", requestDataLen, pfrom->id); return; } - - int32_t offset = 1; - int32_t addrlen = request[offset++]; - if (addrlen >= sizeof(coinaddr) || offset + addrlen > len) - { - LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short or addrlen %d too long, node=%d\n", len, addrlen, pfrom->id); + + int32_t offset = 0; + int32_t addrlen = requestData[offset++]; + if (addrlen >= sizeof(coinaddr) || offset + addrlen > requestDataLen) { + LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short or addrlen %d too long, node=%d\n", requestDataLen, addrlen, pfrom->id); return; } - memcpy(coinaddr, &request[offset], addrlen); + memcpy(coinaddr, &requestData[offset], addrlen); coinaddr[addrlen] = 0; offset += addrlen; - if (offset + sizeof(amount) + sizeof(evalcode) + sizeof(funcidslen) > len) { - LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short, node=%d\n", len, pfrom->id); + if (offset + sizeof(amount) + sizeof(evalcode) + sizeof(funcidslen) > requestDataLen) { + LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short, node=%d\n", requestDataLen, pfrom->id); return; } - offset += iguana_rwnum(IGUANA_READ, &request[offset], sizeof(amount), &amount); - offset += iguana_rwnum(IGUANA_READ, &request[offset], sizeof(evalcode), &evalcode); - funcidslen = request[offset++]; + offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(amount), &amount); + offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(evalcode), &evalcode); + funcidslen = requestData[offset++]; - if (funcidslen >= sizeof(funcids) || offset + funcidslen > len) - { - LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d no room for funcids or too many funcids %d, node=%d\n", len, funcidslen, pfrom->id); + if (funcidslen >= sizeof(funcids) || offset + funcidslen > requestDataLen) { + LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d no room for funcids or too many funcids %d, node=%d\n", requestDataLen, funcidslen, pfrom->id); return; } - memcpy(funcids, &request[offset], funcidslen); + memcpy(funcids, &requestData[offset], funcidslen); funcids[funcidslen] = 0; offset += funcidslen; - if (offset + sizeof(filtertxid) != len) { - LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d incorrect room for filtertxid param, node=%d\n", len, funcidslen, pfrom->id); + if (offset + sizeof(filtertxid) != requestDataLen) { + LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d incorrect room for filtertxid param, node=%d\n", requestDataLen, funcidslen, pfrom->id); return; } - iguana_rwbignum(IGUANA_READ, &request[offset], sizeof(filtertxid), (uint8_t *)&filtertxid); + iguana_rwbignum(IGUANA_READ, &requestData[offset], sizeof(filtertxid), (uint8_t*)&filtertxid); memset(&U, 0, sizeof(U)); - if ((slen = NSPV_getccmoduleutxos(&U, coinaddr, amount, evalcode, funcids, filtertxid)) > 0) - { - response.resize(1 + slen); + if ((slen = NSPV_getccmoduleutxos(&U, coinaddr, amount, evalcode, funcids, filtertxid)) > 0) { + response.resize(nspvHeaderSize + slen); response[0] = NSPV_CCMODULEUTXOSRESP; - if (NSPV_rwutxosresp(IGUANA_WRITE, &response[1], &U) == slen) - { + memcpy(&response[1], requestId, sizeof(requestId)); + if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) == slen) { pfrom->PushMessage("nSPV", response); - pfrom->nspvdata[nData].prevtime = timestamp; - pfrom->nspvdata[nData].nreqs ++; + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_CCMODULEUTXOS returned %d utxos to node=%d\n", (int)U.numutxos, pfrom->id); - } - else + } else LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", slen); NSPV_utxosresp_purge(&U); - } - else + } else LogPrint("nspv", "NSPV_getccmoduleutxos error.%d, node %d\n", slen, pfrom->id); - } + } break; } } From d2257cca0d9f4d5295b48262b483d8890d2957e5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 13 Oct 2021 14:00:36 +0500 Subject: [PATCH 155/348] added limit for max NSPV json request 64k, length vars refactored --- src/komodo_nSPV_defs.h | 1 + src/komodo_nSPV_fullnode.h | 149 ++++++++++++++++++++++--------------- 2 files changed, 88 insertions(+), 62 deletions(-) diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 9d4fd68a12b..f48717a3118 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -25,6 +25,7 @@ #define NSPV_MAXVINS 64 #define NSPV_AUTOLOGOUT 777 #define NSPV_BRANCHID 0x76b809bb +#define NSPV_MAXJSONREQUESTSIZE 65536 // nSPV defines and struct definitions with serialization and purge functions diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index e84ae73bfce..25cb6cb07a5 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -845,7 +845,7 @@ int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid /*, ptr->txproof = (uint8_t*)calloc(1, ptr->txprooflen); memcpy(ptr->txproof, &proof[0], ptr->txprooflen); } - //fprintf(stderr,"gettxproof slen.%d\n",(int32_t)(sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen)); + //fprintf(stderr,"gettxproof respLen.%d\n",(int32_t)(sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen)); } else { LogPrint("nspv-details", "%s txid=%s not found in the block of ht=%d", __func__, txid.GetHex().c_str(), ptr->height); @@ -929,7 +929,6 @@ int32_t NSPV_getspentinfo(struct NSPV_spentinfo* ptr, uint256 txid, int32_t vout // processing nspv requests void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a request { - int32_t slen, reqheight; std::vector response; uint32_t timestamp = (uint32_t)time(NULL); const int nspvHeaderSize = 1 + 4; @@ -965,6 +964,9 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re case NSPV_INFO: // info { struct NSPV_inforesp I; + int32_t respLen; + int32_t reqheight; + //fprintf(stderr,"check info %u vs %u, ind.%d\n", timestamp, pfrom->nspvdata[ind].prevtime, ind); if (requestDataLen == sizeof(reqheight)) iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(reqheight), &reqheight); @@ -972,22 +974,22 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re reqheight = 0; //fprintf(stderr,"request height.%d\n",reqheight); memset(&I, 0, sizeof(I)); - if ((slen = NSPV_getinfo(&I, reqheight)) > 0) { - response.resize(nspvHeaderSize + slen); + if ((respLen = NSPV_getinfo(&I, reqheight)) > 0) { + response.resize(nspvHeaderSize + respLen); response[0] = NSPV_INFORESP; memcpy(&response[1], requestId, sizeof(requestId)); - //fprintf(stderr,"slen.%d version.%d\n",slen,I.version); - if (NSPV_rwinforesp(IGUANA_WRITE, &response[nspvHeaderSize], &I) == slen) { + //fprintf(stderr,"respLen.%d version.%d\n",respLen,I.version); + if (NSPV_rwinforesp(IGUANA_WRITE, &response[nspvHeaderSize], &I) == respLen) { //fprintf(stderr,"send info resp to id %d\n",(int32_t)pfrom->id); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_INFO response: version %d to node=%d\n", I.version, pfrom->id); } else - LogPrint("nspv", "NSPV_rwinforesp incorrect response len.%d\n", slen); + LogPrint("nspv", "NSPV_rwinforesp incorrect response len.%d\n", respLen); NSPV_inforesp_purge(&I); } else - LogPrint("nspv", "NSPV_getinfo error.%d\n", slen); + LogPrint("nspv", "NSPV_getinfo error.%d\n", respLen); } break; @@ -998,6 +1000,8 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re int32_t skipcount = 0; int32_t maxrecords = 0; uint8_t isCC = 0; + int32_t respLen; + //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); if (requestDataLen < 1) { @@ -1036,20 +1040,20 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re LogPrint("nspv-details", "NSPV_UTXOS address=%s isCC.%d skipcount.%d maxrecords.%d\n", coinaddr, isCC, skipcount, maxrecords); memset(&U, 0, sizeof(U)); - if ((slen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, maxrecords)) > 0) { - response.resize(nspvHeaderSize + slen); + if ((respLen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, maxrecords)) > 0) { + response.resize(nspvHeaderSize + respLen); response[0] = NSPV_UTXOSRESP; memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) == slen) { + if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) == respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_UTXOS response: numutxos=%d to node=%d\n", U.numutxos, pfrom->id); } else - LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", slen); + LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", respLen); NSPV_utxosresp_purge(&U); } else - LogPrint("nspv", "NSPV_getaddressutxos error slen.%d\n", slen); + LogPrint("nspv", "NSPV_getaddressutxos error respLen.%d\n", respLen); } break; @@ -1060,6 +1064,8 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re int32_t skipcount = 0; int32_t maxrecords = 0; uint8_t isCC = 0; + int32_t respLen; + //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); if (requestDataLen < 1) { @@ -1099,21 +1105,21 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re LogPrint("nspv-details", "NSPV_TXIDS address=%s isCC.%d skipcount.%d maxrecords.%x\n", coinaddr, isCC, skipcount, maxrecords); memset(&T, 0, sizeof(T)); - if ((slen = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, maxrecords)) > 0) { - //fprintf(stderr,"slen.%d\n",slen); - response.resize(nspvHeaderSize + slen); + if ((respLen = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, maxrecords)) > 0) { + //fprintf(stderr,"respLen.%d\n",respLen); + response.resize(nspvHeaderSize + respLen); response[0] = NSPV_TXIDSRESP; memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwtxidsresp(IGUANA_WRITE, &response[nspvHeaderSize], &T) == slen) { + if (NSPV_rwtxidsresp(IGUANA_WRITE, &response[nspvHeaderSize], &T) == respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_TXIDS response: numtxids=%d to node=%d\n", (int)T.numtxids, pfrom->id); } else - LogPrint("nspv", "NSPV_rwtxidsresp incorrect response len.%d\n", slen); + LogPrint("nspv", "NSPV_rwtxidsresp incorrect response len.%d\n", respLen); NSPV_txidsresp_purge(&T); } else - LogPrint("nspv", "NSPV_getaddresstxids error.%d\n", slen); + LogPrint("nspv", "NSPV_getaddresstxids error.%d\n", respLen); } break; @@ -1125,6 +1131,8 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re uint256 txid; uint8_t funcid, isCC = 0; int8_t addrlen; + int32_t respLen; + if (requestDataLen > sizeof(isCC) + sizeof(funcid) + sizeof(vout) + sizeof(txid) + sizeof(addrlen)) { uint32_t offset = 0; offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(isCC), &isCC); @@ -1136,23 +1144,23 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re memcpy(coinaddr, &requestData[offset], addrlen); coinaddr[addrlen] = 0; offset += addrlen; - LogPrint("nspv-details", "address (%s) isCC.%d funcid.%d %s/v%d len.%d slen.%d\n", coinaddr, isCC, funcid, txid.GetHex().c_str(), vout, requestDataLen, addrlen); + LogPrint("nspv-details", "address (%s) isCC.%d funcid.%d %s/v%d len.%d addrlen.%d\n", coinaddr, isCC, funcid, txid.GetHex().c_str(), vout, requestDataLen, addrlen); memset(&M, 0, sizeof(M)); - if ((slen = NSPV_mempooltxids(&M, coinaddr, isCC, funcid, txid, vout)) > 0) { - //fprintf(stderr,"NSPV_mempooltxids slen.%d\n",slen); - response.resize(nspvHeaderSize + slen); + if ((respLen = NSPV_mempooltxids(&M, coinaddr, isCC, funcid, txid, vout)) > 0) { + //fprintf(stderr,"NSPV_mempooltxids respLen.%d\n",respLen); + response.resize(nspvHeaderSize + respLen); response[0] = NSPV_MEMPOOLRESP; memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwmempoolresp(IGUANA_WRITE, &response[nspvHeaderSize], &M) == slen) { + if (NSPV_rwmempoolresp(IGUANA_WRITE, &response[nspvHeaderSize], &M) == respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_MEMPOOL response: numtxids=%d to node=%d\n", M.numtxids, pfrom->id); } else - LogPrint("nspv", "NSPV_rwmempoolresp incorrect response len.%d\n", slen); + LogPrint("nspv", "NSPV_rwmempoolresp incorrect response len.%d\n", respLen); NSPV_mempoolresp_purge(&M); } else - LogPrint("nspv", "NSPV_mempooltxids err.%d\n", slen); + LogPrint("nspv", "NSPV_mempooltxids err.%d\n", respLen); } else LogPrint("nspv", "NSPV_MEMPOOL incorrect addrlen.%d offset.%d len.%d\n", addrlen, offset, requestDataLen); } else @@ -1165,22 +1173,24 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re struct NSPV_ntzsresp N; int32_t height; if (requestDataLen == sizeof(height)) { + int32_t respLen; + iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(height), &height); memset(&N, 0, sizeof(N)); - if ((slen = NSPV_getntzsresp(&N, height)) > 0) { - response.resize(nspvHeaderSize + slen); + if ((respLen = NSPV_getntzsresp(&N, height)) > 0) { + response.resize(nspvHeaderSize + respLen); response[0] = NSPV_NTZSRESP; memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwntzsresp(IGUANA_WRITE, &response[nspvHeaderSize], &N) == slen) { + if (NSPV_rwntzsresp(IGUANA_WRITE, &response[nspvHeaderSize], &N) == respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_NTZS response: prevntz.txid=%s nextntx.txid=%s node=%d\n", N.prevntz.txid.GetHex().c_str(), N.nextntz.txid.GetHex().c_str(), pfrom->id); } else - LogPrint("nspv", "NSPV_rwntzsresp incorrect response len.%d\n", slen); + LogPrint("nspv", "NSPV_rwntzsresp incorrect response len.%d\n", respLen); NSPV_ntzsresp_purge(&N); } else - LogPrint("nspv", "NSPV_rwntzsresp err.%d\n", slen); + LogPrint("nspv", "NSPV_rwntzsresp err.%d\n", respLen); } else LogPrint("nspv", "NSPV_NTZS bad request len.%d node %d\n", requestDataLen, pfrom->id); } @@ -1191,24 +1201,26 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re struct NSPV_ntzsproofresp P; uint256 prevntz, nextntz; if (requestDataLen == sizeof(prevntz) + sizeof(nextntz)) { + int32_t respLen; + iguana_rwbignum(IGUANA_READ, &requestData[0], sizeof(prevntz), (uint8_t*)&prevntz); iguana_rwbignum(IGUANA_READ, &requestData[sizeof(prevntz)], sizeof(nextntz), (uint8_t*)&nextntz); memset(&P, 0, sizeof(P)); - if ((slen = NSPV_getntzsproofresp(&P, prevntz, nextntz)) > 0) { - // fprintf(stderr,"slen.%d msg prev.%s next.%s\n",slen,prevntz.GetHex().c_str(),nextntz.GetHex().c_str()); - response.resize(nspvHeaderSize + slen); + if ((respLen = NSPV_getntzsproofresp(&P, prevntz, nextntz)) > 0) { + // fprintf(stderr,"respLen.%d msg prev.%s next.%s\n",respLen,prevntz.GetHex().c_str(),nextntz.GetHex().c_str()); + response.resize(nspvHeaderSize + respLen); response[0] = NSPV_NTZSPROOFRESP; memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwntzsproofresp(IGUANA_WRITE, &response[nspvHeaderSize], &P) == slen) { + if (NSPV_rwntzsproofresp(IGUANA_WRITE, &response[nspvHeaderSize], &P) == respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_NTZSPROOF response: prevtxidht=%d nexttxidht=%d node=%d\n", P.prevtxidht, P.nexttxidht, pfrom->id); } else - LogPrint("nspv", "NSPV_rwntzsproofresp incorrect response len.%d\n", slen); + LogPrint("nspv", "NSPV_rwntzsproofresp incorrect response len.%d\n", respLen); NSPV_ntzsproofresp_purge(&P); } else - LogPrint("nspv", "NSPV_NTZSPROOF err.%d\n", slen); + LogPrint("nspv", "NSPV_NTZSPROOF err.%d\n", respLen); } else LogPrint("nspv", "NSPV_NTZSPROOF bad request len.%d node %d\n", requestDataLen, pfrom->id); } @@ -1220,27 +1232,29 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re uint256 txid; int32_t height, vout; if (requestDataLen == sizeof(txid) + sizeof(height) + sizeof(vout)) { + int32_t respLen; + iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(height), &height); iguana_rwnum(IGUANA_READ, &requestData[sizeof(height)], sizeof(vout), &vout); iguana_rwbignum(IGUANA_READ, &requestData[sizeof(height) + sizeof(vout)], sizeof(txid), (uint8_t*)&txid); //fprintf(stderr,"got txid %s/v%d ht.%d\n",txid.GetHex().c_str(),vout,height); memset(&P, 0, sizeof(P)); - if ((slen = NSPV_gettxproof(&P, vout, txid /*,height*/)) > 0) { - //fprintf(stderr,"slen.%d\n",slen); - response.resize(nspvHeaderSize + slen); + if ((respLen = NSPV_gettxproof(&P, vout, txid /*,height*/)) > 0) { + //fprintf(stderr,"respLen.%d\n",respLen); + response.resize(nspvHeaderSize + respLen); response[0] = NSPV_TXPROOFRESP; memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwtxproof(IGUANA_WRITE, &response[nspvHeaderSize], &P) == slen) { + if (NSPV_rwtxproof(IGUANA_WRITE, &response[nspvHeaderSize], &P) == respLen) { //fprintf(stderr,"send response\n"); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_TXPROOF response: txlen=%d txprooflen=%d node=%d\n", P.txlen, P.txprooflen, pfrom->id); } else - LogPrint("nspv", "NSPV_rwtxproof incorrect response len.%d\n", slen); + LogPrint("nspv", "NSPV_rwtxproof incorrect response len.%d\n", respLen); NSPV_txproof_purge(&P); } else - LogPrint("nspv", "gettxproof error.%d\n", slen); + LogPrint("nspv", "gettxproof error.%d\n", respLen); } else LogPrint("nspv", "txproof bad request len.%d node %d\n", requestDataLen, pfrom->id); } @@ -1253,23 +1267,25 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re uint256 txid; if (requestDataLen == sizeof(txid) + sizeof(vout)) { + int32_t respLen; + iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(vout), &vout); iguana_rwbignum(IGUANA_READ, &requestData[sizeof(vout)], sizeof(txid), (uint8_t*)&txid); memset(&S, 0, sizeof(S)); - if ((slen = NSPV_getspentinfo(&S, txid, vout)) > 0) { - response.resize(nspvHeaderSize + slen); + if ((respLen = NSPV_getspentinfo(&S, txid, vout)) > 0) { + response.resize(nspvHeaderSize + respLen); response[0] = NSPV_SPENTINFORESP; memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwspentinfo(IGUANA_WRITE, &response[nspvHeaderSize], &S) == slen) { + if (NSPV_rwspentinfo(IGUANA_WRITE, &response[nspvHeaderSize], &S) == respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_SPENTINFO response: spent txid=%s vout=%d node=%d\n", S.txid.GetHex().c_str(), S.vout, pfrom->id); } else - LogPrint("nspv", "NSPV_rwspentinfo incorrect response len.%d\n", slen); + LogPrint("nspv", "NSPV_rwspentinfo incorrect response len.%d\n", respLen); NSPV_spentinfo_purge(&S); } else - LogPrint("nspv", "NSPV_getspentinfo error.%d node=%d\n", slen, pfrom->id); + LogPrint("nspv", "NSPV_getspentinfo error.%d node=%d\n", respLen, pfrom->id); } else LogPrint("nspv", "NSPV_SPENTINFO bad request len.%d node=%d\n", requestDataLen, pfrom->id); } @@ -1282,24 +1298,25 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re int32_t txlen; if (requestDataLen > sizeof(txid) + sizeof(txlen)) { int32_t offset = 0; + int32_t respLen; offset += iguana_rwbignum(IGUANA_READ, &requestData[offset], sizeof(txid), (uint8_t*)&txid); offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(txlen), &txlen); memset(&B, 0, sizeof(B)); - if (txlen < MAX_TX_SIZE_AFTER_SAPLING && requestDataLen == offset + txlen && (slen = NSPV_sendrawtransaction(&B, &requestData[offset], txlen)) > 0) { - response.resize(nspvHeaderSize + slen); + if (txlen < MAX_TX_SIZE_AFTER_SAPLING && requestDataLen == offset + txlen && (respLen = NSPV_sendrawtransaction(&B, &requestData[offset], txlen)) > 0) { + response.resize(nspvHeaderSize + respLen); response[0] = NSPV_BROADCASTRESP; memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwbroadcastresp(IGUANA_WRITE, &response[nspvHeaderSize], &B) == slen) { + if (NSPV_rwbroadcastresp(IGUANA_WRITE, &response[nspvHeaderSize], &B) == respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_BROADCAST response: txid=%s vout=%d to node=%d\n", B.txid.GetHex().c_str(), pfrom->id); } else - LogPrint("nspv", "NSPV_rwbroadcastresp incorrect response len.%d\n", slen); + LogPrint("nspv", "NSPV_rwbroadcastresp incorrect response len.%d\n", respLen); NSPV_broadcast_purge(&B); } else - LogPrint("nspv", "NSPV_BROADCAST either wrong tx len.%d or NSPV_sendrawtransaction error.%d, node=%d\n", txlen, slen, pfrom->id); + LogPrint("nspv", "NSPV_BROADCAST either wrong tx len.%d or NSPV_sendrawtransaction error.%d, node=%d\n", txlen, respLen, pfrom->id); } else LogPrint("nspv", "NSPV_BROADCAST bad request len.%d node %d\n", requestDataLen, pfrom->id); @@ -1310,13 +1327,19 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re { struct NSPV_remoterpcresp R; int32_t offset = 0; - offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(slen), &slen); + int32_t reqJsonLen; + int32_t respJsonLen; + offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(reqJsonLen), &reqJsonLen); + if (reqJsonLen > NSPV_MAXJSONREQUESTSIZE) { + LogPrint("nspv", "NSPV_REMOTERPC too big json request len.%d\n", reqJsonLen); + return; + } memset(&R, 0, sizeof(R)); - if (requestDataLen == (offset + slen) && (slen = NSPV_remoterpc(&R, (char*)&requestData[offset], slen)) > 0) { - response.resize(nspvHeaderSize + slen); + if (requestDataLen == (offset + reqJsonLen) && (respJsonLen = NSPV_remoterpc(&R, (char*)&requestData[offset], reqJsonLen)) > 0) { + response.resize(nspvHeaderSize + respJsonLen); response[0] = NSPV_REMOTERPCRESP; memcpy(&response[1], requestId, sizeof(requestId)); - NSPV_rwremoterpcresp(IGUANA_WRITE, &response[nspvHeaderSize], &R, slen); + NSPV_rwremoterpcresp(IGUANA_WRITE, &response[nspvHeaderSize], &R, respJsonLen); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; @@ -1337,6 +1360,8 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re char funcids[27]; uint256 filtertxid; bool errorFormat = false; + int32_t respLen; + //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); if (requestDataLen < sizeof(int32_t)) { @@ -1378,20 +1403,20 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re } iguana_rwbignum(IGUANA_READ, &requestData[offset], sizeof(filtertxid), (uint8_t*)&filtertxid); memset(&U, 0, sizeof(U)); - if ((slen = NSPV_getccmoduleutxos(&U, coinaddr, amount, evalcode, funcids, filtertxid)) > 0) { - response.resize(nspvHeaderSize + slen); + if ((respLen = NSPV_getccmoduleutxos(&U, coinaddr, amount, evalcode, funcids, filtertxid)) > 0) { + response.resize(nspvHeaderSize + respLen); response[0] = NSPV_CCMODULEUTXOSRESP; memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) == slen) { + if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) == respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_CCMODULEUTXOS returned %d utxos to node=%d\n", (int)U.numutxos, pfrom->id); } else - LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", slen); + LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", respLen); NSPV_utxosresp_purge(&U); } else - LogPrint("nspv", "NSPV_getccmoduleutxos error.%d, node %d\n", slen, pfrom->id); + LogPrint("nspv", "NSPV_getccmoduleutxos error.%d, node %d\n", respLen, pfrom->id); } break; } From dcbc45990b8e4e15505867080f89f680e156212a Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 14 Oct 2021 21:50:59 +0500 Subject: [PATCH 156/348] removed unused include --- src/cc/CCinclude.h | 6 ------ src/cc/includes/cJSON.h | 2 +- src/cc/includes/curve25519.h | 4 ++-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index c2253d8b620..f2ee24e4d32 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -416,12 +416,6 @@ int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout); int32_t myGet_mempool_txs(std::vector &txs,uint8_t evalcode,uint8_t funcid); /// \endcond -/// \cond INTERNAL -#define IGUANA_READ 0 -#define IGUANA_WRITE 1 -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); -/// \endcond CScript GetScriptForMultisig(int nRequired, const std::vector& keys); diff --git a/src/cc/includes/cJSON.h b/src/cc/includes/cJSON.h index d919a47a9f2..c16093ff106 100755 --- a/src/cc/includes/cJSON.h +++ b/src/cc/includes/cJSON.h @@ -46,7 +46,7 @@ #include #include -#include "../crypto777/OS_portable.h" +//#include "../crypto777/OS_portable.h" #define SATOSHIDEN ((uint64_t)100000000L) #define dstr(x) ((double)(x) / SATOSHIDEN) diff --git a/src/cc/includes/curve25519.h b/src/cc/includes/curve25519.h index 657fab4d011..96df71cd976 100755 --- a/src/cc/includes/curve25519.h +++ b/src/cc/includes/curve25519.h @@ -55,8 +55,8 @@ void vcalc_sha256(char hashstr[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_ void vcalc_sha256cat(uint8_t hash[256 >> 3],uint8_t *src,int32_t len,uint8_t *src2,int32_t len2); void vupdate_sha256(uint8_t hash[256 >> 3],struct sha256_vstate *state,uint8_t *src,int32_t len); bits256 curve25519_shared(bits256 privkey,bits256 otherpub); -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); +//int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); +//int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size); uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen); From 153abe49f26627ea117e601bb0de1fcff1c79bae Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 14 Oct 2021 21:52:35 +0500 Subject: [PATCH 157/348] iguana_rwvarint added --- src/komodo_defs.h | 8 ++++++ src/komodo_nSPV.h | 72 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 17398cd85ac..ef5735f8ef8 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -735,7 +735,15 @@ int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_ #define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" extern int32_t KOMODO_PAX; int32_t komodo_is_issuer(); + +// script tools analogue +#define IGUANA_READ 0 +#define IGUANA_WRITE 1 int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); +int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); +int32_t iguana_rwvarint(int32_t rwflag, uint8_t* serialized, uint64_t* varint64p); +int32_t iguana_rwbuf(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *buf); + int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); int32_t komodo_pending_withdraws(char *opretstr); diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index a9ea5c9545a..2446fd1b31d 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -34,13 +34,71 @@ int32_t iguana_rwbuf(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *buf) { - if ( rwflag != 0 ) - memcpy(serialized,buf,len); - else memcpy(buf,serialized,len); - return(len); + if (rwflag != 0) + memcpy(serialized, buf, len); + else + memcpy(buf, serialized, len); + return (len); +} + +int32_t iguana_varint_size(uint64_t varint64) +{ + if (varint64 < 253) + return 1; + else if (varint64 <= 0xFFFFu) + return 3; + else if (varint64 <= 0xFFFFFFFFu) + return 5; + else + return 9; +} + +int32_t iguana_rwvarint(int32_t rwflag, uint8_t* serialized, uint64_t* varint64p) +{ + if (rwflag != IGUANA_READ) { + if (*varint64p < 253) { + serialized[0]= *varint64p; // this byte contains length 1..252 + return 1; + } else if (*varint64p <= 0xFFFFu) { + uint16_t os_var = htole16(*varint64p); + serialized[0] = 253; // next two bytes contain var length + memcpy(serialized+1, (uint8_t*)&os_var, 2); + return 3; + } else if (*varint64p <= 0xFFFFFFFFu) { + uint32_t os_var = htole32(*varint64p); + serialized[0] = 254; // next four bytes contain var length + memcpy(serialized+1, (uint8_t*)&os_var, 4); + return 5; + } else { + uint64_t os_var = htole64(*varint64p); + serialized[0] = 255; // next eight bytes contain var length + memcpy(serialized+1, (uint8_t*)&os_var, 8); + return 9; + } + } else { + if (serialized[0] < 253) { + *varint64p = serialized[0]; // this byte contains length 1..253 + return 1; + } else if (serialized[0] == 253) { + uint16_t net_var; + memcpy((uint8_t*)&net_var, serialized+1, 2); + *varint64p = le16toh(net_var); + return 3; + } else if (serialized[0] == 254) { + uint32_t net_var; + memcpy((uint8_t*)&net_var, serialized+1, 4); + *varint64p = le32toh(net_var); + return 5; + } else { + uint64_t net_var; + memcpy((uint8_t*)&net_var, serialized+1, 8); + *varint64p = le64toh(net_var); + return 9; + } + } } -int32_t NSPV_rwequihdr(int32_t rwflag,uint8_t *serialized,struct NSPV_equihdr *ptr) +int32_t NSPV_rwequihdr(int32_t rwflag, uint8_t *serialized, struct NSPV_equihdr *ptr) { int32_t len = 0; len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nVersion),&ptr->nVersion); @@ -50,7 +108,9 @@ int32_t NSPV_rwequihdr(int32_t rwflag,uint8_t *serialized,struct NSPV_equihdr *p len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nTime),&ptr->nTime); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nBits),&ptr->nBits); len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->nNonce),(uint8_t *)&ptr->nNonce); - len += iguana_rwbuf(rwflag,&serialized[len],sizeof(ptr->nSolution),ptr->nSolution); + uint64_t nSolutionSize = sizeof(ptr->nSolution); + len += iguana_rwvarint(rwflag, &serialized[len], &nSolutionSize); + len += iguana_rwbuf(rwflag, &serialized[len], nSolutionSize, ptr->nSolution); return(len); } From cf093a9d3bd55591e58ac6f7915218671a4f595c Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 14 Oct 2021 21:55:37 +0500 Subject: [PATCH 158/348] added NSPV_ERRORRESP message; requestId added after reqCode/respCode to route responses inside app, nSolution serialised in equihdr prepended with varint to make compatible with merkleblock msg --- src/komodo_nSPV_defs.h | 17 ++- src/komodo_nSPV_fullnode.h | 253 +++++++++++++++++++++++++++---------- src/net.cpp | 1 + src/net.h | 1 + 4 files changed, 205 insertions(+), 67 deletions(-) diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index f48717a3118..0a90ca7c736 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -19,13 +19,14 @@ #include -#define NSPV_PROTOCOL_VERSION 0x00000004 +#define NSPV_PROTOCOL_VERSION 0x00000005 #define NSPV_POLLITERS 200 #define NSPV_POLLMICROS 50000 #define NSPV_MAXVINS 64 #define NSPV_AUTOLOGOUT 777 #define NSPV_BRANCHID 0x76b809bb #define NSPV_MAXJSONREQUESTSIZE 65536 +#define NSPV_REQUESTIDSIZE 4 // nSPV defines and struct definitions with serialization and purge functions @@ -57,9 +58,21 @@ #define NSPV_CC_TXIDS 16 #define NSPV_REMOTERPC 0x14 #define NSPV_REMOTERPCRESP 0x15 +#define NSPV_ERRORRESP 0xff + +#define NSPV_ERROR_INVALID_REQUEST_TYPE (-10) +#define NSPV_ERROR_INVALID_REQUEST_DATA (-11) +#define NSPV_ERROR_GETINFO_FIRST (-12) +#define NSPV_ERROR_INVALID_VERSION (-13) +#define NSPV_ERROR_READ_DATA (-14) +#define NSPV_ERROR_INVALID_RESPONSE (-15) +#define NSPV_ERROR_BROADCAST (-16) +#define NSPV_ERROR_REMOTE_RPC (-17) #define NSPV_MAXREQSPERSEC 15 +#define NSPV_MAX_VARINT_SIZE 9 + int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int32_t height,CTransaction &tx,uint256 &hashblock,int32_t &txheight,int32_t ¤theight,int64_t extradata,uint32_t tiptime,int64_t &rewardsum); UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); extern uint256 SIG_TXHASH; @@ -200,4 +213,6 @@ void NSPV_CCunspents(std::vector>& indexOutputs, char* coinaddr, bool ccflag); void NSPV_CCtxids(std::vector& txids, char* coinaddr, bool ccflag, uint8_t evalcode, uint256 filtertxid, uint8_t func); +extern std::map nspvErrors; + #endif // KOMODO_NSPV_DEFSH diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 25cb6cb07a5..eaeb9c0480c 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -29,7 +29,16 @@ #include "komodo_nSPV_defs.h" #include "komodo_nSPV.h" - +std::map nspvErrors = { + { NSPV_ERROR_INVALID_REQUEST_TYPE, "invalid request type" }, + { NSPV_ERROR_INVALID_REQUEST_DATA, "invalid request data" }, + { NSPV_ERROR_GETINFO_FIRST, "request getinfo to connect to nspv" }, + { NSPV_ERROR_INVALID_VERSION, "version not supported" }, + { NSPV_ERROR_READ_DATA, "could not get chain data" }, + { NSPV_ERROR_INVALID_RESPONSE, "could not create response message" }, + { NSPV_ERROR_BROADCAST, "could not broadcast transaction" }, + { NSPV_ERROR_REMOTE_RPC, "could not execute rpc" }, +}; static std::map nspv_remote_commands = { @@ -152,7 +161,7 @@ int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) hdr->nBits = pindex->nBits; hdr->nNonce = pindex->nNonce; memcpy(hdr->nSolution,&pindex->nSolution[0],sizeof(hdr->nSolution)); - return(sizeof(*hdr)); + return(sizeof(*hdr) + NSPV_MAX_VARINT_SIZE); } return(-1); } @@ -180,7 +189,7 @@ int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) ptr->version = NSPV_PROTOCOL_VERSION; if (NSPV_setequihdr(&ptr->H, reqheight) < 0) return (-1); - return (sizeof(*ptr)); + return (sizeof(*ptr) + NSPV_MAX_VARINT_SIZE); // add space for nSolution varint length } else return (-1); } @@ -905,7 +914,7 @@ int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp* ptr, uint256 prevntztxi } } //fprintf(stderr, "sizeof ptr %ld, common.%ld lens.%d %d\n", sizeof(*ptr), sizeof(ptr->common), ptr->prevtxlen, ptr->nexttxlen); - return (sizeof(*ptr) + sizeof(*ptr->common.hdrs) * ptr->common.numhdrs - sizeof(ptr->common.hdrs) - sizeof(ptr->prevntz) - sizeof(ptr->nextntz) + ptr->prevtxlen + ptr->nexttxlen); + return (sizeof(*ptr) + (sizeof(*ptr->common.hdrs) + NSPV_MAX_VARINT_SIZE) * ptr->common.numhdrs - sizeof(ptr->common.hdrs) - sizeof(ptr->prevntz) - sizeof(ptr->nextntz) + ptr->prevtxlen + ptr->nexttxlen); } int32_t NSPV_getspentinfo(struct NSPV_spentinfo* ptr, uint256 txid, int32_t vout) @@ -926,25 +935,38 @@ int32_t NSPV_getspentinfo(struct NSPV_spentinfo* ptr, uint256 txid, int32_t vout return (len); } +static void NSPV_senderror(CNode* pfrom, uint32_t requestId, int32_t err) +{ + const uint8_t respCode = NSPV_ERRORRESP; + std::string errDesc = nspvErrors[err]; + + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << respCode << requestId << err << errDesc; + + std::vector response = vuint8_t(ss.begin(), ss.end()); + pfrom->PushMessage("nSPV", response); +} + // processing nspv requests void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a request { std::vector response; uint32_t timestamp = (uint32_t)time(NULL); - const int nspvHeaderSize = 1 + 4; + uint8_t requestType = request[0]; + uint32_t requestId; + const int nspvHeaderSize = sizeof(requestType) + sizeof(requestId); if (request.size() < nspvHeaderSize) { LogPrint("nspv", "request too small from peer %d\n", pfrom->id); return; } - uint8_t requestType = request[0]; - uint8_t requestId[4]; - memcpy(requestId, &request[1], sizeof(requestId)); + requestType = request[0]; + memcpy(&requestId, &request[1], sizeof(requestId)); uint8_t *requestData = &request[nspvHeaderSize]; int32_t requestDataLen = request.size() - nspvHeaderSize; - // rate limit no more 1 request/sec of same type from same node: + // rate limit no more NSPV_MAXREQSPERSEC request/sec of same type from same node: int32_t idata = requestData[0] >> 1; if (idata >= sizeof(pfrom->nspvdata) / sizeof(pfrom->nspvdata[0])) idata = (int32_t)(sizeof(pfrom->nspvdata) / sizeof(pfrom->nspvdata[0])) - 1; @@ -957,39 +979,65 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re return; } } else { - pfrom->nspvdata[idata].nreqs = 0; + pfrom->nspvdata[idata].nreqs = 0; // clear request stat if new second + } + + // check if nspv connected: + if (!pfrom->fNspvConnected) { + if (requestType != NSPV_INFO) { + LogPrint("nspv", "nspv node should call NSPV_INFO first from node=%d\n", pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_GETINFO_FIRST); + return; + } } switch (requestType) { - case NSPV_INFO: // info + case NSPV_INFO: // info, mandatory first request { struct NSPV_inforesp I; int32_t respLen; int32_t reqheight; + uint32_t version; //fprintf(stderr,"check info %u vs %u, ind.%d\n", timestamp, pfrom->nspvdata[ind].prevtime, ind); - if (requestDataLen == sizeof(reqheight)) - iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(reqheight), &reqheight); - else - reqheight = 0; + if (requestDataLen != sizeof(version) + sizeof(reqheight)) { + LogPrint("nspv-details", "NSPV_INFO invalid request from node=%d\n", pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); + return; + } + int32_t offset = 0; + offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(version), &version); + if (version != NSPV_PROTOCOL_VERSION) { + LogPrint("nspv", "nspv version %d not supported from node=%d\n", version, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_VERSION); + return; + } + + iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(reqheight), &reqheight); + //fprintf(stderr,"request height.%d\n",reqheight); memset(&I, 0, sizeof(I)); if ((respLen = NSPV_getinfo(&I, reqheight)) > 0) { response.resize(nspvHeaderSize + respLen); response[0] = NSPV_INFORESP; - memcpy(&response[1], requestId, sizeof(requestId)); + memcpy(&response[1], &requestId, sizeof(requestId)); //fprintf(stderr,"respLen.%d version.%d\n",respLen,I.version); - if (NSPV_rwinforesp(IGUANA_WRITE, &response[nspvHeaderSize], &I) == respLen) { + if (NSPV_rwinforesp(IGUANA_WRITE, &response[nspvHeaderSize], &I) <= respLen) { //fprintf(stderr,"send info resp to id %d\n",(int32_t)pfrom->id); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_INFO response: version %d to node=%d\n", I.version, pfrom->id); - } else + pfrom->fNspvConnected = true; // allow to do nspv requests + } else { LogPrint("nspv", "NSPV_rwinforesp incorrect response len.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_inforesp_purge(&I); - } else + } else { LogPrint("nspv", "NSPV_getinfo error.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); + } } break; @@ -1006,6 +1054,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if (requestDataLen < 1) { LogPrint("nspv", "NSPV_UTXOS bad request too short len.%d node %d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } @@ -1014,6 +1063,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if (offset + addrlen > requestDataLen || addrlen > sizeof(coinaddr) - 1) // out of bounds { LogPrint("nspv", "NSPV_UTXOS bad request len.%d too short or addrlen.%d out of bounds, node=%d\n", requestDataLen, addrlen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } @@ -1035,6 +1085,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re } if (offset != requestDataLen) { LogPrint("nspv", "NSPV_UTXOS bad request parameters format: len.%d, offset.%d, addrlen.%d, node=%d\n", requestDataLen, offset, addrlen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } @@ -1043,17 +1094,21 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if ((respLen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, maxrecords)) > 0) { response.resize(nspvHeaderSize + respLen); response[0] = NSPV_UTXOSRESP; - memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) == respLen) { + memcpy(&response[1], &requestId, sizeof(requestId)); + if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) <= respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_UTXOS response: numutxos=%d to node=%d\n", U.numutxos, pfrom->id); - } else + } else { LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_utxosresp_purge(&U); - } else + } else { LogPrint("nspv", "NSPV_getaddressutxos error respLen.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); + } } break; @@ -1070,6 +1125,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if (requestDataLen < 1) { LogPrint("nspv", "NSPV_TXIDS bad request too short len.%d, node %d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } @@ -1078,6 +1134,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if (offset + addrlen > requestDataLen || addrlen > sizeof(coinaddr) - 1) // out of bounds { LogPrint("nspv", "NSPV_TXIDS bad request len.%d too short or addrlen.%d out of bounds, node=%d\n", requestDataLen, addrlen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } @@ -1099,6 +1156,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re } if (offset != requestDataLen) { LogPrint("nspv", "NSPV_TXIDS bad request parameters format: len.%d, offset.%d, addrlen.%d, node=%d\n", requestDataLen, offset, addrlen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } @@ -1109,17 +1167,21 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re //fprintf(stderr,"respLen.%d\n",respLen); response.resize(nspvHeaderSize + respLen); response[0] = NSPV_TXIDSRESP; - memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwtxidsresp(IGUANA_WRITE, &response[nspvHeaderSize], &T) == respLen) { + memcpy(&response[1], &requestId, sizeof(requestId)); + if (NSPV_rwtxidsresp(IGUANA_WRITE, &response[nspvHeaderSize], &T) <= respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_TXIDS response: numtxids=%d to node=%d\n", (int)T.numtxids, pfrom->id); - } else + } else { LogPrint("nspv", "NSPV_rwtxidsresp incorrect response len.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_txidsresp_purge(&T); - } else + } else { LogPrint("nspv", "NSPV_getaddresstxids error.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); + } } break; @@ -1150,21 +1212,29 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re //fprintf(stderr,"NSPV_mempooltxids respLen.%d\n",respLen); response.resize(nspvHeaderSize + respLen); response[0] = NSPV_MEMPOOLRESP; - memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwmempoolresp(IGUANA_WRITE, &response[nspvHeaderSize], &M) == respLen) { + memcpy(&response[1], &requestId, sizeof(requestId)); + if (NSPV_rwmempoolresp(IGUANA_WRITE, &response[nspvHeaderSize], &M) <= respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_MEMPOOL response: numtxids=%d to node=%d\n", M.numtxids, pfrom->id); - } else + } else { LogPrint("nspv", "NSPV_rwmempoolresp incorrect response len.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_mempoolresp_purge(&M); - } else + } else { LogPrint("nspv", "NSPV_mempooltxids err.%d\n", respLen); - } else + NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); + } + } else { LogPrint("nspv", "NSPV_MEMPOOL incorrect addrlen.%d offset.%d len.%d\n", addrlen, offset, requestDataLen); - } else + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); + } + } else { LogPrint("nspv", "NSPV_MEMPOOL incorrect len.%d too short, node %d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); + } } break; @@ -1180,19 +1250,25 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if ((respLen = NSPV_getntzsresp(&N, height)) > 0) { response.resize(nspvHeaderSize + respLen); response[0] = NSPV_NTZSRESP; - memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwntzsresp(IGUANA_WRITE, &response[nspvHeaderSize], &N) == respLen) { + memcpy(&response[1], &requestId, sizeof(requestId)); + if (NSPV_rwntzsresp(IGUANA_WRITE, &response[nspvHeaderSize], &N) <= respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_NTZS response: prevntz.txid=%s nextntx.txid=%s node=%d\n", N.prevntz.txid.GetHex().c_str(), N.nextntz.txid.GetHex().c_str(), pfrom->id); - } else + } else { LogPrint("nspv", "NSPV_rwntzsresp incorrect response len.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_ntzsresp_purge(&N); - } else + } else { LogPrint("nspv", "NSPV_rwntzsresp err.%d\n", respLen); - } else + NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); + } + } else { LogPrint("nspv", "NSPV_NTZS bad request len.%d node %d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); + } } break; @@ -1210,19 +1286,25 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re // fprintf(stderr,"respLen.%d msg prev.%s next.%s\n",respLen,prevntz.GetHex().c_str(),nextntz.GetHex().c_str()); response.resize(nspvHeaderSize + respLen); response[0] = NSPV_NTZSPROOFRESP; - memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwntzsproofresp(IGUANA_WRITE, &response[nspvHeaderSize], &P) == respLen) { + memcpy(&response[1], &requestId, sizeof(requestId)); + if (NSPV_rwntzsproofresp(IGUANA_WRITE, &response[nspvHeaderSize], &P) <= respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_NTZSPROOF response: prevtxidht=%d nexttxidht=%d node=%d\n", P.prevtxidht, P.nexttxidht, pfrom->id); - } else + } else { LogPrint("nspv", "NSPV_rwntzsproofresp incorrect response len.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_ntzsproofresp_purge(&P); - } else + } else { LogPrint("nspv", "NSPV_NTZSPROOF err.%d\n", respLen); - } else + NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); + } + } else { LogPrint("nspv", "NSPV_NTZSPROOF bad request len.%d node %d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); + } } break; @@ -1243,20 +1325,26 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re //fprintf(stderr,"respLen.%d\n",respLen); response.resize(nspvHeaderSize + respLen); response[0] = NSPV_TXPROOFRESP; - memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwtxproof(IGUANA_WRITE, &response[nspvHeaderSize], &P) == respLen) { + memcpy(&response[1], &requestId, sizeof(requestId)); + if (NSPV_rwtxproof(IGUANA_WRITE, &response[nspvHeaderSize], &P) <= respLen) { //fprintf(stderr,"send response\n"); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_TXPROOF response: txlen=%d txprooflen=%d node=%d\n", P.txlen, P.txprooflen, pfrom->id); - } else + } else { LogPrint("nspv", "NSPV_rwtxproof incorrect response len.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_txproof_purge(&P); - } else + } else { LogPrint("nspv", "gettxproof error.%d\n", respLen); - } else + NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); + } + } else { LogPrint("nspv", "txproof bad request len.%d node %d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); + } } break; @@ -1275,19 +1363,25 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if ((respLen = NSPV_getspentinfo(&S, txid, vout)) > 0) { response.resize(nspvHeaderSize + respLen); response[0] = NSPV_SPENTINFORESP; - memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwspentinfo(IGUANA_WRITE, &response[nspvHeaderSize], &S) == respLen) { + memcpy(&response[1], &requestId, sizeof(requestId)); + if (NSPV_rwspentinfo(IGUANA_WRITE, &response[nspvHeaderSize], &S) <= respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_SPENTINFO response: spent txid=%s vout=%d node=%d\n", S.txid.GetHex().c_str(), S.vout, pfrom->id); - } else + } else { LogPrint("nspv", "NSPV_rwspentinfo incorrect response len.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_spentinfo_purge(&S); - } else + } else { LogPrint("nspv", "NSPV_getspentinfo error.%d node=%d\n", respLen, pfrom->id); - } else + NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); + } + } else { LogPrint("nspv", "NSPV_SPENTINFO bad request len.%d node=%d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); + } } break; @@ -1306,19 +1400,25 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if (txlen < MAX_TX_SIZE_AFTER_SAPLING && requestDataLen == offset + txlen && (respLen = NSPV_sendrawtransaction(&B, &requestData[offset], txlen)) > 0) { response.resize(nspvHeaderSize + respLen); response[0] = NSPV_BROADCASTRESP; - memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwbroadcastresp(IGUANA_WRITE, &response[nspvHeaderSize], &B) == respLen) { + memcpy(&response[1], &requestId, sizeof(requestId)); + if (NSPV_rwbroadcastresp(IGUANA_WRITE, &response[nspvHeaderSize], &B) <= respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_BROADCAST response: txid=%s vout=%d to node=%d\n", B.txid.GetHex().c_str(), pfrom->id); - } else + } else { LogPrint("nspv", "NSPV_rwbroadcastresp incorrect response len.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_broadcast_purge(&B); - } else + } else { LogPrint("nspv", "NSPV_BROADCAST either wrong tx len.%d or NSPV_sendrawtransaction error.%d, node=%d\n", txlen, respLen, pfrom->id); - } else + NSPV_senderror(pfrom, requestId, NSPV_ERROR_BROADCAST); + } + } else { LogPrint("nspv", "NSPV_BROADCAST bad request len.%d node %d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); + } } break; @@ -1332,21 +1432,28 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(reqJsonLen), &reqJsonLen); if (reqJsonLen > NSPV_MAXJSONREQUESTSIZE) { LogPrint("nspv", "NSPV_REMOTERPC too big json request len.%d\n", reqJsonLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } memset(&R, 0, sizeof(R)); - if (requestDataLen == (offset + reqJsonLen) && (respJsonLen = NSPV_remoterpc(&R, (char*)&requestData[offset], reqJsonLen)) > 0) { + if (requestDataLen != (offset + reqJsonLen)) { + LogPrint("nspv", "NSPV_REMOTERPC bad request len.%d node %d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); + } + if ((respJsonLen = NSPV_remoterpc(&R, (char*)&requestData[offset], reqJsonLen)) > 0) { response.resize(nspvHeaderSize + respJsonLen); response[0] = NSPV_REMOTERPCRESP; - memcpy(&response[1], requestId, sizeof(requestId)); + memcpy(&response[1], &requestId, sizeof(requestId)); NSPV_rwremoterpcresp(IGUANA_WRITE, &response[nspvHeaderSize], &R, respJsonLen); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_REMOTERPCRESP response: method=%s json=%s to node=%d\n", R.method, R.json, pfrom->id); NSPV_remoterpc_purge(&R); - } else - LogPrint("nspv", "NSPV_REMOTERPC bad request len.%d node %d\n", requestDataLen, pfrom->id); + } else { + LogPrint("nspv", "NSPV_REMOTERPC could not execute request node %d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_REMOTE_RPC); + } } break; @@ -1366,6 +1473,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if (requestDataLen < sizeof(int32_t)) { LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short, node=%d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } @@ -1373,6 +1481,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re int32_t addrlen = requestData[offset++]; if (addrlen >= sizeof(coinaddr) || offset + addrlen > requestDataLen) { LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short or addrlen %d too long, node=%d\n", requestDataLen, addrlen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } @@ -1382,6 +1491,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if (offset + sizeof(amount) + sizeof(evalcode) + sizeof(funcidslen) > requestDataLen) { LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d too short, node=%d\n", requestDataLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(amount), &amount); @@ -1390,6 +1500,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if (funcidslen >= sizeof(funcids) || offset + funcidslen > requestDataLen) { LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d no room for funcids or too many funcids %d, node=%d\n", requestDataLen, funcidslen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } @@ -1399,6 +1510,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if (offset + sizeof(filtertxid) != requestDataLen) { LogPrint("nspv", "NSPV_CCMODULEUTXOS bad request len.%d incorrect room for filtertxid param, node=%d\n", requestDataLen, funcidslen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } iguana_rwbignum(IGUANA_READ, &requestData[offset], sizeof(filtertxid), (uint8_t*)&filtertxid); @@ -1406,19 +1518,28 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if ((respLen = NSPV_getccmoduleutxos(&U, coinaddr, amount, evalcode, funcids, filtertxid)) > 0) { response.resize(nspvHeaderSize + respLen); response[0] = NSPV_CCMODULEUTXOSRESP; - memcpy(&response[1], requestId, sizeof(requestId)); - if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) == respLen) { + memcpy(&response[1], &requestId, sizeof(requestId)); + if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) <= respLen) { pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_CCMODULEUTXOS returned %d utxos to node=%d\n", (int)U.numutxos, pfrom->id); - } else + } else { LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", respLen); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_utxosresp_purge(&U); - } else + } else { LogPrint("nspv", "NSPV_getccmoduleutxos error.%d, node %d\n", respLen, pfrom->id); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); + } + } break; + + default: + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_TYPE); + break; } } diff --git a/src/net.cpp b/src/net.cpp index aa60ade5966..a291c5df04f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2130,6 +2130,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa fInbound = fInboundIn; fNetworkNode = false; fSuccessfullyConnected = false; + fNspvConnected = false; fDisconnect = false; nRefCount = 0; nSendSize = 0; diff --git a/src/net.h b/src/net.h index 9ea83161f2e..64f55b8aa6b 100644 --- a/src/net.h +++ b/src/net.h @@ -308,6 +308,7 @@ class CNode bool fInbound; bool fNetworkNode; bool fSuccessfullyConnected; + bool fNspvConnected; bool fDisconnect; // We use fRelayTxes for two purposes - // a) it allows us to not relay tx invs before receiving the peer's version message From 91a70e2fe33d5bdbeb3294ed95a2df222979d697 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 15 Oct 2021 13:55:55 +0500 Subject: [PATCH 159/348] logging fixed --- src/komodo_nSPV_fullnode.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index eaeb9c0480c..ad3f3bb8150 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -1001,14 +1001,14 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re //fprintf(stderr,"check info %u vs %u, ind.%d\n", timestamp, pfrom->nspvdata[ind].prevtime, ind); if (requestDataLen != sizeof(version) + sizeof(reqheight)) { - LogPrint("nspv-details", "NSPV_INFO invalid request from node=%d\n", pfrom->id); + LogPrint("nspv", "NSPV_INFO invalid request from node=%d\n", pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } int32_t offset = 0; offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(version), &version); if (version != NSPV_PROTOCOL_VERSION) { - LogPrint("nspv", "nspv version %d not supported from node=%d\n", version, pfrom->id); + LogPrint("nspv", "NSPV_INFO nspv version %d not supported from node=%d\n", version, pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_VERSION); return; } @@ -1027,7 +1027,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; - LogPrint("nspv-details", "NSPV_INFO response: version %d to node=%d\n", I.version, pfrom->id); + LogPrint("nspv-details", "NSPV_INFO sent response: version %d to node=%d\n", I.version, pfrom->id); pfrom->fNspvConnected = true; // allow to do nspv requests } else { LogPrint("nspv", "NSPV_rwinforesp incorrect response len.%d\n", respLen); From 2e85abac4e7743b43a338d7c9caf5737add308b1 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 15 Oct 2021 14:37:59 +0500 Subject: [PATCH 160/348] nspv_info logging improved --- src/komodo_nSPV_fullnode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index ad3f3bb8150..dd101b9de69 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -1001,7 +1001,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re //fprintf(stderr,"check info %u vs %u, ind.%d\n", timestamp, pfrom->nspvdata[ind].prevtime, ind); if (requestDataLen != sizeof(version) + sizeof(reqheight)) { - LogPrint("nspv", "NSPV_INFO invalid request from node=%d\n", pfrom->id); + LogPrint("nspv", "NSPV_INFO invalid request size %d from node=%d\n", requestDataLen, pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } From 51cc81c74b27fd99f68cd7181e4b11260bb257e7 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 16 Oct 2021 16:56:06 +0500 Subject: [PATCH 161/348] 'script' field added to returned nspv utxos --- src/komodo_nSPV.h | 104 +++++++++++++++++++----------------- src/komodo_nSPV_defs.h | 5 +- src/komodo_nSPV_fullnode.h | 9 +++- src/komodo_nSPV_superlite.h | 9 ++-- 4 files changed, 73 insertions(+), 54 deletions(-) diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index 2446fd1b31d..0f8ed0843d1 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -142,64 +142,73 @@ int32_t iguana_rwuint8vec(int32_t rwflag,uint8_t *serialized,int32_t *biglenp,ui return(len); } -int32_t NSPV_rwutxoresp(int32_t rwflag,uint8_t *serialized,struct NSPV_utxoresp *ptr) +int32_t NSPV_rwutxoresp(int32_t rwflag, uint8_t* serialized, struct NSPV_utxoresp* ptr) { int32_t len = 0; - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->satoshis),&ptr->satoshis); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->extradata),&ptr->extradata); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); - return(len); + len += iguana_rwbignum(rwflag, &serialized[len], sizeof(ptr->txid), (uint8_t*)&ptr->txid); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->satoshis), &ptr->satoshis); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->extradata), &ptr->extradata); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->vout), &ptr->vout); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->height), &ptr->height); + len += iguana_rwvarint(rwflag, &serialized[len], &ptr->script_size); + len += iguana_rwbuf(rwflag, &serialized[len], ptr->script_size, ptr->script); + return (len); } -int32_t NSPV_rwutxosresp(int32_t rwflag,uint8_t *serialized,struct NSPV_utxosresp *ptr) // check mempool -{ - int32_t i,len = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->numutxos),&ptr->numutxos); - if ( ptr->numutxos != 0 ) - { - if ( ptr->utxos == 0 ) - ptr->utxos = (struct NSPV_utxoresp *)calloc(sizeof(*ptr->utxos),ptr->numutxos); // relies on uint16_t being "small" to prevent mem exhaustion - for (i=0; inumutxos; i++) - len += NSPV_rwutxoresp(rwflag,&serialized[len],&ptr->utxos[i]); - } - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->total),&ptr->total); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->interest),&ptr->interest); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->maxrecords),&ptr->maxrecords); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); - if ( rwflag != 0 ) - { - memcpy(&serialized[len],ptr->coinaddr,sizeof(ptr->coinaddr)); +int32_t NSPV_rwutxosresp(int32_t rwflag, uint8_t* serialized, struct NSPV_utxosresp* ptr) // check mempool +{ + int32_t i, len = 0; + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->numutxos), &ptr->numutxos); + if (ptr->numutxos != 0) { + if (ptr->utxos == 0) + ptr->utxos = (struct NSPV_utxoresp*)calloc(sizeof(*ptr->utxos), ptr->numutxos); // relies on uint16_t being "small" to prevent mem exhaustion + for (i = 0; i < ptr->numutxos; i++) + len += NSPV_rwutxoresp(rwflag, &serialized[len], &ptr->utxos[i]); + } + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->total), &ptr->total); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->interest), &ptr->interest); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->nodeheight), &ptr->nodeheight); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->maxrecords), &ptr->maxrecords); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->CCflag), &ptr->CCflag); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->skipcount), &ptr->skipcount); + if (rwflag != 0) { + memcpy(&serialized[len], ptr->coinaddr, sizeof(ptr->coinaddr)); len += sizeof(ptr->coinaddr); - } - else - { - memcpy(ptr->coinaddr,&serialized[len],sizeof(ptr->coinaddr)); + } else { + memcpy(ptr->coinaddr, &serialized[len], sizeof(ptr->coinaddr)); len += sizeof(ptr->coinaddr); } - return(len); + return (len); } void NSPV_utxosresp_purge(struct NSPV_utxosresp *ptr) { - if ( ptr != 0 ) - { - if ( ptr->utxos != 0 ) + if (ptr != 0) { + if (ptr->utxos != NULL) { + for(size_t i = 0; i < ptr->numutxos; i ++) + if (ptr->utxos[i].script) + free(ptr->utxos[i].script); free(ptr->utxos); - memset(ptr,0,sizeof(*ptr)); + } + memset(ptr, 0, sizeof(*ptr)); } } void NSPV_utxosresp_copy(struct NSPV_utxosresp *dest,struct NSPV_utxosresp *ptr) { *dest = *ptr; - if ( ptr->utxos != 0 ) - { - dest->utxos = (struct NSPV_utxoresp *)malloc(ptr->numutxos * sizeof(*ptr->utxos)); - memcpy(dest->utxos,ptr->utxos,ptr->numutxos * sizeof(*ptr->utxos)); + if (ptr->utxos != 0) { + dest->utxos = (struct NSPV_utxoresp*)malloc(ptr->numutxos * sizeof(*ptr->utxos)); + memcpy(dest->utxos, ptr->utxos, ptr->numutxos * sizeof(*ptr->utxos)); + for (size_t i = 0; i < ptr->numutxos; i++) { + dest->utxos[i].script = NULL; + dest->utxos[i].script_size = 0; + if (ptr->utxos[i].script) { + dest->utxos->script = (uint8_t*)malloc(ptr->utxos[i].script_size); + memcpy(dest->utxos[i].script, ptr->utxos[i].script, ptr->utxos[i].script_size); + dest->utxos[i].script_size = ptr->utxos[i].script_size; + } + } } } @@ -244,21 +253,20 @@ int32_t NSPV_rwtxidsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidsres void NSPV_txidsresp_purge(struct NSPV_txidsresp *ptr) { - if ( ptr != 0 ) - { - if ( ptr->txids != 0 ) + if (ptr != 0) { + if (ptr->txids != NULL) { free(ptr->txids); - memset(ptr,0,sizeof(*ptr)); + } + memset(ptr, 0, sizeof(*ptr)); } } void NSPV_txidsresp_copy(struct NSPV_txidsresp *dest,struct NSPV_txidsresp *ptr) { *dest = *ptr; - if ( ptr->txids != 0 ) - { - dest->txids = (struct NSPV_txidresp *)malloc(ptr->numtxids * sizeof(*ptr->txids)); - memcpy(dest->txids,ptr->txids,ptr->numtxids * sizeof(*ptr->txids)); + if (ptr->txids != 0) { + dest->txids = (struct NSPV_txidresp*)malloc(ptr->numtxids * sizeof(*ptr->txids)); + memcpy(dest->txids, ptr->txids, ptr->numtxids * sizeof(*ptr->txids)); } } diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 0a90ca7c736..c84cf96b021 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -95,6 +95,7 @@ struct NSPV_utxoresp uint256 txid; int64_t satoshis,extradata; int32_t vout,height; + uint8_t *script; uint64_t script_size; }; struct NSPV_utxosresp @@ -103,14 +104,14 @@ struct NSPV_utxosresp char coinaddr[64]; int64_t total,interest; int32_t nodeheight,skipcount,maxrecords; - uint16_t numutxos,CCflag; + uint16_t numutxos, CCflag; }; struct NSPV_txidresp { uint256 txid; int64_t satoshis; - int32_t vout,height; + int32_t vout, height; }; struct NSPV_txidsresp diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index dd101b9de69..c3dad974d49 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -223,6 +223,8 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool is ptr->utxos = nullptr; ptr->nodeheight = tipheight; + int32_t script_len_total = 0; + if (unspentOutputs.size() >= 0 && skipcount < unspentOutputs.size()) { ptr->utxos = (struct NSPV_utxoresp*)calloc(unspentOutputs.size() - skipcount, sizeof(ptr->utxos[0])); for (std::vector>::const_iterator it = unspentOutputs.begin() + skipcount; @@ -238,6 +240,10 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool is ptr->utxos[n].extradata = komodo_accrued_interest(&txheight, &locktime, ptr->utxos[ind].txid, ptr->utxos[ind].vout, ptr->utxos[ind].height, ptr->utxos[ind].satoshis, tipheight); interest += ptr->utxos[ind].extradata; } + ptr->utxos[ind].script = (uint8_t*)malloc(it->second.script.size()); + memcpy(ptr->utxos[ind].script, &it->second.script[0], it->second.script.size()); + ptr->utxos[ind].script_size = it->second.script.size(); + script_len_total += it->second.script.size() + 9; // add 9 for max varint script size ind++; total += it->second.satoshis; } @@ -247,7 +253,7 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool is } // always return a result: ptr->numutxos = ind; - int32_t len = (int32_t)(sizeof(*ptr) + sizeof(ptr->utxos[0]) * ptr->numutxos - sizeof(ptr->utxos)); + int32_t len = (int32_t)(sizeof(*ptr) + sizeof(ptr->utxos[0]) * ptr->numutxos - sizeof(ptr->utxos)) + script_len_total; //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); ptr->total = total; ptr->interest = interest; @@ -518,6 +524,7 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is ptr->txids[ind].vout = (int32_t)it->first.index; ptr->txids[ind].satoshis = (int64_t)it->second; ptr->txids[ind].height = (int64_t)it->first.blockHeight; + ind++; } } diff --git a/src/komodo_nSPV_superlite.h b/src/komodo_nSPV_superlite.h index c7a20d82a94..fc63b0f82e1 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -404,6 +404,8 @@ UniValue NSPV_utxoresp_json(struct NSPV_utxoresp *utxos,int32_t numutxos) item.push_back(Pair("value",(double)utxos[i].satoshis/COIN)); if ( ASSETCHAINS_SYMBOL[0] == 0 ) item.push_back(Pair("interest",(double)utxos[i].extradata/COIN)); + if (utxos[i].script) + item.push_back(Pair("script", HexStr(utxos[i].script, utxos[i].script+utxos[i].script_size))); array.push_back(item); } return(array); @@ -435,9 +437,10 @@ UniValue NSPV_txidresp_json(struct NSPV_txidresp *utxos,int32_t numutxos) item.push_back(Pair("height",(int64_t)utxos[i].height)); item.push_back(Pair("txid",utxos[i].txid.GetHex())); item.push_back(Pair("value",(double)utxos[i].satoshis/COIN)); - if ( utxos[i].satoshis > 0 ) - item.push_back(Pair("vout",(int64_t)utxos[i].vout)); - else item.push_back(Pair("vin",(int64_t)utxos[i].vout)); + if (utxos[i].satoshis > 0) + item.push_back(Pair("vout", (int64_t)utxos[i].vout)); + else + item.push_back(Pair("vin", (int64_t)utxos[i].vout)); array.push_back(item); } return(array); From 7683775ac110d47d69ec4c1714338dc5fceefc09 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 16 Oct 2021 23:26:41 +0500 Subject: [PATCH 162/348] nspv create token fixed remotepk --- src/rpc/tokensrpc.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 37453016db9..eff35deb6cd 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -347,6 +347,8 @@ static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, UniValue result(UniValue::VOBJ); std::string name, description, hextx; CAmount supply; // changed from uin64_t to int64_t for this 'if ( supply <= 0 )' to work as expected + const CPubKey nullpk; + const CAmount txfee = 0; CCerror.clear(); @@ -373,9 +375,11 @@ static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, return MakeResultError("Token description must be <= " + std::to_string(TOKENS_MAX_DESC_LENGTH)); // allowed > MAX_SCRIPT_ELEMENT_SIZE } - hextx = CreateTokenLocal(0, supply, name, description, vtokenData); + //hextx = CreateTokenLocal(0, supply, name, description, vtokenData); + UniValue rcreate = CreateTokenExt(remotepk.IsValid() ? remotepk : nullpk, txfee, supply, name, description, vtokenData, 0, false); RETURN_IF_ERROR(CCerror); + hextx = ResultGetTx(rcreate); if( hextx.size() > 0 ) return MakeResultSuccess(hextx); else From a4a81fa1d58457617dd93014cdee6ad8f00877d6 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 17 Oct 2021 00:47:23 +0500 Subject: [PATCH 163/348] fix tokencreate return for nspv --- src/rpc/tokensrpc.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index eff35deb6cd..7f98725d84e 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -345,7 +345,7 @@ template static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, bool fHelp, const CPubKey& remotepk) { UniValue result(UniValue::VOBJ); - std::string name, description, hextx; + std::string name, description; CAmount supply; // changed from uin64_t to int64_t for this 'if ( supply <= 0 )' to work as expected const CPubKey nullpk; const CAmount txfee = 0; @@ -379,11 +379,15 @@ static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, UniValue rcreate = CreateTokenExt(remotepk.IsValid() ? remotepk : nullpk, txfee, supply, name, description, vtokenData, 0, false); RETURN_IF_ERROR(CCerror); - hextx = ResultGetTx(rcreate); - if( hextx.size() > 0 ) - return MakeResultSuccess(hextx); - else - return MakeResultError("could not create token"); + if (remotepk.IsValid()) + return rcreate; + else { + std::string hextx = ResultGetTx(rcreate); + if( hextx.size() > 0 ) + return MakeResultSuccess(hextx); + else + return MakeResultError("could not create token"); + } } UniValue tokencreate(const UniValue& params, bool fHelp, const CPubKey& remotepk) From d41ea4e5c40fe283ea6474130933b251ab4b30e0 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 7 Oct 2021 15:47:09 +0500 Subject: [PATCH 164/348] added new CCLTVID dest type for CLTV opcode in scriptPubKey (from Verus codebase) --- src/base58.cpp | 19 +++++++++++++ src/base58.h | 2 ++ src/key_io.cpp | 8 ++++++ src/script/standard.h | 64 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index 58e3fbb3847..985887303a4 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -231,6 +231,7 @@ class CBitcoinAddressVisitor : public boost::static_visitor bool operator()(const CPubKey& key) const { return addr->Set(key); } bool operator()(const CScriptID& id) const { return addr->Set(id); } bool operator()(const CCryptoConditionID& id) const { return addr->Set(id); } + bool operator()(const CCLTVID& id) const { return addr->Set(id); } bool operator()(const CNoDestination& no) const { return false; } }; @@ -261,6 +262,15 @@ bool CBitcoinAddress::Set(const CCryptoConditionID& id) return true; } +bool CBitcoinAddress::Set(const CCLTVID& id) +{ + if (id.which() == TX_PUBKEY) + Set(id.GetPubKey()); + else + Set(id.GetKeyID()); + return true; +} + bool CBitcoinAddress::Set(const CTxDestination& dest) { return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); @@ -375,6 +385,15 @@ bool CCustomBitcoinAddress::Set(const CCryptoConditionID& id) return true; } +bool CCustomBitcoinAddress::Set(const CCLTVID& id) +{ + if (id.which() == TX_PUBKEY) + Set(id.GetPubKey()); + else + Set(id.GetKeyID()); + return true; +} + bool CCustomBitcoinAddress::Set(const CTxDestination& dest) { return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); diff --git a/src/base58.h b/src/base58.h index a86b689d0e7..ee6d026f86b 100644 --- a/src/base58.h +++ b/src/base58.h @@ -134,6 +134,7 @@ class CBitcoinAddress : public CBase58Data { virtual bool Set(const CPubKey &key); virtual bool Set(const CScriptID &id); virtual bool Set(const CCryptoConditionID &id); + virtual bool Set(const CCLTVID& id); bool Set(const CTxDestination &dest); bool IsValid() const; bool IsValid(const CChainParams ¶ms) const; @@ -160,6 +161,7 @@ class CCustomBitcoinAddress : public CBitcoinAddress { bool Set(const CScriptID &id); bool Set(const CTxDestination &dest); bool Set(const CCryptoConditionID &id); + bool Set(const CCLTVID& id); bool IsValid() const; CCustomBitcoinAddress() {} diff --git a/src/key_io.cpp b/src/key_io.cpp index 7c515add247..c51684e7ac6 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -56,6 +56,14 @@ class DestinationEncoder : public boost::static_visitor return EncodeBase58Check(data); } + std::string operator()(const CCLTVID& id) const + { + if (id.which() == TX_PUBKEY) + return operator()(id.GetPubKey()); + else + return operator()(id.GetKeyID()); + } + std::string operator()(const CNoDestination& no) const { return {}; } }; diff --git a/src/script/standard.h b/src/script/standard.h index d9c8f512d11..6a48ad509d5 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -85,11 +85,64 @@ enum txnouttype TX_PUBKEY, TX_PUBKEYHASH, TX_SCRIPTHASH, - TX_MULTISIG, TX_CRYPTOCONDITION, + TX_CLTV, + // ^^ enum order matches types' order in CTxDestination + TX_MULTISIG, TX_NULL_DATA, }; +class CCLTVID +{ +private: + int64_t unlockTime; + txnouttype whichType; + union { + CKeyID keyid; + CPubKey pubkey; + }; + bool unlocked; +public: + CCLTVID(const CKeyID &id, int64_t ut) : keyid(id), unlockTime(ut), whichType(TX_PUBKEYHASH), unlocked(false) {} + CCLTVID(const CPubKey &pk, int64_t ut) : pubkey(pk), unlockTime(ut), whichType(TX_PUBKEY), unlocked(false) {} + + txnouttype which() const { return whichType; } + int64_t GetUnlockTime() const { return unlockTime; } + CKeyID GetKeyID() const { return keyid; } + CPubKey GetPubKey() const { return pubkey; } + CKeyID GetID() const { + if (whichType == TX_PUBKEYHASH) + return keyid; + else + return pubkey.GetID(); + } + void SetUnlocked() { unlocked = true; } + bool IsUnlocked() const { return unlocked; } + friend bool operator==(const CCLTVID &a, const CCLTVID &b) { + if (a.whichType == TX_PUBKEY && b.whichType == TX_PUBKEY) + return a.pubkey == b.pubkey && a.unlocked == b.unlocked; + else + return a.GetID() == b.GetID() && a.unlocked == b.unlocked; + } + friend bool operator<(const CCLTVID &a, const CCLTVID &b) { + if (a.whichType == TX_PUBKEY && b.whichType == TX_PUBKEY) { + if (a.pubkey < b.pubkey) + return true; + else if (a.pubkey == b.pubkey) + return a.unlocked < b.unlocked; + return false; + } + else { + if (a.GetID() < b.GetID()) + return true; + else if (a.GetID() == b.GetID()) + return a.unlocked < b.unlocked; + return false; + } + } +}; + + class CNoDestination { public: friend bool operator==(const CNoDestination &a, const CNoDestination &b) { return true; } @@ -101,15 +154,19 @@ class CNoDestination { * * CNoDestination: no destination set * * CKeyID: TX_PUBKEYHASH destination * * CScriptID: TX_SCRIPTHASH destination + * Komodo added: + * * CCryptoConditionID: TX_CRYPTOCONDITION destination + * * CCLTVID TX_CLTV destination * A CTxDestination is the internal data type encoded in a bitcoin address */ -typedef boost::variant CTxDestination; +typedef boost::variant CTxDestination; +// Verus-format for additional data added after cryptocondition as OP_DROP in the spk class COptCCParams { public: static const uint8_t VERSION_1 = 1; - static const uint8_t VERSION_2 = 2; // i needede to add version2 to allow adding pubkeys (as we violated the OptCCParams format by not adding pubkeys in MakeCCVout1,...) + static const uint8_t VERSION_2 = 2; // i needed to add version2 to allow adding pubkeys (as we violated the OptCCParams format by not adding pubkeys in MakeCCVout1,...) static bool isMyVersion(uint8_t version) { return version >= 1 && version <= 2; } uint8_t version; uint8_t evalCode; @@ -176,6 +233,7 @@ bool IsValidDestination(const CTxDestination& dest); const char* GetTxnOutputType(txnouttype t); bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet); +bool SolverCLTV(const CScript& _scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet, bool &isCltv); int ScriptSigArgsExpected(txnouttype t, const std::vector >& vSolutions); bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType); bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet, bool returnPubKey=false); From 35900f54ca6a847f43ea85a42b05f83b53bc0897 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 7 Oct 2021 15:49:08 +0500 Subject: [PATCH 165/348] added SolverCLTV(); func IsStandard() allows CLTV txns in mempool; ExtractDestination(s) returns CCLTVID too; sign.cpp refactored to use new SolverCLTV() --- src/main.cpp | 5 ++- src/script/sign.cpp | 21 ++-------- src/script/standard.cpp | 90 ++++++++++++++++++++++++++++++++--------- 3 files changed, 79 insertions(+), 37 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 7e7bd0051d2..7d114992d6e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1044,8 +1044,11 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, const CScript& prevScript = prev.scriptPubKey; //printf("Previous script: %s\n", prevScript.ToString().c_str()); - if (!Solver(prevScript, whichType, vSolutions)) + bool iscltv; + // allow CLTV inputs: + if (!SolverCLTV(prevScript, whichType, vSolutions, iscltv)) return false; + int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions); if (nArgsExpected < 0) return false; diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 4cda8a61ad4..70b303362a4 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -347,25 +347,10 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP ret.clear(); vector vSolutions; + bool iscltv; - if (!Solver(scriptPubKey, whichTypeRet, vSolutions)) - { - // if this is a CLTV script, solve for the destination after CLTV - if (scriptPubKey.IsCheckLockTimeVerify()) - { - uint8_t pushOp = scriptPubKey[0]; - uint32_t scriptStart = pushOp + 3; - - // check post CLTV script - CScript postfix = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end()); - - // check again with only postfix subscript - if (!Solver(postfix, whichTypeRet, vSolutions)) - return false; - } - else - return false; - } + if (!SolverCLTV(scriptPubKey, whichTypeRet, vSolutions, iscltv)) + return false; CKeyID keyID; switch (whichTypeRet) diff --git a/src/script/standard.cpp b/src/script/standard.cpp index f240dde79d8..6f9b6544ca3 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -158,6 +158,7 @@ const char* GetTxnOutputType(txnouttype t) case TX_MULTISIG: return "multisig"; case TX_NULL_DATA: return "nulldata"; case TX_CRYPTOCONDITION: return "cryptocondition"; + case TX_CLTV: return "timelocked"; default: return "invalid"; } return NULL; @@ -213,7 +214,7 @@ static bool MatchMultisig(const CScript& script, unsigned int& required, std::ve return (it + 1 == script.end()); } - +// decodes scriptPubKey and returns the addressable part from it bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet) { vSolutionsRet.clear(); @@ -289,6 +290,25 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet, bool &isCltv) +{ + CScript scriptPubKey = _scriptPubKey; + isCltv = false; + if (scriptPubKey.IsCheckLockTimeVerify()) + { + uint8_t pushOp = scriptPubKey[0]; + uint32_t scriptStart = pushOp + 3; + + // continue with post CLTV script + scriptPubKey = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end()); + isCltv = true; + } + return Solver(scriptPubKey, typeRet, vSolutionsRet); +} + int ScriptSigArgsExpected(txnouttype t, const std::vector >& vSolutions) { switch (t) @@ -312,10 +332,13 @@ int ScriptSigArgsExpected(txnouttype t, const std::vector vSolutions; - if (!Solver(scriptPubKey, whichType, vSolutions)) + CScript scriptPubKey = _scriptPubKey; + + bool iscltv = false; + if (!SolverCLTV(scriptPubKey, whichType, vSolutions, iscltv)) { //int32_t i; uint8_t *ptr = (uint8_t *)scriptPubKey.data(); //for (i=0; i scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end()); - } - - if (!Solver(scriptPubKey, whichType, vSolutions)) + bool iscltv = false; + if (!SolverCLTV(scriptPubKey, whichType, vSolutions, iscltv)) return false; + int64_t unlockTime = 0LL; + if (iscltv) + scriptPubKey.IsCheckLockTimeVerify(&unlockTime); + if (whichType == TX_PUBKEY) { CPubKey pubKey(vSolutions[0]); @@ -365,27 +384,41 @@ bool ExtractDestination(const CScript& _scriptPubKey, CTxDestination& addressRet return false; } + CTxDestination dest; if (returnPubKey) - addressRet = pubKey; + dest = pubKey; + else + dest = pubKey.GetID(); + + if (iscltv) + addressRet = CCLTVID(pubKey, unlockTime); else - addressRet = pubKey.GetID(); + addressRet = dest; return true; } else if (whichType == TX_PUBKEYHASH) { - addressRet = CKeyID(uint160(vSolutions[0])); + CTxDestination dest = CKeyID(uint160(vSolutions[0])); + if (iscltv) + addressRet = CCLTVID(boost::get(dest), unlockTime); + else + addressRet = dest; return true; } else if (whichType == TX_SCRIPTHASH) { addressRet = CScriptID(uint160(vSolutions[0])); + // we do not create CCLTVID for P2SH spks as it does not make sense + // however we do not fail it either to provide compatibility with the pre-CCLTVID code (if someone created such spks by chance) return true; } else if (IsCryptoConditionsEnabled() != 0 && whichType == TX_CRYPTOCONDITION) { addressRet = CCryptoConditionID(uint160(vSolutions[0])); + // we do not create CCLTVID for CC spks as it does not make sense (any timelocks should be inside the cc code) + // however we do not fail it either to provide compatibility with the pre-CCLTVID code return true; } // Multisig txns have more than one address... @@ -399,7 +432,8 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto vector vSolutions; // if this is a CLTV script, get the destinations after CLTV - if (scriptPubKey.IsCheckLockTimeVerify()) + int64_t unlockTime; + if (scriptPubKey.IsCheckLockTimeVerify(&unlockTime)) { uint8_t pushOp = scriptPubKey[0]; uint32_t scriptStart = pushOp + 3; @@ -408,7 +442,18 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto CScript postfix = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end()); // check again with only postfix subscript - return(ExtractDestinations(postfix, typeRet, addressRet, nRequiredRet)); + vector dests; + if (ExtractDestinations(postfix, typeRet, dests, nRequiredRet)) { + for (auto const &dest : dests) { + if (dest.which() == TX_PUBKEY) { + CPubKey pubKey(boost::get(dest)); + addressRet.push_back(CCLTVID(pubKey, unlockTime)); // add destinations as CLTV wrappers with unlock time + } + } + if (addressRet.empty()) + return false; + return true; + } } if (!Solver(scriptPubKey, typeRet, vSolutions)) @@ -504,6 +549,15 @@ class CScriptVisitor : public boost::static_visitor script->clear(); return false; // can't create a cc that simple } + // create a CLTV script: + bool operator()(const CCLTVID &dest) const { + script->clear(); + if (dest.which() == TX_PUBKEY) + *script << dest.GetUnlockTime() << OP_CHECKLOCKTIMEVERIFY << OP_DROP << ToByteVector(dest.GetPubKey()) << OP_CHECKSIG; + else + *script << dest.GetUnlockTime() << OP_CHECKLOCKTIMEVERIFY << OP_DROP << OP_DUP << OP_HASH160 << ToByteVector(dest.GetKeyID()) << OP_EQUALVERIFY << OP_CHECKSIG; + return true; + } }; } From 50e796aa93c35075c6c4a29fb11de0416cf46225 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 7 Oct 2021 15:52:10 +0500 Subject: [PATCH 166/348] added komodo_next_tx_locktime() for reuse --- src/komodo_defs.h | 2 ++ src/komodo_utils.h | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index ef5735f8ef8..60ce6c291c0 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -759,4 +759,6 @@ int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig) uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); uint64_t _komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +uint32_t komodo_next_tx_locktime(); + #endif diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 6b2b70be529..6527eeab11b 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -2644,3 +2644,12 @@ bool komodo_txnotarizedconfirmed(uint256 txid, int32_t minconfirms) return (true); return (false); } + +uint32_t komodo_next_tx_locktime() +{ + AssertLockHeld(cs_main); + if (!komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime)) + return (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now + else + return (uint32_t)chainActive.Tip()->GetMedianTimePast(); +} \ No newline at end of file From 86d0f7d57b94f857949715709569c4c6409275c9 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 7 Oct 2021 15:52:30 +0500 Subject: [PATCH 167/348] wallet and listaddressgroupings rpc and TotalPubkeyNormalInputs() are extended for use CCLTVID destinations --- src/cc/CCutils.cpp | 3 +- src/rpc/misc.cpp | 9 ++++- src/wallet/rpcwallet.cpp | 62 ++++++++++++++++++++--------- src/wallet/wallet.cpp | 77 ++++++++++++++++++++++++++---------- src/wallet/wallet.h | 30 ++++++++++++-- src/wallet/wallet_ismine.cpp | 15 +++---- 6 files changed, 141 insertions(+), 55 deletions(-) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index aa28ef33e17..55ec2302222 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -877,8 +877,9 @@ CAmount TotalPubkeyNormalInputs(Eval *eval, const CTransaction &tx, const CPubKe typedef std::vector valtype; std::vector vSolutions; txnouttype whichType; + bool iscltv; - if (Solver(vintx.vout[vin.prevout.n].scriptPubKey, whichType, vSolutions)) { + if (SolverCLTV(vintx.vout[vin.prevout.n].scriptPubKey, whichType, vSolutions, iscltv)) { switch (whichType) { case TX_PUBKEY: if (pubkey == CPubKey(vSolutions[0])) // is my input? diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index e8b09089bb3..1e4ebb058a1 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -390,6 +390,13 @@ class DescribeAddressVisitor : public boost::static_visitor return obj; } + UniValue operator()(const CCLTVID &cltvID) const { + if (cltvID.which() == TX_PUBKEY) + return this->operator()(cltvID.GetPubKey()); + else + return this->operator()(cltvID.GetKeyID()); + } + UniValue operator()(const CCryptoConditionID &ccID) const { return UniValue(UniValue::VOBJ); } // cryptoconditions are not recognised in the wallet yet }; #endif @@ -858,7 +865,7 @@ bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &addr } else if (type == 1) { address = CBitcoinAddress(CKeyID(hash)).ToString(); } else if (type == 3) { - address = CBitcoinAddress(CKeyID(hash)).ToString(); + address = CBitcoinAddress(CCryptoConditionID(hash)).ToString(); } else { return false; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 14eb173709d..2ff4b331a32 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -463,7 +463,7 @@ UniValue getaddressesbyaccount(const UniValue& params, bool fHelp, const CPubKey return ret; } -static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew,uint8_t *opretbuf,int32_t opretlen,long int opretValue) +static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew,uint8_t *opretbuf,int32_t opretlen,long int opretValue, int64_t unlockTime = 0LL) { CAmount curBalance = pwalletMain->GetBalance(); @@ -474,8 +474,15 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr if (nValue > curBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds"); - // Parse Zcash address - CScript scriptPubKey = GetScriptForDestination(address); + // make scriptPubKey for destination + CScriptExt scriptPubKey; + if (unlockTime == 0) + scriptPubKey = GetScriptForDestination(address); + else { + CKeyID keyid; + if (CBitcoinAddress(address).GetKeyID(keyid)) + scriptPubKey.TimeLockSpend(keyid, unlockTime); + } if (scriptPubKey.empty()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid destination"); @@ -511,17 +518,17 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) { - uint8_t opretbuf[IGUANA_MAXSCRIPTSIZE],opretscript[IGUANA_MAXSCRIPTSIZE],*opret=0; char *oprethexstr; int32_t len,opretlen = 0; + uint8_t opretbuf[IGUANA_MAXSCRIPTSIZE],opretscript[IGUANA_MAXSCRIPTSIZE],*opret=0; char *oprethexstr; int32_t len, opretlen = 0; if (!EnsureWalletIsAvailable(fHelp)) return NullUniValue; - if (fHelp || params.size() < 2 || params.size() > 6) + if (fHelp || params.size() < 2 || params.size() > 7) throw runtime_error( - "sendtoaddress \"" + strprintf("%s",komodo_chainname()) + "_address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n" + "sendtoaddress \"" + strprintf("%s",komodo_chainname()) + "_address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount unlocktime )\n" "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n" + HelpRequiringPassphrase() + "\nArguments:\n" - "1. \"" + strprintf("%s",komodo_chainname()) + "_address\" (string, required) The " + strprintf("%s",komodo_chainname()) + " address to send to.\n" + "1. \"" + strprintf("%s", komodo_chainname()) + "_address\" (string, required) The " + strprintf("%s",komodo_chainname()) + " address to send to.\n" "2. \"amount\" (numeric, required) The amount in " + strprintf("%s",komodo_chainname()) + " to send. eg 0.1\n" "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n" " This is not part of the transaction, just kept in your wallet.\n" @@ -529,13 +536,16 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) " to which you're sending the transaction. This is not part of the \n" " transaction, just kept in your wallet.\n" "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n" - " The recipient will receive less " + strprintf("%s",komodo_chainname()) + " than you enter in the amount field.\n6. oprethexstr" + " The recipient will receive less " + strprintf("%s",komodo_chainname()) + " than you enter in the amount field.\n" + "6. oprethexstr\n" + "7. unlocktime (numeric, optional) timestamp or blockheight when the sent funds will be unlocked by CLTV opcode\n" "\nResult:\n" "\"transactionid\" (string) The transaction id.\n" "\nExamples:\n" + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1") + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"donation\" \"seans outpost\"") + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"\" \"\" true") + + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"donation\" \"seans outpost\" false \"\" 2595973") + HelpExampleRpc("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.1, \"donation\", \"seans outpost\"") ); @@ -568,20 +578,27 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) bool fSubtractFeeFromAmount = false; if (params.size() > 4) fSubtractFeeFromAmount = params[4].get_bool(); - if (params.size() > 5) - { - oprethexstr = (char *)params[5].get_str().c_str(); - if ( (len= is_hexstr(oprethexstr,0)) > 1 && len <= sizeof(opretbuf)*2 ) - { + if (params.size() > 5) { + oprethexstr = (char*)params[5].get_str().c_str(); + if ((len = is_hexstr(oprethexstr, 0)) > 1 && len <= sizeof(opretbuf) * 2) { len >>= 1; - decode_hex(opretbuf,len,oprethexstr); - opretlen = komodo_opreturnscript(opretscript,0x00,opretbuf,len); + decode_hex(opretbuf, len, oprethexstr); + opretlen = komodo_opreturnscript(opretscript, 0x00, opretbuf, len); opret = opretscript; - } else opretlen = 0; + } else + opretlen = 0; } + int64_t unlockTime = 0LL; + if (params.size() > 6) { + unlockTime = atoll(params[6].get_str().c_str()); + if (unlockTime < 0LL) + throw JSONRPCError(RPC_TYPE_ERROR, "invalid unlock time"); + } + + EnsureWalletIsUnlocked(); - SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx,opret,opretlen,0); + SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx, opret, opretlen, 0, unlockTime); return wtx.GetHash().GetHex(); } @@ -839,14 +856,21 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp, const CPubKey& LOCK2(cs_main, pwalletMain->cs_wallet); + int64_t txLockTime = komodo_next_tx_locktime(); UniValue jsonGroupings(UniValue::VARR); - std::map balances = pwalletMain->GetAddressBalances(); - for (const std::set& grouping : pwalletMain->GetAddressGroupings()) { + std::map balances = pwalletMain->GetAddressBalances(txLockTime); + for (const std::set& grouping : pwalletMain->GetAddressGroupings(txLockTime)) { UniValue jsonGrouping(UniValue::VARR); for (const CTxDestination& address : grouping) { UniValue addressInfo(UniValue::VARR); addressInfo.push_back(EncodeDestination(address)); + if (address.which() == TX_CLTV) { + if (boost::get(address).IsUnlocked()) + addressInfo.push_back("CLTV-spendable"); + else + addressInfo.push_back("CLTV-locked"); + } addressInfo.push_back(ValueFromAmount(balances[address])); { if (pwalletMain->mapAddressBook.find(address) != pwalletMain->mapAddressBook.end()) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b98cdac42b8..19d4d933388 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -470,7 +470,7 @@ bool CWallet::LoadCScript(const CScript& redeemScript) { std::string strAddr = EncodeDestination(CScriptID(redeemScript)); LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n", - __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr); + __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr.c_str()); return true; } @@ -1795,7 +1795,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl { fIsFromWhiteList = true; // std::cerr << __FUNCTION__ << " tx." << tx.GetHash().ToString() << " passed wallet filter! whitelistaddress." << EncodeDestination(dest) << std::endl; - LogPrintf("tx.%s passed wallet filter! whitelistaddress.%s\n", tx.GetHash().ToString(),EncodeDestination(dest)); + LogPrintf("tx.%s passed wallet filter! whitelistaddress.%s\n", tx.GetHash().ToString().c_str(),EncodeDestination(dest).c_str()); break; } } @@ -1804,7 +1804,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl if (!fIsFromWhiteList) { // std::cerr << __FUNCTION__ << " tx." << tx.GetHash().ToString() << " is NOT passed wallet filter!" << std::endl; - LogPrintf("tx.%s is NOT passed wallet filter!\n", tx.GetHash().ToString()); + LogPrintf("tx.%s is NOT passed wallet filter!\n", tx.GetHash().ToString().c_str()); return false; } } @@ -2211,9 +2211,10 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) { vector vSolutions; txnouttype whichType; - const CScriptExt scriptPubKey = CScriptExt(tx.vout[voutNum].scriptPubKey); + CScriptExt scriptPubKey = CScriptExt(tx.vout[voutNum].scriptPubKey); + bool iscltv; - if (!Solver(scriptPubKey, whichType, vSolutions)) { + if (!SolverCLTV(scriptPubKey, whichType, vSolutions, iscltv)) { if (this->HaveWatchOnly(scriptPubKey)) return ISMINE_WATCH_ONLY; return ISMINE_NO; @@ -2230,6 +2231,8 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) case TX_NULL_DATA: break; + // Note: this is unusable in komodo + // Unlike in Verus the wallet in Komodo can't understand cryptoconditions spks (only appropriate cc modules understand their spks) case TX_CRYPTOCONDITION: // for now, default is that the first value returned will be the script, subsequent values will be // pubkeys. if we have the first pub key in our wallet, we consider this spendable @@ -2257,7 +2260,7 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) scriptID = CScriptID(uint160(vSolutions[0])); if (this->GetCScript(scriptID, subscript)) { - // if this is a CLTV, handle it differently + // if this is a P2SH/CLTV, handle it differently if (subscript.IsCheckLockTimeVerify()) { return (::IsMine(*this, subscript)); @@ -2273,6 +2276,7 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) tx.vout[voutNext].scriptPubKey.size() > 7 && tx.vout[voutNext].scriptPubKey[0] == OP_RETURN) { + // Verus specific: // get the opret script from next vout, verify that the front is CLTV and hash matches // if so, remove it and use the solver opcodetype op; @@ -3633,7 +3637,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int return true; } -bool CWallet::SelectCoins(const CAmount& nTargetValue, set >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl* coinControl) const +bool CWallet::SelectCoins(const CAmount& nTargetValue, set >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl* coinControl, int64_t txLockTime) const { // Output parameter fOnlyCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos. uint64_t tmp; int32_t retval; @@ -3721,6 +3725,18 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set::iterator it = vCoins.begin(); it != vCoins.end();) + { + int64_t nLockTime; + if (it->tx->vout[it->i].scriptPubKey.IsCheckLockTimeVerify(&nLockTime) && !CheckLockTime(nLockTime, txLockTime)) + it = vCoins.erase(it); + else + ++it; + } + + retval = false; if ( nTargetValue <= nValueFromPresetInputs ) retval = true; @@ -3809,10 +3825,11 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight); //if ((uint32_t)chainActive.LastTip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) - if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) + /*if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) txNew.nLockTime = (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now else - txNew.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); + txNew.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast();*/ + txNew.nLockTime = komodo_next_tx_locktime(); // Activates after Overwinter network upgrade if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { @@ -3904,7 +3921,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt bool fOnlyCoinbaseCoins = false; bool fNeedCoinbaseCoins = false; interest2 = 0; - if (!SelectCoins(nTotalValue, setCoins, nValueIn, fOnlyCoinbaseCoins, fNeedCoinbaseCoins, coinControl)) + if (!SelectCoins(nTotalValue, setCoins, nValueIn, fOnlyCoinbaseCoins, fNeedCoinbaseCoins, coinControl, txNew.nLockTime)) { if (fOnlyCoinbaseCoins && Params().GetConsensus().fCoinbaseMustBeProtected) { strFailReason = _("Coinbase funds can only be sent to a zaddr"); @@ -4181,7 +4198,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) // Broadcast if (!wtxNew.AcceptToMemoryPool(false)) { - fprintf(stderr,"commit failed\n"); + // fprintf(stderr,"commit failed\n"); // This must not fail. The transaction has already been signed and recorded. LogPrintf("CommitTransaction(): Error: Transaction not valid\n"); return false; @@ -4475,7 +4492,7 @@ int64_t CWallet::GetOldestKeyPoolTime() return keypool.nTime; } -std::map CWallet::GetAddressBalances() +std::map CWallet::GetAddressBalances(int64_t txLockTime) { map balances; @@ -4502,6 +4519,9 @@ std::map CWallet::GetAddressBalances() continue; if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr)) continue; + // if this is CLTV then set if it is already unlocked for spending for the next txLockTime: + if (addr.which() == TX_CLTV) + SetTimeUnlocked(addr, txLockTime); CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue; @@ -4515,7 +4535,7 @@ std::map CWallet::GetAddressBalances() return balances; } -set< set > CWallet::GetAddressGroupings() +set< set > CWallet::GetAddressGroupings(int64_t txLockTime) { AssertLockHeld(cs_wallet); // mapWallet set< set > groupings; @@ -4536,6 +4556,8 @@ set< set > CWallet::GetAddressGroupings() continue; if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address)) continue; + if (address.which() == TX_CLTV) + SetTimeUnlocked(address, txLockTime); grouping.insert(address); any_mine = true; } @@ -4543,14 +4565,16 @@ set< set > CWallet::GetAddressGroupings() // group change with input addresses if (any_mine) { - BOOST_FOREACH(CTxOut txout, pcoin->vout) - if (IsChange(txout)) - { - CTxDestination txoutAddr; - if(!ExtractDestination(txout.scriptPubKey, txoutAddr)) - continue; - grouping.insert(txoutAddr); - } + BOOST_FOREACH (CTxOut txout, pcoin->vout) + if (IsChange(txout)) { + CTxDestination txoutAddr; + if (!ExtractDestination(txout.scriptPubKey, txoutAddr)) + continue; + // if this is CLTV then set if it is already unlocked for spending for the next txLockTime: + if (txoutAddr.which() == TX_CLTV) + SetTimeUnlocked(txoutAddr, txLockTime); + grouping.insert(txoutAddr); + } } if (grouping.size() > 0) { @@ -4566,6 +4590,11 @@ set< set > CWallet::GetAddressGroupings() CTxDestination address; if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address)) continue; + + // if this is CLTV then set if it is already unlocked for spending for the next txLockTime: + if (address.which() == TX_CLTV) + SetTimeUnlocked(address, txLockTime); + grouping.insert(address); groupings.insert(grouping); grouping.clear(); @@ -4825,6 +4854,12 @@ class CAffectedKeysVisitor : public boost::static_visitor { Process(script); } + void operator()(const CCLTVID &cltv) { + CKeyID keyId = cltv.GetID(); + if (keystore.HaveKey(keyId)) + vKeys.push_back(keyId); + } + void operator()(const CCryptoConditionID &none) {} // no cc in the wallet void operator()(const CNoDestination &none) {} diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 718376429fe..36561a34a28 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -748,7 +748,7 @@ class CAccountingEntry class CWallet : public CCryptoKeyStore, public CValidationInterface { private: - bool SelectCoins(const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl *coinControl = NULL) const; + bool SelectCoins(const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl *coinControl = NULL, int64_t txLockTime = 0LL) const; CWalletDB *pwalletdbEncryption; @@ -1171,8 +1171,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface int64_t GetOldestKeyPoolTime(); void GetAllReserveKeys(std::set& setAddress) const; - std::set< std::set > GetAddressGroupings(); - std::map GetAddressBalances(); + std::set< std::set > GetAddressGroupings(int64_t txUnlockTime); + std::map GetAddressBalances(int64_t txUnlockTime); std::set GetAccountAddresses(const std::string& strAccount) const; @@ -1518,4 +1518,28 @@ class AddSpendingKeyToWallet : public boost::static_visitor= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD) + )) + return false; + if (nLockTime > txLockTime) + { + return false; + } + return true; +} + +// sets unlocked state in the dest +inline void SetTimeUnlocked(CTxDestination &dest, int64_t txLockTime) +{ + CCLTVID& cltv = boost::get(dest); + if (CheckLockTime(cltv.GetUnlockTime(), txLockTime)) + cltv.SetUnlocked(); +} + + #endif // BITCOIN_WALLET_WALLET_H diff --git a/src/wallet/wallet_ismine.cpp b/src/wallet/wallet_ismine.cpp index 55b5e31defd..04df2e21996 100644 --- a/src/wallet/wallet_ismine.cpp +++ b/src/wallet/wallet_ismine.cpp @@ -26,6 +26,9 @@ #include "script/standard.h" #include "cc/eval.h" +#include "chain.h" +extern CChain chainActive; + #include using namespace std; @@ -68,17 +71,9 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& _scriptPubKey, vector vSolutions; txnouttype whichType; CScript scriptPubKey = _scriptPubKey; - - if (scriptPubKey.IsCheckLockTimeVerify()) - { - uint8_t pushOp = scriptPubKey[0]; - uint32_t scriptStart = pushOp + 3; - - // continue with post CLTV script - scriptPubKey = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end()); - } + bool iscltv; - if (!Solver(scriptPubKey, whichType, vSolutions)) { + if (!SolverCLTV(scriptPubKey, whichType, vSolutions, iscltv)) { if (keystore.HaveWatchOnly(scriptPubKey)) return ISMINE_WATCH_ONLY; return ISMINE_NO; From 91b1177c5c1af3b403dc4823397b4845cbcb8555 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 7 Oct 2021 15:52:58 +0500 Subject: [PATCH 168/348] test to decode TX_CLTV --- src/test-komodo/test_script_standard_tests.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test-komodo/test_script_standard_tests.cpp b/src/test-komodo/test_script_standard_tests.cpp index ea08e017c0f..53447f7f32e 100644 --- a/src/test-komodo/test_script_standard_tests.cpp +++ b/src/test-komodo/test_script_standard_tests.cpp @@ -38,6 +38,9 @@ namespace TestScriptStandartTests { case TX_CRYPTOCONDITION: res = "TX_CRYPTOCONDITION"; break; + case TX_CLTV: + res = "TX_CLTV"; + break; default: res = "UNKNOWN"; } From ac693c7abd159a4099577345d6202cea31c8bc3f Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Oct 2021 14:32:02 +0500 Subject: [PATCH 169/348] restore LogPrintf ToString --- src/wallet/wallet.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 19d4d933388..182a1b56876 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -470,7 +470,7 @@ bool CWallet::LoadCScript(const CScript& redeemScript) { std::string strAddr = EncodeDestination(CScriptID(redeemScript)); LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n", - __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr.c_str()); + __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr); return true; } @@ -1795,7 +1795,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl { fIsFromWhiteList = true; // std::cerr << __FUNCTION__ << " tx." << tx.GetHash().ToString() << " passed wallet filter! whitelistaddress." << EncodeDestination(dest) << std::endl; - LogPrintf("tx.%s passed wallet filter! whitelistaddress.%s\n", tx.GetHash().ToString().c_str(),EncodeDestination(dest).c_str()); + LogPrintf("tx.%s passed wallet filter! whitelistaddress.%s\n", tx.GetHash().ToString(),EncodeDestination(dest)); break; } } @@ -1804,7 +1804,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl if (!fIsFromWhiteList) { // std::cerr << __FUNCTION__ << " tx." << tx.GetHash().ToString() << " is NOT passed wallet filter!" << std::endl; - LogPrintf("tx.%s is NOT passed wallet filter!\n", tx.GetHash().ToString().c_str()); + LogPrintf("tx.%s is NOT passed wallet filter!\n", tx.GetHash().ToString()); return false; } } @@ -2211,7 +2211,7 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) { vector vSolutions; txnouttype whichType; - CScriptExt scriptPubKey = CScriptExt(tx.vout[voutNum].scriptPubKey); + const CScriptExt scriptPubKey = CScriptExt(tx.vout[voutNum].scriptPubKey); bool iscltv; if (!SolverCLTV(scriptPubKey, whichType, vSolutions, iscltv)) { From fe089f0db2e09f4b5d765c541ab5fe1d03abfaa0 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 18 Oct 2021 13:26:06 +0500 Subject: [PATCH 170/348] refactored SetCCunspents coinaddr copy; del extra comments; added coinaddr not null check --- src/cc/CCtx.cpp | 61 ++++--------------------------------------------- 1 file changed, 5 insertions(+), 56 deletions(-) diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 16077cc19e9..d4e97836f3c 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -707,6 +707,8 @@ UniValue AddSignatureCCTxV2(vuint8_t & vtx, const UniValue &jsonParams) // set cc or normal unspents from mempool static void AddCCunspentsInMempool(std::vector > &unspentOutputs, char *destaddr, bool isCC) { + if (!destaddr) return; + uint160 hashBytes; std::string addrstr(destaddr); CBitcoinAddress address(addrstr); @@ -722,44 +724,6 @@ static void AddCCunspentsInMempool(std::vector > addresses; addresses.push_back(std::make_pair(hashBytes, type)); mempool.getAddressIndex(addresses, memOutputs); - - //std::cerr << __func__ << " total memOutputs.size=" << memOutputs.size() << " hashBytes=" << hashBytes.GetHex() << " addrstr=" << addrstr << std::endl; - - // non indexed impl: - /* - for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi) { - const CTransaction& memtx = mi->GetTx(); - for (int32_t i = 0; i < memtx.vout.size(); i++) - { - uint256 dummytxid; - int32_t dummyvout; - if (!myIsutxo_spentinmempool(dummytxid, dummyvout, memtx.GetHash(), i)) - { - if (isCC && memtx.vout[i].scriptPubKey.IsPayToCryptoCondition() || !isCC && !memtx.vout[i].scriptPubKey.IsPayToCryptoCondition()) - { - char voutaddr[64]; - Getscriptaddress(voutaddr, memtx.vout[i].scriptPubKey); - if (strcmp(voutaddr, destaddr) == 0) - { - // create unspent output key value pair - CAddressUnspentKey key; - CAddressUnspentValue value; - - key.type = type; - key.hashBytes = hashBytes; - key.txhash = memtx.GetHash(); - key.index = i; - - value.satoshis = memtx.vout[i].nValue; - value.blockHeight = 0; - value.script = memtx.vout[i].scriptPubKey; - unspentOutputs.push_back(std::make_pair(key, value)); - } - } - } - } - } - */ // impl using mempool address and spent indexes for (std::vector >::iterator mo = memOutputs.begin(); mo != memOutputs.end(); mo ++) @@ -799,12 +763,9 @@ void SetCCunspents(std::vector >::iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); ) - { - uint256 dummytxid; - int32_t dummyvout; - if (myIsutxo_spentinmempool(dummytxid, dummyvout, it->first.txhash, it->first.index)) { - //std::cerr << __func__ << " erasing spent in mempool txid=" << it->first.txhash.GetHex() << " index=" << it->first.index << " spenttxid=" << dummytxid.GetHex() << std::endl; - it = unspentOutputs.erase(it); - } - else - it++; - } */ AddCCunspentsInMempool(unspentOutputs, coinaddr, ccflag); } From 52c02fe17a1cce5cd94b23dbafd066f23edc16a9 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 19 Oct 2021 13:50:49 +0500 Subject: [PATCH 171/348] added check for cltv coins to cc AddNormalInputs.. funcs; wallet's AvailableCoins now checks for cltv inputs --- src/cc/CCtx.cpp | 22 ++++++++++++++---- src/komodo_utils.h | 1 + src/script/standard.h | 49 +++++++++++++++++++++++++++++++++------- src/wallet/rpcwallet.cpp | 16 +++++++++---- src/wallet/wallet.cpp | 41 ++++++++++++++++----------------- src/wallet/wallet.h | 31 ++++++++----------------- 6 files changed, 100 insertions(+), 60 deletions(-) diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index d4e97836f3c..86fcf30614f 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -708,7 +708,7 @@ UniValue AddSignatureCCTxV2(vuint8_t & vtx, const UniValue &jsonParams) static void AddCCunspentsInMempool(std::vector > &unspentOutputs, char *destaddr, bool isCC) { if (!destaddr) return; - + uint160 hashBytes; std::string addrstr(destaddr); CBitcoinAddress address(addrstr); @@ -1124,7 +1124,8 @@ CAmount AddNormalinputsLocal(CMutableTransaction& mtx, CPubKey mypk, CAmount tot assert(pwalletMain != NULL); const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); - pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); + int64_t txLockTime = (int64_t)komodo_next_tx_locktime(); + pwalletMain->AvailableCoins(vecOutputs, false, NULL, true, txLockTime); utxos = (struct CC_utxo*)calloc(CC_MAXVINS, sizeof(*utxos)); if (maxinputs > CC_MAXVINS) maxinputs = CC_MAXVINS; @@ -1132,12 +1133,17 @@ CAmount AddNormalinputsLocal(CMutableTransaction& mtx, CPubKey mypk, CAmount tot threshold = total / maxinputs; else threshold = total;*/ + + + //TokelRemoveTimeLockedCoins(vecOutputs, txLockTime); + sum = 0LL; BOOST_FOREACH (const COutput& out, vecOutputs) { if (out.fSpendable != 0 && (vecOutputs.size() < maxinputs || out.tx->vout[out.i].nValue > 0LL)) { // threshold not used as may lead to insufficient inputs messages txid = out.tx->GetHash(); vout = out.i; - if (myGetTransaction(txid, tx, hashBlock) != false && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0) { + if (myGetTransaction(txid, tx, hashBlock) != false && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0) + { { LOCK(cs_main); if (CoinbaseGetBlocksToMaturity(tx, hashBlock) > 0) { @@ -1239,6 +1245,8 @@ CAmount AddNormalinputsRemote(CMutableTransaction& mtx, CPubKey mypk, CAmount to else SetCCunspentsWithMempool(unspentOutputs, coinaddr, false); + int64_t txLockTime = (int64_t)komodo_next_tx_locktime(); + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; @@ -1247,7 +1255,13 @@ CAmount AddNormalinputsRemote(CMutableTransaction& mtx, CPubKey mypk, CAmount to if (it->second.satoshis == 0) continue; //skip null outputs - if (myGetTransaction(txid, tx, hashBlock) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0) { + // if CLTV tx check it is spendable already + int64_t nLockTime; + if (it->second.script.IsCheckLockTimeVerify(&nLockTime) && !TokelCheckLockTimeHelper(nLockTime, txLockTime)) + continue; + + if (myGetTransaction(txid, tx, hashBlock) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0) + { { LOCK(cs_main); if (CoinbaseGetBlocksToMaturity(tx, hashBlock) > 0) { diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 6527eeab11b..23ed5b7df10 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -2645,6 +2645,7 @@ bool komodo_txnotarizedconfirmed(uint256 txid, int32_t minconfirms) return (false); } +// creates a nLockTime value for a new tx, with Dec 2019 hardfork check uint32_t komodo_next_tx_locktime() { AssertLockHeld(cs_main); diff --git a/src/script/standard.h b/src/script/standard.h index 6a48ad509d5..a9402f16451 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -120,24 +120,34 @@ class CCLTVID bool IsUnlocked() const { return unlocked; } friend bool operator==(const CCLTVID &a, const CCLTVID &b) { if (a.whichType == TX_PUBKEY && b.whichType == TX_PUBKEY) - return a.pubkey == b.pubkey && a.unlocked == b.unlocked; + return a.pubkey == b.pubkey && (a.unlocked == b.unlocked && !a.unlocked ? b.unlockTime == a.unlockTime : a.unlocked == b.unlocked); else - return a.GetID() == b.GetID() && a.unlocked == b.unlocked; + return a.GetID() == b.GetID() && (a.unlocked == b.unlocked && !a.unlocked ? b.unlockTime == a.unlockTime : a.unlocked == b.unlocked); } friend bool operator<(const CCLTVID &a, const CCLTVID &b) { if (a.whichType == TX_PUBKEY && b.whichType == TX_PUBKEY) { if (a.pubkey < b.pubkey) return true; - else if (a.pubkey == b.pubkey) - return a.unlocked < b.unlocked; - return false; + else if (a.pubkey == b.pubkey) { + if (a.unlocked == b.unlocked && !a.unlocked) + return a.unlockTime < b.unlockTime; + else + return a.unlocked < b.unlocked; + } + else + return false; } else { if (a.GetID() < b.GetID()) return true; - else if (a.GetID() == b.GetID()) - return a.unlocked < b.unlocked; - return false; + else if (a.GetID() == b.GetID()) { + if (a.unlocked == b.unlocked && !a.unlocked) + return a.unlockTime < b.unlockTime; + else + return a.unlocked < b.unlocked; + } + else + return false; } } }; @@ -242,4 +252,27 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std:: CScript GetScriptForDestination(const CTxDestination& dest); CScript GetScriptForMultisig(int nRequired, const std::vector& keys); +// helper to check if locktime from OP_CLTV opcode not more than tx lock time. Return true if nScriptLockTime <= txLockTime so the utxo spendable +inline bool TokelCheckLockTimeHelper(int64_t nScriptLockTime, int64_t txLockTime) +{ + if (!( + (txLockTime < LOCKTIME_THRESHOLD && nScriptLockTime < LOCKTIME_THRESHOLD) || + (txLockTime >= LOCKTIME_THRESHOLD && nScriptLockTime >= LOCKTIME_THRESHOLD) + )) + return false; + if (nScriptLockTime > txLockTime) + { + return false; + } + return true; +} + +// sets unlocked state in the CLTV dest +inline void TokelSetIfTimeUnlocked(CTxDestination &dest, int64_t txLockTime) +{ + CCLTVID& cltv = boost::get(dest); + if (TokelCheckLockTimeHelper(cltv.GetUnlockTime(), txLockTime)) + cltv.SetUnlocked(); +} + #endif // BITCOIN_SCRIPT_STANDARD_H diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2ff4b331a32..7779527421a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -866,10 +866,16 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp, const CPubKey& UniValue addressInfo(UniValue::VARR); addressInfo.push_back(EncodeDestination(address)); if (address.which() == TX_CLTV) { - if (boost::get(address).IsUnlocked()) + const CCLTVID &cltv = boost::get(address); + if (cltv.IsUnlocked()) addressInfo.push_back("CLTV-spendable"); - else + else { addressInfo.push_back("CLTV-locked"); + if (cltv.GetUnlockTime() > LOCKTIME_THRESHOLD) + addressInfo.push_back( strprintf("%lld (%s)", cltv.GetUnlockTime(), DateTimeStrFormat("%Y-%m-%d %H:%M:%S UTC", cltv.GetUnlockTime())) ); + else + addressInfo.push_back( strprintf("%lld", cltv.GetUnlockTime()) ); + } } addressInfo.push_back(ValueFromAmount(balances[address])); { @@ -5507,9 +5513,9 @@ UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& m } -#include "script/sign.h" -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); -extern std::string NOTARY_PUBKEY; +//#include "script/sign.h" +//int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); +//extern std::string NOTARY_PUBKEY; int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void *pTr) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 182a1b56876..461657af93e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3386,7 +3386,7 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const /** * populate vCoins with vector of available COutputs. */ -void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase) const +void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase, int64_t txLockTime) const { uint64_t interest,*ptr; vCoins.clear(); @@ -3462,7 +3462,15 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const (*ptr) = 0; } } - vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO)); + + bool bStillTimeLocked = false; + { + int64_t nLockTime; + if(pcoin->vout[i].scriptPubKey.IsCheckLockTimeVerify(&nLockTime)) + bStillTimeLocked = !TokelCheckLockTimeHelper(nLockTime, txLockTime); + } + + vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO && !bStillTimeLocked)); } } } @@ -3647,8 +3655,8 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set vCoinsNoCoinbase, vCoinsWithCoinbase; - AvailableCoins(vCoinsNoCoinbase, true, coinControl, false, false); - AvailableCoins(vCoinsWithCoinbase, true, coinControl, false, true); + AvailableCoins(vCoinsNoCoinbase, true, coinControl, false, false, txLockTime); + AvailableCoins(vCoinsWithCoinbase, true, coinControl, false, true, txLockTime); fOnlyCoinbaseCoinsRet = vCoinsNoCoinbase.size() == 0 && vCoinsWithCoinbase.size() > 0; // If coinbase utxos can only be sent to zaddrs, exclude any coinbase utxos from coin selection. @@ -3726,17 +3734,6 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set::iterator it = vCoins.begin(); it != vCoins.end();) - { - int64_t nLockTime; - if (it->tx->vout[it->i].scriptPubKey.IsCheckLockTimeVerify(&nLockTime) && !CheckLockTime(nLockTime, txLockTime)) - it = vCoins.erase(it); - else - ++it; - } - - retval = false; if ( nTargetValue <= nValueFromPresetInputs ) retval = true; @@ -4520,8 +4517,8 @@ std::map CWallet::GetAddressBalances(int64_t txLockTime if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr)) continue; // if this is CLTV then set if it is already unlocked for spending for the next txLockTime: - if (addr.which() == TX_CLTV) - SetTimeUnlocked(addr, txLockTime); + if (addr.which() == TX_CLTV) + TokelSetIfTimeUnlocked(addr, txLockTime); CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue; @@ -4557,7 +4554,7 @@ set< set > CWallet::GetAddressGroupings(int64_t txLockTime) if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address)) continue; if (address.which() == TX_CLTV) - SetTimeUnlocked(address, txLockTime); + TokelSetIfTimeUnlocked(address, txLockTime); grouping.insert(address); any_mine = true; } @@ -4571,8 +4568,8 @@ set< set > CWallet::GetAddressGroupings(int64_t txLockTime) if (!ExtractDestination(txout.scriptPubKey, txoutAddr)) continue; // if this is CLTV then set if it is already unlocked for spending for the next txLockTime: - if (txoutAddr.which() == TX_CLTV) - SetTimeUnlocked(txoutAddr, txLockTime); + if (txoutAddr.which() == TX_CLTV) + TokelSetIfTimeUnlocked(txoutAddr, txLockTime); grouping.insert(txoutAddr); } } @@ -4592,8 +4589,8 @@ set< set > CWallet::GetAddressGroupings(int64_t txLockTime) continue; // if this is CLTV then set if it is already unlocked for spending for the next txLockTime: - if (address.which() == TX_CLTV) - SetTimeUnlocked(address, txLockTime); + if (address.which() == TX_CLTV) + TokelSetIfTimeUnlocked(address, txLockTime); grouping.insert(address); groupings.insert(grouping); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 36561a34a28..a8056acd4dc 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -993,7 +993,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface //! check whether we are allowed to upgrade (or already support) to the named feature bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; } - void AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false, bool fIncludeCoinBase=true) const; + void AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false, bool fIncludeCoinBase=true, int64_t txLockTime = 0L) const; bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector vCoins, std::set >& setCoinsRet, CAmount& nValueRet) const; bool IsSpent(const uint256& hash, unsigned int n) const; @@ -1518,28 +1518,17 @@ class AddSpendingKeyToWallet : public boost::static_visitor &vCoins, int64_t txLockTime) { - if (!( - (txLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) || - (txLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD) - )) - return false; - if (nLockTime > txLockTime) + // remove still timelocked coins + for (std::vector::iterator it = vCoins.begin(); it != vCoins.end();) { - return false; + int64_t nLockTime; + if (it->tx->vout[it->i].scriptPubKey.IsCheckLockTimeVerify(&nLockTime) && !TokelCheckLockTimeHelper(nLockTime, txLockTime)) + it = vCoins.erase(it); + else + ++it; } - return true; -} - -// sets unlocked state in the dest -inline void SetTimeUnlocked(CTxDestination &dest, int64_t txLockTime) -{ - CCLTVID& cltv = boost::get(dest); - if (CheckLockTime(cltv.GetUnlockTime(), txLockTime)) - cltv.SetUnlocked(); -} - +}*/ #endif // BITCOIN_WALLET_WALLET_H From 7c36a1f379deb376f09c233ffa6b5cc7d9ddf404 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 19 Oct 2021 23:58:40 +0500 Subject: [PATCH 172/348] disable test sendtoaddress cltv code --- src/wallet/rpcwallet.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 7779527421a..08d1b3124b3 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -522,7 +522,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) if (!EnsureWalletIsAvailable(fHelp)) return NullUniValue; - if (fHelp || params.size() < 2 || params.size() > 7) + if (fHelp || params.size() < 2 || params.size() > 6) throw runtime_error( "sendtoaddress \"" + strprintf("%s",komodo_chainname()) + "_address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount unlocktime )\n" "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n" @@ -545,7 +545,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1") + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"donation\" \"seans outpost\"") + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"\" \"\" true") - + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"donation\" \"seans outpost\" false \"\" 2595973") +// test cltv: + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"donation\" \"seans outpost\" false \"\" 1634663625") + HelpExampleRpc("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.1, \"donation\", \"seans outpost\"") ); @@ -588,17 +588,18 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) } else opretlen = 0; } + + /* test cltv coins: int64_t unlockTime = 0LL; if (params.size() > 6) { unlockTime = atoll(params[6].get_str().c_str()); if (unlockTime < 0LL) throw JSONRPCError(RPC_TYPE_ERROR, "invalid unlock time"); - } - + } */ EnsureWalletIsUnlocked(); - SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx, opret, opretlen, 0, unlockTime); + SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx, opret, opretlen, 0, 0LL); return wtx.GetHash().GetHex(); } From 0ead4b8987cf205cc8ab6025650c026c57c563bd Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 20 Oct 2021 00:20:50 +0500 Subject: [PATCH 173/348] disable test nspv messages --- src/komodo_nSPV_fullnode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index c3dad974d49..78e3ed31881 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -53,7 +53,7 @@ static std::map nspv_remote_commands = { { "tokenask", false }, { "tokenbid", false }, { "tokenfillask", false }, { "tokenfillbid", false }, { "tokencancelask", false }, { "tokencancelbid", false }, { "tokenorders", false }, { "mytokenorders", false }, { "tokentransfer", false },{ "tokencreate", false }, { "tokenv2ask", true }, { "tokenv2bid", true }, { "tokenv2fillask", true }, { "tokenv2fillbid", true }, { "tokenv2cancelask", true }, { "tokenv2cancelbid", true }, - { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", true },{ "tokenv2create", true }, { "tokenv2address", true }, + { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", false }, { "tokenv2create", false }, { "tokenv2address", true }, // nspv helpers { "createtxwithnormalinputs", true }, { "tokenv2addccinputs", true }, { "tokenv2infotokel", true }, { "gettransactionsmany", true }, }; From ad975e0c9af5e00076fc9babae7fc280cda41cad Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 22 Oct 2021 11:58:25 +0500 Subject: [PATCH 174/348] Revert "Merge branch 'tokel' into tkltest" This reverts commit fb72ec0b8824c1dbfe8dcd7c60be61b0ebe8c76f, reversing changes made to 424740e9aa317608b70ab6b4eb5add0a09a88f8e. --- README.md | 16 +- configure.ac | 40 + src/Makefile.am | 82 +- src/alert.h | 2 + src/base58.cpp | 10 +- src/bitcoin-cli.cpp | 29 +- src/bitcoind.cpp | 57 +- src/cc/CCImportGateway.h | 4 + src/cc/CCTokelData.cpp | 1 - src/cc/CCcustom.cpp | 93 +- src/cc/CCinclude.h | 28 +- src/cc/CCtokens.cpp | 7 +- src/cc/CCtokens_impl.h | 81 + src/cc/CCtokenutils.cpp | 1 + src/cc/CCtx.cpp | 7 +- src/cc/CCutils.cpp | 153 +- src/cc/import.cpp | 20 +- src/cc/importgateway.cpp | 2 +- src/cc/pegs.cpp | 2 - src/chainparams.cpp | 11 +- src/chainparams.h | 1 + src/chainparamsseeds.h | 15 +- src/coins.cpp | 3 - src/crosschain.cpp | 2 - src/crypto/equihash.h | 1 + src/cryptoconditions/src/cryptoconditions.c | 1 + src/cryptoconditions/src/threshold.c | 2 +- src/cryptoconditions/src/utils.c | 2 +- src/deprecation.cpp | 2 +- src/importcoin.cpp | 3 - src/importcoin.h | 3 + src/init.cpp | 15 +- src/init.h | 2 + src/key_io.cpp | 8 + src/komodo-tx.cpp | 3 +- src/komodo.h | 10 +- src/komodo_DEX.h | 56 +- src/komodo_bitcoind.h | 39 +- src/komodo_defs.h | 101 +- src/komodo_gateway.h | 5 - src/komodo_globals.h | 24 +- src/komodo_nSPV.h | 8 +- src/komodo_nSPV_defs.h | 5 +- src/komodo_nSPV_fullnode.h | 462 +++--- src/komodo_nSPV_superlite.h | 29 +- src/komodo_nSPV_wallet.h | 4 +- src/komodo_utils.h | 30 +- src/main.cpp | 80 +- src/miner.cpp | 60 +- src/net.cpp | 1 + src/net.h | 6 +- src/rest.cpp | 6 - src/rpc/blockchain.cpp | 20 +- src/rpc/ccutilsrpc.cpp | 144 +- src/rpc/mining.cpp | 7 - src/rpc/misc.cpp | 37 +- src/rpc/net.cpp | 63 - src/rpc/rawtransaction.cpp | 10 - src/rpc/server.cpp | 6 +- src/rpc/server.h | 693 ++++---- src/rpc/testtransactions.cpp | 268 --- src/rpc/tokensrpc.cpp | 100 ++ src/rpcblockchain.old | 1625 ------------------- src/script/standard.h | 7 + src/sync.cpp | 3 +- src/util.cpp | 65 +- src/util.h | 13 +- src/wallet/rpcdisclosure.cpp | 4 +- src/wallet/rpcdump.cpp | 5 +- src/wallet/rpcwallet.cpp | 37 +- src/wallet/rpcwallet.h | 1 + src/wallet/wallet.cpp | 9 +- tokel_chain_flow.md | 54 - zcutil/build-mac.sh | 18 +- zcutil/build-win.sh | 21 +- zcutil/build.sh | 14 +- 76 files changed, 1616 insertions(+), 3243 deletions(-) delete mode 100644 src/rpc/testtransactions.cpp delete mode 100644 src/rpcblockchain.old delete mode 100644 tokel_chain_flow.md diff --git a/README.md b/README.md index fb38a79c0a1..f3179378402 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,12 @@ ![Tokel Header](https://github.com/TokelPlatform/tokel_app/blob/development/assets/tokel-header.png "Tokel Header") -## The Tokel blockchain repository +## Komodo's 'Tokel' Branch -This is the official repository of the Tokel Platform's blockchain source code. Tokel uses the komodo daemon to run our independent blockchain. +This is the `tokel` branch of Komodo's sourcecode repository. This branch is required to run and use the main Tokel blockchain and hosts Tokel specific developments. -The 'tokel' branch is required to run and use the main Tokel blockchain and hosts numerous Tokel specific developments you will not find in the master Komodo repository. - -Instructions to run the Tokel blockchain can be found at: -- https://docs.tokel.io/guides/LaunchTheChain/ - -To run Tokel's test chain (TKLTEST), please use the 'tkltest' branch of this repository. You can find instructions here: -- https://docs.tokel.io/guides/LaunchTKLTESTchain/ -- https://github.com/TokelPlatform/komodo/tree/tkltest +To run Tokel's test chain, please use the repository below instead. +- https://github.com/TokelPlatform/komodo/ ## What is the Tokel Platform? @@ -45,7 +39,7 @@ Tokel is a dedicated token platform. This platform will provide a solid foundati The all-in-one Tokel application is an open-sourced application that will be the one stop shop for all Tokel related features. This application is built using nSPV superlite wallet technology that has been developed by the Komodo platform, for an incredibly fast and reliable experience. This application accesses all of the features offered on the Tokel blockchain whilst keeping users funds in their own wallets (completely non-custodial). This application is in development. You can keep up with progress on the github, or find out more by having a chat in our discord. -https://github.com/TokelPlatform/tokel_dapp +https://github.com/TokelPlatform/tokel_app #### Application features include: - A TKL coin wallet diff --git a/configure.ac b/configure.ac index e0629a1c56d..98d3b098ffc 100644 --- a/configure.ac +++ b/configure.ac @@ -975,6 +975,46 @@ PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP" ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no --enable-module-recovery" AC_CONFIG_SUBDIRS([src/secp256k1 src/snark src/univalue src/cryptoconditions]) +# build custom executable with customised args: + +AC_ARG_WITH([custom-bin], + [AS_HELP_STRING([--with-custom-bin], + [build custom named daemon cli (default=no)])], + [build_custom_bin=$withval], + [build_custom_bin=no]) + +# build custom executable added with an Makefile.nnn.include +AM_CONDITIONAL([BUILD_CUSTOM_BIN], [test "x$build_custom_bin" = "xyes"]) + +AC_ARG_VAR(CUSTOM_BIN_NAME, [custom executable prefix]) +if test "x${CUSTOM_BIN_NAME+set}" = "xset"; then + AC_SUBST([CUSTOM_BIN_NAME], ${CUSTOM_BIN_NAME}) +else + AC_SUBST([CUSTOM_BIN_NAME], '') +fi + +AC_ARG_VAR(CUSTOM_BRAND_NAME, [custom brand name]) +if test "x${CUSTOM_BRAND_NAME+set}" = "xset"; then + AC_SUBST([CUSTOM_BRAND_NAME], ${CUSTOM_BRAND_NAME}) +else + AC_SUBST([CUSTOM_BRAND_NAME], '') +fi + +AC_ARG_VAR(CUSTOM_SERVER_ARGS, [custom daemon params]) +if test "x${CUSTOM_SERVER_ARGS+set}" = "xset"; then + AC_SUBST([CUSTOM_SERVER_ARGS], ${CUSTOM_SERVER_ARGS}) +else + AC_SUBST([CUSTOM_SERVER_ARGS], '') +fi + +AC_ARG_VAR(CUSTOM_CLIENT_ARGS, [custom cli params]) +if test "x${CUSTOM_CLIENT_ARGS+set}" = "xset"; then + AC_SUBST([CUSTOM_CLIENT_ARGS], ${CUSTOM_CLIENT_ARGS}) +else + AC_SUBST([CUSTOM_CLIENT_ARGS], '') +fi + + AC_OUTPUT dnl Taken from https://wiki.debian.org/RpathIssue diff --git a/src/Makefile.am b/src/Makefile.am index 8abfd389430..4fb31dc0f59 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -281,7 +281,7 @@ obj/build.h: FORCE $(abs_top_srcdir) libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h -# server: zcashd +# server: komodod libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ @@ -796,3 +796,83 @@ include Makefile.kcctest.include #include Makefile.test.include #include Makefile.gtest.include endif + +# build custom executables with customised params +if BUILD_CUSTOM_BIN +# include Makefile.tokel.include + +# custom server lib compiled with -DCUSTOM_BIN_NAME -DCUSTOM_SERVER_ARGS +LIBCUSTOM_SERVER=libcustom_server.a -lcurl +libcustom_server_a_CPPFLAGS = $(libbitcoin_server_a_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_BRAND_NAME=\"$(CUSTOM_BRAND_NAME)\" -DCUSTOM_SERVER_ARGS=\"$(CUSTOM_SERVER_ARGS)\" +libcustom_server_a_CXXFLAGS = $(libbitcoin_server_a_CXXFLAGS) +libcustom_server_a_SOURCES = $(libbitcoin_server_a_SOURCES) + +EXTRA_LIBRARIES += $(LIBCUSTOM_SERVER) + +bin_PROGRAMS += customd + +# custom daemon binary # +customd_SOURCES = $(komodod_SOURCES) +customd_CPPFLAGS = $(komodod_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_BRAND_NAME=\"$(CUSTOM_BRAND_NAME)\" -DCUSTOM_SERVER_ARGS=\"$(CUSTOM_SERVER_ARGS)\" +customd_CXXFLAGS = $(komodod_CXXFLAGS) +customd_LDFLAGS = $(komodod_LDFLAGS) +customd_LDADD = \ + $(LIBCUSTOM_SERVER) \ + $(LIBBITCOIN_COMMON) \ + $(LIBUNIVALUE) \ + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_ZMQ) \ + $(LIBBITCOIN_PROTON) \ + $(LIBBITCOIN_CRYPTO) \ + $(LIBVERUS_CRYPTO) \ + $(LIBVERUS_PORTABLE_CRYPTO) \ + $(LIBZCASH) \ + $(LIBSNARK) \ + $(LIBLEVELDB) \ + $(LIBMEMENV) \ + $(LIBSECP256K1) \ + $(LIBCRYPTOCONDITIONS) + +if ENABLE_WALLET +customd_LDADD += $(LIBBITCOIN_WALLET) +endif + +customd_LDADD += \ + $(BOOST_LIBS) \ + $(BDB_LIBS) \ + $(SSL_LIBS) \ + $(CRYPTO_LIBS) \ + $(EVENT_PTHREADS_LIBS) \ + $(EVENT_LIBS) \ + $(ZMQ_LIBS) \ + $(PROTON_LIBS) \ + $(LIBBITCOIN_CRYPTO) \ + $(LIBVERUS_CRYPTO) \ + $(LIBVERUS_PORTABLE_CRYPTO) \ + $(LIBZCASH_LIBS) + +customd_LDADD += $(LIBDYNCUSTOMCONSENSUS) $(LIBSECP256K1) + +if ENABLE_PROTON +customd_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) +endif + +customd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(customd_CXXFLAGS) \ + $(CXXFLAGS) $(customd_LDFLAGS) $(LDFLAGS) -o $(CUSTOM_BIN_NAME)d$(EXEEXT) + + +bin_PROGRAMS += custom-cli + +# custom cli binary # +custom_cli_SOURCES = $(komodo_cli_SOURCES) +custom_cli_CPPFLAGS = $(komodo_cli_CPPFLAGS) -DCUSTOM_BIN_NAME=\"$(CUSTOM_BIN_NAME)\" -DCUSTOM_BRAND_NAME=\"$(CUSTOM_BRAND_NAME)\" -DCUSTOM_CLIENT_ARGS=\"$(CUSTOM_CLIENT_ARGS)\" +custom_cli_CXXFLAGS = $(komodo_cli_CXXFLAGS) +custom_cli_LDFLAGS = $(komodo_cli_LDFLAGS) +custom_cli_LDADD = $(komodo_cli_LDADD) + +custom_cli_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(custom_cli_CXXFLAGS) \ + $(CXXFLAGS) $(custom_cli_LDFLAGS) $(LDFLAGS) -o $(CUSTOM_BIN_NAME)-cli$(EXEEXT) + +endif \ No newline at end of file diff --git a/src/alert.h b/src/alert.h index 16204c9c533..cd978c5546f 100644 --- a/src/alert.h +++ b/src/alert.h @@ -124,4 +124,6 @@ class CAlert : public CUnsignedAlert static CAlert getAlertByHash(const uint256 &hash); }; +void ThreadSendAlert(); + #endif // BITCOIN_ALERT_H diff --git a/src/base58.cpp b/src/base58.cpp index a6a33a8baee..985887303a4 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -285,7 +285,8 @@ bool CBitcoinAddress::IsValid(const CChainParams& params) const { bool fCorrectSize = vchData.size() == 20; bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) || - vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); + vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS) || + vchVersion == params.Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS); return fCorrectSize && fKnownVersion; } @@ -309,6 +310,8 @@ CTxDestination CBitcoinAddress::Get() const return CKeyID(id); else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) return CScriptID(id); + else if (vchVersion == Params().Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS)) + return CCryptoConditionID(id); else return CNoDestination(); } @@ -325,8 +328,11 @@ bool CBitcoinAddress::GetIndexKey(uint160& hashBytes, int& type, bool ccflag) co memcpy(&hashBytes, &vchData[0], 20); type = 2; return true; + } else if (vchVersion == Params().Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS)) { + memcpy(&hashBytes, &vchData[0], 20); + type = 3; + return true; } - return false; } diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 544972586aa..e38cf348d26 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -95,18 +95,38 @@ static int AppInitRPC(int argc, char* argv[]) // Parameters // ParseParameters(argc, argv); + +#if defined(CUSTOM_CLIENT_ARGS) + // add custom chain parameters + try { + AddSettings(mapArgs, mapMultiArgs, CUSTOM_CLIENT_ARGS); + } catch (const std::exception& e) { + fprintf(stderr,"Error in custom parameters: %s\n", e.what()); + return EXIT_FAILURE; + } +#endif + + std::string cliname = "komodo-cli"; + std::string brandname = "Komodo"; +#if defined(CUSTOM_BIN_NAME) + cliname = std::string(CUSTOM_BIN_NAME) + "-cli"; +#endif +#if defined(CUSTOM_BRAND_NAME) + brandname = std::string("Komodo") + " " + std::string(CUSTOM_BRAND_NAME); +#endif + std:string name; name = GetArg("-ac_name",""); if ( !name.empty() ) strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) { - std::string strUsage = _("Komodo RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); + std::string strUsage = brandname + " " + _("RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); if (!mapArgs.count("-version")) { strUsage += "\n" + _("Usage:") + "\n" + - " komodo-cli [options] [params] " + _("Send command to Komodo") + "\n" + - " komodo-cli [options] help " + _("List commands") + "\n" + - " komodo-cli [options] help " + _("Get help for a command") + "\n"; + " " + cliname + " [options] [params] " + _("Send command to ") + brandname + "\n" + + " " + cliname + " [options] help " + _("List commands") + "\n" + + " " + cliname + " [options] help " + _("Get help for a command") + "\n"; strUsage += "\n" + HelpMessageCli(); } else { @@ -124,6 +144,7 @@ static int AppInitRPC(int argc, char* argv[]) fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str()); return EXIT_FAILURE; } + try { ReadConfigFile(mapArgs, mapMultiArgs); } catch (const std::exception& e) { diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index ef7b09a37f0..0e6492c3580 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -57,15 +57,6 @@ static bool fDaemon; #include "komodo_defs.h" -#define KOMODO_ASSETCHAIN_MAXLEN 65 -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern int32_t ASSETCHAINS_BLOCKTIME; -extern uint64_t ASSETCHAINS_CBOPRET; -void komodo_passport_iteration(); -uint64_t komodo_interestsum(); -int32_t komodo_longestchain(); -void komodo_cbopretupdate(int32_t forceflag); -CBlockIndex *komodo_chainactive(int32_t height); void WaitForShutdown(boost::thread_group* threadGroup) { @@ -77,14 +68,7 @@ void WaitForShutdown(boost::thread_group* threadGroup) fprintf(stderr,"error: earlytx must be before block height %d or tx does not exist\n",KOMODO_EARLYTXID_HEIGHT); StartShutdown(); } - /*if ( ASSETCHAINS_STAKED == 0 && ASSETCHAINS_ADAPTIVEPOW == 0 && (pindex= komodo_chainactive(1)) != 0 ) - { - if ( pindex->nTime > ADAPTIVEPOW_CHANGETO_DEFAULTON ) - { - ASSETCHAINS_ADAPTIVEPOW = 1; - fprintf(stderr,"default activate adaptivepow\n"); - } else fprintf(stderr,"height1 time %u vs %u\n",pindex->nTime,ADAPTIVEPOW_CHANGETO_DEFAULTON); - } //else fprintf(stderr,"cant find height 1\n");*/ + if ( ASSETCHAINS_CBOPRET != 0 ) komodo_pricesinit(); /* @@ -108,11 +92,6 @@ void WaitForShutdown(boost::thread_group* threadGroup) // // Start // -extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY; -extern uint32_t ASSETCHAIN_INIT; -extern std::string NOTARY_PUBKEY; -int32_t komodo_is_issuer(); -void komodo_passport_iteration(); bool AppInit(int argc, char* argv[]) { @@ -120,7 +99,16 @@ bool AppInit(int argc, char* argv[]) CScheduler scheduler; bool fRet = false; - + std::string daemonname = "komodod"; + std::string cliname = "komodo-cli"; +#if defined(CUSTOM_BIN_NAME) + daemonname = std::string(CUSTOM_BIN_NAME) + "d"; + cliname = std::string(CUSTOM_BIN_NAME) + "-cli"; +#endif + std::string brandname = "Komodo"; +#if defined(CUSTOM_BRAND_NAME) + brandname = std::string("Komodo") + " " + std::string(CUSTOM_BRAND_NAME); +#endif // // Parameters // @@ -139,7 +127,7 @@ bool AppInit(int argc, char* argv[]) else { strUsage += "\n" + _("Usage:") + "\n" + - " komodod [options] " + _("Start Komodo Daemon") + "\n"; + " " + daemonname + " [options] " + _("Start ") + brandname + _(" Daemon") + "\n"; strUsage += "\n" + HelpMessage(HMM_BITCOIND); } @@ -155,7 +143,14 @@ bool AppInit(int argc, char* argv[]) fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); return false; } + +#if defined(CUSTOM_SERVER_ARGS) + // add custom chain parameters + AddSettings(mapArgs, mapMultiArgs, CUSTOM_SERVER_ARGS); +#endif + void komodo_args(char *argv0); + komodo_args(argv[0]); void chainparams_commandline(); chainparams_commandline(); @@ -172,16 +167,16 @@ bool AppInit(int argc, char* argv[]) ReadConfigFile(mapArgs, mapMultiArgs); } catch (const missing_zcash_conf& e) { fprintf(stderr, - (_("Before starting komodod, you need to create a configuration file:\n" + (_("Before starting ") + daemonname + _(", you need to create a configuration file:\n" "%s\n" "It can be completely empty! That indicates you are happy with the default\n" - "configuration of komodod. But requiring a configuration file to start ensures\n" - "that komodod won't accidentally compromise your privacy if there was a default\n" + "configuration of ") + daemonname + _(". But requiring a configuration file to start ensures\n" + "that ") + daemonname + _(" won't accidentally compromise your privacy if there was a default\n" "option you needed to change.\n" "\n" "You can look at the example configuration file for suggestions of default\n" "options that you may want to change. It should be in one of these locations,\n" - "depending on how you installed Komodo:\n") + + "depending on how you installed ") + brandname + _(":\n") + _("- Source code: %s\n" "- .deb package: %s\n")).c_str(), GetConfigFile().string().c_str(), @@ -196,12 +191,12 @@ bool AppInit(int argc, char* argv[]) // Command-line RPC bool fCommandLine = false; for (int i = 1; i < argc; i++) - if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "komodo:")) + if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "komodo:")) // Are there any "komodo:" params? fCommandLine = true; if (fCommandLine) { - fprintf(stderr, "Error: There is no RPC client functionality in komodod. Use the komodo-cli utility instead.\n"); + std::cerr << "Error: There is no RPC client functionality in " << daemonname << ". Use the " << cliname << " utility instead." << std::endl; exit(EXIT_FAILURE); } @@ -209,7 +204,7 @@ bool AppInit(int argc, char* argv[]) fDaemon = GetBoolArg("-daemon", false); if (fDaemon) { - fprintf(stdout, "Komodo %s server starting\n",ASSETCHAINS_SYMBOL); + fprintf(stdout, "Komodo %s server starting\n", ASSETCHAINS_SYMBOL); // Daemonize pid_t pid = fork(); diff --git a/src/cc/CCImportGateway.h b/src/cc/CCImportGateway.h index ee741a1487e..a139538803e 100644 --- a/src/cc/CCImportGateway.h +++ b/src/cc/CCImportGateway.h @@ -33,4 +33,8 @@ UniValue ImportGatewayExternalAddress(uint256 bindtxid,CPubKey pubkey); UniValue ImportGatewayDumpPrivKey(uint256 bindtxid,CKey key); UniValue ImportGatewayList(); UniValue ImportGatewayInfo(uint256 bindtxid); + +int64_t ImportGatewayVerify(char *refdepositaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2); +uint8_t DecodeImportGatewayBindOpRet(char *depositaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); + #endif diff --git a/src/cc/CCTokelData.cpp b/src/cc/CCTokelData.cpp index 6927d263a52..063bb1179db 100644 --- a/src/cc/CCTokelData.cpp +++ b/src/cc/CCTokelData.cpp @@ -163,7 +163,6 @@ static bool UnmarshalTokelVData(const vuint8_t &vdata, std::mapinit_to_zeros(); + cp->clear(); cp->evalcode = evalcode; + bool ismixed = false; switch ( evalcode ) { case EVAL_ASSETS: - strcpy(cp->unspendableCCaddr,AssetsCCaddr); - strcpy(cp->normaladdr,AssetsNormaladdr); strcpy(cp->CChexstr,AssetsCChexstr); memcpy(cp->CCpriv,AssetsCCpriv,32); cp->validate = AssetsValidate; cp->ismyvin = IsAssetsInput; break; case EVAL_FAUCET: - strcpy(cp->unspendableCCaddr,FaucetCCaddr); - strcpy(cp->normaladdr,FaucetNormaladdr); strcpy(cp->CChexstr,FaucetCChexstr); memcpy(cp->CCpriv,FaucetCCpriv,32); cp->validate = FaucetValidate; cp->ismyvin = IsFaucetInput; break; case EVAL_REWARDS: - strcpy(cp->unspendableCCaddr,RewardsCCaddr); - strcpy(cp->normaladdr,RewardsNormaladdr); strcpy(cp->CChexstr,RewardsCChexstr); memcpy(cp->CCpriv,RewardsCCpriv,32); cp->validate = RewardsValidate; cp->ismyvin = IsRewardsInput; break; case EVAL_DICE: - strcpy(cp->unspendableCCaddr,DiceCCaddr); - strcpy(cp->normaladdr,DiceNormaladdr); strcpy(cp->CChexstr,DiceCChexstr); memcpy(cp->CCpriv,DiceCCpriv,32); cp->validate = DiceValidate; cp->ismyvin = IsDiceInput; break; case EVAL_LOTTO: - strcpy(cp->unspendableCCaddr,LottoCCaddr); - strcpy(cp->normaladdr,LottoNormaladdr); strcpy(cp->CChexstr,LottoCChexstr); memcpy(cp->CCpriv,LottoCCpriv,32); cp->validate = LottoValidate; cp->ismyvin = IsLottoInput; break; case EVAL_FSM: - strcpy(cp->unspendableCCaddr,FSMCCaddr); - strcpy(cp->normaladdr,FSMNormaladdr); strcpy(cp->CChexstr,FSMCChexstr); memcpy(cp->CCpriv,FSMCCpriv,32); cp->validate = FSMValidate; cp->ismyvin = IsFSMInput; break; case EVAL_AUCTION: - strcpy(cp->unspendableCCaddr,AuctionCCaddr); - strcpy(cp->normaladdr,AuctionNormaladdr); strcpy(cp->CChexstr,AuctionCChexstr); memcpy(cp->CCpriv,AuctionCCpriv,32); cp->validate = AuctionValidate; cp->ismyvin = IsAuctionInput; break; case EVAL_HEIR: - strcpy(cp->unspendableCCaddr,HeirCCaddr); - strcpy(cp->normaladdr,HeirNormaladdr); strcpy(cp->CChexstr,HeirCChexstr); memcpy(cp->CCpriv,HeirCCpriv,32); cp->validate = HeirValidate; cp->ismyvin = IsHeirInput; break; case EVAL_CHANNELS: - strcpy(cp->unspendableCCaddr,ChannelsCCaddr); - strcpy(cp->normaladdr,ChannelsNormaladdr); strcpy(cp->CChexstr,ChannelsCChexstr); memcpy(cp->CCpriv,ChannelsCCpriv,32); cp->validate = ChannelsValidate; cp->ismyvin = IsChannelsInput; break; case EVAL_ORACLES: - strcpy(cp->unspendableCCaddr,OraclesCCaddr); - strcpy(cp->normaladdr,OraclesNormaladdr); strcpy(cp->CChexstr,OraclesCChexstr); memcpy(cp->CCpriv,OraclesCCpriv,32); cp->validate = OraclesValidate; cp->ismyvin = IsOraclesInput; break; case EVAL_PRICES: - strcpy(cp->unspendableCCaddr,PricesCCaddr); - strcpy(cp->normaladdr,PricesNormaladdr); strcpy(cp->CChexstr,PricesCChexstr); memcpy(cp->CCpriv,PricesCCpriv,32); cp->validate = PricesValidate; cp->ismyvin = IsPricesInput; break; case EVAL_PEGS: - strcpy(cp->unspendableCCaddr,PegsCCaddr); - strcpy(cp->normaladdr,PegsNormaladdr); strcpy(cp->CChexstr,PegsCChexstr); memcpy(cp->CCpriv,PegsCCpriv,32); cp->validate = PegsValidate; cp->ismyvin = IsPegsInput; break; case EVAL_PAYMENTS: - strcpy(cp->unspendableCCaddr,PaymentsCCaddr); - strcpy(cp->normaladdr,PaymentsNormaladdr); strcpy(cp->CChexstr,PaymentsCChexstr); memcpy(cp->CCpriv,PaymentsCCpriv,32); cp->validate = PaymentsValidate; cp->ismyvin = IsPaymentsInput; break; case EVAL_GATEWAYS: - strcpy(cp->unspendableCCaddr,GatewaysCCaddr); - strcpy(cp->normaladdr,GatewaysNormaladdr); strcpy(cp->CChexstr,GatewaysCChexstr); memcpy(cp->CCpriv,GatewaysCCpriv,32); cp->validate = GatewaysValidate; @@ -451,16 +390,12 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) break; case EVAL_TOKENS: - strcpy(cp->unspendableCCaddr, TokensCCaddr); - strcpy(cp->normaladdr, TokensNormaladdr); strcpy(cp->CChexstr, TokensCChexstr); memcpy(cp->CCpriv, TokensCCpriv, 32); cp->validate = TokensValidate; cp->ismyvin = IsTokensInput; break; case EVAL_IMPORTGATEWAY: - strcpy(cp->unspendableCCaddr, ImportGatewayCCaddr); - strcpy(cp->normaladdr, ImportGatewayNormaladdr); strcpy(cp->CChexstr, ImportGatewayCChexstr); memcpy(cp->CCpriv, ImportGatewayCCpriv, 32); cp->validate = ImportGatewayValidate; @@ -468,32 +403,36 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) break; case EVAL_TOKENSV2: - strcpy(cp->unspendableCCaddr, Tokensv2CCaddr); - strcpy(cp->normaladdr, Tokensv2Normaladdr); strcpy(cp->CChexstr, Tokensv2CChexstr); memcpy(cp->CCpriv, Tokensv2CCpriv, 32); cp->validate = Tokensv2Validate; cp->ismyvin = IsTokensv2Input; + ismixed = true; break; case EVAL_ASSETSV2: - strcpy(cp->unspendableCCaddr,Assetsv2CCaddr); - strcpy(cp->normaladdr,Assetsv2Normaladdr); strcpy(cp->CChexstr,Assetsv2CChexstr); memcpy(cp->CCpriv,Assetsv2CCpriv,32); cp->validate = Assetsv2Validate; cp->ismyvin = IsAssetsv2Input; + ismixed = true; break; case EVAL_TOKELDATA: cp->validate = TokelDataValidate; cp->ismyvin = IsTokelDataInput; + ismixed = true; break; default: - if ( CClib_initcp(cp,evalcode) < 0 ) + if (CClib_initcp(cp, evalcode) < 0) return(0); break; } + // init addresses now here: + if (cp->CChexstr[0]) { + _GetCCaddress(cp->unspendableCCaddr, cp->evalcode, pubkey2pk(ParseHex(cp->CChexstr)), ismixed); + Getscriptaddress(cp->normaladdr, CScript() << ParseHex(cp->CChexstr) << OP_CHECKSIG); + } return(cp); } diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 6075f61d333..f2ee24e4d32 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -291,7 +291,7 @@ struct CCcontract_info std::vector< struct CCVintxProbe > CCvintxprobes; // > &unspentOutputs, const char *coinaddr, uint256 creationId); - -/// SetCCunspents returns a vector of unspent outputs for a cc address -/// @param[out] unspentOutputs vector of pairs of objects CAddressUnspentCCKey and CAddressUnspentCCValue -/// @param coinaddr cc address where unspent outputs are searched -void SetCCunspentsCCIndex(std::vector > &unspentOutputs, const char *coinaddr); +void SetCCunspentsCCIndex(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId = uint256()); /// Adds mempool outputs to a vector of unspent outputs for a cc address /// @param[out] unspentOutputs vector of pairs of objects CAddressUnspentCCKey and CAddressUnspentCCValue /// @param coinaddr cc address where unspent outputs are searched -/// @param creationId txid of cc instance creation tx, might be empty to return all txns on coinaddr -void AddCCunspentsCCIndexMempool(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId); +/// @param creationId txid of cc instance creation tx, can be empty to return all txns on coinaddr +void AddCCunspentsCCIndexMempool(std::vector > &unspentOutputs, const char *coinaddr, uint256 creationId = uint256()); /// SetAddressIndexOutputs searches address index for a vector of outputs on an address /// @param[out] addressIndex vector of pairs of address index key and amount @@ -1031,16 +1021,6 @@ UniValue OracleFormat(uint8_t *data,int32_t datalen,char *format,int32_t formatl /// @private CScript GetCCDropAsOpret(const CScript &scriptPubKey); -/*! \cond INTERNAL */ -// curve25519 and sha256 -bits256 curve25519_shared(bits256 privkey,bits256 otherpub); -bits256 curve25519_basepoint9(); -bits256 curve25519(bits256 mysecret,bits256 basepoint); -void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); -bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); -// UniValue ValueFromAmount(const CAmount& amount); // defined in server.h -/*! \endcond */ - /*! \cond INTERNAL */ CAmount TotalPubkeyNormalInputs(Eval *eval, const CTransaction &tx, const CPubKey &pubkey); CAmount TotalPubkeyCCInputs(Eval *eval, const CTransaction &tx, const CPubKey &pubkey); diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 6b19ee55e5c..c615b81a065 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -831,12 +831,13 @@ UniValue TokenList() }; SetCCtxids(txids, cp->normaladdr, false, cp->evalcode, 0, zeroid, 'c'); // find by old normal addr marker + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "cp->normaladdr=" << cp->normaladdr << " SetCCtxids txids.size()=" << txids.size() << std::endl); for (std::vector::const_iterator it = txids.begin(); it != txids.end(); it++) { addTokenId(*it); } SetCCunspents(unspentOutputs, cp->unspendableCCaddr, true); // find by burnable validated cc addr marker - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "cp->unspendableCCaddr=" << cp->unspendableCCaddr << " SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { addTokenId(it->first.txhash); } @@ -929,7 +930,7 @@ UniValue TokenV2List(const UniValue ¶ms) std::vector > unspentOutputs; SetCCunspentsCCIndex(unspentOutputs, cp->unspendableCCaddr, zeroid); // find by burnable validated cc addr marker - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetCCunspentsCCIndex unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " cp->unspendableCCaddr=" << cp->unspendableCCaddr << " SetCCunspentsCCIndex unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (const auto &it : unspentOutputs) { LOCK(cs_main); if (IsTxidInActiveChain(it.first.creationid)) @@ -941,7 +942,7 @@ UniValue TokenV2List(const UniValue ¶ms) std::vector > unspentOutputs; SetCCunspents(unspentOutputs, cp->unspendableCCaddr, CC_OUTPUTS_TRUE); - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " cp->unspendableCCaddr=" << cp->unspendableCCaddr << " SetCCunspents unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (const auto &it : unspentOutputs) { CTransaction creationtx; uint256 hashBlock; diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 35a0d342874..92f0453363e 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -540,6 +540,87 @@ CAmount GetTokenBalance(CPubKey pk, uint256 tokenid, bool usemempool) return(AddTokenCCInputs(cp, mtx, pk, tokenid, 0, 0, usemempool)); } +template +UniValue GetAllTokenBalances(CPubKey pk, bool useMempool) +{ + const bool CC_INPUTS_TRUE = true; + const char *funcname = __func__; + + UniValue result(UniValue::VARR); + + struct CCcontract_info *cp, C; + cp = CCinit(&C, V::EvalCode()); + + char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; + GetTokensCCaddress(cp, tokenaddr, pk, V::IsMixed()); + + std::map mapBalances; + + // make lambda to use it for either index kind: + auto add_token_amount = [&](uint256 txhash, int32_t index, CAmount satoshis) -> void + { + CTransaction tx; + uint256 hashBlock; + + if (satoshis == 0) + return; // skip null utxos + + if (myGetTransaction(txhash, tx, hashBlock) != 0) + { + char destaddr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(destaddr, tx.vout[index].scriptPubKey); + if (strcmp(destaddr, tokenaddr) != 0) + return; + + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << "()" << " checking tx vout destaddress=" << destaddr << " amount=" << tx.vout[index].nValue << std::endl); + + uint8_t funcId = 0; + uint256 tokenIdInOpret; + CScript opret; + std::string errorStr; + + CAmount retAmount = V::CheckTokensvout(cp, NULL, tx, index, opret, tokenIdInOpret, funcId, errorStr); + + if (retAmount > 0 && !myIsutxo_spentinmempool(ignoretxid, ignorevin, txhash, index)) + { + CAmount prevAmount = result[tokenIdInOpret.GetHex()].get_int64(); + mapBalances[tokenIdInOpret] += retAmount; + } + } + }; // auto add_token_amount + + if (fUnspentCCIndex) + { + std::vector > unspentOutputs; + + SetCCunspentsCCIndex(unspentOutputs, tokenaddr); + if (useMempool) + AddCCunspentsCCIndexMempool(unspentOutputs, tokenaddr); + + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspent ccindex found unspentOutputs=" << unspentOutputs.size() << std::endl); + for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) + add_token_amount(it->first.txhash, it->first.index, it->second.satoshis); + } + else + { + std::vector > unspentOutputs; + + if (useMempool) + SetCCunspentsWithMempool(unspentOutputs, (char*)tokenaddr, CC_INPUTS_TRUE); + else + SetCCunspents(unspentOutputs, (char*)tokenaddr, CC_INPUTS_TRUE); + + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspent index found unspentOutputs=" << unspentOutputs.size() << std::endl); + for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) + add_token_amount(it->first.txhash, it->first.index, it->second.satoshis); + } + + for(auto const &m : mapBalances) + result.pushKV(m.first.GetHex(), m.second); + + return result; +} + template UniValue TokenInfo(uint256 tokenid, E parseExtraData) { diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index d1521c618f1..c01024eb330 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -416,6 +416,7 @@ CTxOut MakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount n CCwrapper payoutCond( MakeTokensv2CCcondMofN(evalcode1, evalcode2, M, pks) ); if (!CCtoAnon(payoutCond.get())) return vout; + vout = CTxOut(nValue, CCPubKey(payoutCond.get(),true)); { diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 8059f3ee7fa..86fcf30614f 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -799,7 +799,8 @@ void SetCCunspentsCCIndex(std::vector >::iterator it = searchKeys.begin(); it != searchKeys.end(); it++) { if (GetUnspentCCIndex((*it).first, (*it).second, unspentOutputs, -1, -1, 0) == 0) @@ -1146,7 +1147,7 @@ CAmount AddNormalinputsLocal(CMutableTransaction& mtx, CPubKey mypk, CAmount tot { LOCK(cs_main); if (CoinbaseGetBlocksToMaturity(tx, hashBlock) > 0) { - std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; + //std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; continue; } } @@ -1264,7 +1265,7 @@ CAmount AddNormalinputsRemote(CMutableTransaction& mtx, CPubKey mypk, CAmount to { LOCK(cs_main); if (CoinbaseGetBlocksToMaturity(tx, hashBlock) > 0) { - std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; + //std::cerr << __func__ << " skipping immature coinbase tx=" << txid.GetHex() << " COINBASE_MATURITY=" << COINBASE_MATURITY << std::endl; continue; } } diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 541b8f41e5f..55ec2302222 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -16,25 +16,14 @@ /* CCutils has low level functions that are universally useful for all contracts. */ - +#include "key_io.h" +#include "komodo_defs.h" +#include "komodo_structs.h" #include "CCinclude.h" #include "CCtokens.h" -#include "komodo_structs.h" -#include "komodo_defs.h" -#include "key_io.h" - thread_local CCERROR CCerror = ""; -#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; - void endiancpy(uint8_t *dest,uint8_t *src,int32_t len) { int32_t i,j=0; @@ -846,94 +835,6 @@ uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::ve return merkleBlock.txn.ExtractMatches(txids); } -int64_t komodo_get_blocktime(uint256 hashBlock) -{ - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi != mapBlockIndex.end() && (*mi).second) - { - CBlockIndex* pindex = (*mi).second; - if (chainActive.Contains(pindex)) - return pindex->GetBlockTime(); - } - return 0; -} - -extern struct NSPV_inforesp NSPV_inforesult; -int32_t komodo_get_current_height() -{ - if ( KOMODO_NSPV_SUPERLITE ) - { - return (NSPV_inforesult.height); - } - else return chainActive.LastTip()->GetHeight(); -} - -bool komodo_txnotarizedconfirmed(uint256 txid, int32_t minconfirms) -{ - char str[65]; - int32_t confirms,minimumconfirms,notarized=0,txheight=0,currentheight=0;; - CTransaction tx; - uint256 hashBlock; - CBlockIndex *pindex; - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - - if (minconfirms==0) return (true); - if ( KOMODO_NSPV_SUPERLITE ) - { - if ( NSPV_myGetTransaction(txid,tx,hashBlock,txheight,currentheight) == 0 ) - { - fprintf(stderr,"komodo_txnotarizedconfirmed cant find txid %s\n",txid.ToString().c_str()); - return(0); - } - else if (txheight<=0) - { - fprintf(stderr,"komodo_txnotarizedconfirmed no txheight.%d for txid %s\n",txheight,txid.ToString().c_str()); - return(0); - } - else if (txheight>currentheight) - { - fprintf(stderr,"komodo_txnotarizedconfirmed backwards heights for txid %s hts.(%d %d)\n",txid.ToString().c_str(),txheight,currentheight); - return(0); - } - confirms=1 + currentheight - txheight; - } - else - { - 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= komodo_blockindex(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 (minconfirms>1) minimumconfirms=minconfirms; - else minimumconfirms=MIN_NON_NOTARIZED_CONFIRMS; - 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 >= minimumconfirms) - return (true); - return (false); -} - CPubKey check_signing_pubkey(CScript scriptSig) { bool found = false; @@ -1235,54 +1136,6 @@ uint8_t *SuperNET_ciphercalc(uint8_t **ptrp,int32_t *cipherlenp,bits256 privkey, return(origptr); } -uint8_t *komodo_DEX_encrypt(uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 destpubkey,bits256 privkey) -{ - int32_t cipherlen; uint8_t *cipher; - cipher = SuperNET_ciphercalc(allocatedp,&cipherlen,privkey,destpubkey,data,*datalenp); - *datalenp = cipherlen; - return(cipher); -} - -uint8_t *komodo_DEX_decrypt(uint8_t *senderpub,uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 privkey) -{ - int32_t msglen; - *allocatedp = 0; - if ( (msglen= *datalenp) <= crypto_box_NONCEBYTES + crypto_box_ZEROBYTES + sizeof(bits256) ) - { - *datalenp = 0; - return(0); - } - if ( (data= SuperNET_deciphercalc(senderpub,allocatedp,&msglen,privkey,data,*datalenp)) == 0 ) - { - //printf("komodo_DEX_decrypt decrytion error\n"); - *datalenp = 0; - return(0); - } else *datalenp = msglen; - return(data); -} - -void komodo_DEX_privkey(bits256 &privkey) -{ - bits256 priv,hash; - Myprivkey(priv.bytes); - vcalc_sha256(0,hash.bytes,priv.bytes,32); - vcalc_sha256(0,privkey.bytes,hash.bytes,32); - memset(priv.bytes,0,sizeof(priv)); - memset(hash.bytes,0,sizeof(hash)); -} - -void komodo_DEX_pubkey(bits256 &pubkey) -{ - bits256 privkey; - komodo_DEX_privkey(privkey); - /*{ - char *bits256_str(char hexstr[65],bits256 x); - char str[65]; - fprintf(stderr,"new DEX_privkey %s\n",bits256_str(str,privkey)); - }*/ - pubkey = curve25519(privkey,curve25519_basepoint9()); - memset(privkey.bytes,0,sizeof(privkey)); -} // add probe vintx conditions for making CCSig in FinalizeCCTx void CCAddVintxCond(struct CCcontract_info *cp, const CCwrapper &condWrapped, const uint8_t *priv) diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 1a8c2f4519b..74344e951a4 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -13,14 +13,16 @@ * * ******************************************************************************/ +#include #include "cc/eval.h" #include "cc/utils.h" +#include "komodo_defs.h" #include "importcoin.h" #include "crosschain.h" #include "primitives/transaction.h" #include "cc/CCinclude.h" -#include #include "cc/CCtokens.h" +#include "cc/CCImportGateway.h" #include "key_io.h" #define CODA_BURN_ADDRESS "KPrrRoPfHOnNpZZQ6laHXdQDkSQDkVHaN0V+LizLlHxz7NaA59sBAAAA" @@ -33,22 +35,6 @@ ##### 0xffffffff is a special CCid for single chain/dual daemon imports */ -extern std::string ASSETCHAINS_SELFIMPORT; -extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT; -extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; -extern uint256 KOMODO_EARLYTXID; - -// utilities from gateways.cpp -uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::vector &txids); -uint256 GatewaysReverseScan(uint256 &txid, int32_t height, uint256 reforacletxid, uint256 batontxid); -int32_t GatewaysCointxidExists(struct CCcontract_info *cp, uint256 cointxid); -uint8_t DecodeImportGatewayBindOpRet(char *burnaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); -int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2); -char *nonportable_path(char *str); -char *portable_path(char *str); -void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); -void *filestr(long *allocsizep,char *_fname); - cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,char const *arg3,char const *arg4,char const *arg5) { char cmdstr[5000],fname[256],*jsonstr; diff --git a/src/cc/importgateway.cpp b/src/cc/importgateway.cpp index 782fcc9e6fc..8948ec5c731 100644 --- a/src/cc/importgateway.cpp +++ b/src/cc/importgateway.cpp @@ -13,9 +13,9 @@ * * ******************************************************************************/ -#include "CCImportGateway.h" #include "key_io.h" #include "../importcoin.h" +#include "CCImportGateway.h" // start of consensus code diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 6de6baa4000..824bad2ce34 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -100,8 +100,6 @@ pegs CC is able to create a coin backed (by any supported coin with gateways CC #endif // PEGS_THRESHOLDS #define CC_MARKER_VALUE 10000 -extern uint64_t ASSETCHAINS_PEGSCCPARAMS[3]; - extern uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); //extern int64_t GetTokenBalance(CPubKey pk, uint256 tokenid); extern int32_t komodo_currentheight(); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index fcae87cb6c4..fb2b3399f66 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -182,12 +182,13 @@ class CMainParams : public CChainParams { assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); vFixedSeeds.clear(); vSeeds.clear(); - vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); // Static contolled seeds list (Kolo) - vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); // Active seeds crawler (Kolo) + //vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); // Static contolled seeds list (Kolo) + //vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); // Active seeds crawler (Kolo) // TODO: we need more seed crawlers from other community members base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,60); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,85); base58Prefixes[SECRET_KEY] = std::vector(1,188); + base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container >(); // guarantees the first two characters, when base58 encoded, are "zc" @@ -197,6 +198,8 @@ class CMainParams : public CChainParams { // guarantees the first two characters, when base58 encoded, are "SK" base58Prefixes[ZCSPENDING_KEY] = {171,54}; + base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); + bech32HRPs[SAPLING_PAYMENT_ADDRESS] = "zs"; bech32HRPs[SAPLING_FULL_VIEWING_KEY] = "zviews"; bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivks"; @@ -307,6 +310,8 @@ class CTestNetParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,0); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,5); base58Prefixes[SECRET_KEY] = std::vector(1,128); + base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); + base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); base58Prefixes[ZCPAYMENT_ADDRRESS] = {20,81}; @@ -428,6 +433,8 @@ class CRegTestParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,60); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,85); base58Prefixes[SECRET_KEY] = std::vector(1,188); + base58Prefixes[CRYPTOCONDITION_ADDRESS] = std::vector(1,0x1c); + //base58Prefixes[PUBKEY_ADDRESS] = {0x1D,0x25}; //base58Prefixes[SCRIPT_ADDRESS] = {0x1C,0xBA}; //base58Prefixes[SECRET_KEY] = {0xEF}; diff --git a/src/chainparams.h b/src/chainparams.h index daa16af8c40..23916b7ef17 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -63,6 +63,7 @@ class CChainParams ZCPAYMENT_ADDRRESS, ZCSPENDING_KEY, ZCVIEWING_KEY, + CRYPTOCONDITION_ADDRESS, MAX_BASE58_TYPES }; diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index e3dac3ca641..4a6a2248632 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -23,12 +23,15 @@ * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly. */ static SeedSpec6 pnSeed6_main[] = { - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27487}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27487}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27487} +/** + * no need in zcash seeds: + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27485}, + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27487}, + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27485}, + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27487}, + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27485}, + * {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27487} + */ }; static SeedSpec6 pnSeed6_test[] = { diff --git a/src/coins.cpp b/src/coins.cpp index 92206b65379..77a46d38b90 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -565,9 +565,6 @@ const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const return coins->vout[input.prevout.n]; } -//uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; const CScript &CCoinsViewCache::GetSpendFor(const CCoins *coins, const CTxIn& input) { diff --git a/src/crosschain.cpp b/src/crosschain.cpp index 0a081c0868a..375d5ac9174 100644 --- a/src/crosschain.cpp +++ b/src/crosschain.cpp @@ -43,8 +43,6 @@ int NOTARISATION_SCAN_LIMIT_BLOCKS = 1440; -CBlockIndex *komodo_getblockindex(uint256 hash); - /* On KMD */ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, diff --git a/src/crypto/equihash.h b/src/crypto/equihash.h index 57c434dae96..7d1275079ce 100644 --- a/src/crypto/equihash.h +++ b/src/crypto/equihash.h @@ -13,6 +13,7 @@ #include "komodo_nk.h" #include +#include #include #include #include diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index 8eab9628ec1..7d608f7449e 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -172,6 +172,7 @@ void asnCondition(const CC *cond, Condition_t *asn) { case Condition_PR_ed25519Sha256: choice = &asn->choice.ed25519Sha256; break; case Condition_PR_secp256k1Sha256: choice = &asn->choice.secp256k1Sha256; break; case Condition_PR_evalSha256: choice = &asn->choice.evalSha256; break; + default: return; }; choice->cost = cc_getCost(cond); choice->fingerprint.buf = calloc(1, 32); diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 82aeca4c85e..8415ac8efa8 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -293,7 +293,7 @@ static CC *thresholdFromJSON(const cJSON *params, char *err) { for (int i=0; isize; i++) { sub = cJSON_GetArrayItem(subfulfillments_item, i); cond->subconditions[i] = cc_conditionFromJSON(sub, err); - if (err[0] || cond->subconditions[i]==NULL) + if (/*err[0] || */ cond->subconditions[i]==NULL) // it should not be any 'err' if subconditions was created okay. This 'err[0]' check caused cc_conditionFromJSON failure if err not inited by the user { if (cond) cc_free(cond); return NULL; diff --git a/src/cryptoconditions/src/utils.c b/src/cryptoconditions/src/utils.c index 26d5f706976..0baa88da446 100644 --- a/src/cryptoconditions/src/utils.c +++ b/src/cryptoconditions/src/utils.c @@ -216,7 +216,7 @@ void hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp, uint8_t * ASN_STRUCT_FREE(*asnType, fp); if (rc.encoded < 1) { fprintf(stderr, "Encoding fingerprint failed\n"); - return 0; + return; } sha256(buf, rc.encoded, out); } diff --git a/src/deprecation.cpp b/src/deprecation.cpp index 6005918ec66..9d84fab0761 100644 --- a/src/deprecation.cpp +++ b/src/deprecation.cpp @@ -25,9 +25,9 @@ #include "ui_interface.h" #include "util.h" #include "chainparams.h" +#include "komodo_defs.h" static const std::string CLIENT_VERSION_STR = FormatVersion(CLIENT_VERSION); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; void EnforceNodeDeprecation(int nHeight, bool forceLogging, bool fThread) { diff --git a/src/importcoin.cpp b/src/importcoin.cpp index db1346f286c..1b0224685a5 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -28,9 +28,6 @@ #include "cc/CCtokens.h" #include "cc/CCtokens_impl.h" - -//int32_t komodo_nextheight(); - // makes import tx for either coins or tokens CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride) { diff --git a/src/importcoin.h b/src/importcoin.h index 0f7c52aa520..16dc49150d1 100644 --- a/src/importcoin.h +++ b/src/importcoin.h @@ -122,4 +122,7 @@ bool CheckVinPubKey(const CTransaction &sourcetx, int32_t i, uint8_t pubkey33[33 CMutableTransaction MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount); int32_t GetSelfimportProof(const CMutableTransaction sourceMtx, CMutableTransaction &templateMtx, ImportProof &proofNull); +extern std::string ASSETCHAINS_SELFIMPORT; +extern uint16_t ASSETCHAINS_CODAPORT, ASSETCHAINS_BEAMPORT; + #endif /* IMPORTCOIN_H */ \ No newline at end of file diff --git a/src/init.cpp b/src/init.cpp index fdbb56fd765..190b09ab5ba 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -23,6 +23,7 @@ #endif #include "init.h" +#include "alert.h" #include "crypto/common.h" #include "primitives/block.h" #include "addrman.h" @@ -93,14 +94,6 @@ using namespace std; #include "komodo_defs.h" -extern void ThreadSendAlert(); -extern bool komodo_dailysnapshot(int32_t height); -extern int32_t KOMODO_LOADINGBLOCKS; -extern bool VERUS_MINTBLOCKS; -extern char ASSETCHAINS_SYMBOL[]; -extern int32_t KOMODO_SNAPSHOT_INTERVAL; - -extern void komodo_init(int32_t height); ZCJoinSplit* pzcashParams = NULL; @@ -754,10 +747,6 @@ void ThreadNotifyRecentlyAdded() } } -/* declarations needed for ThreadUpdateKomodoInternals */ -void komodo_passport_iteration(); -void komodo_cbopretupdate(int32_t forceflag); - void ThreadUpdateKomodoInternals() { RenameThread("int-updater"); @@ -923,8 +912,6 @@ bool AppInitServers(boost::thread_group& threadGroup) /** Initialize bitcoin. * @pre Parameters should be parsed and config file should be read. */ -extern int32_t KOMODO_REWIND; - bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) { // ********************************************************* Step 1: setup diff --git a/src/init.h b/src/init.h index 108339865be..7bef5d37836 100644 --- a/src/init.h +++ b/src/init.h @@ -51,4 +51,6 @@ enum HelpMessageMode { /** Help for options shared between UI and daemon (for -help) */ std::string HelpMessage(HelpMessageMode mode); +extern std::atomic fRequestShutdown; + #endif // BITCOIN_INIT_H diff --git a/src/key_io.cpp b/src/key_io.cpp index f013275b85a..c51684e7ac6 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -87,6 +87,14 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin()); return CScriptID(hash); } + + // added cc addresses decode: + const std::vector& cc_prefix = params.Base58Prefix(CChainParams::CRYPTOCONDITION_ADDRESS); + if (data.size() == hash.size() + cc_prefix.size() && std::equal(cc_prefix.begin(), cc_prefix.end(), data.begin())) { + std::copy(data.begin() + cc_prefix.size(), data.end(), hash.begin()); + return CCryptoConditionID(hash); + } + } return CNoDestination(); } diff --git a/src/komodo-tx.cpp b/src/komodo-tx.cpp index 21752778454..d25cbc8af42 100644 --- a/src/komodo-tx.cpp +++ b/src/komodo-tx.cpp @@ -41,9 +41,10 @@ using namespace std; #include "uint256.h" #include "arith_uint256.h" +#include "komodo_defs.h" #include "komodo_structs.h" #include "komodo_globals.h" -#include "komodo_defs.h" + #include "komodo_interest.h" diff --git a/src/komodo.h b/src/komodo.h index 88e741df7f7..bfcfb0b789c 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -37,10 +37,7 @@ uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID; #include "uthash.h" #include "utlist.h" -int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); -void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); -int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); -bool check_pprevnotarizedht(); +//bool check_pprevnotarizedht(); #include "komodo_structs.h" #include "komodo_globals.h" @@ -67,7 +64,6 @@ void komodo_currentheight_set(int32_t height) sp->CURRENT_HEIGHT = height; } -extern struct NSPV_inforesp NSPV_inforesult; int32_t komodo_currentheight() { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; @@ -792,7 +788,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar // if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed // OP_RETURN: 'D' -> deposit, 'W' -> withdraw -int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); +//int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]) { @@ -820,6 +816,8 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash; int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count; + + AssertLockHeld(cs_main); if ( pindex == 0 ) { fprintf(stderr,"komodo_connectblock null pindex\n"); diff --git a/src/komodo_DEX.h b/src/komodo_DEX.h index 4eb4c9ef524..c2711f0af57 100644 --- a/src/komodo_DEX.h +++ b/src/komodo_DEX.h @@ -60,11 +60,6 @@ detect evil peer: 'Q' is directly protected by txpow, G is a fixed size, so it cant be very big and invalid request can be detected. 'P' message will lead to 'G' queries that cannot be answered, 'R' needs to have high priority */ -uint8_t *komodo_DEX_encrypt(uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 pubkey,bits256 privkey); -uint8_t *komodo_DEX_decrypt(uint8_t *senderpub,uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 privkey); -void komodo_DEX_pubkey(bits256 &pub0); -void komodo_DEX_privkey(bits256 &priv0); -int32_t komodo_DEX_request(int32_t priority,uint32_t shorthash,uint32_t timestamp,char *tagA,char *tagB); #define KOMODO_DEX_PURGELIST 0 @@ -171,6 +166,29 @@ static struct DEX_globals FILE *fp; } *G; +void komodo_DEX_privkey(bits256 &privkey) +{ + bits256 priv,hash; + Myprivkey(priv.bytes); + vcalc_sha256(0,hash.bytes,priv.bytes,32); + vcalc_sha256(0,privkey.bytes,hash.bytes,32); + memset(priv.bytes,0,sizeof(priv)); + memset(hash.bytes,0,sizeof(hash)); +} + +void komodo_DEX_pubkey(bits256 &pubkey) +{ + bits256 privkey; + komodo_DEX_privkey(privkey); + /*{ + char *bits256_str(char hexstr[65],bits256 x); + char str[65]; + fprintf(stderr,"new DEX_privkey %s\n",bits256_str(str,privkey)); + }*/ + pubkey = curve25519(privkey,curve25519_basepoint9()); + memset(privkey.bytes,0,sizeof(privkey)); +} + void komodo_DEX_pubkeyupdate() { komodo_DEX_pubkey(DEX_pubkey); @@ -253,6 +271,34 @@ uint32_t komodo_DEXquotehash(bits256 &hash,uint8_t *msg,int32_t len) return(_komodo_DEXquotehash(hash,len)); } +uint8_t *komodo_DEX_encrypt(uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 destpubkey,bits256 privkey) +{ + int32_t cipherlen; uint8_t *cipher; + cipher = SuperNET_ciphercalc(allocatedp,&cipherlen,privkey,destpubkey,data,*datalenp); + *datalenp = cipherlen; + return(cipher); +} + +uint8_t *komodo_DEX_decrypt(uint8_t *senderpub,uint8_t **allocatedp,uint8_t *data,int32_t *datalenp,bits256 privkey) +{ + int32_t msglen; + *allocatedp = 0; + if ( (msglen= *datalenp) <= crypto_box_NONCEBYTES + crypto_box_ZEROBYTES + sizeof(bits256) ) + { + *datalenp = 0; + return(0); + } + if ( (data= SuperNET_deciphercalc(senderpub,allocatedp,&msglen,privkey,data,*datalenp)) == 0 ) + { + //printf("komodo_DEX_decrypt decrytion error\n"); + *datalenp = 0; + return(0); + } else *datalenp = msglen; + return(data); +} + + + uint16_t _komodo_DEXpeerpos(uint32_t timestamp,int32_t peerid) { // this needs to maintain the bitposition from epoch to epoch, to preserve the accuracy of the GETBIT() diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 15ab79f0e68..8226a76080c 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -19,22 +19,14 @@ #include #include "primitives/nonce.h" #include "consensus/params.h" -#include "komodo_defs.h" #include "script/standard.h" +#include "init.h" +#include "main.h" +#include "komodo_defs.h" #include "cc/CCinclude.h" const char *LOG_KOMODOBITCOIND = "komodostaking"; -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); -int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp); -unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); -bool EnsureWalletIsAvailable(bool avoidException); -extern bool fRequestShutdown; -extern CScript KOMODO_EARLYTXID_SCRIPTPUB; - -uint32_t komodo_heightstamp(int32_t height); - //#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr)) struct MemoryStruct { char *memory; size_t size; }; @@ -942,6 +934,7 @@ int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) uint32_t komodo_chainactive_timestamp() { + AssertLockHeld(cs_main); if ( chainActive.LastTip() != 0 ) return((uint32_t)chainActive.LastTip()->GetBlockTime()); else return(0); @@ -949,6 +942,7 @@ uint32_t komodo_chainactive_timestamp() CBlockIndex *komodo_chainactive(int32_t height) { + AssertLockHeld(cs_main); if ( chainActive.LastTip() != 0 ) { if ( height <= chainActive.LastTip()->GetHeight() ) @@ -961,6 +955,7 @@ CBlockIndex *komodo_chainactive(int32_t height) uint32_t komodo_heightstamp(int32_t height) { + AssertLockHeld(cs_main); CBlockIndex *ptr; if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 ) return(ptr->nTime); @@ -1268,11 +1263,11 @@ uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_ return(locktime); } -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); - uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight) { uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex; + AssertLockHeld(cs_main); + if ( (pindex= chainActive[tipheight]) != 0 ) tiptime = (uint32_t)pindex->nTime; else fprintf(stderr,"cant find height[%d]\n",tipheight); @@ -1288,15 +1283,25 @@ uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 int32_t komodo_nextheight() { - CBlockIndex *pindex; int32_t ht; - if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->GetHeight()) > 0 ) - return(ht+1); - else return(komodo_longestchain() + 1); + CBlockIndex* pindex; + int32_t ht; + + { + LOCK(cs_main); // dimxy added to protect chainActive concurrent use. + pindex = chainActive.LastTip(); + } + + if (pindex != nullptr && (ht = pindex->GetHeight()) > 0) + return (ht + 1); + else + return (komodo_longestchain() + 1); } int32_t komodo_isrealtime(int32_t *kmdheightp) { struct komodo_state *sp; CBlockIndex *pindex; + + AssertLockHeld(cs_main); if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) *kmdheightp = sp->CURRENT_HEIGHT; else *kmdheightp = 0; diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 5c3ef903db5..60ce6c291c0 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -18,7 +18,12 @@ #include #include "arith_uint256.h" +#include "script/script.h" +#include "pubkey.h" #include "chain.h" +#include "primitives/transaction.h" +#include "threadsafety.h" + #include "komodo_nk.h" #define KOMODO_EARLYTXID_HEIGHT 100 @@ -40,6 +45,10 @@ #define ASSETCHAINS_STAKED_MIN_POW_DIFF 536900000 // 537000000 537300000 #define _COINBASE_MATURITY 100 +#define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff + +#define IS_KMD_CHAIN() (ASSETCHAINS_SYMBOL[0] == '\0') + #define KOMODO_ADDRESS_BUFSIZE 64 // KMD Notary Seasons @@ -483,7 +492,7 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = #define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1) #endif -extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC; +extern uint8_t ASSETCHAINS_TXPOW; extern int8_t ASSETCHAINS_ADAPTIVEPOW; int32_t MAX_BLOCK_SIZE(int32_t height); extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; @@ -504,7 +513,10 @@ extern int32_t VERUS_MIN_STAKEAGE; extern uint32_t ASSETCHAINS_VERUSHASH, ASSETCHAINS_VERUSHASHV1_1, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB; extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; -//extern std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; +extern std::vector ASSETCHAINS_PRICES, ASSETCHAINS_STOCKS; +extern std::vector Mineropret; // opreturn data set by the data gathering code +extern uint64_t ASSETCHAINS_PEGSCCPARAMS[3]; +extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEYHASH[]; extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD; extern uint256 KOMODO_EARLYTXID; @@ -533,7 +545,6 @@ void komodo_netevent(std::vector payload); int32_t getacseason(uint32_t timestamp); int32_t getkmdseason(int32_t height); -#define IGUANA_MAXSCRIPTSIZE 10001 #define KOMODO_KVDURATION 1440 #define KOMODO_KVBINARY 2 #define PRICES_SMOOTHWIDTH 1 @@ -543,10 +554,8 @@ int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *bas int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); -int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); uint32_t komodo_blocktime(uint256 hash); -int32_t komodo_longestchain(); int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); int8_t komodo_segid(int32_t nocache,int32_t height); int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight); @@ -555,7 +564,6 @@ int32_t komodo_priceind(const char *symbol); int32_t komodo_pricesinit(); int64_t komodo_priceave(int64_t *tmpbuf,int64_t *correlated,int32_t cskip); int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth); -int32_t komodo_nextheight(); uint32_t komodo_heightstamp(int32_t height); int64_t komodo_pricemult_to10e8(int32_t ind); int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks); @@ -580,6 +588,84 @@ int32_t komodo_blockload(CBlock& block, CBlockIndex *pindex); uint32_t komodo_chainactive_timestamp(); uint32_t GetLatestTimestamp(int32_t height); int32_t komodo_get_current_height(); +struct komodo_state *komodo_stateptrget(char *base); + +void komodo_prefetch(FILE *fp); +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); +void komodo_init(int32_t height); +int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); +int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); +char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); +int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); +int32_t komodo_isrealtime(int32_t *kmdheightp); +uint64_t komodo_paxtotal(); +int32_t komodo_longestchain(); +uint64_t komodo_maxallowed(int32_t baseid); +int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); +int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); +int64_t komodo_block_unlocktime(uint32_t nHeight); +int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void *pTr); +uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); +CScript komodo_mineropret(int32_t nHeight); +bool komodo_appendACscriptpub(); +uint64_t komodo_commission(const CBlock *pblock,int32_t height); +int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); +uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); +int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk); +int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len); +int32_t komodo_is_notarytx(const CTransaction& tx); +int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag); +uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len); +CScript komodo_makeopret(CBlock *pblock, bool fNew); +int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); +int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); +int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); +int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime); +void komodo_passport_iteration(); +void komodo_cbopretupdate(int32_t forceflag); +uint64_t komodo_interestsum(); +uint64_t komodo_interest(int32_t txheight, uint64_t nValue, uint32_t nLockTime, uint32_t tiptime); +bool komodo_dailysnapshot(int32_t height); +void komodo_setactivation(int32_t height); +void komodo_pricesupdate(int32_t height,CBlock *pblock); +void komodo_broadcast(CBlock *pblock,int32_t limit); +int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); +void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); +int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main) ; +arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); +int32_t komodo_baseid(char *origbase); +int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); +uint64_t komodo_current_supply(uint32_t nHeight); + +int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); +bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); + +char *nonportable_path(char *str); +char *portable_path(char *str); +void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); +void *filestr(long *allocsizep,char *_fname); + +extern uint64_t KOMODO_INTERESTSUM, KOMODO_WALLETBALANCE; +extern int32_t KOMODO_INSYNC, KOMODO_LASTMINED, prevKOMODO_LASTMINED; +extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS + 1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS + 1]; +extern uint64_t ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS + 1]; +extern uint64_t ASSETCHAINS_LINEAR, ASSETCHAINS_SUPPLY; +extern uint8_t ASSETCHAINS_PUBLIC, ASSETCHAINS_PRIVATE; +extern int32_t KOMODO_LOADINGBLOCKS; +extern int32_t ASSETCHAINS_FOUNDERS; +extern char ASSETCHAINS_USERPASS[]; +extern int32_t KOMODO_REWIND; +extern uint32_t ASSETCHAINS_NUMALGOS; +extern uint32_t STAKING_MIN_DIFF; +extern uint32_t ASSETCHAINS_MINDIFF[]; +extern uint64_t ASSETCHAINS_TIMEUNLOCKFROM; +extern uint64_t ASSETCHAINS_TIMEUNLOCKTO; +extern uint32_t KOMODO_DPOWCONFS; +extern uint16_t KMD_PORT, BITCOIND_RPCPORT, DEST_PORT; +extern char KMDUSERPASS[], BTCUSERPASS[]; +extern uint32_t KOMODO_STOPAT; +extern int32_t ASSETCHAINS_CBMATURITY; #ifndef KOMODO_NSPV_FULLNODE #define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) @@ -602,6 +688,9 @@ struct komodo_staking *komodo_addutxo(struct komodo_staking *array, int32_t *num void komodo_createminerstransactions(); uint32_t komodo_segid32(char *coinaddr); +int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp); + + // #ifndef _WIN32 void OS_randombytes(unsigned char *x, long xlen); // this func impl exists for win too // #endif diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index de72ab0d30f..b422f9fa8c1 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -682,8 +682,6 @@ int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max) return(i); } -void komodo_passport_iteration(); - int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime) // verify above block is valid pax pricing { static uint256 array[64]; static int32_t numbanned,indallvouts; @@ -1426,8 +1424,6 @@ int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,ch return(-1); } -uint64_t komodo_interestsum(); - void komodo_passport_iteration() { static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest; @@ -1582,7 +1578,6 @@ void komodo_passport_iteration() } -extern std::vector Mineropret; // opreturn data set by the data gathering code #define PRICES_ERRORRATE (COIN / 100) // maximum acceptable change, set at 1% #define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR #define KOMODO_LOCALPRICE_CACHESIZE 13 diff --git a/src/komodo_globals.h b/src/komodo_globals.h index ab3ed76f3a9..87c94052dd7 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -14,22 +14,7 @@ ******************************************************************************/ #include "komodo_defs.h" - -void komodo_prefetch(FILE *fp); -uint32_t komodo_heightstamp(int32_t height); -void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); -void komodo_init(int32_t height); -int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); -int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); -char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); -void komodo_init(int32_t height); -int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); -int32_t komodo_isrealtime(int32_t *kmdheightp); -uint64_t komodo_paxtotal(); -int32_t komodo_longestchain(); -uint64_t komodo_maxallowed(int32_t baseid); -int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); -int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); +#include "komodo_structs.h" pthread_mutex_t komodo_mutex,staked_mutex; @@ -79,14 +64,13 @@ int64_t MAX_MONEY = 200000000 * 100000000LL; // to be verifiable, timelocks require additional data that enables them to be validated and their ownership and // release time determined from the blockchain. to do this, every time locked output according to this // spec will use an op_return with CLTV at front and anything after |OP_RETURN|PUSH of rest|OPRETTYPE_TIMELOCK|script| -#define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff uint64_t ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF; uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0,ASSETCHAINS_CBOPRET=0; uint64_t ASSETCHAINS_LASTERA = 1; uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_PEGSCCPARAMS[3]; uint8_t ASSETCHAINS_CCDISABLES[256],ASSETCHAINS_CCZEROTXFEE[256]; -std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; +std::vector ASSETCHAINS_PRICES, ASSETCHAINS_STOCKS; #define _ASSETCHAINS_EQUIHASH 0 uint32_t ASSETCHAINS_NUMALGOS = 3; @@ -116,9 +100,9 @@ int32_t ASSETCHAINS_STAKED; uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REWARD; uint32_t KOMODO_INITDONE; -char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; +char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; +uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; uint64_t PENDING_KOMODO_TX; -extern int32_t KOMODO_LOADINGBLOCKS; unsigned int MAX_BLOCK_SIGOPS = 20000; int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL; diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index 65f5422f865..0f8ed0843d1 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -26,6 +26,12 @@ #ifndef KOMODO_NSPV_H #define KOMODO_NSPV_H +#include +#include "main.h" +#include "komodo_defs.h" +#include "cc/CCinclude.h" +#include "komodo_nSPV_defs.h" + int32_t iguana_rwbuf(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *buf) { if (rwflag != 0) @@ -228,7 +234,7 @@ int32_t NSPV_rwtxidsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidsres len += NSPV_rwtxidresp(rwflag,&serialized[len],&ptr->txids[i]); } len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->filter),&ptr->filter); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->maxrecords),&ptr->maxrecords); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); if ( rwflag != 0 ) diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index bf9ab1e7400..c84cf96b021 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -118,8 +118,8 @@ struct NSPV_txidsresp { struct NSPV_txidresp *txids; char coinaddr[64]; - int32_t nodeheight,skipcount,filter; - uint16_t numtxids,CCflag; + int32_t nodeheight, skipcount, maxrecords; + uint16_t numtxids, CCflag; }; struct NSPV_mempoolresp @@ -208,6 +208,7 @@ struct NSPV_remoterpcresp char *json; }; +extern struct NSPV_inforesp NSPV_inforesult; void NSPV_CCunspents(std::vector>& unspentOutputs, char* coinaddr, bool ccflag); void NSPV_CCindexOutputs(std::vector>& indexOutputs, char* coinaddr, bool ccflag); diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index a72a14b0622..78e3ed31881 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -19,6 +19,10 @@ // NSPV_get... functions need to return the exact serialized length, which is the size of the structure minus size of pointers, plus size of allocated data +#include + +#include "main.h" +#include "komodo_defs.h" #include "notarisationdb.h" #include "rpc/server.h" #include "cc/CCinclude.h" @@ -103,6 +107,8 @@ int32_t NSPV_notarized_bracket(struct NSPV_ntzargs *prev,struct NSPV_ntzargs *ne int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint256 desttxid,int32_t ntzheight) { CBlockIndex *pindex; + + LOCK(cs_main); ptr->blockhash = *chainActive[ntzheight]->phashBlock; ptr->height = ntzheight; ptr->txidheight = txidht; @@ -116,8 +122,11 @@ int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint int32_t NSPV_getntzsresp(struct NSPV_ntzsresp *ptr,int32_t origreqheight) { struct NSPV_ntzargs prev,next; int32_t reqheight = origreqheight; - if ( reqheight < chainActive.LastTip()->GetHeight() ) - reqheight++; + { + LOCK(cs_main); + if ( reqheight < chainActive.LastTip()->GetHeight() ) + reqheight++; + } if ( NSPV_notarized_bracket(&prev,&next,reqheight) == 0 ) { if ( prev.ntzheight != 0 ) @@ -138,6 +147,8 @@ int32_t NSPV_getntzsresp(struct NSPV_ntzsresp *ptr,int32_t origreqheight) int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) { CBlockIndex *pindex; + LOCK(cs_main); + if ( (pindex= komodo_chainactive(height)) != 0 ) { hdr->nVersion = pindex->nVersion; @@ -157,19 +168,22 @@ int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) { - int32_t prevMoMheight,len = 0; CBlockIndex *pindex, *pindex2; struct NSPV_ntzsresp pair; - if ( (pindex= chainActive.LastTip()) != 0 ) - { + int32_t prevMoMheight, len = 0; + CBlockIndex *pindex, *pindex2; + struct NSPV_ntzsresp pair; + LOCK(cs_main); + + if ((pindex = chainActive.LastTip()) != 0) { ptr->height = pindex->GetHeight(); ptr->blockhash = pindex->GetBlockHash(); - memset(&pair,0,sizeof(pair)); - if ( NSPV_getntzsresp(&pair,ptr->height-1) < 0 ) - return(-1); + memset(&pair, 0, sizeof(pair)); + if (NSPV_getntzsresp(&pair, ptr->height - 1) < 0) + return (-1); ptr->notarization = pair.prevntz; - if ( (pindex2= komodo_chainactive(ptr->notarization.txidheight)) != 0 ) - ptr->notarization.timestamp = pindex->nTime; + if ((pindex2 = komodo_chainactive(ptr->notarization.txidheight)) != 0) + ptr->notarization.timestamp = pindex2->nTime; //fprintf(stderr, "timestamp.%i\n", ptr->notarization.timestamp ); - if ( reqheight == 0 ) + if (reqheight == 0) reqheight = ptr->height; ptr->hdrheight = reqheight; ptr->version = NSPV_PROTOCOL_VERSION; @@ -180,17 +194,30 @@ int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) return (-1); } -int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC,int32_t skipcount,uint32_t filter) +int32_t NSPV_getaddressutxos(struct NSPV_utxosresp* ptr, char* coinaddr, bool isCC, int32_t skipcount, int32_t maxrecords) { - int64_t total = 0,interest=0; uint32_t locktime; int32_t ind=0,tipheight,maxlen,txheight,n = 0,len = 0; - std::vector > unspentOutputs; - SetCCunspents(unspentOutputs,coinaddr,isCC); - maxlen = MAX_BLOCK_SIZE(tipheight) - 512; - maxlen /= sizeof(*ptr->utxos); - strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); + CAmount total = 0LL, interest = 0LL; + uint32_t locktime; + int32_t ind = 0, tipheight, /*maxlen,*/ txheight, n = 0; + + std::vector> unspentOutputs; + SetCCunspents(unspentOutputs, coinaddr, isCC); + + { + LOCK(cs_main); + tipheight = chainActive.LastTip()->GetHeight(); + } + + // use maxrecords + //maxlen = MAX_BLOCK_SIZE(tipheight) - 512; + //maxlen /= sizeof(*ptr->utxos); + if (maxrecords <= 0 || maxrecords >= std::numeric_limits::max()) + maxrecords = std::numeric_limits::max(); // prevent large requests + + strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = isCC; - ptr->filter = filter; - if ( skipcount < 0 ) + ptr->maxrecords = maxrecords; + if (skipcount < 0) skipcount = 0; ptr->skipcount = skipcount; ptr->utxos = nullptr; @@ -204,21 +231,14 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC it != unspentOutputs.end() && ind < maxrecords; it++) { // if gettxout is != null to handle mempool { - // if gettxout is != null to handle mempool - { - if ( n >= skipcount && myIsutxo_spentinmempool(ignoretxid,ignorevin,it->first.txhash,(int32_t)it->first.index) == 0 ) - { - ptr->utxos[ind].txid = it->first.txhash; - ptr->utxos[ind].vout = (int32_t)it->first.index; - ptr->utxos[ind].satoshis = it->second.satoshis; - ptr->utxos[ind].height = it->second.blockHeight; - if ( ASSETCHAINS_SYMBOL[0] == 0 && it->second.satoshis >= 10*COIN ) - { - ptr->utxos[n].extradata = komodo_accrued_interest(&txheight,&locktime,ptr->utxos[ind].txid,ptr->utxos[ind].vout,ptr->utxos[ind].height,ptr->utxos[ind].satoshis,tipheight); - interest += ptr->utxos[ind].extradata; - } - ind++; - total += it->second.satoshis; + if (!myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index)) { + ptr->utxos[ind].txid = it->first.txhash; + ptr->utxos[ind].vout = (int32_t)it->first.index; + ptr->utxos[ind].satoshis = it->second.satoshis; + ptr->utxos[ind].height = it->second.blockHeight; + if (IS_KMD_CHAIN() && it->second.satoshis >= 10 * COIN) { // calc interest on the kmd chain + ptr->utxos[n].extradata = komodo_accrued_interest(&txheight, &locktime, ptr->utxos[ind].txid, ptr->utxos[ind].vout, ptr->utxos[ind].height, ptr->utxos[ind].satoshis, tipheight); + interest += ptr->utxos[ind].extradata; } ptr->utxos[ind].script = (uint8_t*)malloc(it->second.script.size()); memcpy(ptr->utxos[ind].script, &it->second.script[0], it->second.script.size()); @@ -227,17 +247,9 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC ind++; total += it->second.satoshis; } + n++; } } - ptr->numutxos = ind; - if ( len < maxlen ) - { - len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->utxos)*ptr->numutxos - sizeof(ptr->utxos)); - //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); - ptr->total = total; - ptr->interest = interest; - return(len); - } } // always return a result: ptr->numutxos = ind; @@ -321,7 +333,7 @@ class DefaultCCChecker : public BaseCCChecker { isEof = ss.eof(); ); opretTxid = revuint256(opretTxid); - std::cerr << __func__ << " " << "opretEvalcode=" << opretEvalcode << " opretFuncid=" << (char)opretFuncid << " isCreateTx=" << isCreateTx << " opretTxid=" << opretTxid.GetHex() << std::endl; + //std::cerr << __func__ << " " << "opretEvalcode=" << opretEvalcode << " opretFuncid=" << (char)opretFuncid << " isCreateTx=" << isCreateTx << " opretTxid=" << opretTxid.GetHex() << std::endl; if( parseOk /*parseOk=true if eof reached*/|| !isEof /*more data means okay*/) { if (evalcode == opretEvalcode && std::find(funcids.begin(), funcids.end(), (char)opretFuncid) != funcids.end() && @@ -362,6 +374,10 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ std::vector > unspentOutputs; SetCCunspents(unspentOutputs, coinaddr, true); + { + LOCK(cs_main); + tipheight = chainActive.LastTip()->GetHeight(); + } maxlen = MAX_BLOCK_SIZE(tipheight) - 512; //maxlen /= sizeof(*ptr->utxos); // TODO why was this? we need maxlen in bytes, don't we? @@ -372,12 +388,12 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ ptr->numutxos = 0; strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = 1; - tipheight = chainActive.LastTip()->GetHeight(); + ptr->nodeheight = tipheight; // will be checked in libnspv //} // select all appropriate utxos: - std::cerr << __func__ << " " << "searching addr=" << coinaddr << std::endl; + //std::cerr << __func__ << " " << "searching addr=" << coinaddr << std::endl; for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { if (myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index) == 0) @@ -393,7 +409,7 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ // if a checker is set for evalcode use it otherwise use the default checker: if (baseChecker && baseChecker->checkCC(it->first.txhash, tx.vout, nvout, evalcode, funcids, filtertxid) || defaultCCChecker.checkCC(it->first.txhash, tx.vout, nvout, evalcode, funcids, filtertxid)) { - std::cerr << __func__ << " " << "filtered utxo with amount=" << tx.vout[nvout].nValue << std::endl; + //std::cerr << __func__ << " " << "filtered utxo with amount=" << tx.vout[nvout].nValue << std::endl; struct CC_utxo utxo; utxo.txid = it->first.txhash; @@ -409,7 +425,6 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ } } - if (amount == 0) { // just return total value ptr->total = total; @@ -475,18 +490,28 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ } } -int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC,int32_t skipcount,uint32_t filter) +int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool isCC, int32_t skipcount, int32_t maxrecords) { - int32_t maxlen,txheight,ind=0,n = 0,len = 0; CTransaction tx; uint256 hashBlock; - std::vector > txids; - SetAddressIndexOutputs(txids,coinaddr,isCC); - ptr->nodeheight = chainActive.LastTip()->GetHeight(); - maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; - maxlen /= sizeof(*ptr->txids); - strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); + int32_t txheight, ind = 0, len = 0; + //CTransaction tx; + //uint256 hashBlock; + std::vector> txids; + SetAddressIndexOutputs(txids, coinaddr, isCC); + { + LOCK(cs_main); + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + } + + // using maxrecords instead: + //maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; + //maxlen /= sizeof(*ptr->txids); + if (maxrecords <= 0 || maxrecords >= std::numeric_limits::max()) + maxrecords = std::numeric_limits::max(); // prevent large requests + + strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = isCC; - ptr->filter = filter; - if ( skipcount < 0 ) + ptr->maxrecords = maxrecords; + if (skipcount < 0) skipcount = 0; ptr->skipcount = skipcount; ptr->txids = nullptr; @@ -502,140 +527,141 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC ind++; } - ptr->numtxids = ind; - len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); - return(len); } - if ( ptr->txids != 0 ) + // always return a result: + ptr->numtxids = ind; + len = (int32_t)(sizeof(*ptr) + sizeof(ptr->txids[0]) * ptr->numtxids - sizeof(ptr->txids)); + return (len); + /*if (ptr->txids != nullptr) free(ptr->txids); - memset(ptr,0,sizeof(*ptr)); - return(0); + memset(ptr, 0, sizeof(*ptr)); + return (0);*/ } -int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector &txids,char *coinaddr,bool isCC,uint8_t funcid,uint256 txid,int32_t vout) +// get txids from addressindex or mempool by different criteria +// looks like as a set of ad-hoc functions and it should be rewritten +int32_t NSPV_mempoolfuncs(bits256* satoshisp, int32_t* vindexp, std::vector& txids, char* coinaddr, bool isCC, uint8_t funcid, uint256 txid, int32_t vout) { - int32_t num = 0,vini = 0,vouti = 0; uint8_t evalcode=0,func=0; std::vector vopret; char destaddr[64]; + int32_t num = 0, vini = 0, vouti = 0; + uint8_t evalcode = 0, func = 0; + std::vector vopret; + char destaddr[64]; *vindexp = -1; - memset(satoshisp,0,sizeof(*satoshisp)); - if ( funcid == NSPV_CC_TXIDS) - { - std::vector > tmp_txids; uint256 tmp_txid,hashBlock; - int32_t n=0,skipcount=vout>>16; uint8_t eval=(vout>>8)&0xFF, func=vout&0xFF; + memset(satoshisp, 0, sizeof(*satoshisp)); + if (funcid == NSPV_CC_TXIDS) { + std::vector> tmp_txids; + uint256 tmp_txid, hashBlock; + int32_t n = 0, skipcount = vout >> 16; + uint8_t eval = (vout >> 8) & 0xFF, func = vout & 0xFF; CTransaction tx; - SetAddressIndexOutputs(tmp_txids,coinaddr,isCC); - if ( skipcount < 0 ) skipcount = 0; - if ( skipcount >= tmp_txids.size() ) - skipcount = tmp_txids.size()-1; - if ( tmp_txids.size()-skipcount > 0 ) - { - for (std::vector >::const_iterator it=tmp_txids.begin(); it!=tmp_txids.end(); it++) - { - if (txid!=zeroid || func!=0) - { - myGetTransaction(it->first.txhash,tx,hashBlock); - std::vector oprets; uint256 tokenid,txid; - std::vector vopret,vOpretExtra; uint8_t *script,e,f; + SetAddressIndexOutputs(tmp_txids, coinaddr, isCC); + if (skipcount < 0) + skipcount = 0; + if (skipcount >= tmp_txids.size()) + skipcount = tmp_txids.size() - 1; + if (tmp_txids.size() - skipcount > 0) { + for (std::vector>::const_iterator it = tmp_txids.begin(); it != tmp_txids.end(); it++) { + if (txid != zeroid || func != 0) { + myGetTransaction(it->first.txhash, tx, hashBlock); + std::vector oprets; + uint256 tokenid, txid; + std::vector vopret, vOpretExtra; + uint8_t *script, e, f; std::vector pubkeys; - if (DecodeTokenOpRetV1(tx.vout[tx.vout.size()-1].scriptPubKey,tokenid,pubkeys,oprets)!=0 && GetOpReturnCCBlob(oprets, vOpretExtra) && vOpretExtra.size()>0) - { - vopret=vOpretExtra; - } - else GetOpReturnData(tx.vout[tx.vout.size()-1].scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && script[0]==eval ) - { - switch (eval) - { - case EVAL_CHANNELS:EVAL_PEGS:EVAL_ORACLES:EVAL_GAMES:EVAL_IMPORTGATEWAY:EVAL_ROGUE: - E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> tmp_txid;); - if (e!=eval || (txid!=zeroid && txid!=tmp_txid) || (func!=0 && f!=func)) continue; - break; - case EVAL_TOKENS:EVAL_DICE:EVAL_DILITHIUM:EVAL_FAUCET:EVAL_LOTO:EVAL_PAYMENTS:EVAL_REWARDS: - E_UNMARSHAL(vopret,ss >> e; ss >> f;); - if (e!=eval || (func!=0 && f!=func)) continue; - break; - default: - break; + if (DecodeTokenOpRetV1(tx.vout[tx.vout.size() - 1].scriptPubKey, tokenid, pubkeys, oprets) != 0 && GetOpReturnCCBlob(oprets, vOpretExtra) && vOpretExtra.size() > 0) { + vopret = vOpretExtra; + } else + GetOpReturnData(tx.vout[tx.vout.size() - 1].scriptPubKey, vopret); + script = (uint8_t*)vopret.data(); + if (vopret.size() > 2 && script[0] == eval) { + switch (eval) { + case EVAL_CHANNELS: + EVAL_PEGS: + EVAL_ORACLES: + EVAL_GAMES: + EVAL_IMPORTGATEWAY: + EVAL_ROGUE: + E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> tmp_txid;); + if (e != eval || (txid != zeroid && txid != tmp_txid) || (func != 0 && f != func)) + continue; + break; + case EVAL_TOKENS: + EVAL_DICE: + EVAL_DILITHIUM: + EVAL_FAUCET: + EVAL_LOTO: + EVAL_PAYMENTS: + EVAL_REWARDS: + E_UNMARSHAL(vopret, ss >> e; ss >> f;); + if (e != eval || (func != 0 && f != func)) + continue; + break; + default: + break; } - } + } } - if ( n >= skipcount ) txids.push_back(it->first.txhash); + if (n >= skipcount) + txids.push_back(it->first.txhash); n++; } - return (n-skipcount); + return (n - skipcount); } return (0); } - if ( mempool.size() == 0 ) - return(0); - if ( funcid == NSPV_MEMPOOL_CCEVALCODE ) - { + if (mempool.size() == 0) + return (0); + if (funcid == NSPV_MEMPOOL_CCEVALCODE) { isCC = true; evalcode = vout & 0xff; func = (vout >> 8) & 0xff; } LOCK(mempool.cs); - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - if ( funcid == NSPV_MEMPOOL_ALL ) - { + BOOST_FOREACH (const CTxMemPoolEntry& e, mempool.mapTx) { + const CTransaction& tx = e.GetTx(); + const uint256& hash = tx.GetHash(); + if (funcid == NSPV_MEMPOOL_ALL) { txids.push_back(hash); num++; continue; - } - else if ( funcid == NSPV_MEMPOOL_INMEMPOOL ) - { - if ( hash == txid ) - { + } else if (funcid == NSPV_MEMPOOL_INMEMPOOL) { + if (hash == txid) { txids.push_back(hash); - return(++num); + return (++num); } continue; - } - else if ( funcid == NSPV_MEMPOOL_CCEVALCODE ) - { - if ( tx.vout.size() > 1 ) - { - CScript scriptPubKey = tx.vout[tx.vout.size()-1].scriptPubKey; - if ( GetOpReturnData(scriptPubKey,vopret) != 0 ) - { - if ( vopret[0] != evalcode || (func!=0 && vopret[1] != func) ) continue; + } else if (funcid == NSPV_MEMPOOL_CCEVALCODE) { + if (tx.vout.size() > 1) { + CScript scriptPubKey = tx.vout[tx.vout.size() - 1].scriptPubKey; + if (GetOpReturnData(scriptPubKey, vopret) != 0) { + if (vopret[0] != evalcode || (func != 0 && vopret[1] != func)) + continue; txids.push_back(hash); num++; } } continue; } - if ( funcid == NSPV_MEMPOOL_ISSPENT ) - { - BOOST_FOREACH(const CTxIn &txin,tx.vin) - { + if (funcid == NSPV_MEMPOOL_ISSPENT) { + BOOST_FOREACH (const CTxIn& txin, tx.vin) { //fprintf(stderr,"%s/v%d ",uint256_str(str,txin.prevout.hash),txin.prevout.n); - if ( txin.prevout.n == vout && txin.prevout.hash == txid ) - { + if (txin.prevout.n == vout && txin.prevout.hash == txid) { txids.push_back(hash); *vindexp = vini; - return(++num); + return (++num); } vini++; } - } - else if ( funcid == NSPV_MEMPOOL_ADDRESS ) - { - BOOST_FOREACH(const CTxOut &txout,tx.vout) - { - if ( txout.scriptPubKey.IsPayToCryptoCondition() == isCC ) - { - Getscriptaddress(destaddr,txout.scriptPubKey); - if ( strcmp(destaddr,coinaddr) == 0 ) - { + } else if (funcid == NSPV_MEMPOOL_ADDRESS) { + BOOST_FOREACH (const CTxOut& txout, tx.vout) { + if (txout.scriptPubKey.IsPayToCryptoCondition() == isCC) { + Getscriptaddress(destaddr, txout.scriptPubKey); + if (strcmp(destaddr, coinaddr) == 0) { txids.push_back(hash); *vindexp = vouti; - if ( num < 4 ) + if (num < 4) satoshisp->ulongs[num] = txout.nValue; num++; } @@ -645,44 +671,45 @@ int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector txids; bits256 satoshis; uint256 tmp,tmpdest; int32_t i,len = 0; - ptr->nodeheight = chainActive.LastTip()->GetHeight(); - strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); + std::vector txids; + bits256 satoshis; + uint256 tmp, tmpdest; + int32_t i, len = 0; + { + LOCK(cs_main); + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + } + strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = isCC; ptr->txid = txid; ptr->vout = vout; ptr->funcid = funcid; - if ( NSPV_mempoolfuncs(&satoshis,&ptr->vindex,txids,coinaddr,isCC,funcid,txid,vout) >= 0 ) - { - if ( (ptr->numtxids= (int32_t)txids.size()) >= 0 ) - { - if ( ptr->numtxids > 0 ) - { - ptr->txids = (uint256 *)calloc(ptr->numtxids,sizeof(*ptr->txids)); - for (i=0; inumtxids; i++) - { + if (NSPV_mempoolfuncs(&satoshis, &ptr->vindex, txids, coinaddr, isCC, funcid, txid, vout) >= 0) { + if ((ptr->numtxids = (int32_t)txids.size()) >= 0) { + if (ptr->numtxids > 0) { + ptr->txids = (uint256*)calloc(ptr->numtxids, sizeof(*ptr->txids)); + for (i = 0; i < ptr->numtxids; i++) { tmp = txids[i]; - iguana_rwbignum(IGUANA_READ,(uint8_t *)&tmp,sizeof(*ptr->txids),(uint8_t *)&ptr->txids[i]); + iguana_rwbignum(IGUANA_READ, (uint8_t*)&tmp, sizeof(*ptr->txids), (uint8_t*)&ptr->txids[i]); } } - if ( funcid == NSPV_MEMPOOL_ADDRESS ) - { - memcpy(&tmp,&satoshis,sizeof(tmp)); - iguana_rwbignum(IGUANA_READ,(uint8_t *)&tmp,sizeof(ptr->txid),(uint8_t *)&ptr->txid); + if (funcid == NSPV_MEMPOOL_ADDRESS) { + memcpy(&tmp, &satoshis, sizeof(tmp)); + iguana_rwbignum(IGUANA_READ, (uint8_t*)&tmp, sizeof(ptr->txid), (uint8_t*)&ptr->txid); } - len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); - return(len); + len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids) * ptr->numtxids - sizeof(ptr->txids)); + return (len); } } - if ( ptr->txids != 0 ) + if (ptr->txids != 0) free(ptr->txids); - memset(ptr,0,sizeof(*ptr)); - return(0); + memset(ptr, 0, sizeof(*ptr)); + return (0); } int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n) @@ -727,7 +754,7 @@ int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n) rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id); response=rpc_result.write(); } - catch (const runtime_error& e) + catch (const std::runtime_error& e) { rpc_result = JSONRPCReplyObj(NullUniValue,JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); response=rpc_result.write(); @@ -753,7 +780,7 @@ uint8_t *NSPV_getrawtx(CTransaction &tx,uint256 &hashBlock,int32_t *txlenp,uint2 //fprintf(stderr,"error getting transaction %s\n",txid.GetHex().c_str()); return(0); } - string strHex = EncodeHexTx(tx); + std::string strHex = EncodeHexTx(tx); *txlenp = (int32_t)strHex.size() >> 1; if ( *txlenp > 0 ) { @@ -773,7 +800,7 @@ int32_t NSPV_sendrawtransaction(struct NSPV_broadcastresp *ptr,uint8_t *data,int //LOCK(cs_main); ptr->txid = tx.GetHash(); //fprintf(stderr,"try to addmempool transaction %s\n",ptr->txid.GetHex().c_str()); - if ( myAddtomempool(tx) != 0 ) + if (myAddtomempool(tx) != 0) { ptr->retcode = 1; //int32_t i; @@ -781,53 +808,58 @@ int32_t NSPV_sendrawtransaction(struct NSPV_broadcastresp *ptr,uint8_t *data,int // fprintf(stderr,"%02x",data[i]); fprintf(stderr," relay transaction %s retcode.%d\n",ptr->txid.GetHex().c_str(),ptr->retcode); RelayTransaction(tx); - } else ptr->retcode = -3; + } + else + ptr->retcode = -3; - } else ptr->retcode = -1; + } + else + ptr->retcode = -1; return(sizeof(*ptr)); } // get txproof for txid, // to get the proof object the height should be passed // otherwise only block hash alone will be returned -int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid, int32_t height) +// Note: not clear why we should have passed the height? Txid is sufficient, let's ignore height +int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid /*, int32_t height*/) { - int32_t flag = 0, len = 0; + int32_t len = 0; CTransaction _tx; uint256 hashBlock; CBlock block; CBlockIndex* pindex; ptr->height = -1; - if ((ptr->tx = NSPV_getrawtx(_tx, hashBlock, &ptr->txlen, txid)) != 0) { + if ((ptr->tx = NSPV_getrawtx(_tx, hashBlock, &ptr->txlen, txid)) != nullptr) { ptr->txid = txid; ptr->vout = vout; ptr->hashblock = hashBlock; - if (height == 0) + { + LOCK(cs_main); ptr->height = komodo_blockheight(hashBlock); - else { - ptr->height = height; - if ((pindex = komodo_chainactive(height)) != 0 && komodo_blockload(block, pindex) == 0) { - BOOST_FOREACH (const CTransaction& tx, block.vtx) { - if (tx.GetHash() == txid) { - flag = 1; - break; - } + pindex = komodo_chainactive(ptr->height); + } + if (pindex != nullptr && komodo_blockload(block, pindex) == 0) { + bool found = false; + BOOST_FOREACH (const CTransaction& tx, block.vtx) { + if (tx.GetHash() == txid) { + found = true; + break; } - if (flag != 0) { - set setTxids; - CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); - setTxids.insert(txid); - CMerkleBlock mb(block, setTxids); - ssMB << mb; - std::vector proof(ssMB.begin(), ssMB.end()); - ptr->txprooflen = (int32_t)proof.size(); - LogPrint("nspv-details", "%s txid.%s found txproof.(%s) height.%d\n", __func__, txid.GetHex().c_str(), HexStr(proof).c_str(), ptr->height); - if (ptr->txprooflen > 0) { - ptr->txproof = (uint8_t*)calloc(1, ptr->txprooflen); - memcpy(ptr->txproof, &proof[0], ptr->txprooflen); - } - //fprintf(stderr,"gettxproof slen.%d\n",(int32_t)(sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen)); + } + if (found) { + std::set setTxids; + CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); + setTxids.insert(txid); + CMerkleBlock mb(block, setTxids); + ssMB << mb; + std::vector proof(ssMB.begin(), ssMB.end()); + ptr->txprooflen = (int32_t)proof.size(); + LogPrint("nspv-details", "%s txid.%s found txproof.(%s) height.%d\n", __func__, txid.GetHex().c_str(), HexStr(proof).c_str(), ptr->height); + if (ptr->txprooflen > 0) { + ptr->txproof = (uint8_t*)calloc(1, ptr->txprooflen); + memcpy(ptr->txproof, &proof[0], ptr->txprooflen); } //fprintf(stderr,"gettxproof respLen.%d\n",(int32_t)(sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen)); } @@ -892,24 +924,22 @@ int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp* ptr, uint256 prevntztxi return (sizeof(*ptr) + (sizeof(*ptr->common.hdrs) + NSPV_MAX_VARINT_SIZE) * ptr->common.numhdrs - sizeof(ptr->common.hdrs) - sizeof(ptr->prevntz) - sizeof(ptr->nextntz) + ptr->prevtxlen + ptr->nexttxlen); } -int32_t NSPV_getspentinfo(struct NSPV_spentinfo *ptr,uint256 txid,int32_t vout) +int32_t NSPV_getspentinfo(struct NSPV_spentinfo* ptr, uint256 txid, int32_t vout) { int32_t len = 0; ptr->txid = txid; ptr->vout = vout; ptr->spentvini = -1; len = (int32_t)(sizeof(*ptr) - sizeof(ptr->spent.tx) - sizeof(ptr->spent.txproof)); - if ( CCgetspenttxid(ptr->spent.txid,ptr->spentvini,ptr->spent.height,txid,vout) == 0 ) - { - if ( NSPV_gettxproof(&ptr->spent,0,ptr->spent.txid,ptr->spent.height) > 0 ) + if (CCgetspenttxid(ptr->spent.txid, ptr->spentvini, ptr->spent.height, txid, vout) == 0) { + if (NSPV_gettxproof(&ptr->spent, 0, ptr->spent.txid /*,ptr->spent.height*/) > 0) len += ptr->spent.txlen + ptr->spent.txprooflen; - else - { + else { NSPV_txproof_purge(&ptr->spent); - return(-1); + return (-1); } } - return(len); + return (len); } static void NSPV_senderror(CNode* pfrom, uint32_t requestId, int32_t err) @@ -1066,7 +1096,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re return; } - LogPrint("nspv-details", "NSPV_UTXOS address=%s isCC.%d skipcount.%d filter.%x\n", coinaddr, isCC, skipcount, filter); + LogPrint("nspv-details", "NSPV_UTXOS address=%s isCC.%d skipcount.%d maxrecords.%d\n", coinaddr, isCC, skipcount, maxrecords); memset(&U, 0, sizeof(U)); if ((respLen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, maxrecords)) > 0) { response.resize(nspvHeaderSize + respLen); @@ -1087,7 +1117,6 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); } } - break; case NSPV_TXIDS: @@ -1501,7 +1530,6 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; - LogPrint("nspv-details", "NSPV_CCMODULEUTXOS returned %d utxos to node=%d\n", (int)U.numutxos, pfrom->id); } else { LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", respLen); diff --git a/src/komodo_nSPV_superlite.h b/src/komodo_nSPV_superlite.h index 960802c062b..fc63b0f82e1 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -17,6 +17,15 @@ #ifndef KOMODO_NSPVSUPERLITE_H #define KOMODO_NSPVSUPERLITE_H +#include + +#include "main.h" +#include "komodo_defs.h" +#include "notarisationdb.h" +#include "rpc/server.h" +#include "cc/CCinclude.h" +#include "komodo_nSPV_defs.h" +#include "komodo_nSPV.h" #include "komodo_DEX.h" // nSPV client. VERY simplistic "single threaded" networking model. for production GUI best to multithread, etc. @@ -231,17 +240,17 @@ CNode *NSPV_req(CNode *pnode,uint8_t *msg,int32_t len,uint64_t mask,int32_t ind) n = 0; BOOST_FOREACH(CNode *ptr,vNodes) { - if ( ptr->prevtimes[ind] > timestamp ) - ptr->prevtimes[ind] = 0; + if ( ptr->nspvdata[ind].prevtime > timestamp ) + ptr->nspvdata[ind].prevtime = 0; if ( ptr->hSocket == INVALID_SOCKET ) continue; - if ( (ptr->nServices & mask) == mask && timestamp > ptr->prevtimes[ind] ) + if ( (ptr->nServices & mask) == mask && timestamp > ptr->nspvdata[ind].prevtime ) { flag = 1; pnodes[n++] = ptr; if ( n == sizeof(pnodes)/sizeof(*pnodes) ) break; - } // else fprintf(stderr,"nServices %llx vs mask %llx, t%u vs %u, ind.%d\n",(long long)ptr->nServices,(long long)mask,timestamp,ptr->prevtimes[ind],ind); + } // else fprintf(stderr,"nServices %llx vs mask %llx, t%u vs %u, ind.%d\n",(long long)ptr->nServices,(long long)mask,timestamp,ptr->nspvdata[ind].prevtime,ind); } if ( n > 0 ) pnode = pnodes[rand() % n]; @@ -254,7 +263,7 @@ CNode *NSPV_req(CNode *pnode,uint8_t *msg,int32_t len,uint64_t mask,int32_t ind) if ( (0) && KOMODO_NSPV_SUPERLITE ) fprintf(stderr,"pushmessage [%d] len.%d\n",msg[0],len); pnode->PushMessage("getnSPV",request); - pnode->prevtimes[ind] = timestamp; + pnode->nspvdata[ind].prevtime = timestamp; return(pnode); } else fprintf(stderr,"no pnodes\n"); return(0); @@ -285,11 +294,11 @@ void komodo_nSPV(CNode *pto) // polling loop from SendMessages NSPV_logout(); if ( (pto->nServices & NODE_NSPV) == 0 ) return; - if ( pto->prevtimes[NSPV_INFO>>1] > timestamp ) - pto->prevtimes[NSPV_INFO>>1] = 0; + if ( pto->nspvdata[NSPV_INFO>>1].prevtime > timestamp ) + pto->nspvdata[NSPV_INFO>>1].prevtime = 0; if ( KOMODO_NSPV_SUPERLITE ) { - if ( timestamp > NSPV_lastinfo + ASSETCHAINS_BLOCKTIME/2 && timestamp > pto->prevtimes[NSPV_INFO>>1] + 2*ASSETCHAINS_BLOCKTIME/3 ) + if ( timestamp > NSPV_lastinfo + ASSETCHAINS_BLOCKTIME/2 && timestamp > pto->nspvdata[NSPV_INFO>>1].prevtime + 2*ASSETCHAINS_BLOCKTIME/3 ) { int32_t reqht; reqht = 0; @@ -414,7 +423,7 @@ UniValue NSPV_utxosresp_json(struct NSPV_utxosresp *ptr) result.push_back(Pair("balance",(double)ptr->total/COIN)); if ( ASSETCHAINS_SYMBOL[0] == 0 ) result.push_back(Pair("interest",(double)ptr->interest/COIN)); - result.push_back(Pair("filter",(int64_t)ptr->filter)); + result.push_back(Pair("maxrecords",(int64_t)ptr->maxrecords)); result.push_back(Pair("lastpeer",NSPV_lastpeer)); return(result); } @@ -446,7 +455,7 @@ UniValue NSPV_txidsresp_json(struct NSPV_txidsresp *ptr) result.push_back(Pair("isCC",ptr->CCflag)); result.push_back(Pair("height",(int64_t)ptr->nodeheight)); result.push_back(Pair("numtxids",(int64_t)ptr->numtxids)); - result.push_back(Pair("filter",(int64_t)ptr->filter)); + result.push_back(Pair("maxrecords",(int64_t)ptr->maxrecords)); result.push_back(Pair("lastpeer",NSPV_lastpeer)); return(result); } diff --git a/src/komodo_nSPV_wallet.h b/src/komodo_nSPV_wallet.h index 3c13ee817f8..fc7793e8694 100644 --- a/src/komodo_nSPV_wallet.h +++ b/src/komodo_nSPV_wallet.h @@ -23,9 +23,8 @@ #include "komodo_nSPV_superlite.h" - // nSPV wallet uses superlite functions (and some komodod built in functions) to implement nSPV_spend -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +//extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); int32_t NSPV_validatehdrs(struct NSPV_ntzsproofresp *ptr) { @@ -396,6 +395,7 @@ UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis) // what its a mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; mtx.nVersion = SAPLING_TX_VERSION; if ( ASSETCHAINS_SYMBOL[0] == 0 ) { + LOCK(cs_main); if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) mtx.nLockTime = (uint32_t)time(NULL) - 777; else diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 56fd73d6230..23ed5b7df10 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -12,9 +12,12 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ -#include "komodo_defs.h" #include "key_io.h" +#include "net.h" +#include "util.h" +#include "komodo_defs.h" #include "cc/CCinclude.h" +#include "importcoin.h" #include #ifdef _WIN32 @@ -1669,10 +1672,6 @@ uint64_t komodo_ac_block_subsidy(int nHeight) return(subsidy); } -extern int64_t MAX_MONEY; -void komodo_cbopretupdate(int32_t forceflag); -void SplitStr(const std::string& strVal, std::vector &outVals); - int8_t equihash_params_possible(uint64_t n, uint64_t k) { /* To add more of these you also need to edit: @@ -1772,10 +1771,10 @@ void komodo_args(char *argv0) ASSETCHAINS_PUBLIC = GetArg("-ac_public",0); ASSETCHAINS_PRIVATE = GetArg("-ac_private",0); KOMODO_SNAPSHOT_INTERVAL = GetArg("-ac_snapshot",0); - Split(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); + SplitIntoU64List(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); // -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height.... - Split(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), ccEnablesHeight, 0); + SplitIntoU64List(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), ccEnablesHeight, 0); // fill map with all eval codes and activation height of 0. for ( int i = 0; i < 256; i++ ) mapHeightEvalActivate[i] = 0; @@ -1849,11 +1848,11 @@ void komodo_args(char *argv0) ASSETCHAINS_TIMEUNLOCKFROM = ASSETCHAINS_TIMEUNLOCKTO = 0; } - Split(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0); - Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0); - Split(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0); - Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); - Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); + SplitIntoU64List(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0); + SplitIntoU64List(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0); + SplitIntoU64List(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0); + SplitIntoU64List(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); + SplitIntoU64List(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); for ( int i = 0; i < ASSETCHAINS_MAX_ERAS; i++ ) { @@ -1923,7 +1922,7 @@ void komodo_args(char *argv0) { uint8_t prevCCi = 0; ASSETCHAINS_CCLIB = GetArg("-ac_cclib",""); - Split(GetArg("-ac_ccenable",""), sizeof(ccenables)/sizeof(*ccenables), ccenables, 0); + SplitIntoU64List(GetArg("-ac_ccenable",""), sizeof(ccenables)/sizeof(*ccenables), ccenables, 0); for (i=nonz=0; i<0x100; i++) { if ( ccenables[i] != prevCCi && ccenables[i] != 0 ) @@ -1989,7 +1988,7 @@ void komodo_args(char *argv0) } else if ( ASSETCHAINS_SELFIMPORT == "PEGSCC") { - Split(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); + SplitIntoU64List(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); if (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_COMMISSION!=0) { fprintf(stderr,"when using import for pegsCC these must be set: -ac_end=1 -ac_perc=0\n"); @@ -2654,5 +2653,4 @@ uint32_t komodo_next_tx_locktime() return (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now else return (uint32_t)chainActive.Tip()->GetMedianTimePast(); -} - +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 6b3e382124a..7d114992d6e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -80,14 +80,14 @@ using namespace std; #define TMPFILE_START 100000000 CCriticalSection cs_main; -extern uint8_t NOTARY_PUBKEY33[33]; -extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI; +//extern uint8_t NOTARY_PUBKEY33[33]; +//extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI; int32_t KOMODO_NEWBLOCKS; -int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); +//int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); //void komodo_broadcast(CBlock *pblock,int32_t limit); -bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); -void komodo_setactivation(int32_t height); -void komodo_pricesupdate(int32_t height,CBlock *pblock); +//bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); +//void komodo_setactivation(int32_t height); +//void komodo_pricesupdate(int32_t height,CBlock *pblock); BlockMap mapBlockIndex; CChain chainActive; @@ -649,6 +649,7 @@ CBlockTreeDB *pblocktree = NULL; // Komodo globals #define KOMODO_ZCASH +#include "komodo_defs.h" #include "komodo.h" UniValue komodo_snapshot(int top) @@ -1456,7 +1457,7 @@ int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime) // from ac_private return(0); } -int32_t komodo_acpublic(uint32_t tiptime); +//int32_t komodo_acpublic(uint32_t tiptime); bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransaction& tx, CValidationState &state) { @@ -1817,7 +1818,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (limit > 0) { size_t n = tx.vin.size(); if (n > limit) { - LogPrint("mempool", "Dropping txid %s : too many transparent inputs %zu > limit %zu\n", tx.GetHash().ToString(), n, limit ); + LogPrint("mempool", "Dropping txid %s : too many transparent inputs %zu > limit %zu\n", tx.GetHash().ToString().c_str(), n, limit ); return state.Error("AcceptToMemoryPool: too many inputs"); } } @@ -1825,12 +1826,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa auto verifier = libzcash::ProofVerifier::Strict(); if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,chainActive.LastTip()->GetHeight()+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 ) { - fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n"); + LogPrint("mempool-tx", "%s: komodo_validate_interest failed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Error("AcceptToMemoryPool: komodo_validate_interest failed"); } if (!CheckTransaction(tiptime,tx, state, verifier, 0, 0)) { + LogPrint("mempool", "%s: CheckTransaction failed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return error("AcceptToMemoryPool: CheckTransaction failed"); // state must be already set } @@ -1838,13 +1840,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Check transaction contextually against the set of consensus rules which apply in the next block to be mined. if (!ContextualCheckTransaction(0,0,0,tx, state, nextBlockHeight, (dosLevel == -1) ? 10 : dosLevel)) { + LogPrint("mempool-tx", "%s: ContextualCheckTransaction failed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return error("AcceptToMemoryPool: ContextualCheckTransaction failed"); // state must be already set } //fprintf(stderr,"addmempool 2\n"); // Coinbase is only valid in a block, not as a loose transaction if (tx.IsCoinBase()) { - fprintf(stderr,"AcceptToMemoryPool coinbase as individual tx\n"); + LogPrint("mempool-tx", "%s: coinbase as individual tx not supported, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(100, error("AcceptToMemoryPool: coinbase as individual tx"), REJECT_INVALID, "coinbase"); } @@ -1852,7 +1855,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa string reason; if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) { - //fprintf(stderr,"AcceptToMemoryPool reject nonstandard transaction: %s\nscriptPubKey: %s\n",reason.c_str(),tx.vout[0].scriptPubKey.ToString().c_str()); + LogPrint("mempool-tx","%s reject nonstandard transaction: reason %s tx: %s\n", __func__, reason.c_str(), HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(0,error("AcceptToMemoryPool: nonstandard transaction: %s", reason), REJECT_NONSTANDARD, reason); } @@ -1861,7 +1864,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // be mined yet. if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) { - //fprintf(stderr,"AcceptToMemoryPool reject non-final\n"); + LogPrint("mempool-tx", "%s: reject non final, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(0, false, REJECT_NONSTANDARD, "non-final"); } //fprintf(stderr,"addmempool 3\n"); @@ -1869,7 +1872,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa uint256 hash = tx.GetHash(); if (pool.exists(hash)) { - //fprintf(stderr,"already in mempool\n"); + LogPrint("mempool-tx", "%s: reject already in mempool, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); } @@ -1882,6 +1885,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (pool.mapNextTx.count(outpoint)) { // Disable replacement feature for now + LogPrint("mempool-tx", "%s: transaction replacement in mempool not allowed, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Error("AcceptToMemoryPool: transaction replacement in mempool not allowed"); } } @@ -1915,14 +1919,17 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (view.HaveCoins(hash)) { //fprintf(stderr,"view.HaveCoins(hash) error\n"); + LogPrint("mempool-tx", "%s: already have coins, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Invalid(false, REJECT_DUPLICATE, "already have coins"); } if (tx.IsCoinImport() || tx.IsPegsImport()) { // Inverse of normal case; if input exists, it's been spent - if (ExistsImportTombstone(tx, view)) + if (ExistsImportTombstone(tx, view)) { + LogPrint("mempool-tx", "%s: import tombstone exists, tx: %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists"); + } } else { @@ -1935,7 +1942,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { if (pfMissingInputs) *pfMissingInputs = true; - fprintf(stderr,"%s missing inputs for tx %s prevout.hash=%s\n", __func__, tx.GetHash().GetHex().c_str(), txin.prevout.hash.GetHex().c_str()); //TODO: remove + LogPrint("mempool-tx", "%s missing inputs for tx %s prevout.hash=%s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str(), txin.prevout.hash.GetHex().c_str()); return false; /* https://github.com/zcash/zcash/blob/master/src/main.cpp#L1490 @@ -1947,6 +1954,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (!view.HaveInputs(tx)) { //fprintf(stderr,"accept failure.1\n"); + LogPrint("mempool-tx", "%s inputs already spent for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); } } @@ -1968,8 +1976,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa view.SetBackend(dummy); } // Check for non-standard pay-to-script-hash in inputs - if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId)) + if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId)) { + LogPrint("mempool-tx", "%s reject nonstandard transaction input for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Error("AcceptToMemoryPool: reject nonstandard transaction input"); + } // Check that the transaction doesn't have an excessive number of // sigops, making it impossible to mine. Since the coinbase transaction @@ -1987,8 +1997,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa CAmount nValueOut = tx.GetValueOut(); CAmount nFees = nValueIn-nValueOut; double dPriority = view.GetPriority(tx, chainActive.Height()); - if ( nValueOut > 777777*COIN && KOMODO_VALUETOOBIG(nValueOut - 777777*COIN) != 0 ) // some room for blockreward and txfees + if ( nValueOut > 777777*COIN && KOMODO_VALUETOOBIG(nValueOut - 777777*COIN) != 0 ) { // some room for blockreward and txfees + LogPrint("mempool-tx", "%s GetValueOut too big for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(100, error("AcceptToMemoryPool: GetValueOut too big"),REJECT_INVALID,"tx valueout is too big"); + } // Keep track of transactions that spend a coinbase, which we re-scan // during reorgs to ensure COINBASE_MATURITY is still met. @@ -2020,7 +2032,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (fLimitFree && nFees < txMinFee) { //fprintf(stderr,"accept failure.5\n"); - return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d",hash.ToString(), nFees, txMinFee),REJECT_INSUFFICIENTFEE, "insufficient fee"); + LogPrint("mempool-tx", "%s not enough fees for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d", hash.ToString(), nFees, txMinFee),REJECT_INSUFFICIENTFEE, "insufficient fee"); } } @@ -2050,6 +2063,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000) { //fprintf(stderr,"accept failure.7\n"); + LogPrint("mempool-tx", "%s free transaction rejected by rate limiter for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); return state.DoS(0, error("AcceptToMemoryPool: free transaction rejected by rate limiter"), REJECT_INSUFFICIENTFEE, "rate limited free transaction"); } LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize); @@ -2062,6 +2076,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa hash.ToString(), nFees, ::minRelayTxFee.GetFee(nSize) * 10000); LogPrint("mempool", errmsg.c_str()); + LogPrint("mempool-tx", "%s rejected %s for tx %s\n", __func__, errmsg.c_str(), HexStr(E_MARSHAL(ss << tx)).c_str()); return state.Error("AcceptToMemoryPool: " + errmsg); } //fprintf(stderr,"addmempool 6\n"); @@ -2073,7 +2088,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, evalcodeChecker)) { //fprintf(stderr,"accept failure.9\n"); - return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString()); + LogPrint("mempool-tx", "%s ConnectInputs failed for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); + return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString().c_str()); } // Check again against just the consensus-critical mandatory script @@ -2101,7 +2117,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } if (!ContextualCheckOutputs(tx, state, true, txdata, evalcodeChecker)) - return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ContextualCheckOutputs failed %s", hash.ToString());; + return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ContextualCheckOutputs failed %s", hash.ToString()); if (flag != 0) KOMODO_CONNECTING = -1; @@ -2470,12 +2486,6 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW) } //uint64_t komodo_moneysupply(int32_t height); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1]; -extern uint32_t ASSETCHAINS_MAGIC; -extern uint64_t ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; -extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; -extern int32_t ASSETCHAINS_STAKED; CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) { @@ -6922,7 +6932,7 @@ bool InitBlockIndex() { pblocktree->WriteFlag("spentindex", fSpentIndex); fprintf(stderr,"fAddressIndex.%d/%d fSpentIndex.%d/%d\n",fAddressIndex,DEFAULT_ADDRESSINDEX,fSpentIndex,DEFAULT_SPENTINDEX); - fUnspentCCIndex = GetBoolArg("-unspentccindex", false); + fUnspentCCIndex = GetBoolArg("-unspentccindex", DEFAULT_UNSPENTCCINDEX); pblocktree->WriteFlag("unspentccindex", fUnspentCCIndex); fprintf(stderr, "fUnspentCCIndex.%d\n", fUnspentCCIndex); @@ -7454,10 +7464,18 @@ void static ProcessGetData(CNode* pfrom) // Send stream from relay memory bool pushed = false; { - LOCK(cs_mapRelay); - map::iterator mi = mapRelay.find(inv); - if (mi != mapRelay.end()) { - pfrom->PushMessage(inv.GetCommand(), (*mi).second); + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + bool found = false; + { + LOCK(cs_mapRelay); + map::iterator mi = mapRelay.find(inv); + if (mi != mapRelay.end()) { + ss = ((*mi).second); + found = true; + } + } + if (found) { + pfrom->PushMessage(inv.GetCommand(), ss); pushed = true; } } diff --git a/src/miner.cpp b/src/miner.cpp index 7e44511d49f..e7f8a74aa75 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -64,6 +64,9 @@ #endif #include +#include "komodo_defs.h" +#include "cc/CCinclude.h" + using namespace std; ////////////////////////////////////////////////////////////////////////////// @@ -71,6 +74,12 @@ using namespace std; // BitcoinMiner // + +extern CCriticalSection cs_metrics; + +uint32_t Mining_start,Mining_height; +int32_t My_notaryid = -1; + // // Unconfirmed transactions in the memory pool often depend on other // transactions in the memory pool. When we select transactions from the @@ -133,34 +142,6 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); } } -#include "komodo_defs.h" -#include "cc/CCinclude.h" - -extern CCriticalSection cs_metrics; -void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); - -uint32_t Mining_start,Mining_height; -int32_t My_notaryid = -1; -int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); -int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize); -int32_t komodo_baseid(char *origbase); -int32_t komodo_longestchain(); -int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); -int64_t komodo_block_unlocktime(uint32_t nHeight); -uint64_t komodo_commission(const CBlock *block,int32_t height); -int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); -int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk); -uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); -int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); -int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void* ptr); -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); -int32_t komodo_is_notarytx(const CTransaction& tx); -uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len); -CScript komodo_mineropret(int32_t nHeight); -bool komodo_appendACscriptpub(); -CScript komodo_makeopret(CBlock *pblock, bool fNew); int32_t komodo_waituntilelegible(uint32_t blocktime, int32_t stakeHeight, uint32_t delay) { @@ -1136,13 +1117,10 @@ static bool ProcessBlockFound(CBlock* pblock) return true; } -int32_t komodo_baseid(char *origbase); -int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); -arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); -int32_t FOUND_BLOCK,KOMODO_MAYBEMINED; -extern int32_t KOMODO_LASTMINED,KOMODO_INSYNC; + +int32_t FOUND_BLOCK, KOMODO_MAYBEMINED; int32_t roundrobin_delay; -arith_uint256 HASHTarget,HASHTarget_POW; +arith_uint256 HASHTarget, HASHTarget_POW; // wait for peers to connect void waitForPeers(const CChainParams &chainparams) @@ -1191,19 +1169,17 @@ void waitForPeers(const CChainParams &chainparams) } #ifdef ENABLE_WALLET -CBlockIndex *get_chainactive(int32_t height) +CBlockIndex* get_chainactive(int32_t height) { - if ( chainActive.LastTip() != 0 ) - { - if ( height <= chainActive.LastTip()->GetHeight() ) - { - LOCK(cs_main); - return(chainActive[height]); + LOCK(cs_main); // moved lock at the begininng as getting the vector size is unsafe in the multithread env + if (chainActive.LastTip() != 0) { + if (height <= chainActive.LastTip()->GetHeight()) { + return (chainActive[height]); } // else fprintf(stderr,"get_chainactive height %d > active.%d\n",height,chainActive.Tip()->GetHeight()); } //fprintf(stderr,"get_chainactive null chainActive.Tip() height %d\n",height); - return(0); + return (0); } /* diff --git a/src/net.cpp b/src/net.cpp index d653724c0d4..a291c5df04f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2146,6 +2146,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa nPingUsecTime = 0; fPingQueued = false; nMinPingUsecTime = std::numeric_limits::max(); + memset(nspvdata, '\0', sizeof(nspvdata)); { LOCK(cs_nLastNodeId); diff --git a/src/net.h b/src/net.h index b16306c585e..64f55b8aa6b 100644 --- a/src/net.h +++ b/src/net.h @@ -284,7 +284,11 @@ class CNode int64_t nLastRecv; int64_t nTimeConnected; int64_t nTimeOffset; - uint32_t prevtimes[16],dexlastping; + struct { + uint32_t prevtime; + uint32_t nreqs; + } nspvdata[16]; + uint32_t dexlastping; // Address of this peer CAddress addr; // Bind address of our side of the connection diff --git a/src/rest.cpp b/src/rest.cpp index 3fb87f8f386..63de162c8fb 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -71,12 +71,6 @@ struct CCoin { } }; -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); -extern UniValue mempoolInfoToJSON(); -extern UniValue mempoolToJSON(bool fVerbose = false); -extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -extern UniValue blockheaderToJSON(const CBlockIndex* blockindex); static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, string message) { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 565a5bfb92d..0fb2f67dce4 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -46,15 +46,17 @@ #include "cc/CCinclude.h" #include "cc/CCPrices.h" -using namespace std; - -extern int32_t KOMODO_INSYNC; -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -int32_t komodo_notarized_height(int32_t *prevMoMheightp, uint256 *hashp, uint256 *txidp); #include "komodo_defs.h" #include "komodo_structs.h" +using namespace std; + +//extern int32_t KOMODO_INSYNC; +//extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +//void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +//int32_t komodo_notarized_height(int32_t *prevMoMheightp, uint256 *hashp, uint256 *txidp); + + double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) { // Floating point number that is a multiple of the minimum difficulty, @@ -288,7 +290,7 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) return result; } -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails) { UniValue result(UniValue::VOBJ); uint256 notarized_hash, notarized_desttxid; int32_t prevMoMheight, notarized_height; @@ -451,7 +453,7 @@ bool mytxid_inmempool(uint256 txid) return(false); } -UniValue mempoolToJSON(bool fVerbose = false) +UniValue mempoolToJSON(bool fVerbose) { if (fVerbose) { @@ -1123,8 +1125,6 @@ UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk) return ret; } -int32_t komodo_pending_withdraws(char *opretstr); -int32_t pax_fiatstatus(uint64_t *available, uint64_t *deposited, uint64_t *issued, uint64_t *withdrawn, uint64_t *approved, uint64_t *redeemed, char *base); extern char CURRENCIES[][8]; UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk) diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index c4bf88f7bd4..08282211851 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -90,12 +90,152 @@ UniValue listccunspents(const UniValue& params, bool fHelp, const CPubKey& mypk) } +// a helper function for nspv clients: creates a tx and add normal inputs for the requested amount +UniValue createtxwithnormalinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || (params.size() < 1 || params.size() > 2)) + { + string msg = "createtxwithnormalinputs amount [pubkey]\n" + "\nReturns a new tx with added normal inputs and previous txns. Note that the caller must add the change output\n" + "\nArguments:\n" + //"address which utxos are added from\n" + "amount (in satoshi) which will be added as normal inputs (equal or more)\n" + "pubkey optional, if not set -pubkey used\n" + "Result: json object with created tx and added vin txns\n\n"; + throw runtime_error(msg); + } + /*std::string address = params[0].get_str(); + if (!CBitcoinAddress(address.c_str()).IsValid()) + throw runtime_error("address invalid");*/ + CAmount amount = atoll(params[0].get_str().c_str()); + if (amount <= 0) + throw runtime_error("amount invalid"); + + CPubKey usedpk = remotepk; + if (params.size() >= 2) { + CPubKey pk = pubkey2pk(ParseHex(params[1].get_str())); + if (!pk.IsValid()) + throw runtime_error("pubkey invalid"); + usedpk = pk; + } + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + std::vector vintxns; + CAmount added = AddNormalinputsRemote(mtx, usedpk, amount, CC_MAXVINS, &vintxns); + if (added < amount) + throw runtime_error("could not find normal inputs"); + + for (auto const & vin : mtx.vin) { + CTransaction tx; + uint256 hashBlock; + if (myGetTransaction(vin.prevout.hash, tx, hashBlock)) + vintxns.push_back(tx); + } + UniValue result (UniValue::VOBJ); + UniValue array (UniValue::VARR); + + result.pushKV("txhex", HexStr(E_MARSHAL(ss << mtx))); + for (auto const &vtx : vintxns) + array.push_back(HexStr(E_MARSHAL(ss << vtx))); + result.pushKV("previousTxns", array); + return result; +} + +// helper for nspv clients, to load several txns by their txids +UniValue gettransactionsmany(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() < 1 || params.size() > 0x1000) + { + string msg = "gettransactionsmany txid1 txid2 ...\n" + "\nReturns a list of confirmed transactions for the given txids.\n" + "\nArguments:\n" + "txid1 txid2... - txids to load, with max number of no more than 4096\n" + "Result: json object with txns in hex and optional list of txids that could not be loaded\n\n"; + throw runtime_error(msg); + } + + UniValue result(UniValue::VOBJ); + UniValue txns(UniValue::VARR); + UniValue notloaded(UniValue::VARR); + + for (size_t i = 0; i < params.size(); i ++) + { + uint256 txid = Parseuint256(params[i].get_str().c_str()); + if (txid.IsNull()) + throw std::runtime_error("txid invalid for i=" + std::to_string(i)); + + CTransaction tx; + uint256 hashBlock; + if (myGetTransaction(txid, tx, hashBlock) && !hashBlock.IsNull()) { + UniValue elem(UniValue::VOBJ); + elem.pushKV("tx", HexStr(E_MARSHAL(ss << tx))); + + LOCK(cs_main); + CBlockIndex *pindex = komodo_getblockindex(hashBlock); + if (pindex) { + CNetworkBlockHeader nethdr = pindex->GetBlockHeader(); + elem.pushKV("blockHeader", HexStr(E_MARSHAL(ss << nethdr))); + elem.pushKV("blockHeight", pindex->GetHeight()); + elem.pushKV("blockHash", hashBlock.GetHex()); + } + txns.push_back(elem); + } + else + notloaded.push_back(txid.GetHex()); + } + result.pushKV("transactions", txns); + if (!notloaded.empty()) + result.pushKV("notloaded", notloaded); + + return result; +} + +// helper for testing, returns index key for a cryptoconditon scriptPubKey +UniValue getindexkeyforcc(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() != 2) + { + string msg = "getindexkeyforcc cc-as-json is-mixed\n" + "\nReturns indexing key (formely cc address) for scriptPubKey made from a cryptocondition\n" + "\nArguments:\n" + //"address which utxos are added from\n" + "cc-as-json cryptocondition in json\n" + "is-mixed is mixed mode, true or false" + "Result: indexing key\n\n" + "Sample:\n" + "getindexkeyforcc \'{ \"type\": \"threshold-sha-256\", \"threshold\": 2, \"subfulfillments\":" + "[{\"type\":\"eval-sha-256\",\"code\":\"9A\"}, {\"type\":\"threshold-sha-256\", \"threshold\":1," + "subfulfillments\":[{ \"type\": \"secp256k1-sha-256\", \"publicKey\": \"03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12\" }] }] }\' true\n\n" + ; + throw std::runtime_error(msg); + } + + char err[128];// = ""; + CCwrapper cc = cc_conditionFromJSONString(params[0].get_str().c_str(), err); + if (cc == nullptr) + throw std::runtime_error(std::string("could not create cryptocondition: ") + err); + bool ismixed = false; + if (params[1].get_str() == "true") + ismixed = true; + else if (params[1].get_str() == "false") + ismixed = false; + else + throw std::runtime_error(std::string("is-mixed must be true or false")); + + CScript spk = CCPubKey(cc.get(), ismixed); + char ccaddress[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(ccaddress, spk); + return ccaddress; +} static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- - // tokens & assets - { "ccutils", "listccunspents", &listccunspents, true } + // cc helpers + { "ccutils", "listccunspents", &listccunspents, true }, + { "ccutils", "getindexkeyforcc", &getindexkeyforcc, true }, + { "nspv", "createtxwithnormalinputs", &createtxwithnormalinputs, true }, + { "nspv", "gettransactionsmany", &gettransactionsmany, true }, }; void RegisterCCUtilsRPCCommands(CRPCTable &tableRPC) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index d2e891556c2..bb0e475fd06 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -50,12 +50,6 @@ using namespace std; #include "komodo_defs.h" -extern int32_t ASSETCHAINS_FOUNDERS; -uint64_t komodo_commission(const CBlock *pblock,int32_t height); -int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex); -arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); -int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); - /** * Return average network hashes per second based on the last 'lookup' blocks, * or over the difficulty averaging window if 'lookup' is nonpositive. @@ -404,7 +398,6 @@ UniValue setgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk) } #endif -CBlockIndex *komodo_chainactive(int32_t height); arith_uint256 zawy_ctB(arith_uint256 bnTarget,uint32_t solvetime); UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 66f9463aaa1..1e4ebb058a1 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -28,6 +28,7 @@ #include "txmempool.h" #include "util.h" #include "notaries_staked.h" +#include "komodo_defs.h" #include "cc/eval.h" #include "cc/CCinclude.h" #ifdef ENABLE_WALLET @@ -59,33 +60,8 @@ using namespace std; * Or alternatively, create a specific query method for the information. **/ -int32_t Jumblr_depositaddradd(char *depositaddr); -int32_t Jumblr_secretaddradd(char *secretaddr); -uint64_t komodo_interestsum(); -int32_t komodo_longestchain(); -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); -//bool komodo_txnotarizedconfirmed(uint256 txid); -uint32_t komodo_chainactive_timestamp(); -int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); -extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; -extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN,IS_STAKED_NOTARY,IS_KOMODO_NOTARY,STAKED_ERA,KOMODO_INSYNC; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -uint32_t komodo_segid32(char *coinaddr); -int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); -int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); -int8_t StakedNotaryID(std::string ¬aryname, char *Raddress); -uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); - #define KOMODO_VERSION "0.6.1" #define VERUS_VERSION "0.4.0g" -extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; -extern uint32_t ASSETCHAINS_CC; -extern uint32_t ASSETCHAINS_MAGIC,ASSETCHAINS_ALGO; -extern uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; -extern int32_t ASSETCHAINS_LWMAPOS,ASSETCHAINS_SAPLING,ASSETCHAINS_STAKED; -extern uint64_t ASSETCHAINS_ENDSUBSIDY[],ASSETCHAINS_REWARD[],ASSETCHAINS_HALVING[],ASSETCHAINS_DECAY[],ASSETCHAINS_NOTARY_PAY[]; -extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS; extern uint8_t NOTARY_PUBKEY33[]; int32_t getera(int timestamp) { @@ -221,11 +197,11 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) + HelpExampleCli("getinfo", "") + HelpExampleRpc("getinfo", "") ); - //#ifdef ENABLE_WALLET - // LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); - //#else - LOCK(cs_main); - //#endif + #ifdef ENABLE_WALLET + LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); + #else + LOCK(cs_main); + #endif proxyType proxy; GetProxy(NET_IPV4, proxy); @@ -422,7 +398,6 @@ class DescribeAddressVisitor : public boost::static_visitor } UniValue operator()(const CCryptoConditionID &ccID) const { return UniValue(UniValue::VOBJ); } // cryptoconditions are not recognised in the wallet yet - }; #endif diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index f87d953eaf1..68a5c915063 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -171,69 +171,6 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) return ret; } -int32_t KOMODO_LONGESTCHAIN; -int32_t komodo_longestchain() -{ - static int32_t depth; - int32_t ht,n=0,num=0,maxheight=0,height = 0; - if ( depth < 0 ) - depth = 0; - if ( depth == 0 ) - { - - /** - * Seems here we need to try to lock cs_main, to avoid wrong order of lock (cs_main, cs_vNodes), - * implementation of getting max(nStartingHeight, nSyncHeight, nCommonHeight) from CNodeStateStats - * and loop here is similar to getpeerinfo RPC and there we have LOCK(cs_main). If we'll not able - * to acquire lock on cs_main komodo_longestchain() will return previous saved value of - * KOMODO_LONGESTCHAIN, anyway, on next call it will be updated, when lock will success. - */ - - TRY_LOCK(cs_main, lockMain); // Acquire cs_main - if (!lockMain) { - return(KOMODO_LONGESTCHAIN); - } - - depth++; - vector vstats; - { - //LOCK(cs_main); - CopyNodeStats(vstats); - } - BOOST_FOREACH(const CNodeStats& stats, vstats) - { - //fprintf(stderr,"komodo_longestchain iter.%d\n",n); - CNodeStateStats statestats; - bool fStateStats = GetNodeStateStats(stats.nodeid,statestats); - if ( statestats.nSyncHeight < 0 ) - continue; - ht = 0; - if ( stats.nStartingHeight > ht ) - ht = stats.nStartingHeight; - if ( statestats.nSyncHeight > ht ) - ht = statestats.nSyncHeight; - if ( statestats.nCommonHeight > ht ) - ht = statestats.nCommonHeight; - if ( maxheight == 0 || ht > maxheight*1.01 ) - maxheight = ht, num = 1; - else if ( ht > maxheight*0.99 ) - num++; - if ( ht > height ) - height = ht; - } - depth--; - if ( num > (n >> 1) ) - { - if ( 0 && height != KOMODO_LONGESTCHAIN ) - fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",ASSETCHAINS_SYMBOL,height); - KOMODO_LONGESTCHAIN = height; - return(height); - } - KOMODO_LONGESTCHAIN = 0; - } - return(KOMODO_LONGESTCHAIN); -} - UniValue addnode(const UniValue& params, bool fHelp, const CPubKey& mypk) { string strCommand; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index eaf1ec002c5..d20807e5331 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -41,20 +41,12 @@ #endif #include "komodo_defs.h" - #include - #include - #include -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); - using namespace std; -extern char ASSETCHAINS_SYMBOL[]; -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); - void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex) { txnouttype type; @@ -140,8 +132,6 @@ UniValue TxJoinSplitToJSON(const CTransaction& tx) { return vjoinsplit; } -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - UniValue TxShieldedSpendsToJSON(const CTransaction& tx) { UniValue vdesc(UniValue::VARR); for (const SpendDescription& spendDesc : tx.vShieldedSpend) { diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 57068503a5b..c8645442f4c 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -876,7 +876,11 @@ std::string HelpExampleCli(const std::string& methodname, const std::string& arg } else if ((strncmp(ASSETCHAINS_SYMBOL, "HUSH3", 5) == 0) ) { return "> hush-cli " + methodname + " " + args + "\n"; } else { - return "> komodo-cli -ac_name=" + strprintf("%s", ASSETCHAINS_SYMBOL) + " " + methodname + " " + args + "\n"; +#if !defined CUSTOM_BIN_NAME + return std::string("> komodo-cli -ac_name=") + std::string(ASSETCHAINS_SYMBOL) + " " + methodname + " " + args + "\n"; +#else + return std::string("> ") + std::string(CUSTOM_BIN_NAME) + std::string("-cli") + " " + methodname + " " + args + "\n"; +#endif } } diff --git a/src/rpc/server.h b/src/rpc/server.h index 5975e0e1d8b..f8e27b156fb 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -35,6 +35,9 @@ #include #include +#include "primitives/block.h" +#include "primitives/transaction.h" +#include "script/script.h" class AsyncRPCQueue; class CRPCCommand; @@ -180,355 +183,363 @@ extern CRPCTable tableRPC; * Utilities: convert hex-encoded Values * (throws error if not hex). */ -extern uint256 ParseHashV(const UniValue& v, std::string strName); -extern uint256 ParseHashO(const UniValue& o, std::string strKey); -extern std::vector ParseHexV(const UniValue& v, std::string strName); -extern std::vector ParseHexO(const UniValue& o, std::string strKey); +uint256 ParseHashV(const UniValue& v, std::string strName); +uint256 ParseHashO(const UniValue& o, std::string strKey); +std::vector ParseHexV(const UniValue& v, std::string strName); +std::vector ParseHexO(const UniValue& o, std::string strKey); extern int64_t nWalletUnlockTime; -extern CAmount AmountFromValue(const UniValue& value); -extern UniValue ValueFromAmount(const CAmount& amount); -extern double GetDifficulty(const CBlockIndex* blockindex = NULL); -extern double GetNetworkDifficulty(const CBlockIndex* blockindex = NULL); -extern std::string HelpRequiringPassphrase(); -extern std::string HelpExampleCli(const std::string& methodname, const std::string& args); -extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args); - -extern void EnsureWalletIsUnlocked(); +CAmount AmountFromValue(const UniValue& value); +UniValue ValueFromAmount(const CAmount& amount); +double GetDifficulty(const CBlockIndex* blockindex = NULL); +double GetNetworkDifficulty(const CBlockIndex* blockindex = NULL); +std::string HelpRequiringPassphrase(); +std::string HelpExampleCli(const std::string& methodname, const std::string& args); +std::string HelpExampleRpc(const std::string& methodname, const std::string& args); + +void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); +UniValue mempoolInfoToJSON(); +UniValue mempoolToJSON(bool fVerbose = false); +void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +UniValue blockheaderToJSON(const CBlockIndex* blockindex); +UniValue TxJoinSplitToJSON(const CTransaction& tx); + +void EnsureWalletIsUnlocked(); bool StartRPC(); void InterruptRPC(); void StopRPC(); std::string JSONRPCExecBatch(const UniValue& vReq); -extern std::string experimentalDisabledHelpMsg(const std::string& rpc, const std::string& enableArg); - -extern UniValue getconnectioncount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcnet.cpp -extern UniValue getaddressmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddressutxos(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddressdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddresstxids(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getsnapshot(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddressbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue checknotarization(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnotarypayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue ping(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue addnode(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue disconnectnode(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnettotals(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue setban(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue clearbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dumpwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue getgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmining.cpp -extern UniValue setgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getlocalsolps(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnetworksolps(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnetworkhashps(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getmininginfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue prioritisetransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue submitblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue estimatefee(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue estimatepriority(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heiraddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heirfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heiradd(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heirclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heirinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue heirlist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oracleslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclescreate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclesfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclesregister(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclessubscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclesdata(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclessample(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue oraclessamples(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue priceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue mypriceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paymentsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_release(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_fund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_merge(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_txidopret(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_create(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_airdrop(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_airdroptokens(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_info(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue payments_list(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue cclibaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue cclibinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue cclib(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysdumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysbind(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayswithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayspartialsign(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayscompletesigning(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysmarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayspendingdeposits(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewayspendingwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gatewaysprocessed(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelsopen(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelspayment(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelsclose(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue channelsrefund(const UniValue& params, bool fHelp, const CPubKey& mypk); -//extern UniValue tokenswapask(const UniValue& params, bool fHelp, const CPubKey& mypk); -//extern UniValue tokenfillswap(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue faucetfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue faucetget(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue faucetaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue faucetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardscreatefunding(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardsaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardslock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue rewardsunlock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue diceaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dicefund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dicelist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue diceinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue diceaddfunds(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dicebet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dicefinish(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue dicestatus(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue lottoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue FSMaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue FSMcreate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue FSMlist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue FSMinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue auctionaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegscreate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsget(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsredeem(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsliquidate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsexchange(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsaccounthistory(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsaccountinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsworstaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -//extern UniValue getnewaddress64(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue getaccountaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getrawchangeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getaddressesbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue signmessage(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue verifymessage(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getbalance64(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getunconfirmedbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue movecmd(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue addmultisigaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue createmultisig(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listaddressgroupings(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listsinceblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gettransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue backupwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue keypoolrefill(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue walletpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue walletpassphrasechange(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue walletlock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue encryptwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue decodeccopret(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getiguanajson(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnotarysendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue setstakingsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getwalletinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getnetworkinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getdeprecationinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue setmocktime(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue resendwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue zc_benchmark(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue zc_raw_keygen(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue zc_raw_receive(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue jumblr_deposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_secret(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_pause(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_resume(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rcprawtransaction.cpp -extern UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue createrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue decodescript(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue fundrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gettxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue verifytxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue getblockcount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcblockchain.cpp -extern UniValue getbestblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getdifficulty(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue settxfee(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getmempoolinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getrawmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblockhashes(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblockdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getlastsegidstakes(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue verifychain(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getchaintips(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue invalidateblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue reconsiderblock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getspentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue selfimport(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importdual(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewayaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaybind(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaydeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaywithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaywithdrawsign(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaymarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaypendingsignwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaysignedwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewayexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue importgatewaydumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue nspv_getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_login(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_mempool(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_spentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_notarizations(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_hdrsproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_txproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_spend(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_logout(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue nspv_listccmoduleunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue DEX_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_anonsend(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_list(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_get(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_stats(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_orderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_cancel(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_publish(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_subscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_stream(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_streamsub(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue DEX_notarize(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue getblocksubsidy(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue z_exportkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_importkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_listaddresses(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_exportwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp -extern UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_getoperationstatus(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_getoperationresult(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp -extern UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmisc.cpp -extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp -extern UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp - -extern UniValue MoMoMdata(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue calc_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue height_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue assetchainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue crosschainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue scanNotarisationsDB(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getimports(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getwalletburntransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_converttoexport(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_checkburntransactionsource(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue migrate_createnotaryapprovaltransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue minerids(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue kvsearch(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxprice(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxprices(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxwithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue prices(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesbet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricessetcostbasis(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricescashout(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesrekt(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesgetorderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesrefillfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +std::string experimentalDisabledHelpMsg(const std::string& rpc, const std::string& enableArg); + +UniValue getconnectioncount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcnet.cpp +UniValue getaddressmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddressutxos(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddressdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddresstxids(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getsnapshot(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddressbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue checknotarization(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnotarypayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue ping(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue addnode(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue disconnectnode(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddednodeinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnettotals(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue setban(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue clearbanned(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dumpwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue getgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmining.cpp +UniValue setgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getlocalsolps(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnetworksolps(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnetworkhashps(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getmininginfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue prioritisetransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue submitblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue estimatefee(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue estimatepriority(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heiraddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heirfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heiradd(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heirclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heirinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue heirlist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oracleslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclescreate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclesfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclesregister(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclessubscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclesdata(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclessample(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue oraclessamples(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue priceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue mypriceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paymentsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_release(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_fund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_merge(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_txidopret(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_create(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_airdrop(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_airdroptokens(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_info(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue payments_list(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue cclibaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue cclibinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue cclib(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysdumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysbind(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysclaim(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayswithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayspartialsign(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayscompletesigning(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysmarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayspendingdeposits(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewayspendingwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gatewaysprocessed(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelsopen(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelspayment(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelsclose(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue channelsrefund(const UniValue& params, bool fHelp, const CPubKey& mypk); +//UniValue tokenswapask(const UniValue& params, bool fHelp, const CPubKey& mypk); +//UniValue tokenfillswap(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue faucetfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue faucetget(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue faucetaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue faucetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardslist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardscreatefunding(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardsaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardslock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue rewardsunlock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue diceaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dicefund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dicelist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue diceinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue diceaddfunds(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dicebet(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dicefinish(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue dicestatus(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue lottoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue FSMaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue FSMcreate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue FSMlist(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue FSMinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue auctionaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegscreate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsfund(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsget(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsredeem(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsliquidate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsexchange(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsaccounthistory(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsaccountinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsworstaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pegsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +//UniValue getnewaddress64(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue getaccountaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getrawchangeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getaddressesbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue signmessage(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue verifymessage(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getbalance64(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getunconfirmedbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue movecmd(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue addmultisigaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue createmultisig(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listaddressgroupings(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listsinceblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gettransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue backupwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue keypoolrefill(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue walletpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue walletpassphrasechange(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue walletlock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue encryptwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue decodeccopret(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getiguanajson(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnotarysendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue setstakingsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getwalletinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getnetworkinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getdeprecationinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue setmocktime(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue resendwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue zc_benchmark(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue zc_raw_keygen(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue zc_raw_receive(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue jumblr_deposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue jumblr_secret(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue jumblr_pause(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue jumblr_resume(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rcprawtransaction.cpp +UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue createrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue decodescript(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue fundrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gettxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue verifytxoutproof(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue getblockcount(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcblockchain.cpp +UniValue getbestblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getdifficulty(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue settxfee(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getmempoolinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getrawmempool(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblockhashes(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblockdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getlastsegidstakes(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue verifychain(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getchaintips(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue invalidateblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue reconsiderblock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getspentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue selfimport(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importdual(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewayaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewayinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaybind(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaydeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaywithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaywithdrawsign(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaymarkdone(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaypendingsignwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaysignedwithdraws(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewayexternaladdress(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue importgatewaydumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue nspv_getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_login(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_listtransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_mempool(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_spentinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_notarizations(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_hdrsproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_txproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_spend(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_logout(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue nspv_listccmoduleunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue DEX_broadcast(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_anonsend(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_list(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_get(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_stats(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_orderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_cancel(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_publish(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_subscribe(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_stream(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_streamsub(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue DEX_notarize(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue getblocksubsidy(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue z_exportkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_importkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_listaddresses(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_exportwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp +UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_getoperationstatus(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_getoperationresult(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmisc.cpp +UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp +UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp + +UniValue MoMoMdata(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue calc_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue height_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue assetchainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue crosschainproof(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue scanNotarisationsDB(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getimports(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue getwalletburntransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_converttoexport(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_checkburntransactionsource(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue migrate_createnotaryapprovaltransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue minerids(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue kvsearch(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paxprice(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paxprices(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paxdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue paxwithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); + +UniValue prices(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesbet(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricessetcostbasis(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricescashout(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesrekt(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesgetorderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); +UniValue pricesrefillfund(const UniValue& params, bool fHelp, const CPubKey& mypk); diff --git a/src/rpc/testtransactions.cpp b/src/rpc/testtransactions.cpp deleted file mode 100644 index c41e97e1036..00000000000 --- a/src/rpc/testtransactions.cpp +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - -#include - -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "crosschain.h" -#include "base58.h" -#include "consensus/validation.h" -#include "cc/eval.h" -#include "main.h" -#include "primitives/transaction.h" -#include "rpc/server.h" -#include "streams.h" -#include "sync.h" -#include "util.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "script/standard.h" - -#include - -#include - -#include - - -#include "cc/CCinclude.h" -#include "cc/CCPrices.h" - -using namespace std; - -int32_t ensure_CCrequirements(uint8_t evalcode); - -UniValue test_ac(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 4)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_HEIR) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - std::vector pubkey1; - std::vector pubkey2; - - pubkey1 = ParseHex(params[0].get_str().c_str()); - pubkey2 = ParseHex(params[1].get_str().c_str()); - - CPubKey pk1 = pubkey2pk(pubkey1); - CPubKey pk2 = pubkey2pk(pubkey2); - - if (!pk1.IsValid() || !pk2.IsValid()) - throw runtime_error("invalid pubkey\n"); - - int64_t txfee = 10000; - int64_t amount = atoll(params[2].get_str().c_str()) * COIN; - uint256 fundingtxid = Parseuint256((char *)params[3].get_str().c_str()); - - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, txfee + amount, 60); - - if (normalInputs < txfee + amount) - throw runtime_error("not enough normals\n"); - - mtx.vout.push_back(MakeCC1of2vout(EVAL_HEIR, amount, pk1, pk2)); - - CScript opret; - fundingtxid = revuint256(fundingtxid); - - opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'A' << fundingtxid << (uint8_t)0); - - cp = CCinit(&C, EVAL_HEIR); - return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret)); -} - -UniValue test_heirmarker(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 1)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_HEIR) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - uint256 fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); - - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); - if (normalInputs < 10000) - throw runtime_error("not enough normals\n"); - - mtx.vin.push_back(CTxIn(fundingtxid, 1)); - mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, 10000, myPubkey)); - - CScript opret; - fundingtxid = revuint256(fundingtxid); - - opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'C' << fundingtxid << (uint8_t)0); - - cp = CCinit(&C, EVAL_HEIR); - return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret)); -} - -UniValue test_burntx(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 1)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_TOKENS) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str()); - - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); - if (normalInputs < 10000) - throw runtime_error("not enough normals\n"); - - CPubKey burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY)); - - mtx.vin.push_back(CTxIn(tokenid, 0)); - mtx.vin.push_back(CTxIn(tokenid, 1)); - mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, 1, burnpk)); - - std::vector voutPubkeys; - voutPubkeys.push_back(burnpk); - - cp = CCinit(&C, EVAL_TOKENS); - - std::vector vopret; - GetNonfungibleData(tokenid, vopret); - if (vopret.size() > 0) - cp->additionalTokensEvalcode2 = vopret.begin()[0]; - - uint8_t tokenpriv[33]; - char unspendableTokenAddr[64]; - CPubKey unspPk = GetUnspendable(cp, tokenpriv); - GetCCaddress(cp, unspendableTokenAddr, unspPk); - CCaddr2set(cp, EVAL_TOKENS, unspPk, tokenpriv, unspendableTokenAddr); - return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, EncodeTokenOpRet(tokenid, voutPubkeys, std::make_pair(0, vscript_t())))); -} - -UniValue test_proof(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); - std::vectorproof; - - if (fHelp || (params.size() != 2)) - throw runtime_error("incorrect params\n"); - - - proof = ParseHex(params[0].get_str()); - uint256 cointxid = Parseuint256((char *)params[1].get_str().c_str()); - - std::vector txids; - - CMerkleBlock merkleBlock; - if (!E_UNMARSHAL(proof, ss >> merkleBlock)) { - result.push_back(Pair("error", "could not unmarshal proof")); - return result; - } - uint256 merkleRoot = merkleBlock.txn.ExtractMatches(txids); - - result.push_back(Pair("source_root", merkleRoot.GetHex())); - - for (int i = 0; i < txids.size(); i++) - std::cerr << "merkle block txid=" << txids[0].GetHex() << std::endl; - - - std::vector vMatches(txids.size()); - for (auto v : vMatches) v = true; - CPartialMerkleTree verifTree(txids, vMatches); - - result.push_back(Pair("verif_root", verifTree.ExtractMatches(txids).GetHex())); - - if (std::find(txids.begin(), txids.end(), cointxid) == txids.end()) { - fprintf(stderr, "invalid proof for this cointxid\n"); - } - - std::vector vMerkleTree; - bool f; - ::BuildMerkleTree(&f, txids, vMerkleTree); - - std::vector vMerkleBranch = ::GetMerkleBranch(0, txids.size(), vMerkleTree); - - uint256 ourResult = SafeCheckMerkleBranch(zeroid, vMerkleBranch, 0); - result.push_back(Pair("SafeCheckMerkleBranch", ourResult.GetHex())); - - return result; -} - -extern CScript prices_costbasisopret(uint256 bettxid, CPubKey mypk, int32_t height, int64_t costbasis); -UniValue test_pricesmarker(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 1)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_PRICES) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - uint256 bettxid = Parseuint256((char *)params[0].get_str().c_str()); - - cp = CCinit(&C, EVAL_PRICES); - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); - if (normalInputs < 10000) - throw runtime_error("not enough normals\n"); - - mtx.vin.push_back(CTxIn(bettxid, 1)); - mtx.vout.push_back(CTxOut(1000, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG)); - - return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, prices_costbasisopret(bettxid, myPubkey, 100, 100))); -} - - -static const CRPCCommand commands[] = -{ // category name actor (function) okSafeMode - // --------------------- ------------------------ ----------------------- ---------- - - /* Not shown in help */ - { "hidden", "test_ac", &test_ac, true }, - { "hidden", "test_heirmarker", &test_heirmarker, true }, - { "hidden", "test_proof", &test_proof, true }, - { "hidden", "test_burntx", &test_burntx, true }, - { "hidden", "test_pricesmarker", &test_pricesmarker, true } -}; - -void RegisterTesttransactionsRPCCommands(CRPCTable &tableRPC) -{ - for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); -} diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 3ab2b2aa33b..7f98725d84e 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -61,11 +61,33 @@ UniValue tokenaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) return CCaddress(cp, "Tokens", pubkey, false); } +UniValue tokenv2indexkey(const UniValue& params, bool fHelp, const CPubKey& mypk) +{ + struct CCcontract_info *cp,C; + vuint8_t vpubkey; + + cp = CCinit(&C, EVAL_TOKENSV2); + if (fHelp || params.size() != 1) + throw runtime_error("tokenv2address pubkey\n"); + if (ensure_CCrequirements(cp->evalcode) < 0) + throw runtime_error(CC_REQUIREMENTS_MSG); + vpubkey = ParseHex(params[0].get_str().c_str()); + CPubKey pk = pubkey2pk(vpubkey); + if (!pk.IsValid()) + throw runtime_error("invalid pubkey\n"); + + char address[KOMODO_ADDRESS_BUFSIZE]; + GetCCaddress(cp, address, pk, true); + + return address; +} + UniValue tokenv2address(const UniValue& params, bool fHelp, const CPubKey& mypk) { struct CCcontract_info *cp,C; vuint8_t pubkey; + throw runtime_error("tokenv2address not supported, use tokenv2indexkey\n"); cp = CCinit(&C, EVAL_TOKENSV2); if (fHelp || params.size() > 1) throw runtime_error("tokenv2address [pubkey]\n"); @@ -286,6 +308,39 @@ UniValue tokenv2balance(const UniValue& params, bool fHelp, const CPubKey& remot return tokenbalance("tokenv2balance", params, fHelp, remotepk); } +template +static UniValue tokenallbalances(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() > 1) + throw runtime_error(name + " [pubkey]\n"); + if (ensure_CCrequirements(V::EvalCode()) < 0) + throw runtime_error(CC_REQUIREMENTS_MSG); + + // LOCK(cs_main); + // no need to lock cs_main as we use only indexes in this rpc + // but still use lock if you need to get chainActive.Height() or something like that + + std::vector vpubkey; + if (params.size() == 1) + vpubkey = ParseHex(params[0].get_str().c_str()); + else + vpubkey = Mypubkey(); + + UniValue result = GetAllTokenBalances(pubkey2pk(vpubkey), false); + return result; +} + +UniValue tokenallbalances(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + return tokenallbalances("tokenallbalances", params, fHelp, remotepk); +} +UniValue tokenv2allbalances(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + return tokenallbalances("tokenv2allbalances", params, fHelp, remotepk); +} + + + template static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, bool fHelp, const CPubKey& remotepk) { @@ -1071,6 +1126,47 @@ UniValue addccv2signature(const UniValue& params, bool fHelp, const CPubKey& rem } +UniValue tokenv2addccinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() != 3) + { + string msg = "tokenv2addccinputs tokenid pubkey amount\n" + "\nReturns a new tx with added token inputs and the matching previous txns. Note that the caller must add the change output\n" + "\nArguments:\n" + //"address which utxos are added from\n" + "amount (in satoshi) which will be added as normal inputs (equal or more)\n" + "Result: json object with created tx and added vin txns\n\n"; + throw runtime_error(msg); + } + + uint256 tokenid = Parseuint256(params[0].get_str().c_str()); + CPubKey pk = pubkey2pk( ParseHex(params[1].get_str().c_str()) ); + CAmount amount = atoll(params[2].get_str().c_str()); + if (amount <= 0) + throw runtime_error("amount invalid"); + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cp, C; + cp = CCinit(&C, EVAL_TOKENSV2); + + CAmount added = AddTokenCCInputs(cp, mtx, pk, tokenid, amount, CC_MAXVINS, false); + if (added < amount) + throw runtime_error("could not find token cc inputs"); + + UniValue result (UniValue::VOBJ); + UniValue array (UniValue::VARR); + + result.pushKV("txhex", HexStr(E_MARSHAL(ss << mtx))); + for (auto const &vin : mtx.vin) { + CTransaction vintx; + uint256 hashBlock; + if (myGetTransaction(vin.prevout.hash, vintx, hashBlock)) + array.push_back(HexStr(E_MARSHAL(ss << vintx))); + } + result.pushKV("previousTxns", array); + return result; +} + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- @@ -1088,8 +1184,11 @@ static const CRPCCommand commands[] = { "tokens v2", "mytokenv2orders", &mytokenv2orders, true }, { "tokens", "tokenaddress", &tokenaddress, true }, { "tokens v2", "tokenv2address", &tokenv2address, true }, +// { "tokens v2", "tokenv2indexkey", &tokenv2indexkey, true }, { "tokens", "tokenbalance", &tokenbalance, true }, { "tokens v2", "tokenv2balance", &tokenv2balance, true }, + { "tokens", "tokenallbalances", &tokenallbalances, true }, + { "tokens v2", "tokenv2allbalances", &tokenv2allbalances, true }, { "tokens", "tokencreate", &tokencreate, true }, { "tokens v2", "tokenv2create", &tokenv2create, true }, { "tokens", "tokentransfer", &tokentransfer, true }, @@ -1117,6 +1216,7 @@ static const CRPCCommand commands[] = { "tokens v2", "tokenv2createtokel", &tokenv2createtokel, true }, { "tokens", "tokeninfotokel", &tokeninfotokel, true }, { "tokens v2", "tokenv2infotokel", &tokenv2infotokel, true }, + { "nspv", "tokenv2addccinputs", &tokenv2addccinputs, true }, }; void RegisterTokensRPCCommands(CRPCTable &tableRPC) diff --git a/src/rpcblockchain.old b/src/rpcblockchain.old deleted file mode 100644 index a91f73a6364..00000000000 --- a/src/rpcblockchain.old +++ /dev/null @@ -1,1625 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "crosschain.h" -#include "base58.h" -#include "consensus/validation.h" -#include "cc/eval.h" -#include "main.h" -#include "primitives/transaction.h" -#include "rpcserver.h" -#include "sync.h" -#include "util.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "script/standard.h" - -#include - -#include - -#include - -using namespace std; - -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -int32_t komodo_longestchain(); -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -<<<<<<< HEAD:src/rpcblockchain.old -extern int32_t KOMODO_LONGESTCHAIN; -======= ->>>>>>> master:src/rpcblockchain.cpp - -double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) -{ - // Floating point number that is a multiple of the minimum difficulty, - // minimum difficulty = 1.0. - if (blockindex == NULL) - { - if (chainActive.LastTip() == NULL) - return 1.0; - else - blockindex = chainActive.LastTip(); - } - - uint32_t bits; - if (networkDifficulty) { - bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus()); - } else { - bits = blockindex->nBits; - } - - uint32_t powLimit = - UintToArith256(Params().GetConsensus().powLimit).GetCompact(); - int nShift = (bits >> 24) & 0xff; - int nShiftAmount = (powLimit >> 24) & 0xff; - - double dDiff = - (double)(powLimit & 0x00ffffff) / - (double)(bits & 0x00ffffff); - - while (nShift < nShiftAmount) - { - dDiff *= 256.0; - nShift++; - } - while (nShift > nShiftAmount) - { - dDiff /= 256.0; - nShift--; - } - - return dDiff; -} - -double GetDifficulty(const CBlockIndex* blockindex) -{ - return GetDifficultyINTERNAL(blockindex, false); -} - -double GetNetworkDifficulty(const CBlockIndex* blockindex) -{ - return GetDifficultyINTERNAL(blockindex, true); -} - -static UniValue ValuePoolDesc( - const std::string &name, - const boost::optional chainValue, - const boost::optional valueDelta) -{ - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("id", name)); - rv.push_back(Pair("monitored", (bool)chainValue)); - if (chainValue) { - rv.push_back(Pair("chainValue", ValueFromAmount(*chainValue))); - rv.push_back(Pair("chainValueZat", *chainValue)); - } - if (valueDelta) { - rv.push_back(Pair("valueDelta", ValueFromAmount(*valueDelta))); - rv.push_back(Pair("valueDeltaZat", *valueDelta)); - } - return rv; -} - -UniValue blockheaderToJSON(const CBlockIndex* blockindex) -{ - UniValue result(UniValue::VOBJ); - if ( blockindex == 0 ) - { - result.push_back(Pair("error", "null blockhash")); - return(result); - } - result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) - confirmations = chainActive.Height() - blockindex->nHeight + 1; - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", blockindex->nVersion)); - result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex())); - result.push_back(Pair("time", (int64_t)blockindex->nTime)); - result.push_back(Pair("nonce", blockindex->nNonce.GetHex())); - result.push_back(Pair("solution", HexStr(blockindex->nSolution))); - result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) -{ - UniValue result(UniValue::VOBJ); - result.push_back(Pair("hash", block.GetHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) { - confirmations = chainActive.Height() - blockindex->nHeight + 1; - } else { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block is an orphan"); - } - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - - UniValue deltas(UniValue::VARR); - - for (unsigned int i = 0; i < block.vtx.size(); i++) { - const CTransaction &tx = block.vtx[i]; - const uint256 txhash = tx.GetHash(); - - UniValue entry(UniValue::VOBJ); - entry.push_back(Pair("txid", txhash.GetHex())); - entry.push_back(Pair("index", (int)i)); - - UniValue inputs(UniValue::VARR); - - if (!tx.IsCoinBase()) { - - for (size_t j = 0; j < tx.vin.size(); j++) { - const CTxIn input = tx.vin[j]; - - UniValue delta(UniValue::VOBJ); - - CSpentIndexValue spentInfo; - CSpentIndexKey spentKey(input.prevout.hash, input.prevout.n); - - if (GetSpentIndex(spentKey, spentInfo)) { - if (spentInfo.addressType == 1) { - delta.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); - } - else if (spentInfo.addressType == 2) { - delta.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); - } - else { - continue; - } - delta.push_back(Pair("satoshis", -1 * spentInfo.satoshis)); - delta.push_back(Pair("index", (int)j)); - delta.push_back(Pair("prevtxid", input.prevout.hash.GetHex())); - delta.push_back(Pair("prevout", (int)input.prevout.n)); - - inputs.push_back(delta); - } else { - throw JSONRPCError(RPC_INTERNAL_ERROR, "Spent information not available"); - } - - } - } - - entry.push_back(Pair("inputs", inputs)); - - UniValue outputs(UniValue::VARR); - - for (unsigned int k = 0; k < tx.vout.size(); k++) { - const CTxOut &out = tx.vout[k]; - - UniValue delta(UniValue::VOBJ); - - if (out.scriptPubKey.IsPayToScriptHash()) { - vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); - delta.push_back(Pair("address", CBitcoinAddress(CScriptID(uint160(hashBytes))).ToString())); - - } - else if (out.scriptPubKey.IsPayToPublicKeyHash()) { - vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); - delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); - } - else if (out.scriptPubKey.IsPayToPublicKey() || out.scriptPubKey.IsPayToCryptoCondition()) { - CTxDestination address; - if (ExtractDestination(out.scriptPubKey, address)) - { - //vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); - //xxx delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); - delta.push_back(Pair("address", CBitcoinAddress(address).ToString())); - } - } - else { - continue; - } - - delta.push_back(Pair("satoshis", out.nValue)); - delta.push_back(Pair("index", (int)k)); - - outputs.push_back(delta); - } - - entry.push_back(Pair("outputs", outputs)); - deltas.push_back(entry); - - } - result.push_back(Pair("deltas", deltas)); - result.push_back(Pair("time", block.GetBlockTime())); - result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast())); - result.push_back(Pair("nonce", block.nNonce.GetHex())); - result.push_back(Pair("bits", strprintf("%08x", block.nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) -{ - UniValue result(UniValue::VOBJ); - result.push_back(Pair("hash", block.GetHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) - confirmations = chainActive.Height() - blockindex->nHeight + 1; - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - UniValue txs(UniValue::VARR); - BOOST_FOREACH(const CTransaction&tx, block.vtx) - { - if(txDetails) - { - UniValue objTx(UniValue::VOBJ); - TxToJSON(tx, uint256(), objTx); - txs.push_back(objTx); - } - else - txs.push_back(tx.GetHash().GetHex()); - } - result.push_back(Pair("tx", txs)); - result.push_back(Pair("time", block.GetBlockTime())); - result.push_back(Pair("nonce", block.nNonce.GetHex())); - result.push_back(Pair("solution", HexStr(block.nSolution))); - result.push_back(Pair("bits", strprintf("%08x", block.nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex())); - - UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue)); - result.push_back(Pair("valuePools", valuePools)); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue getblockcount(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getblockcount\n" - "\nReturns the number of blocks in the best valid block chain.\n" - "\nResult:\n" - "n (numeric) The current block count\n" - "\nExamples:\n" - + HelpExampleCli("getblockcount", "") - + HelpExampleRpc("getblockcount", "") - ); - - LOCK(cs_main); - return chainActive.Height(); -} - -UniValue getbestblockhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getbestblockhash\n" - "\nReturns the hash of the best (tip) block in the longest block chain.\n" - "\nResult\n" - "\"hex\" (string) the block hash hex encoded\n" - "\nExamples\n" - + HelpExampleCli("getbestblockhash", "") - + HelpExampleRpc("getbestblockhash", "") - ); - - LOCK(cs_main); - return chainActive.LastTip()->GetBlockHash().GetHex(); -} - -UniValue getdifficulty(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getdifficulty\n" - "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - "\nResult:\n" - "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - "\nExamples:\n" - + HelpExampleCli("getdifficulty", "") - + HelpExampleRpc("getdifficulty", "") - ); - - LOCK(cs_main); - return GetNetworkDifficulty(); -} - -bool myIsutxo_spentinmempool(uint256 txid,int32_t vout) -{ - //char *uint256_str(char *str,uint256); char str[65]; - //LOCK(mempool.cs); - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - BOOST_FOREACH(const CTxIn &txin,tx.vin) - { - //fprintf(stderr,"%s/v%d ",uint256_str(str,txin.prevout.hash),txin.prevout.n); - if ( txin.prevout.n == vout && txin.prevout.hash == txid ) - return(true); - } - //fprintf(stderr,"are vins for %s\n",uint256_str(str,hash)); - } - return(false); -} - -bool mytxid_inmempool(uint256 txid) -{ - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - if ( txid == hash ) - return(true); - } - return(false); -} - -UniValue mempoolToJSON(bool fVerbose = false) -{ - if (fVerbose) - { - LOCK(mempool.cs); - UniValue o(UniValue::VOBJ); - BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) - { - const uint256& hash = e.GetTx().GetHash(); - UniValue info(UniValue::VOBJ); - info.push_back(Pair("size", (int)e.GetTxSize())); - info.push_back(Pair("fee", ValueFromAmount(e.GetFee()))); - info.push_back(Pair("time", e.GetTime())); - info.push_back(Pair("height", (int)e.GetHeight())); - info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight()))); - info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height()))); - const CTransaction& tx = e.GetTx(); - set setDepends; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - { - if (mempool.exists(txin.prevout.hash)) - setDepends.insert(txin.prevout.hash.ToString()); - } - - UniValue depends(UniValue::VARR); - BOOST_FOREACH(const string& dep, setDepends) - { - depends.push_back(dep); - } - - info.push_back(Pair("depends", depends)); - o.push_back(Pair(hash.ToString(), info)); - } - return o; - } - else - { - vector vtxid; - mempool.queryHashes(vtxid); - - UniValue a(UniValue::VARR); - BOOST_FOREACH(const uint256& hash, vtxid) - a.push_back(hash.ToString()); - - return a; - } -} - -UniValue getrawmempool(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() > 1) - throw runtime_error( - "getrawmempool ( verbose )\n" - "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" - "\nArguments:\n" - "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" - "\nResult: (for verbose = false):\n" - "[ (json array of string)\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - "]\n" - "\nResult: (for verbose = true):\n" - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - " \"size\" : n, (numeric) transaction size in bytes\n" - " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" - " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" - " \"height\" : n, (numeric) block height when transaction entered pool\n" - " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n" - " \"currentpriority\" : n, (numeric) transaction priority now\n" - " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" - " \"transactionid\", (string) parent transaction id\n" - " ... ]\n" - " }, ...\n" - "}\n" - "\nExamples\n" - + HelpExampleCli("getrawmempool", "true") - + HelpExampleRpc("getrawmempool", "true") - ); - - LOCK(cs_main); - - bool fVerbose = false; - if (params.size() > 0) - fVerbose = params[0].get_bool(); - - return mempoolToJSON(fVerbose); -} - -UniValue getblockdeltas(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error(""); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - - if(!ReadBlockFromDisk(block, pblockindex,1)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); - - return blockToDeltasJSON(block, pblockindex); -} - -UniValue getblockhashes(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 2) - throw runtime_error( - "getblockhashes timestamp\n" - "\nReturns array of hashes of blocks within the timestamp range provided.\n" - "\nArguments:\n" - "1. high (numeric, required) The newer block timestamp\n" - "2. low (numeric, required) The older block timestamp\n" - "3. options (string, required) A json object\n" - " {\n" - " \"noOrphans\":true (boolean) will only include blocks on the main chain\n" - " \"logicalTimes\":true (boolean) will include logical timestamps with hashes\n" - " }\n" - "\nResult:\n" - "[\n" - " \"hash\" (string) The block hash\n" - "]\n" - "[\n" - " {\n" - " \"blockhash\": (string) The block hash\n" - " \"logicalts\": (numeric) The logical timestamp\n" - " }\n" - "]\n" - "\nExamples:\n" - + HelpExampleCli("getblockhashes", "1231614698 1231024505") - + HelpExampleRpc("getblockhashes", "1231614698, 1231024505") - + HelpExampleCli("getblockhashes", "1231614698 1231024505 '{\"noOrphans\":false, \"logicalTimes\":true}'") - ); - - unsigned int high = params[0].get_int(); - unsigned int low = params[1].get_int(); - bool fActiveOnly = false; - bool fLogicalTS = false; - - if (params.size() > 2) { - if (params[2].isObject()) { - UniValue noOrphans = find_value(params[2].get_obj(), "noOrphans"); - UniValue returnLogical = find_value(params[2].get_obj(), "logicalTimes"); - - if (noOrphans.isBool()) - fActiveOnly = noOrphans.get_bool(); - - if (returnLogical.isBool()) - fLogicalTS = returnLogical.get_bool(); - } - } - - std::vector > blockHashes; - - if (fActiveOnly) - LOCK(cs_main); - - if (!GetTimestampIndex(high, low, fActiveOnly, blockHashes)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for block hashes"); - } - - UniValue result(UniValue::VARR); - - for (std::vector >::const_iterator it=blockHashes.begin(); it!=blockHashes.end(); it++) { - if (fLogicalTS) { - UniValue item(UniValue::VOBJ); - item.push_back(Pair("blockhash", it->first.GetHex())); - item.push_back(Pair("logicalts", (int)it->second)); - result.push_back(item); - } else { - result.push_back(it->first.GetHex()); - } - } - - return result; -} - -UniValue getblockhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "getblockhash index\n" - "\nReturns hash of block in best-block-chain at index provided.\n" - "\nArguments:\n" - "1. index (numeric, required) The block index\n" - "\nResult:\n" - "\"hash\" (string) The block hash\n" - "\nExamples:\n" - + HelpExampleCli("getblockhash", "1000") - + HelpExampleRpc("getblockhash", "1000") - ); - - LOCK(cs_main); - - int nHeight = params[0].get_int(); - if (nHeight < 0 || nHeight > chainActive.Height()) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - - CBlockIndex* pblockindex = chainActive[nHeight]; - return pblockindex->GetBlockHash().GetHex(); -} - -/*uint256 _komodo_getblockhash(int32_t nHeight) -{ - uint256 hash; - LOCK(cs_main); - if ( nHeight >= 0 && nHeight <= chainActive.Height() ) - { - CBlockIndex* pblockindex = chainActive[nHeight]; - hash = pblockindex->GetBlockHash(); - int32_t i; - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&hash)[i]); - printf(" blockhash.%d\n",nHeight); - } else memset(&hash,0,sizeof(hash)); - return(hash); -}*/ - -UniValue getblockheader(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getblockheader \"hash\" ( verbose )\n" - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" - "If verbose is true, returns an Object with information about blockheader .\n" - "\nArguments:\n" - "1. \"hash\" (string, required) The block hash\n" - "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" - "\nResult (for verbose = true):\n" - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - "\nResult (for verbose=false):\n" - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - "\nExamples:\n" - + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - ); - - LOCK(cs_main); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - - bool fVerbose = true; - if (params.size() > 1) - fVerbose = params[1].get_bool(); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (!fVerbose) - { - CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); - ssBlock << pblockindex->GetBlockHeader(); - std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); - return strHex; - } - - return blockheaderToJSON(pblockindex); -} - -UniValue getblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getblock \"hash|height\" ( verbose )\n" - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash|height'.\n" - "If verbose is true, returns an Object with information about block .\n" - "\nArguments:\n" - "1. \"hash|height\" (string, required) The block hash or height\n" - "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" - "\nResult (for verbose = true):\n" - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided hash)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"size\" : n, (numeric) The block size\n" - " \"height\" : n, (numeric) The block height or index (same as provided height)\n" - " \"version\" : n, (numeric) The block version\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"tx\" : [ (array of string) The transaction ids\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - " ],\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - "\nResult (for verbose=false):\n" - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - "\nExamples:\n" - + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleCli("getblock", "12800") - + HelpExampleRpc("getblock", "12800") - ); - - LOCK(cs_main); - - std::string strHash = params[0].get_str(); - - // If height is supplied, find the hash - if (strHash.size() < (2 * sizeof(uint256))) { - // std::stoi allows characters, whereas we want to be strict - regex r("[[:digit:]]+"); - if (!regex_match(strHash, r)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); - } - - int nHeight = -1; - try { - nHeight = std::stoi(strHash); - } - catch (const std::exception &e) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); - } - - if (nHeight < 0 || nHeight > chainActive.Height()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - } - strHash = chainActive[nHeight]->GetBlockHash().GetHex(); - } - - uint256 hash(uint256S(strHash)); - - bool fVerbose = true; - if (params.size() > 1) - fVerbose = params[1].get_bool(); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - - if(!ReadBlockFromDisk(block, pblockindex,1)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); - - if (!fVerbose) - { - CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); - ssBlock << block; - std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); - return strHex; - } - - return blockToJSON(block, pblockindex); -} - -UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "gettxoutsetinfo\n" - "\nReturns statistics about the unspent transaction output set.\n" - "Note this call may take some time.\n" - "\nResult:\n" - "{\n" - " \"height\":n, (numeric) The current block height (index)\n" - " \"bestblock\": \"hex\", (string) the best block hash hex\n" - " \"transactions\": n, (numeric) The number of transactions\n" - " \"txouts\": n, (numeric) The number of output transactions\n" - " \"bytes_serialized\": n, (numeric) The serialized size\n" - " \"hash_serialized\": \"hash\", (string) The serialized hash\n" - " \"total_amount\": x.xxx (numeric) The total amount\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("gettxoutsetinfo", "") - + HelpExampleRpc("gettxoutsetinfo", "") - ); - - UniValue ret(UniValue::VOBJ); - - CCoinsStats stats; - FlushStateToDisk(); - if (pcoinsTip->GetStats(stats)) { - ret.push_back(Pair("height", (int64_t)stats.nHeight)); - ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); - ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); - ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs)); - ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize)); - ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex())); - ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount))); - } - return ret; -} - -#include "komodo_defs.h" -#include "komodo_structs.h" - -#define IGUANA_MAXSCRIPTSIZE 10001 -#define KOMODO_KVDURATION 1440 -#define KOMODO_KVBINARY 2 -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume); -int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); -int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); -int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); - -UniValue kvsearch(const UniValue& params, bool fHelp) -{ - UniValue ret(UniValue::VOBJ); uint32_t flags; uint8_t value[IGUANA_MAXSCRIPTSIZE*8],key[IGUANA_MAXSCRIPTSIZE*8]; int32_t duration,j,height,valuesize,keylen; uint256 refpubkey; static uint256 zeroes; - if (fHelp || params.size() != 1 ) - throw runtime_error( - "kvsearch key\n" - "\nSearch for a key stored via the kvupdate command. This feature is only available for asset chains.\n" - "\nArguments:\n" - "1. key (string, required) search the chain for this key\n" - "\nResult:\n" - "{\n" - " \"coin\": \"xxxxx\", (string) chain the key is stored on\n" - " \"currentheight\": xxxxx, (numeric) current height of the chain\n" - " \"key\": \"xxxxx\", (string) key\n" - " \"keylen\": xxxxx, (string) length of the key \n" - " \"owner\": \"xxxxx\" (string) hex string representing the owner of the key \n" - " \"height\": xxxxx, (numeric) height the key was stored at\n" - " \"expiration\": xxxxx, (numeric) height the key will expire\n" - " \"flags\": x (numeric) 1 if the key was created with a password; 0 otherwise.\n" - " \"value\": \"xxxxx\", (string) stored value\n" - " \"valuesize\": xxxxx (string) amount of characters stored\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("kvsearch", "examplekey") - + HelpExampleRpc("kvsearch", "\"examplekey\"") - ); - LOCK(cs_main); - if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 ) - { - ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - ret.push_back(Pair("currentheight", (int64_t)chainActive.LastTip()->nHeight)); - ret.push_back(Pair("key",params[0].get_str())); - ret.push_back(Pair("keylen",keylen)); - if ( keylen < sizeof(key) ) - { - memcpy(key,params[0].get_str().c_str(),keylen); - if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&flags,&height,value,key,keylen)) >= 0 ) - { - std::string val; char *valuestr; - val.resize(valuesize); - valuestr = (char *)val.data(); - memcpy(valuestr,value,valuesize); - if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) - ret.push_back(Pair("owner",refpubkey.GetHex())); - ret.push_back(Pair("height",height)); - duration = ((flags >> 2) + 1) * KOMODO_KVDURATION; - ret.push_back(Pair("expiration", (int64_t)(height+duration))); - ret.push_back(Pair("flags",(int64_t)flags)); - ret.push_back(Pair("value",val)); - ret.push_back(Pair("valuesize",valuesize)); - } else ret.push_back(Pair("error",(char *)"cant find key")); - } else ret.push_back(Pair("error",(char *)"key too big")); - } else ret.push_back(Pair("error",(char *)"null key")); - return ret; -} - -UniValue minerids(const UniValue& params, bool fHelp) -{ - uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); uint8_t minerids[2000],pubkeys[65][33]; int32_t i,j,n,numnotaries,tally[129]; - if ( fHelp || params.size() != 1 ) - throw runtime_error("minerids needs height\n"); - LOCK(cs_main); - int32_t height = atoi(params[0].get_str().c_str()); - if ( height <= 0 ) - height = chainActive.LastTip()->nHeight; - else - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - timestamp = pblockindex->GetBlockTime(); - } - if ( (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 ) - { - memset(tally,0,sizeof(tally)); - numnotaries = komodo_notaries(pubkeys,height,timestamp); - if ( numnotaries > 0 ) - { - for (i=0; i= numnotaries ) - tally[128]++; - else tally[minerids[i]]++; - } - for (i=0; i<64; i++) - { - UniValue item(UniValue::VOBJ); std::string hex,kmdaddress; char *hexstr,kmdaddr[64],*ptr; int32_t m; - hex.resize(66); - hexstr = (char *)hex.data(); - for (j=0; j<33; j++) - sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]); - item.push_back(Pair("notaryid", i)); - - bitcoin_address(kmdaddr,60,pubkeys[i],33); - m = (int32_t)strlen(kmdaddr); - kmdaddress.resize(m); - ptr = (char *)kmdaddress.data(); - memcpy(ptr,kmdaddr,m); - item.push_back(Pair("KMDaddress", kmdaddress)); - - item.push_back(Pair("pubkey", hex)); - item.push_back(Pair("blocks", tally[i])); - a.push_back(item); - } - UniValue item(UniValue::VOBJ); - item.push_back(Pair("pubkey", (char *)"external miners")); - item.push_back(Pair("blocks", tally[128])); - a.push_back(item); - } - ret.push_back(Pair("mined", a)); - ret.push_back(Pair("numnotaries", numnotaries)); - } else ret.push_back(Pair("error", (char *)"couldnt extract minerids")); - return ret; -} - -UniValue notaries(const UniValue& params, bool fHelp) -{ - UniValue a(UniValue::VARR); uint32_t timestamp=0; UniValue ret(UniValue::VOBJ); int32_t i,j,n,m; char *hexstr; uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr; - if ( fHelp || (params.size() != 1 && params.size() != 2) ) - throw runtime_error("notaries height timestamp\n"); - LOCK(cs_main); - int32_t height = atoi(params[0].get_str().c_str()); - if ( params.size() == 2 ) - timestamp = (uint32_t)atol(params[1].get_str().c_str()); - else timestamp = (uint32_t)time(NULL); - if ( height < 0 ) - { - height = chainActive.LastTip()->nHeight; - timestamp = chainActive.LastTip()->GetBlockTime(); - } - else if ( params.size() < 2 ) - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - timestamp = pblockindex->GetBlockTime(); - } - if ( (n= komodo_notaries(pubkeys,height,timestamp)) > 0 ) - { - for (i=0; i 0 ) - ret.push_back(Pair("withdraws", opretbuf)); - else ret.push_back(Pair("withdraws", (char *)"")); - for (baseid=0; baseid<32; baseid++) - { - UniValue item(UniValue::VOBJ); UniValue obj(UniValue::VOBJ); - if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 ) - { - if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 ) - { - item.push_back(Pair("available", ValueFromAmount(available))); - item.push_back(Pair("deposited", ValueFromAmount(deposited))); - item.push_back(Pair("issued", ValueFromAmount(issued))); - item.push_back(Pair("withdrawn", ValueFromAmount(withdrawn))); - item.push_back(Pair("approved", ValueFromAmount(approved))); - item.push_back(Pair("redeemed", ValueFromAmount(redeemed))); - obj.push_back(Pair(CURRENCIES[baseid],item)); - a.push_back(obj); - } - } - } - ret.push_back(Pair("fiatstatus", a)); - return ret; -} - -UniValue paxprice(const UniValue& params, bool fHelp) -{ - if ( fHelp || params.size() > 4 || params.size() < 2 ) - throw runtime_error("paxprice \"base\" \"rel\" height\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); uint64_t basevolume=0,relvolume,seed; - std::string base = params[0].get_str(); - std::string rel = params[1].get_str(); - int32_t height; - if ( params.size() == 2 ) - height = chainActive.LastTip()->nHeight; - else height = atoi(params[2].get_str().c_str()); - //if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 ) - basevolume = 100000; - relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume); - ret.push_back(Pair("base", base)); - ret.push_back(Pair("rel", rel)); - ret.push_back(Pair("height", height)); - char seedstr[32]; - sprintf(seedstr,"%llu",(long long)seed); - ret.push_back(Pair("seed", seedstr)); - if ( height < 0 || height > chainActive.Height() ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - else - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime)); - if ( basevolume != 0 && relvolume != 0 ) - { - ret.push_back(Pair("price",((double)relvolume / (double)basevolume))); - ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume))); - ret.push_back(Pair("basevolume",ValueFromAmount(basevolume))); - ret.push_back(Pair("relvolume",ValueFromAmount(relvolume))); - } else ret.push_back(Pair("error", "overflow or error in one or more of parameters")); - } - return ret; -} - -UniValue paxprices(const UniValue& params, bool fHelp) -{ - if ( fHelp || params.size() != 3 ) - throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)]; - std::string base = params[0].get_str(); - std::string rel = params[1].get_str(); - int32_t maxsamples = atoi(params[2].get_str().c_str()); - if ( maxsamples < 1 ) - maxsamples = 1; - else if ( maxsamples > sizeof(heights)/sizeof(*heights) ) - maxsamples = sizeof(heights)/sizeof(*heights); - ret.push_back(Pair("base", base)); - ret.push_back(Pair("rel", rel)); - n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str()); - UniValue a(UniValue::VARR); - for (i=0; i chainActive.Height() ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - else - { - CBlockIndex *pblockindex = chainActive[heights[i]]; - - item.push_back(Pair("t", (int64_t)pblockindex->nTime)); - item.push_back(Pair("p", (double)prices[i] / COIN)); - a.push_back(item); - } - } - ret.push_back(Pair("array", a)); - return ret; -} - -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - -UniValue gettxout(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 2 || params.size() > 3) - throw runtime_error( - "gettxout \"txid\" n ( includemempool )\n" - "\nReturns details about an unspent transaction output.\n" - "\nArguments:\n" - "1. \"txid\" (string, required) The transaction id\n" - "2. n (numeric, required) vout value\n" - "3. includemempool (boolean, optional) Whether to include the mempool\n" - "\nResult:\n" - "{\n" - " \"bestblock\" : \"hash\", (string) the block hash\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"code\", (string) \n" - " \"hex\" : \"hex\", (string) \n" - " \"reqSigs\" : n, (numeric) Number of required signatures\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" - " \"addresses\" : [ (array of string) array of Komodo addresses\n" - " \"komodoaddress\" (string) Komodo address\n" - " ,...\n" - " ]\n" - " },\n" - " \"version\" : n, (numeric) The version\n" - " \"coinbase\" : true|false (boolean) Coinbase or not\n" - "}\n" - - "\nExamples:\n" - "\nGet unspent transactions\n" - + HelpExampleCli("listunspent", "") + - "\nView the details\n" - + HelpExampleCli("gettxout", "\"txid\" 1") + - "\nAs a json rpc call\n" - + HelpExampleRpc("gettxout", "\"txid\", 1") - ); - - LOCK(cs_main); - - UniValue ret(UniValue::VOBJ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - int n = params[1].get_int(); - bool fMempool = true; - if (params.size() > 2) - fMempool = params[2].get_bool(); - - CCoins coins; - if (fMempool) { - LOCK(mempool.cs); - CCoinsViewMemPool view(pcoinsTip, mempool); - if (!view.GetCoins(hash, coins)) - return NullUniValue; - mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool - } else { - if (!pcoinsTip->GetCoins(hash, coins)) - return NullUniValue; - } - if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull()) - return NullUniValue; - - BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); - CBlockIndex *pindex = it->second; - ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex())); - if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT) - ret.push_back(Pair("confirmations", 0)); - else - { - ret.push_back(Pair("confirmations", komodo_dpowconfs(coins.nHeight,pindex->nHeight - coins.nHeight + 1))); - ret.push_back(Pair("rawconfirmations", pindex->nHeight - coins.nHeight + 1)); - } - ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue))); - uint64_t interest; int32_t txheight; uint32_t locktime; - if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue,(int32_t)pindex->nHeight)) != 0 ) - ret.push_back(Pair("interest", ValueFromAmount(interest))); - UniValue o(UniValue::VOBJ); - ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true); - ret.push_back(Pair("scriptPubKey", o)); - ret.push_back(Pair("version", coins.nVersion)); - ret.push_back(Pair("coinbase", coins.fCoinBase)); - - return ret; -} - -UniValue verifychain(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() > 2) - throw runtime_error( - "verifychain ( checklevel numblocks )\n" - "\nVerifies blockchain database.\n" - "\nArguments:\n" - "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n" - "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n" - "\nResult:\n" - "true|false (boolean) Verified or not\n" - "\nExamples:\n" - + HelpExampleCli("verifychain", "") - + HelpExampleRpc("verifychain", "") - ); - - LOCK(cs_main); - - int nCheckLevel = GetArg("-checklevel", 3); - int nCheckDepth = GetArg("-checkblocks", 288); - if (params.size() > 0) - nCheckLevel = params[0].get_int(); - if (params.size() > 1) - nCheckDepth = params[1].get_int(); - - return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth); -} - -/** Implementation of IsSuperMajority with better feedback */ -static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams) -{ - int nFound = 0; - CBlockIndex* pstart = pindex; - for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++) - { - if (pstart->nVersion >= minVersion) - ++nFound; - pstart = pstart->pprev; - } - - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("status", nFound >= nRequired)); - rv.push_back(Pair("found", nFound)); - rv.push_back(Pair("required", nRequired)); - rv.push_back(Pair("window", consensusParams.nMajorityWindow)); - return rv; -} - -static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) -{ - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("id", name)); - rv.push_back(Pair("version", version)); - rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))); - rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams))); - return rv; -} - -static UniValue NetworkUpgradeDesc(const Consensus::Params& consensusParams, Consensus::UpgradeIndex idx, int height) -{ - UniValue rv(UniValue::VOBJ); - auto upgrade = NetworkUpgradeInfo[idx]; - rv.push_back(Pair("name", upgrade.strName)); - rv.push_back(Pair("activationheight", consensusParams.vUpgrades[idx].nActivationHeight)); - switch (NetworkUpgradeState(height, consensusParams, idx)) { - case UPGRADE_DISABLED: rv.push_back(Pair("status", "disabled")); break; - case UPGRADE_PENDING: rv.push_back(Pair("status", "pending")); break; - case UPGRADE_ACTIVE: rv.push_back(Pair("status", "active")); break; - } - rv.push_back(Pair("info", upgrade.strInfo)); - return rv; -} - -void NetworkUpgradeDescPushBack( - UniValue& networkUpgrades, - const Consensus::Params& consensusParams, - Consensus::UpgradeIndex idx, - int height) -{ - // Network upgrades with an activation height of NO_ACTIVATION_HEIGHT are - // hidden. This is used when network upgrade implementations are merged - // without specifying the activation height. - if (consensusParams.vUpgrades[idx].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) { - networkUpgrades.push_back(Pair( - HexInt(NetworkUpgradeInfo[idx].nBranchId), - NetworkUpgradeDesc(consensusParams, idx, height))); - } -} - - -UniValue getblockchaininfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getblockchaininfo\n" - "Returns an object containing various state info regarding block chain processing.\n" - "\nNote that when the chain tip is at the last block before a network upgrade activation,\n" - "consensus.chaintip != consensus.nextblock.\n" - "\nResult:\n" - "{\n" - " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" - " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" - " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" - " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" - " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" - " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" - " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" - " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" - " \"commitments\": xxxxxx, (numeric) the current number of note commitments in the commitment tree\n" - " \"softforks\": [ (array) status of softforks in progress\n" - " {\n" - " \"id\": \"xxxx\", (string) name of softfork\n" - " \"version\": xx, (numeric) block version\n" - " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n" - " \"status\": xx, (boolean) true if threshold reached\n" - " \"found\": xx, (numeric) number of blocks with the new version found\n" - " \"required\": xx, (numeric) number of blocks required to trigger\n" - " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n" - " },\n" - " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" - " }, ...\n" - " ],\n" - " \"upgrades\": { (object) status of network upgrades\n" - " \"xxxx\" : { (string) branch ID of the upgrade\n" - " \"name\": \"xxxx\", (string) name of upgrade\n" - " \"activationheight\": xxxxxx, (numeric) block height of activation\n" - " \"status\": \"xxxx\", (string) status of upgrade\n" - " \"info\": \"xxxx\", (string) additional information about upgrade\n" - " }, ...\n" - " },\n" - " \"consensus\": { (object) branch IDs of the current and upcoming consensus rules\n" - " \"chaintip\": \"xxxxxxxx\", (string) branch ID used to validate the current chain tip\n" - " \"nextblock\": \"xxxxxxxx\" (string) branch ID that the next block will be validated under\n" - " }\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getblockchaininfo", "") - + HelpExampleRpc("getblockchaininfo", "") - ); - - LOCK(cs_main); - double progress; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - progress = Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.LastTip()); - } else { - int32_t longestchain = KOMODO_LONGESTCHAIN;//komodo_longestchain(); - progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0; - } - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("chain", Params().NetworkIDString())); - obj.push_back(Pair("blocks", (int)chainActive.Height())); - obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1)); - obj.push_back(Pair("bestblockhash", chainActive.LastTip()->GetBlockHash().GetHex())); - obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); - obj.push_back(Pair("verificationprogress", progress)); - obj.push_back(Pair("chainwork", chainActive.LastTip()->nChainWork.GetHex())); - obj.push_back(Pair("pruned", fPruneMode)); - obj.push_back(Pair("size_on_disk", CalculateCurrentUsage())); - - ZCIncrementalMerkleTree tree; - pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree); - #ifdef __APPLE__ - obj.push_back(Pair("commitments", (uint64_t)tree.size())); - #else - obj.push_back(Pair("commitments", tree.size())); - #endif - - CBlockIndex* tip = chainActive.LastTip(); - UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none)); - obj.push_back(Pair("valuePools", valuePools)); - - const Consensus::Params& consensusParams = Params().GetConsensus(); - UniValue softforks(UniValue::VARR); - softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); - softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); - softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - obj.push_back(Pair("softforks", softforks)); - - UniValue upgrades(UniValue::VOBJ); - for (int i = Consensus::UPGRADE_OVERWINTER; i < Consensus::MAX_NETWORK_UPGRADES; i++) { - NetworkUpgradeDescPushBack(upgrades, consensusParams, Consensus::UpgradeIndex(i), tip->nHeight); - } - obj.push_back(Pair("upgrades", upgrades)); - - UniValue consensus(UniValue::VOBJ); - consensus.push_back(Pair("chaintip", HexInt(CurrentEpochBranchId(tip->nHeight, consensusParams)))); - consensus.push_back(Pair("nextblock", HexInt(CurrentEpochBranchId(tip->nHeight + 1, consensusParams)))); - obj.push_back(Pair("consensus", consensus)); - - if (fPruneMode) - { - CBlockIndex *block = chainActive.LastTip(); - while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) - block = block->pprev; - - obj.push_back(Pair("pruneheight", block->nHeight)); - } - return obj; -} - -/** Comparison function for sorting the getchaintips heads. */ -struct CompareBlocksByHeight -{ - bool operator()(const CBlockIndex* a, const CBlockIndex* b) const - { - /* Make sure that unequal blocks with the same height do not compare - equal. Use the pointers themselves to make a distinction. */ - - if (a->nHeight != b->nHeight) - return (a->nHeight > b->nHeight); - - return a < b; - } -}; - -#include - -UniValue getchaintips(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getchaintips\n" - "Return information about all known tips in the block tree," - " including the main chain as well as orphaned branches.\n" - "\nResult:\n" - "[\n" - " {\n" - " \"height\": xxxx, (numeric) height of the chain tip\n" - " \"hash\": \"xxxx\", (string) block hash of the tip\n" - " \"branchlen\": 0 (numeric) zero for main chain\n" - " \"status\": \"active\" (string) \"active\" for the main chain\n" - " },\n" - " {\n" - " \"height\": xxxx,\n" - " \"hash\": \"xxxx\",\n" - " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" - " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" - " }\n" - "]\n" - "Possible values for status:\n" - "1. \"invalid\" This branch contains at least one invalid block\n" - "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" - "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" - "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" - "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" - "\nExamples:\n" - + HelpExampleCli("getchaintips", "") - + HelpExampleRpc("getchaintips", "") - ); - - LOCK(cs_main); - - /* Build up a list of chain tips. We start with the list of all - known blocks, and successively remove blocks that appear as pprev - of another block. */ - /*static pthread_mutex_t mutex; static int32_t didinit; - if ( didinit == 0 ) - { - pthread_mutex_init(&mutex,NULL); - didinit = 1; - } - pthread_mutex_lock(&mutex);*/ - std::set setTips; - int32_t n = 0; - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) - { - n++; - setTips.insert(item.second); - } - fprintf(stderr,"iterations getchaintips %d\n",n); - n = 0; - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) - { - const CBlockIndex* pprev=0; - n++; - if ( item.second != 0 ) - pprev = item.second->pprev; - if (pprev) - setTips.erase(pprev); - } - fprintf(stderr,"iterations getchaintips %d\n",n); - //pthread_mutex_unlock(&mutex); - - // Always report the currently active tip. - setTips.insert(chainActive.LastTip()); - - /* Construct the output array. */ - UniValue res(UniValue::VARR); const CBlockIndex *forked; - BOOST_FOREACH(const CBlockIndex* block, setTips) - BOOST_FOREACH(const CBlockIndex* block, setTips) - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("height", block->nHeight)); - obj.push_back(Pair("hash", block->phashBlock->GetHex())); - forked = chainActive.FindFork(block); - if ( forked != 0 ) - { - const int branchLen = block->nHeight - forked->nHeight; - obj.push_back(Pair("branchlen", branchLen)); - - string status; - if (chainActive.Contains(block)) { - // This block is part of the currently active chain. - status = "active"; - } else if (block->nStatus & BLOCK_FAILED_MASK) { - // This block or one of its ancestors is invalid. - status = "invalid"; - } else if (block->nChainTx == 0) { - // This block cannot be connected because full block data for it or one of its parents is missing. - status = "headers-only"; - } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) { - // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized. - status = "valid-fork"; - } else if (block->IsValid(BLOCK_VALID_TREE)) { - // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain. - status = "valid-headers"; - } else { - // No clue. - status = "unknown"; - } - obj.push_back(Pair("status", status)); - } - res.push_back(obj); - } - - return res; -} - -UniValue mempoolInfoToJSON() -{ - UniValue ret(UniValue::VOBJ); - ret.push_back(Pair("size", (int64_t) mempool.size())); - ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize())); - ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); - - return ret; -} - -UniValue getmempoolinfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getmempoolinfo\n" - "\nReturns details on the active state of the TX memory pool.\n" - "\nResult:\n" - "{\n" - " \"size\": xxxxx (numeric) Current tx count\n" - " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n" - " \"usage\": xxxxx (numeric) Total memory usage for the mempool\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getmempoolinfo", "") - + HelpExampleRpc("getmempoolinfo", "") - ); - - return mempoolInfoToJSON(); -} - -UniValue invalidateblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "invalidateblock \"hash\"\n" - "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the block to mark as invalid\n" - "\nResult:\n" - "\nExamples:\n" - + HelpExampleCli("invalidateblock", "\"blockhash\"") - + HelpExampleRpc("invalidateblock", "\"blockhash\"") - ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - CValidationState state; - - { - LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - InvalidateBlock(state, pblockindex); - } - - if (state.IsValid()) { - ActivateBestChain(state); - } - - if (!state.IsValid()) { - throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); - } - - return NullUniValue; -} - -UniValue reconsiderblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "reconsiderblock \"hash\"\n" - "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" - "This can be used to undo the effects of invalidateblock.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the block to reconsider\n" - "\nResult:\n" - "\nExamples:\n" - + HelpExampleCli("reconsiderblock", "\"blockhash\"") - + HelpExampleRpc("reconsiderblock", "\"blockhash\"") - ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - CValidationState state; - - { - LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - ReconsiderBlock(state, pblockindex); - } - - if (state.IsValid()) { - ActivateBestChain(state); - } - - if (!state.IsValid()) { - throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); - } - - return NullUniValue; -} diff --git a/src/script/standard.h b/src/script/standard.h index c8d9fc68e93..a9402f16451 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -40,6 +40,13 @@ class CScriptID : public uint160 CScriptID(const uint160& in) : uint160(in) {} }; +class CCryptoConditionID : public uint160 +{ +public: + CCryptoConditionID() : uint160() {} + CCryptoConditionID(const uint160& in) : uint160(in) {} +}; + static const unsigned int MAX_OP_RETURN_RELAY = 8192; //! bytes extern unsigned nMaxDatacarrierBytes; diff --git a/src/sync.cpp b/src/sync.cpp index 31c3301bd25..2f17a401bad 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -157,7 +157,8 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) static void pop_lock() { dd_mutex.lock(); - (*lockstack).pop_back(); + if (lockstack.get() != NULL) + (*lockstack).pop_back(); dd_mutex.unlock(); } diff --git a/src/util.cpp b/src/util.cpp index 65ecfe6ec7f..bee7903d2b5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -30,8 +30,7 @@ #include "sync.h" #include "utilstrencodings.h" #include "utiltime.h" -//#include "komodo_defs.h" // plz dont add this where it is not used, we have build errors for komodo-cli - +#include "komodo_defs.h" #include #include #include @@ -394,8 +393,8 @@ void ParseParameters(int argc, const char* const argv[]) } } -// split string using by space or comma as a delimiter char -void SplitStr(const std::string& strVal, std::vector &outVals) +// split string using space, comma (default) or other char (param) as a delimiter +void SplitStr(const std::string& strVal, std::vector &outVals, const std::string &delims) { stringstream ss(strVal); @@ -406,7 +405,7 @@ void SplitStr(const std::string& strVal, std::vector &outVals) while (std::isspace(ss.peek())) ss.ignore(); - while ((c = ss.get()) != EOF && !std::isspace(c) && c != ',') + while ((c = ss.get()) != EOF && !std::isspace(c) && delims.find(c) == std::string::npos) str += c; if (!str.empty()) @@ -414,36 +413,34 @@ void SplitStr(const std::string& strVal, std::vector &outVals) } } -void Split(const std::string& strVal, int32_t outsize, uint64_t *outVals, const uint64_t nDefault) +void SplitIntoU64List(const std::string& strVal, int32_t outsize, uint64_t* outVals, const uint64_t nDefault) { stringstream ss(strVal); vector vec; - uint64_t i, nLast, numVals = 0; + uint64_t val, nLast, numVals = 0; - while ( ss.peek() == ' ' ) + while (ss.peek() == ' ') ss.ignore(); - while ( ss >> i ) - { - outVals[numVals] = i; - numVals += 1; + while (ss >> val && numVals < outsize) { + outVals[numVals] = val; + numVals++; - while ( ss.peek() == ' ' ) + while (ss.peek() == ' ') ss.ignore(); - if ( ss.peek() == ',' ) + if (ss.peek() == ',') ss.ignore(); - while ( ss.peek() == ' ' ) + while (ss.peek() == ' ') ss.ignore(); } - if ( numVals > 0 ) + if (numVals > 0) nLast = outVals[numVals - 1]; else nLast = nDefault; - for ( i = numVals; i < outsize; i++ ) - { + for (int i = numVals; i < outsize; i++) { outVals[i] = nLast; } } @@ -735,7 +732,6 @@ void ReadConfigFile(map& mapSettingsRet, } // If datadir is changed in .conf file: ClearDatadirCache(); - extern uint16_t BITCOIND_RPCPORT; BITCOIND_RPCPORT = GetArg("-rpcport",BaseParams().RPCPort()); } @@ -1040,3 +1036,34 @@ int GetNumCores() return boost::thread::physical_concurrency(); } +// add settings to args maps (to add default opts for a specific chain defined outside) +void AddSettings(std::map& mapSettingsRet, + std::map >& mapMultiSettingsRet, const std::string &strOpts) +{ + std::vector vOpts; + SplitStr(strOpts, vOpts, " "); + for (auto const &opt : vOpts) + { + std::vector namevalue; + SplitStr(opt, namevalue, "="); + if (namevalue.size() != 2) + throw std::runtime_error("Invalid option name-value format in override-settings variable"); + std::string name = namevalue[0]; + std::string value = namevalue[1]; + if (name[0] != '-') + throw std::runtime_error("Invalid option format in override-settings variable"); + + // Interpret --foo as -foo. + // If both --foo and -foo are set, the last takes effect. + if (name.length() > 1 && name[1] == '-') + name = name.substr(1); + + if (mapSettingsRet.count(name) == 0) + { + mapSettingsRet[name] = value; + // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set) + InterpretNegativeSetting(name, mapSettingsRet); + } + mapMultiSettingsRet[name].push_back(value); + } +} \ No newline at end of file diff --git a/src/util.h b/src/util.h index 17bf19952b0..554555d0530 100644 --- a/src/util.h +++ b/src/util.h @@ -179,13 +179,13 @@ inline bool IsSwitchChar(char c) /** * Return string argument or default value * - * @param strVal string to split + * @param strVal string to split into array of uint64_t * @param outVals array of numbers from string or default - * if the string is null, nDefault is used for all array entries - * else if the string has fewer than _MAX_ERAS entries, then the last - * entry fills remaining entries + * if the strVal is null, nDefault is used for all array entries + * else if the strVal has fewer than outsize entries, then the last + * entry fills remaining entries in outVals */ -void Split(const std::string& strVal, int32_t outsize, uint64_t *outVals, uint64_t nDefault); +void SplitIntoU64List(const std::string& strVal, int32_t outsize, uint64_t *outVals, uint64_t nDefault); /** * Return string argument or default value @@ -288,7 +288,8 @@ template void TraceThread(const char* name, Callable func) } // split string using by space or comma as a delimiter char -void SplitStr(const std::string& strVal, std::vector &outVals); +void SplitStr(const std::string& strVal, std::vector &outVals, const std::string &delims = ","); +void AddSettings(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet, const std::string &strOpts); #define KOMODO_ASSETCHAIN_MAXLEN 65 diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index cd0cc42a6c5..e42628f6416 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -42,11 +42,11 @@ #include "zcash/Note.hpp" #include "zcash/NoteEncryption.hpp" +#include "rpcwallet.h" + using namespace std; using namespace libzcash; -// Function declaration for function implemented in wallet/rpcwallet.cpp -bool EnsureWalletIsAvailable(bool avoidException); /** * RPC call to generate a payment disclosure diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 31f583ee4f1..3795a7077ad 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -37,10 +37,9 @@ #include -using namespace std; +#include "rpcwallet.h" -void EnsureWalletIsUnlocked(); -bool EnsureWalletIsAvailable(bool avoidException); +using namespace std; UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys); UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e7d8c849e9c..08d1b3124b3 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -63,6 +63,8 @@ #include "komodo_defs.h" #include +#include "rpcwallet.h" + #include "../cc/CCfaucet.h" #include "../cc/CCrewards.h" #include "../cc/CCdice.h" @@ -81,16 +83,8 @@ using namespace std; using namespace libzcash; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; const std::string ADDR_TYPE_SPROUT = "sprout"; const std::string ADDR_TYPE_SAPLING = "sapling"; -extern UniValue TxJoinSplitToJSON(const CTransaction& tx); -extern int32_t KOMODO_INSYNC; -uint32_t komodo_segid32(char *coinaddr); -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime); // from ac_private chains only -CBlockIndex *komodo_getblockindex(uint256 hash); int64_t nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; @@ -102,8 +96,6 @@ UniValue z_getoperationstatus_IMPL(const UniValue&, bool); #define VALID_PLAN_NAME(x) (strlen(x) <= PLAN_NAME_MAX) #define THROW_IF_SYNCING(INSYNC) if (INSYNC == 0) { throw runtime_error(strprintf("%s: Chain still syncing at height %d, aborting to prevent linkability analysis!",__FUNCTION__,chainActive.Tip()->GetHeight())); } -int tx_height( const uint256 &hash ); - std::string HelpRequiringPassphrase() { return pwalletMain && pwalletMain->IsCrypted() @@ -524,8 +516,6 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); } -int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); - UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) { uint8_t opretbuf[IGUANA_MAXSCRIPTSIZE],opretscript[IGUANA_MAXSCRIPTSIZE],*opret=0; char *oprethexstr; int32_t len, opretlen = 0; @@ -614,29 +604,6 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) return wtx.GetHash().GetHex(); } -#include "komodo_defs.h" - -#define KOMODO_KVPROTECTED 1 -#define KOMODO_KVBINARY 2 -#define KOMODO_KVDURATION 1440 -#define IGUANA_MAXSCRIPTSIZE 10001 -uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey37[37],char *coinaddr,int32_t height,char *base,int64_t fiatoshis); -int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); -#define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" -extern int32_t KOMODO_PAX; -extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; -int32_t komodo_is_issuer(); -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -int32_t komodo_isrealtime(int32_t *kmdheightp); -int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); -int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); -int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize); -uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen); -uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 privkey); -int32_t komodo_kvduration(uint32_t flags); -uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase); -int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig); - UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk) { static uint256 zeroes; diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 3e7a54d4afe..226647b1986 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -24,5 +24,6 @@ class CRPCTable; void RegisterWalletRPCCommands(CRPCTable &tableRPC); bool EnsureWalletIsAvailable(bool avoidException); +void EnsureWalletIsUnlocked(); #endif //BITCOIN_WALLET_RPCWALLET_H diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6e33d24ffc2..461657af93e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -38,6 +38,8 @@ #include "crypter.h" #include "coins.h" #include "zcash/zip32.h" + +#include "komodo_defs.h" #include "cc/CCinclude.h" #include @@ -58,12 +60,7 @@ unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; bool bSpendZeroConfChange = true; bool fSendFreeTransactions = false; bool fPayAtLeastCustomFee = true; -#include "komodo_defs.h" -CBlockIndex *komodo_chainactive(int32_t height); -extern std::string DONATION_PUBKEY; -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -int tx_height( const uint256 &hash ); /** * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) @@ -4233,7 +4230,7 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge } -void komodo_prefetch(FILE *fp); +//void komodo_prefetch(FILE *fp); DBErrors CWallet::LoadWallet(bool& fFirstRunRet) { diff --git a/tokel_chain_flow.md b/tokel_chain_flow.md deleted file mode 100644 index a8d6604b604..00000000000 --- a/tokel_chain_flow.md +++ /dev/null @@ -1,54 +0,0 @@ -# Tokel blockchain code commit process/flow - -## Repository overview - -### TokelPlatform/komodo - -#### Tkltest branch - -https://github.com/TokelPlatform/komodo/tree/tkltest - -Used to test blockchain code in a community environment using the TKLTEST (test net) blockchains. - -#### Tokel branch - -https://github.com/TokelPlatform/komodo/tree/tokel - -This is the Tokel ‘master’ branch. The Tokel chain runs off this branch. - -This branch is to be kept identical to the KomodoPlatform/Komodo ‘tokel’ branch. - -### KomodoPlatform/Komodo - -#### Tokel branch - -https://github.com/KomodoPlatform/komodo/tree/tokel - -This branch is used by Komodo Notary Nodes. This branch is a ‘gateway’ between the Komodo & Tokel branches. All Tokel development is pushed through here, and vice versa for Komodo development/updates. - -## The Process - working on the Tokel Blockchain features - -Feature development -> Team/Community testing -> PR to the `tokel` branch - -## Feature development - -1. Fork this repository and make a new feature branch. -2. Once done make a PR to TokelPlatform/komodo ‘tkltest’. -3. Reach out to someone to review your code. - -## Team/community testing - -After getting you PR reviewed and merge to `tkltest` Team/community performs through testing. - -## Accepted/tested code - -If all the tests have gone well, the resulting code is PRd into these repositories: -1. `TokelPlatform/Komodo` `tokel` branch -2. `KomodoPlatform/Komodo` `tokel` branch - -## Updates coming from Komodo side - -1. PR from a branch in Komodo repository - - -## Updates coming from Komodo side diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index 5f7c1d5f7be..fd00a245914 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -47,6 +47,7 @@ PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 +# cclib building now added to src/Makefile.am #BUILD CCLIB # WD=$PWD # cd src/cc @@ -54,11 +55,20 @@ make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 # echo Making cclib... # ./makecustom # cd $WD -# cclib building now added to src/Makefile.am + +# build cryptoconditions +cd ./src/cryptoconditions +./autogen.sh +./configure +make +cd ../.. ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ -./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" +CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ +./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" \ + --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ + CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ + CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' -make "$@" V=1 NO_GTEST=1 STATIC=1 +make "$@" V=1 NO_GTEST=1 STATIC=1 \ No newline at end of file diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index a445ef873b7..eef4b4f27f2 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -13,17 +13,28 @@ cd "$(dirname "$(readlink -f "$0")")/.." cd depends/ && make HOST=$HOST V=1 NO_QT=1 cd ../ +# build cryptoconditions +cd ./src/cryptoconditions +./autogen.sh +./configure --host=x86_64-w64-mingw32 --enable-static --disable-shared +CC="${CC} -g " CXX="${CXX} -g " make V=1 +cd ../.. + +# note: cclib building now added to src/Makefile.am #BUILD CCLIB # WD=$PWD # cd src/cc # echo $PWD # ./makecustom # cd $WD -# cclib building now added to src/Makefile.am - ./autogen.sh -CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared -sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure +CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared \ + --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ + CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ + CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' +sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure + cd src/ -CC="${CC} -g " CXX="${CXX} -g " make V=1 komodod.exe komodo-cli.exe komodo-tx.exe +# note: to build tokeld, tokel-cli it should not exist 'komodod.exe komodo-cli.exe' param here: +CC="${CC} -g " CXX="${CXX} -g " make V=1 diff --git a/zcutil/build.sh b/zcutil/build.sh index 9033ac32fbc..3a64f2d2e69 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -96,17 +96,27 @@ eval "$MAKE" --version as --version ld -v +# build cryptoconditions +cd ./src/cryptoconditions +./autogen.sh +./configure +make +cd ../.. + HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh -CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' +CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' \ + --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ + CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ + CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' +# cclib building now added to src/Makefile.am: #BUILD CCLIB #WD=$PWD #cd src/cc #echo $PWD #./makecustom #cd $WD -# cclib building now added to src/Makefile.am "$MAKE" "$@" V=1 From e9538bc271decffe912f981cd2c487047d62da29 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 21 Oct 2021 23:42:48 +0500 Subject: [PATCH 175/348] remove bad cryptoconditions build cmds from build..sh --- zcutil/build-mac.sh | 7 ------- zcutil/build-win.sh | 7 ------- zcutil/build.sh | 7 ------- 3 files changed, 21 deletions(-) diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index fd00a245914..9dd86537007 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -56,13 +56,6 @@ make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 # ./makecustom # cd $WD -# build cryptoconditions -cd ./src/cryptoconditions -./autogen.sh -./configure -make -cd ../.. - ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index eef4b4f27f2..b89271e4833 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -13,13 +13,6 @@ cd "$(dirname "$(readlink -f "$0")")/.." cd depends/ && make HOST=$HOST V=1 NO_QT=1 cd ../ -# build cryptoconditions -cd ./src/cryptoconditions -./autogen.sh -./configure --host=x86_64-w64-mingw32 --enable-static --disable-shared -CC="${CC} -g " CXX="${CXX} -g " make V=1 -cd ../.. - # note: cclib building now added to src/Makefile.am #BUILD CCLIB # WD=$PWD diff --git a/zcutil/build.sh b/zcutil/build.sh index 3a64f2d2e69..2c1a9c66e86 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -96,13 +96,6 @@ eval "$MAKE" --version as --version ld -v -# build cryptoconditions -cd ./src/cryptoconditions -./autogen.sh -./configure -make -cd ../.. - HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh From a61eb74a7fdaab93f496ad47c1141533e75c6509 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 22 Oct 2021 13:13:14 +0500 Subject: [PATCH 176/348] del test help message --- src/wallet/rpcwallet.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 08d1b3124b3..5cd1a5227be 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -538,7 +538,6 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n" " The recipient will receive less " + strprintf("%s",komodo_chainname()) + " than you enter in the amount field.\n" "6. oprethexstr\n" - "7. unlocktime (numeric, optional) timestamp or blockheight when the sent funds will be unlocked by CLTV opcode\n" "\nResult:\n" "\"transactionid\" (string) The transaction id.\n" "\nExamples:\n" From 6d9c83308f21345b53d0bfe6460448afee0f0dbf Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Fri, 22 Oct 2021 23:22:14 +1100 Subject: [PATCH 177/348] updated dapp link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3179378402..7f7c9d2d518 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Tokel is a dedicated token platform. This platform will provide a solid foundati The all-in-one Tokel application is an open-sourced application that will be the one stop shop for all Tokel related features. This application is built using nSPV superlite wallet technology that has been developed by the Komodo platform, for an incredibly fast and reliable experience. This application accesses all of the features offered on the Tokel blockchain whilst keeping users funds in their own wallets (completely non-custodial). This application is in development. You can keep up with progress on the github, or find out more by having a chat in our discord. -https://github.com/TokelPlatform/tokel_app +https://github.com/TokelPlatform/tokel_dapp #### Application features include: - A TKL coin wallet From dacb54bd8e213be5085824a1c28bc44b212eab86 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 23 Oct 2021 14:00:39 +0500 Subject: [PATCH 178/348] nspv fix verifyntz check to remove long unneeded remote call --- src/komodo_nSPV.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index 0f8ed0843d1..dbd18d40462 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -651,7 +651,7 @@ uint256 NSPV_opretextract(int32_t *heightp,uint256 *blockhashp,char *symbol,std: int32_t NSPV_notarizationextract(int32_t verifyntz,int32_t *ntzheightp,uint256 *blockhashp,uint256 *desttxidp,CTransaction tx) { - int32_t numsigs=0; uint8_t elected[64][33]; char *symbol; std::vector opret; uint32_t nTime; + char *symbol; std::vector opret; AssertLockHeld(cs_main); if ( tx.vout.size() >= 2 ) @@ -662,13 +662,19 @@ int32_t NSPV_notarizationextract(int32_t verifyntz,int32_t *ntzheightp,uint256 * { //sleep(1); // needed to avoid no pnodes error *desttxidp = NSPV_opretextract(ntzheightp,blockhashp,symbol,opret,tx.GetHash()); - nTime = NSPV_blocktime(*ntzheightp); - komodo_notaries(elected,*ntzheightp,nTime); - if ( verifyntz != 0 && (numsigs= NSPV_fastnotariescount(tx,elected,nTime)) < 12 ) + if (verifyntz != 0) { - LogPrintf("%s error numsigs.%d less than 12\n", __func__, numsigs); - return(-3); - } + uint32_t nTime = NSPV_blocktime(*ntzheightp); + int32_t numsigs=0; + uint8_t elected[64][33]; + + komodo_notaries(elected,*ntzheightp,nTime); + if ((numsigs= NSPV_fastnotariescount(tx,elected,nTime)) < 12 ) + { + LogPrintf("%s error notaries numsigs.%d less than required min 12\n", __func__, numsigs); + return(-3); + } + } return(0); } else From 024d2cb07b7533b9cf47ea46c4199014a688e3ba Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 23 Oct 2021 17:44:36 +0500 Subject: [PATCH 179/348] enabled tokenindexkey rpc --- src/rpc/tokensrpc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 7f98725d84e..70ccd0aec2d 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -1184,7 +1184,7 @@ static const CRPCCommand commands[] = { "tokens v2", "mytokenv2orders", &mytokenv2orders, true }, { "tokens", "tokenaddress", &tokenaddress, true }, { "tokens v2", "tokenv2address", &tokenv2address, true }, -// { "tokens v2", "tokenv2indexkey", &tokenv2indexkey, true }, + { "tokens v2", "tokenv2indexkey", &tokenv2indexkey, true }, { "tokens", "tokenbalance", &tokenbalance, true }, { "tokens v2", "tokenv2balance", &tokenv2balance, true }, { "tokens", "tokenallbalances", &tokenallbalances, true }, From b7c50bc009481a8fad11fda14ce1c0d6541297e6 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 23 Oct 2021 17:45:50 +0500 Subject: [PATCH 180/348] SetCCunspentsCCIndex indexkey fixed (fixes tokenlist) --- src/cc/CCtx.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 86fcf30614f..7c1f2fe6531 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -799,8 +799,7 @@ void SetCCunspentsCCIndex(std::vector >::iterator it = searchKeys.begin(); it != searchKeys.end(); it++) { if (GetUnspentCCIndex((*it).first, (*it).second, unspentOutputs, -1, -1, 0) == 0) From 6e35248afba08385e876888401ddf829a2209cf6 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 23 Oct 2021 17:47:17 +0500 Subject: [PATCH 181/348] tokenallbalances result fixed --- src/cc/CCtokens_impl.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 92f0453363e..0c429b9f706 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -575,16 +575,16 @@ UniValue GetAllTokenBalances(CPubKey pk, bool useMempool) LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << "()" << " checking tx vout destaddress=" << destaddr << " amount=" << tx.vout[index].nValue << std::endl); uint8_t funcId = 0; - uint256 tokenIdInOpret; + uint256 tokenIdOut; CScript opret; std::string errorStr; - CAmount retAmount = V::CheckTokensvout(cp, NULL, tx, index, opret, tokenIdInOpret, funcId, errorStr); + CAmount retAmount = V::CheckTokensvout(cp, NULL, tx, index, opret, tokenIdOut, funcId, errorStr); if (retAmount > 0 && !myIsutxo_spentinmempool(ignoretxid, ignorevin, txhash, index)) - { - CAmount prevAmount = result[tokenIdInOpret.GetHex()].get_int64(); - mapBalances[tokenIdInOpret] += retAmount; + { + CAmount prevAmount = mapBalances[tokenIdOut]; + mapBalances[tokenIdOut] = prevAmount + retAmount; } } }; // auto add_token_amount @@ -615,8 +615,11 @@ UniValue GetAllTokenBalances(CPubKey pk, bool useMempool) add_token_amount(it->first.txhash, it->first.index, it->second.satoshis); } - for(auto const &m : mapBalances) - result.pushKV(m.first.GetHex(), m.second); + for(auto const &m : mapBalances) { + UniValue elem(UniValue::VOBJ); + elem.pushKV(m.first.GetHex(), m.second); + result.push_back(elem); + } return result; } From 7720143e14a378795da7d5360177791d83e63c16 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 8 Nov 2021 14:42:17 +0500 Subject: [PATCH 182/348] py tests for tokenbalance tokenlist --- src/tui/tui_assets_orders.py | 143 ++++++++++++++++++++++++++++++----- 1 file changed, 126 insertions(+), 17 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index e2db27965ee..a9ed0ed691d 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -5,12 +5,14 @@ import time import json from slickrpc.exc import RpcException +import configparser # test creates fungible and non-fungible tokens # performs transfers and multiple transfers # then runs assets cc ask/bids tests header = "komodo assets cc tokenask/bid v2 test\n" +tui_config_name = './tui_assets_orders.ini' def get_result_error(r): if isinstance(r, dict) : @@ -44,18 +46,23 @@ def check_txid(txid) : return True return False -def run_tokens_create(rpc): +def run_tokens_create(): # set your own two node params # DIMXY20 - rpc1 = rpclib.rpc_connect("user3088995989", "pass53c05895f37aa1eda9b0de63944275668e1956abb8c38f186132262fe53ae9be7c", 14723) - rpc2 = rpclib.rpc_connect("user2898668153", "passe99167496d2bbe43876e60430d52eb37b547fa1085b741a15776454eb126d9a603", 15723) - rpc3 = rpclib.rpc_connect("user972794450", "passe7eb16f5c015a53463cc5f27a004854cb76f4ec5c9aece177f01d8b3d13119e445", 16723) + # rpc1 = rpclib.rpc_connect("user3088995989", "pass53c05895f37aa1eda9b0de63944275668e1956abb8c38f186132262fe53ae9be7c", 14723) + # rpc2 = rpclib.rpc_connect("user2898668153", "passe99167496d2bbe43876e60430d52eb37b547fa1085b741a15776454eb126d9a603", 15723) + # rpc3 = rpclib.rpc_connect("user972794450", "passe7eb16f5c015a53463cc5f27a004854cb76f4ec5c9aece177f01d8b3d13119e445", 16723) + # DIMXY29 + rpc1 = rpclib.rpc_connect("user977812407", "pass45a4a6ce9ffafbebd2a478d3858d55c8a4bded74632bb488c8c93164d048237516", 14723) + rpc2 = rpclib.rpc_connect("user4228621419", "pass4e51de899bd15c12569d762ded036e5aecd5aeb7be40788a339e72e1fea7359d7e", 15723) + rpc3 = rpclib.rpc_connect("user3877003389", "passea3e5a6c7a8a88f5447cc39bc8720cf783bbcef43345b16be9aadc0a1b381006eb", 16723) - for v in ["", "v2"] : + + ## for v in ["", "v2"] : ## for v in [""] : - ## for v in ["v2"] : + for v in ["v2"] : print("creating fungible token 1...") result = call_rpc(rpc1, "token"+v+"create", "T1", str(0.000001)) # 100 assert(check_tx(result)) @@ -104,7 +111,14 @@ def run_tokens_create(rpc): assert(check_tx(result)) nftf7id4 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id4) + print("tokens for tests created okay!") + + # test tokenlist: + check_tokenlist(rpc1, v, [tokenid1, tokenid2, nft00id1, nft00id2, nftf7id1, nftf7id2, nftf7id3, nftf7id4]) + # test tokenallbalances: + check_tokenallbalances(rpc1, v, {tokenid1: 100, tokenid2: 1000_0000, nft00id1: 1, nft00id2: 1, nftf7id1: 1, nftf7id2: 1, nftf7id3: 1, nftf7id4: 1} ) + ''' # first try transfer tokens to a pk and back, then run assets tests print("starting transfer tests for tokenid version=" + v + "...") run_transfers(rpc1, rpc2, v, tokenid1, tokenid2, 10) @@ -112,7 +126,7 @@ def run_tokens_create(rpc): run_transfers(rpc1, rpc2, v, nft00id1, nft00id2, 1) print("starting transfer tests for nftf7id version=" + v + "...") run_transfers(rpc1, rpc2, v, nftf7id1, nftf7id2, 1) - print("token transfers tests finished okay") + print("token transfers tests finished okay!") time.sleep(3) # assets cc tests: @@ -131,6 +145,7 @@ def run_tokens_create(rpc): print("starting assets order expiration tests for tokenid1 version=" + v + "...") run_assets_expired_orders(rpc1, rpc2, v, tokenid1, 10, 8, 0.0001, False) + print("assets tests finished okay!") if v == "v2" : # MofN supported for tokens cc v2 only print("running MofN tests for tokens v2:") @@ -139,9 +154,11 @@ def run_tokens_create(rpc): print("starting MofN tests for nft00id1...") run_MofN_transfers(rpc1, rpc2, rpc3, nft00id1, 1) print("starting MofN tests for nftf7id1...") - run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) + run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) + print("token MofN transfer tests finished okay!") + ''' - print("token/assets tests finished okay") + print("all token/assets tests finished okay!") time.sleep(3) exit @@ -197,7 +214,7 @@ def call_rpc_retry(rpc, rpcname, stop_error, *args) : for i in range(retries): print("calling " + rpcname) result = rpcfunc(*args) - print(rpcname + " result:", result) + # print(rpcname + " result:", result) if check_tx(result): break if stop_error and get_result_error(result) == stop_error : @@ -207,11 +224,12 @@ def call_rpc_retry(rpc, rpcname, stop_error, *args) : print("retrying " + rpcname + '...') time.sleep(delay) assert(check_tx(result)) - print(rpcname + " tx created") + # print(rpcname + " finished okay") return result def call_token_rpc(rpc, rpcname, stop_error, *args) : - print("calling " + rpcname + " for tokenid=", args[0]) + if len(args) > 0 : + print("calling " + rpcname + " for tokenid=", args[0]) return call_rpc_retry(rpc, rpcname, stop_error, *args) def run_transfers(rpc1, rpc2, v, tokenid1, tokenid2, amount): @@ -670,13 +688,103 @@ def run_assets_expired_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, i print("trying to cancel not yet expired order with other pk: token"+v+"cancelbid...") cancelid3 = call_token_rpc_send_tx(rpc1, "token"+v+"cancelbid", 'bid is empty', tokenid, bidid1) +def check_tokenlist(rpc, v, tokenids) : + rpcname = "token" + v + "list" + results = {} + retries = 24 + delay = 10 + for i in range(retries) : + tokenlist = call_token_rpc(rpc, rpcname, '') + for tid in tokenids : + if tid in tokenlist : + results[tid] = 1 + if len(results) == len(tokenids) : + break + time.sleep(delay) + print('retrying check_tokenlist waiting for txns to mine...') + assert len(results) == len(tokenids), "not all tokenids found in " + rpcname + " results" + print('check_tokenlist okay!') + +def check_tokenallbalances(rpc, v, checkbalances) : + rpcname = "token" + v + "allbalances" + results = {} + retries = 24 + delay = 10 + for i in range(retries) : + tokenbalances = call_token_rpc(rpc, rpcname, '') + # print('tokenbalances', tokenbalances) + for i, (checktid, checkamount) in enumerate(checkbalances.items()) : + for tbalance in tokenbalances : + for tid, amount in tbalance.items() : # get tokenid and amount from tokenallbalances items like {'1233937': 100000} + if tid == checktid : + assert amount == checkamount, 'invalid token amount ' + str(amount) + ' returned from ' + rpcname + ' for tokenid ' + checktid + results[tid] = 1 + if len(results) == len(checkbalances) : + break + time.sleep(delay) + print('retrying check_tokenallbalances waiting for txns to mine...') + assert len(results) == len(checkbalances), "not all tokenids have correct amounts in " + rpcname + " results" + print('check_tokenallbalances okay!') menuItems = [ {"run token create/transfers and assets orders": run_tokens_create}, {"Exit": exit} ] +def readConfig(path) : + + tui_config = configparser.ConfigParser() + tui_config.read(tui_config_name) + node_ini_path = tui_config['DEFAULT'][path] + assert node_ini_path, "cannot read " + path + " property from tui config" + + chain_config = configparser.ConfigParser() + chain_config.read(node_ini_path) + uname = chain_config['DEFAULT']['rpcuser'] + passw = chain_config['DEFAULT']['rpcpassword'] + port = chain_config['DEFAULT']['rpcport'] + + assert uname and passw and port, node_ini_path + ' has empty params rpcuser or rpcpassword or rpcport' + r = {'rpcuser' : uname, 'rpcpassword' : passw, 'rpcport': port } + return r + + +def makeTuiConfig() : + + tui_config = configparser.ConfigParser() + tui_config.read(tui_config_name) + old_path1 = old_path2 = old_path3 = '' + if tui_config.read(tui_config_name) : + old_path1 = tui_config['path1'] + old_path2 = tui_config['path2'] + old_path3 = tui_config['path3'] + + ask_path1 = "" + if old_path1 : + ask_path1 = "(" + old_path1 + ")" + path1 = input("node1 path " + ask_path1 + ":" ) + + ask_path2 = "" + if old_path2 : + ask_path2 = "(" + old_path2 + ")" + path2 = input("node2 path " + ask_path2 + ":" ) + + ask_path3 = "" + if old_path3 : + ask_path3 = "(" + old_path3 + ")" + path3 = input("node3 path " + ask_path3 + ":" ) + + if path1 or path2 or path3 : + assert path1 != path2 and path1 != path3 and path2 != path3, 'paths should be different' + if path1 : + tui_config['path1'] = path1 + if path2 : + tui_config['path2'] = path2 + if path3 : + tui_config['path3'] = path3 + with open(tui_config_name, 'w') as configfile: # save tui config + tui_config.write(configfile) def main(): while True: @@ -693,14 +801,15 @@ def main(): if list(menuItems[int(choice)].keys())[0] == "Exit": list(menuItems[int(choice)].values())[0]() else: - list(menuItems[int(choice)].values())[0](rpc_connection) + list(menuItems[int(choice)].values())[0]() except (ValueError, IndexError): pass if __name__ == "__main__": - print("starting assets orders test (remember to set rpc params for two nodes for your chain)") - time.sleep(2) - rpc_connection = "" - main() + print("starting assets orders test\n plz first start a chain of three nodes and enter paths for your node config files)") + # time.sleep(2) + makeTuiConfig() + # main() + #run_tokens_create() From a9bfc2e1b456eb3453405818ccd7827171354519 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 8 Nov 2021 14:43:11 +0500 Subject: [PATCH 183/348] NSPV_notarized_bracket fixed to find correct bracket --- src/komodo_nSPV_defs.h | 11 +-- src/komodo_nSPV_fullnode.h | 140 +++++++++++++++++++++++-------------- 2 files changed, 92 insertions(+), 59 deletions(-) diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index c84cf96b021..ed151037ab9 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -146,11 +146,12 @@ struct NSPV_ntzsresp struct NSPV_inforesp { - struct NSPV_ntz notarization; - uint256 blockhash; - int32_t height,hdrheight; - struct NSPV_equihdr H; - uint32_t version; + struct NSPV_ntz notarization; // last notarisation + uint256 blockhash; // chain tip blockhash + int32_t height; // chain tip height + int32_t hdrheight; // requested block height (it will be the tip height if requested height is 0) + struct NSPV_equihdr H; // requested block header (it will be the tip if requested height is 0) + uint32_t version; // NSPV protocol version }; struct NSPV_txproof diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 78e3ed31881..4867b9d1bff 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -64,44 +64,66 @@ struct NSPV_ntzargs int32_t txidht,ntzheight; }; -int32_t NSPV_notarization_find(struct NSPV_ntzargs *args,int32_t height,int32_t dir) +// search for notary txid starting from 'height' in the backward or forward direction +int32_t NSPV_notarization_find(struct NSPV_ntzargs* args, int32_t height, int32_t dir) { - int32_t ntzheight = 0; uint256 hashBlock; CTransaction tx; Notarisation nota; char *symbol; std::vector opret; - symbol = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; - memset(args,0,sizeof(*args)); - if ( dir > 0 ) - height += 10; - if ( (args->txidht= ScanNotarisationsDB(height,symbol,1440,nota)) == 0 ) - return(-1); + int32_t ntzheight = 0; + uint256 hashBlock; + CTransaction tx; + Notarisation nota; + char* symbol; + std::vector opret; + + symbol = (ASSETCHAINS_SYMBOL[0] == 0) ? (char*)"KMD" : ASSETCHAINS_SYMBOL; + memset(args, 0, sizeof(*args)); + //if ( dir > 0 ) + // height += 10; + std::cerr << __func__ << " calling ScanNotarisationsDB for height=" << height << " dir=" << dir << std::endl; + if (dir < 0) { + if ((args->txidht = ScanNotarisationsDB(height, symbol, 1440, nota)) == 0) + return (-1); + } else { + if ((args->txidht = ScanNotarisationsDB2(height, symbol, 1440, nota)) == 0) + return (-1); + } + std::cerr << __func__ << " found nota height=" << nota.second.height << " MoMdepth=" << nota.second.MoMDepth << std::endl; args->txid = nota.first; - if ( !GetTransaction(args->txid,tx,hashBlock,false) || tx.vout.size() < 2 ) - return(-2); - GetOpReturnData(tx.vout[1].scriptPubKey,opret); - if ( opret.size() >= 32*2+4 ) - args->desttxid = NSPV_opretextract(&args->ntzheight,&args->blockhash,symbol,opret,args->txid); - return(args->ntzheight); + if (!GetTransaction(args->txid, tx, hashBlock, false) || tx.vout.size() < 2) + return (-2); + GetOpReturnData(tx.vout[1].scriptPubKey, opret); + if (opret.size() >= 32 * 2 + 4) + args->desttxid = NSPV_opretextract(&args->ntzheight, &args->blockhash, symbol, opret, args->txid); + return (args->ntzheight); } -int32_t NSPV_notarized_bracket(struct NSPV_ntzargs *prev,struct NSPV_ntzargs *next,int32_t height) +// finds notarisation bracket: +// prev notary txid with notarized height < height +// and next notary txid with notarised height >= height +// if not found (chain not notarised returns zeroed bracket) +int32_t NSPV_notarized_bracket(struct NSPV_ntzargs* prev, struct NSPV_ntzargs* next, int32_t height) { - uint256 bhash; int32_t txidht,ntzht,nextht,i=0; - memset(prev,0,sizeof(*prev)); - memset(next,0,sizeof(*next)); - if ( (ntzht= NSPV_notarization_find(prev,height,-1)) < 0 || ntzht > height || ntzht == 0 ) - return(-1); - txidht = height+1; - while ( (ntzht= NSPV_notarization_find(next,txidht,1)) < height ) - { - nextht = next->txidht + 10*i; -//fprintf(stderr,"found forward ntz, but ntzht.%d vs height.%d, txidht.%d -> nextht.%d\n",next->ntzheight,height,txidht,nextht); - memset(next,0,sizeof(*next)); - txidht = nextht; - if ( ntzht <= 0 ) - break; - if ( i++ > 10 ) + const int BACKWARD = -1, FORWARD = 1; + memset(prev, 0, sizeof(*prev)); + memset(next, 0, sizeof(*next)); + + // search back + int32_t ntzbackwardht = NSPV_notarization_find(prev, height, BACKWARD); + LogPrint("nspv-details", "%s search backward ntz result ntzht.%d vs height.%d, txidht.%d\n", __func__, prev->ntzheight, height, prev->txidht); + + int32_t forwardht = height; + if (ntzbackwardht > 0 && prev->txidht == height) + forwardht ++; // off 1 for not finding next the same as prev + while(true) { + int32_t ntzforwardht = NSPV_notarization_find(next, forwardht, FORWARD); + LogPrint("nspv-details", "%s search forward ntz result ntzht.%d height.%d (will be new prev if less), txidht.%d\n", __func__, next->ntzheight, height, next->txidht); + if (ntzforwardht > 0 && ntzforwardht < height) { + *prev = *next; // this is the new prev + forwardht = next->txidht+1; // search next next + } + else break; } - return(0); + return (0); } int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint256 desttxid,int32_t ntzheight) @@ -119,29 +141,23 @@ int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint return(0); } -int32_t NSPV_getntzsresp(struct NSPV_ntzsresp *ptr,int32_t origreqheight) +int32_t NSPV_getntzsresp(struct NSPV_ntzsresp* ptr, int32_t reqheight) { - struct NSPV_ntzargs prev,next; int32_t reqheight = origreqheight; - { - LOCK(cs_main); - if ( reqheight < chainActive.LastTip()->GetHeight() ) - reqheight++; - } - if ( NSPV_notarized_bracket(&prev,&next,reqheight) == 0 ) + struct NSPV_ntzargs prev, next; + + if (NSPV_notarized_bracket(&prev, &next, reqheight) == 0) // get notarization pair, before and after the requested height (zeroed if not found or the chain is not notarised) { - if ( prev.ntzheight != 0 ) - { - ptr->reqheight = origreqheight; - if ( NSPV_ntzextract(&ptr->prevntz,prev.txid,prev.txidht,prev.desttxid,prev.ntzheight) < 0 ) - return(-1); + if (prev.ntzheight != 0) { + if (NSPV_ntzextract(&ptr->prevntz, prev.txid, prev.txidht, prev.desttxid, prev.ntzheight) < 0) + return -1; } - if ( next.ntzheight != 0 ) - { - if ( NSPV_ntzextract(&ptr->nextntz,next.txid,next.txidht,next.desttxid,next.ntzheight) < 0 ) - return(-1); + if (next.ntzheight != 0) { + if (NSPV_ntzextract(&ptr->nextntz, next.txid, next.txidht, next.desttxid, next.ntzheight) < 0) + return -1; } + return sizeof(*ptr); } - return(sizeof(*ptr)); + return -1; } int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) @@ -177,9 +193,9 @@ int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) ptr->height = pindex->GetHeight(); ptr->blockhash = pindex->GetBlockHash(); memset(&pair, 0, sizeof(pair)); - if (NSPV_getntzsresp(&pair, ptr->height - 1) < 0) + if (NSPV_getntzsresp(&pair, ptr->height - 1) < 0) return (-1); - ptr->notarization = pair.prevntz; + ptr->notarization = pair.prevntz; // use prev notarization as latest notarization if ((pindex2 = komodo_chainactive(ptr->notarization.txidheight)) != 0) ptr->notarization.timestamp = pindex2->nTime; //fprintf(stderr, "timestamp.%i\n", ptr->notarization.timestamp ); @@ -516,6 +532,7 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is ptr->skipcount = skipcount; ptr->txids = nullptr; + //std::cerr << __func__ << " coinaddr=" << coinaddr << std::endl; if (txids.size() >= 0 && skipcount < txids.size()) { ptr->txids = (struct NSPV_txidresp*)calloc(txids.size() - skipcount, sizeof(ptr->txids[0])); for (std::vector>::const_iterator it = txids.begin() + skipcount; @@ -525,6 +542,21 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is ptr->txids[ind].satoshis = (int64_t)it->second; ptr->txids[ind].height = (int64_t)it->first.blockHeight; + /* + CTransaction tx; + uint256 hashBlock; + myGetTransaction(it->first.txhash, tx, hashBlock); + char a[64]; + Getscriptaddress(a, tx.vout[it->first.index].scriptPubKey); + + int32_t type = 0; + uint160 hashBytes; + CBitcoinAddress address(a); + if (address.GetIndexKey(hashBytes, type, isCC) == 0) + std::cerr << __func__ << " txhash=" << it->first.txhash.ToString() << " index=" << " cant find indexkey" << std::endl; + else + std::cerr << __func__ << " txhash=" << it->first.txhash.ToString() << " index=" << it->first.index << " address=" << a << " hashBytes=" << HexStr(hashBytes) << " amount=" << it->second << std::endl; + */ ind++; } } @@ -907,14 +939,14 @@ int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp* ptr, uint256 prevntztxi return (-7); } //fprintf(stderr, "%s -> prevht.%d, %s -> nexht.%d\n", ptr->prevtxid.GetHex().c_str(), ptr->common.prevht, ptr->nexttxid.GetHex().c_str(), ptr->common.nextht); - ptr->common.numhdrs = (ptr->common.nextht - ptr->common.prevht + 1); + ptr->common.numhdrs = (ptr->common.nextht - ptr->common.prevht); ptr->common.hdrs = (struct NSPV_equihdr*)calloc(ptr->common.numhdrs, sizeof(*ptr->common.hdrs)); //fprintf(stderr, "prev.%d next.%d allocate numhdrs.%d\n", ptr->common.prevht, ptr->common.nextht, ptr->common.numhdrs); for (i = 0; i < ptr->common.numhdrs; i++) { //hashBlock = NSPV_hdrhash(&ptr->common.hdrs[i]); //fprintf(stderr,"hdr[%d] %s\n",prevht+i,hashBlock.GetHex().c_str()); - if (NSPV_setequihdr(&ptr->common.hdrs[i], ptr->common.prevht + i) < 0) { - LogPrintf("%s error setting hdr.%d\n", __func__, ptr->common.prevht + i); + if (NSPV_setequihdr(&ptr->common.hdrs[i], ptr->common.prevht + i + 1) < 0) { + LogPrintf("%s error setting hdr for ht.%d\n", __func__, ptr->common.prevht + i + 1); free(ptr->common.hdrs); ptr->common.hdrs = 0; return (-1); From e1c0c4f4c6faa85dda9c73c97dbeda9bd54ee116 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 19 Nov 2021 13:01:28 +0500 Subject: [PATCH 184/348] NSPV v006: fixed finding notarisation tx embracing the requested height, prev ntz tx is not returned and mom depth is added instead, fixed komodo lite client for NSPV v006 --- src/consensus/upgrades.cpp | 10 +- src/komodo_defs.h | 4 + src/komodo_nSPV.h | 258 +++++++++++++-------------- src/komodo_nSPV_defs.h | 72 ++++++-- src/komodo_nSPV_fullnode.h | 339 ++++++++++++++++++++---------------- src/komodo_nSPV_superlite.h | 53 +++--- src/komodo_nSPV_wallet.h | 86 +++++---- src/komodo_utils.h | 2 +- src/script/sign.cpp | 8 +- src/wallet/rpcdump.cpp | 32 +--- 10 files changed, 464 insertions(+), 400 deletions(-) diff --git a/src/consensus/upgrades.cpp b/src/consensus/upgrades.cpp index b75e0c002c1..3a0deff5bf4 100644 --- a/src/consensus/upgrades.cpp +++ b/src/consensus/upgrades.cpp @@ -18,17 +18,11 @@ ******************************************************************************/ #include "consensus/upgrades.h" +#include "komodo_nSPV_defs.h" + extern int32_t KOMODO_NSPV; #define NSPV_BRANCHID 0x76b809bb -#ifndef KOMODO_NSPV_FULLNODE -#define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) -#endif // !KOMODO_NSPV_FULLNODE - -#ifndef KOMODO_NSPV_SUPERLITE -#define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) -#endif // !KOMODO_NSPV_SUPERLITE - /** * General information about each network upgrade. * Ordered by Consensus::UpgradeIndex. diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 60ce6c291c0..621e6179692 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -24,6 +24,7 @@ #include "primitives/transaction.h" #include "threadsafety.h" +#include "komodo_structs.h" #include "komodo_nk.h" #define KOMODO_EARLYTXID_HEIGHT 100 @@ -666,6 +667,9 @@ extern uint16_t KMD_PORT, BITCOIND_RPCPORT, DEST_PORT; extern char KMDUSERPASS[], BTCUSERPASS[]; extern uint32_t KOMODO_STOPAT; extern int32_t ASSETCHAINS_CBMATURITY; +extern struct komodo_state KOMODO_STATES[]; +extern int32_t KOMODO_EXTRASATOSHI; + #ifndef KOMODO_NSPV_FULLNODE #define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index dbd18d40462..5c19ce89cbc 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -98,48 +98,45 @@ int32_t iguana_rwvarint(int32_t rwflag, uint8_t* serialized, uint64_t* varint64p } } -int32_t NSPV_rwequihdr(int32_t rwflag, uint8_t *serialized, struct NSPV_equihdr *ptr) +int32_t NSPV_rwequihdr(int32_t rwflag, uint8_t* serialized, struct NSPV_equihdr* ptr) { int32_t len = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nVersion),&ptr->nVersion); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashPrevBlock),(uint8_t *)&ptr->hashPrevBlock); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashMerkleRoot),(uint8_t *)&ptr->hashMerkleRoot); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashFinalSaplingRoot),(uint8_t *)&ptr->hashFinalSaplingRoot); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nTime),&ptr->nTime); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nBits),&ptr->nBits); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->nNonce),(uint8_t *)&ptr->nNonce); - uint64_t nSolutionSize = sizeof(ptr->nSolution); - len += iguana_rwvarint(rwflag, &serialized[len], &nSolutionSize); - len += iguana_rwbuf(rwflag, &serialized[len], nSolutionSize, ptr->nSolution); - return(len); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->nVersion), &ptr->nVersion); + len += iguana_rwbignum(rwflag, &serialized[len], sizeof(ptr->hashPrevBlock), (uint8_t*)&ptr->hashPrevBlock); + len += iguana_rwbignum(rwflag, &serialized[len], sizeof(ptr->hashMerkleRoot), (uint8_t*)&ptr->hashMerkleRoot); + len += iguana_rwbignum(rwflag, &serialized[len], sizeof(ptr->hashFinalSaplingRoot), (uint8_t*)&ptr->hashFinalSaplingRoot); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->nTime), &ptr->nTime); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->nBits), &ptr->nBits); + len += iguana_rwbignum(rwflag, &serialized[len], sizeof(ptr->nNonce), (uint8_t*)&ptr->nNonce); + len += iguana_rwvarint(rwflag, &serialized[len], &ptr->nSolutionLen); + len += iguana_rwbuf(rwflag, &serialized[len], ptr->nSolutionLen, ptr->nSolution); + return (len); } -int32_t iguana_rwequihdrvec(int32_t rwflag,uint8_t *serialized,uint16_t *vecsizep,struct NSPV_equihdr **ptrp) +int32_t iguana_rwequihdrvec(int32_t rwflag, uint8_t* serialized, uint16_t* vecsizep, struct NSPV_equihdr** hdrspp) { - int32_t i,vsize,len = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(*vecsizep),vecsizep); - if ( (vsize= *vecsizep) != 0 ) - { - //fprintf(stderr,"vsize.%d ptrp.%p alloc %ld\n",vsize,*ptrp,sizeof(struct NSPV_equihdr)*vsize); - if ( *ptrp == 0 ) - *ptrp = (struct NSPV_equihdr *)calloc(sizeof(struct NSPV_equihdr),vsize); // relies on uint16_t being "small" to prevent mem exhaustion - for (i=0; i 0 && vsize < MAX_TX_SIZE_AFTER_SAPLING ) - { - if ( *ptrp == 0 ) - *ptrp = (uint8_t *)calloc(1,vsize); - len += iguana_rwbuf(rwflag,&serialized[len],vsize,*ptrp); + int32_t vsize, len = 0; + len += iguana_rwnum(rwflag, &serialized[len], sizeof(*biglenp), biglenp); + if ((vsize = *biglenp) > 0 && vsize < MAX_TX_SIZE_AFTER_SAPLING) { + if (*ptrp == nullptr) + *ptrp = (uint8_t*)calloc(1, vsize); + len += iguana_rwbuf(rwflag, &serialized[len], vsize, *ptrp); } - return(len); + return (len); } int32_t NSPV_rwutxoresp(int32_t rwflag, uint8_t* serialized, struct NSPV_utxoresp* ptr) @@ -157,12 +154,12 @@ int32_t NSPV_rwutxoresp(int32_t rwflag, uint8_t* serialized, struct NSPV_utxores int32_t NSPV_rwutxosresp(int32_t rwflag, uint8_t* serialized, struct NSPV_utxosresp* ptr) // check mempool { - int32_t i, len = 0; + int32_t len = 0; len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->numutxos), &ptr->numutxos); if (ptr->numutxos != 0) { - if (ptr->utxos == 0) + if (ptr->utxos == nullptr) ptr->utxos = (struct NSPV_utxoresp*)calloc(sizeof(*ptr->utxos), ptr->numutxos); // relies on uint16_t being "small" to prevent mem exhaustion - for (i = 0; i < ptr->numutxos; i++) + for (int32_t i = 0; i < ptr->numutxos; i++) len += NSPV_rwutxoresp(rwflag, &serialized[len], &ptr->utxos[i]); } len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->total), &ptr->total); @@ -183,10 +180,10 @@ int32_t NSPV_rwutxosresp(int32_t rwflag, uint8_t* serialized, struct NSPV_utxosr void NSPV_utxosresp_purge(struct NSPV_utxosresp *ptr) { - if (ptr != 0) { - if (ptr->utxos != NULL) { + if (ptr != nullptr) { + if (ptr->utxos != nullptr) { for(size_t i = 0; i < ptr->numutxos; i ++) - if (ptr->utxos[i].script) + if (ptr->utxos[i].script != nullptr) free(ptr->utxos[i].script); free(ptr->utxos); } @@ -228,7 +225,7 @@ int32_t NSPV_rwtxidsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidsres len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->numtxids),&ptr->numtxids); if ( ptr->numtxids != 0 ) { - if ( ptr->txids == 0 ) + if ( ptr->txids == nullptr ) ptr->txids = (struct NSPV_txidresp *)calloc(sizeof(*ptr->txids),ptr->numtxids); for (i=0; inumtxids; i++) len += NSPV_rwtxidresp(rwflag,&serialized[len],&ptr->txids[i]); @@ -253,8 +250,8 @@ int32_t NSPV_rwtxidsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidsres void NSPV_txidsresp_purge(struct NSPV_txidsresp *ptr) { - if (ptr != 0) { - if (ptr->txids != NULL) { + if (ptr != nullptr) { + if (ptr->txids != nullptr) { free(ptr->txids); } memset(ptr, 0, sizeof(*ptr)); @@ -276,7 +273,7 @@ int32_t NSPV_rwmempoolresp(int32_t rwflag,uint8_t *serialized,struct NSPV_mempoo len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->numtxids),&ptr->numtxids); if ( ptr->numtxids != 0 ) { - if ( ptr->txids == 0 ) + if ( ptr->txids == nullptr ) ptr->txids = (uint256 *)calloc(sizeof(*ptr->txids),ptr->numtxids); for (i=0; inumtxids; i++) len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txids[i]),(uint8_t *)&ptr->txids[i]); @@ -303,9 +300,9 @@ int32_t NSPV_rwmempoolresp(int32_t rwflag,uint8_t *serialized,struct NSPV_mempoo void NSPV_mempoolresp_purge(struct NSPV_mempoolresp *ptr) { - if ( ptr != 0 ) + if ( ptr != nullptr ) { - if ( ptr->txids != 0 ) + if ( ptr->txids != nullptr ) free(ptr->txids); memset(ptr,0,sizeof(*ptr)); } @@ -314,30 +311,30 @@ void NSPV_mempoolresp_purge(struct NSPV_mempoolresp *ptr) void NSPV_mempoolresp_copy(struct NSPV_mempoolresp *dest,struct NSPV_mempoolresp *ptr) { *dest = *ptr; - if ( ptr->txids != 0 ) + if (ptr->txids != nullptr) { dest->txids = (uint256 *)malloc(ptr->numtxids * sizeof(*ptr->txids)); memcpy(dest->txids,ptr->txids,ptr->numtxids * sizeof(*ptr->txids)); } } -int32_t NSPV_rwntz(int32_t rwflag,uint8_t *serialized,struct NSPV_ntz *ptr) +int32_t NSPV_rwntz(int32_t rwflag, uint8_t* serialized, struct NSPV_ntz* ptr) { int32_t len = 0; - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->blockhash),(uint8_t *)&ptr->blockhash); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->othertxid),(uint8_t *)&ptr->othertxid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->txidheight),&ptr->txidheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->timestamp),&ptr->timestamp); - return(len); + len += iguana_rwbignum(rwflag, &serialized[len], sizeof(ptr->ntzblockhash), (uint8_t*)&ptr->ntzblockhash); + len += iguana_rwbignum(rwflag, &serialized[len], sizeof(ptr->txid), (uint8_t*)&ptr->txid); + len += iguana_rwbignum(rwflag, &serialized[len], sizeof(ptr->desttxid), (uint8_t*)&ptr->desttxid); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->ntzheight), &ptr->ntzheight); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->txidheight), &ptr->txidheight); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->timestamp), &ptr->timestamp); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->depth), &ptr->depth); + return (len); } int32_t NSPV_rwntzsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_ntzsresp *ptr) { int32_t len = 0; - len += NSPV_rwntz(rwflag,&serialized[len],&ptr->prevntz); - len += NSPV_rwntz(rwflag,&serialized[len],&ptr->nextntz); + len += NSPV_rwntz(rwflag,&serialized[len],&ptr->ntz); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->reqheight),&ptr->reqheight); return(len); } @@ -349,27 +346,27 @@ void NSPV_ntzsresp_copy(struct NSPV_ntzsresp *dest,struct NSPV_ntzsresp *ptr) void NSPV_ntzsresp_purge(struct NSPV_ntzsresp *ptr) { - if ( ptr != 0 ) + if (ptr != nullptr) memset(ptr,0,sizeof(*ptr)); } -int32_t NSPV_rwinforesp(int32_t rwflag,uint8_t *serialized,struct NSPV_inforesp *ptr) +int32_t NSPV_rwinforesp(int32_t rwflag, uint8_t* serialized, struct NSPV_inforesp* ptr) { int32_t len = 0; - len += NSPV_rwntz(rwflag,&serialized[len],&ptr->notarization); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->blockhash),(uint8_t *)&ptr->blockhash); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->hdrheight),&ptr->hdrheight); - len += NSPV_rwequihdr(rwflag,&serialized[len],&ptr->H); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->version),&ptr->version); -//fprintf(stderr,"getinfo rwlen.%d\n",len); - return(len); + len += NSPV_rwntz(rwflag, &serialized[len], &ptr->ntz); + len += iguana_rwbignum(rwflag, &serialized[len], sizeof(ptr->blockhash), (uint8_t*)&ptr->blockhash); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->height), &ptr->height); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->hdrheight), &ptr->hdrheight); + len += NSPV_rwequihdr(rwflag, &serialized[len], &ptr->H); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->version), &ptr->version); + //fprintf(stderr,"getinfo rwlen.%d\n",len); + return (len); } -void NSPV_inforesp_purge(struct NSPV_inforesp *ptr) +void NSPV_inforesp_purge(struct NSPV_inforesp* ptr) { - if ( ptr != 0 ) - memset(ptr,0,sizeof(*ptr)); + if (ptr != nullptr) + memset(ptr, 0, sizeof(*ptr)); } int32_t NSPV_rwtxproof(int32_t rwflag,uint8_t *serialized,struct NSPV_txproof *ptr) @@ -402,73 +399,58 @@ void NSPV_txproof_copy(struct NSPV_txproof *dest,struct NSPV_txproof *ptr) void NSPV_txproof_purge(struct NSPV_txproof *ptr) { - if ( ptr != 0 ) - { - if ( ptr->tx != 0 ) + if (ptr != nullptr) { + if (ptr->tx != nullptr) free(ptr->tx); - if ( ptr->txproof != 0 ) + if (ptr->txproof != nullptr) free(ptr->txproof); - memset(ptr,0,sizeof(*ptr)); + memset(ptr, 0, sizeof(*ptr)); } } -int32_t NSPV_rwntzproofshared(int32_t rwflag,uint8_t *serialized,struct NSPV_ntzproofshared *ptr) +int32_t NSPV_rwntzproofshared(int32_t rwflag, uint8_t* serialized, struct NSPV_ntzproofshared* ptr) { int32_t len = 0; - len += iguana_rwequihdrvec(rwflag,&serialized[len],&ptr->numhdrs,&ptr->hdrs); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->prevht),&ptr->prevht); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nextht),&ptr->nextht); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad32),&ptr->pad32); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad16),&ptr->pad16); + len += iguana_rwequihdrvec(rwflag, &serialized[len], &ptr->numhdrs, &ptr->hdrs); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->nextht), &ptr->nextht); + //len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad32),&ptr->pad32); + //len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad16),&ptr->pad16); //fprintf(stderr,"rwcommon prev.%d next.%d\n",ptr->prevht,ptr->nextht); - return(len); + return (len); } -int32_t NSPV_rwntzsproofresp(int32_t rwflag,uint8_t *serialized,struct NSPV_ntzsproofresp *ptr) +int32_t NSPV_rwntzsproofresp(int32_t rwflag, uint8_t* serialized, struct NSPV_ntzsproofresp* ptr) { int32_t len = 0; - len += NSPV_rwntzproofshared(rwflag,&serialized[len],&ptr->common); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->prevtxid),(uint8_t *)&ptr->prevtxid); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->nexttxid),(uint8_t *)&ptr->nexttxid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->prevtxidht),&ptr->prevtxidht); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nexttxidht),&ptr->nexttxidht); - len += iguana_rwuint8vec(rwflag,&serialized[len],&ptr->prevtxlen,&ptr->prevntz); - len += iguana_rwuint8vec(rwflag,&serialized[len],&ptr->nexttxlen,&ptr->nextntz); + len += NSPV_rwntzproofshared(rwflag, &serialized[len], &ptr->common); + len += iguana_rwbignum(rwflag, &serialized[len], sizeof(ptr->nexttxid), (uint8_t*)&ptr->nexttxid); + len += iguana_rwnum(rwflag, &serialized[len], sizeof(ptr->nexttxidht), &ptr->nexttxidht); + len += iguana_rwuint8vec(rwflag, &serialized[len], &ptr->nexttxlen, &ptr->nextntz); //fprintf(stderr,"retlen.%d\n",len); - return(len); + return (len); } -void NSPV_ntzsproofresp_copy(struct NSPV_ntzsproofresp *dest,struct NSPV_ntzsproofresp *ptr) +void NSPV_ntzsproofresp_copy(struct NSPV_ntzsproofresp* dest, struct NSPV_ntzsproofresp* ptr) { *dest = *ptr; - if ( ptr->common.hdrs != 0 ) - { - dest->common.hdrs = (struct NSPV_equihdr *)malloc(ptr->common.numhdrs * sizeof(*ptr->common.hdrs)); - memcpy(dest->common.hdrs,ptr->common.hdrs,ptr->common.numhdrs * sizeof(*ptr->common.hdrs)); - } - if ( ptr->prevntz != 0 ) - { - dest->prevntz = (uint8_t *)malloc(ptr->prevtxlen); - memcpy(dest->prevntz,ptr->prevntz,ptr->prevtxlen); + if (ptr->common.hdrs != 0) { + dest->common.hdrs = (struct NSPV_equihdr*)malloc(ptr->common.numhdrs * sizeof(*ptr->common.hdrs)); + memcpy(dest->common.hdrs, ptr->common.hdrs, ptr->common.numhdrs * sizeof(*ptr->common.hdrs)); } - if ( ptr->nextntz != 0 ) - { - dest->nextntz = (uint8_t *)malloc(ptr->nexttxlen); - memcpy(dest->nextntz,ptr->nextntz,ptr->nexttxlen); + if (ptr->nextntz != 0) { + dest->nextntz = (uint8_t*)malloc(ptr->nexttxlen); + memcpy(dest->nextntz, ptr->nextntz, ptr->nexttxlen); } } -void NSPV_ntzsproofresp_purge(struct NSPV_ntzsproofresp *ptr) +void NSPV_ntzsproofresp_purge(struct NSPV_ntzsproofresp* ptr) { - if ( ptr != 0 ) - { - if ( ptr->common.hdrs != 0 ) + if (ptr != nullptr) { + if (ptr->common.hdrs != nullptr) free(ptr->common.hdrs); - if ( ptr->prevntz != 0 ) - free(ptr->prevntz); - if ( ptr->nextntz != 0 ) + if (ptr->nextntz != nullptr) free(ptr->nextntz); - memset(ptr,0,sizeof(*ptr)); + memset(ptr, 0, sizeof(*ptr)); } } @@ -561,7 +543,6 @@ int32_t NSPV_txextract(CTransaction &tx,uint8_t *data,int32_t datalen) return(-1); } -bool NSPV_SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey,uint32_t nTime); int32_t NSPV_fastnotariescount(CTransaction tx,uint8_t elected[64][33],uint32_t nTime) { @@ -636,32 +617,53 @@ int32_t NSPV_notariescount(CTransaction tx,uint8_t elected[64][33]) return(numsigs); } -uint256 NSPV_opretextract(int32_t *heightp,uint256 *blockhashp,char *symbol,std::vector opret,uint256 txid) +/*int32_t NSPV_opretextract(int32_t* heightp, uint256* blockhashp, uint256 *desttxidp, const char* symbol, vuint8_t vopret) { - uint256 desttxid; int32_t i; - iguana_rwnum(0,&opret[32],sizeof(*heightp),heightp); - for (i=0; i<32; i++) - ((uint8_t *)blockhashp)[i] = opret[i]; + //uint256 desttxid; int32_t i; + int32_t read = iguana_rwnum(0, &vopret[0], sizeof(*blockhashp), blockhashp); + read += iguana_rwnum(0, &vopret[32], sizeof(*heightp), heightp); + // detect is back + bool isBack = (ASSETCHAINS_SYMBOL[0] != 0); + if (!isBack) { + // check sybol is KMD? + vopret.size() > read + 32) + } + + + iguana_rwnum(0, &vopret[32], sizeof(*heightp), heightp); + + for (i = 0; i < 32; i++) + ((uint8_t *)blockhashp)[i] = vopret[i]; for (i=0; i<32; i++) - ((uint8_t *)&desttxid)[i] = opret[4 + 32 + i]; - if ( 0 && *heightp != 2690 ) - fprintf(stderr," ntzht.%d %s <- txid.%s size.%d\n",*heightp,(*blockhashp).GetHex().c_str(),(txid).GetHex().c_str(),(int32_t)opret.size()); + ((uint8_t *)&desttxid)[i] = vopret[4 + 32 + i]; + //if ( 0 && *heightp != 2690 ) + // fprintf(stderr," ntzht.%d %s <- txid.%s size.%d\n",*heightp,(*blockhashp).GetHex().c_str(),(txid).GetHex().c_str(),(int32_t)opret.size()); return(desttxid); -} + Notarisation nota; + if (E_UNMARSHAL(vopret, ss >> nota)) + return 0; + return -1; +}*/ -int32_t NSPV_notarizationextract(int32_t verifyntz,int32_t *ntzheightp,uint256 *blockhashp,uint256 *desttxidp,CTransaction tx) +int32_t NSPV_notarizationextract(int32_t verifyntz, int32_t* ntzheightp, uint256* blockhashp, uint256* desttxidp, int16_t *momdepthp, CTransaction tx) { - char *symbol; std::vector opret; + vuint8_t vopret; AssertLockHeld(cs_main); if ( tx.vout.size() >= 2 ) { - symbol = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; - GetOpReturnData(tx.vout[1].scriptPubKey,opret); - if ( opret.size() >= 32*2+4 ) + //const char *symbol = (ASSETCHAINS_SYMBOL[0] == 0) ? "KMD" : ASSETCHAINS_SYMBOL; + NotarisationData nota; + GetOpReturnData(tx.vout[1].scriptPubKey, vopret); + //if ( vopret.size() >= 32*2+4 ) + if (!vopret.empty() && E_UNMARSHAL(vopret, ss >> nota)) { //sleep(1); // needed to avoid no pnodes error - *desttxidp = NSPV_opretextract(ntzheightp,blockhashp,symbol,opret,tx.GetHash()); + //*desttxidp = NSPV_opretextract(ntzheightp, blockhashp, symbol, vopret); + *ntzheightp = nota.height; + *blockhashp = nota.blockHash; + *desttxidp = nota.txHash; + *momdepthp = nota.MoMDepth; if (verifyntz != 0) { uint32_t nTime = NSPV_blocktime(*ntzheightp); @@ -679,7 +681,7 @@ int32_t NSPV_notarizationextract(int32_t verifyntz,int32_t *ntzheightp,uint256 * } else { - LogPrintf("%s opretsize.%d error\n", __func__, (int32_t)opret.size()); + LogPrintf("%s opretsize.%d error\n", __func__, (int32_t)vopret.size()); return(-2); } } else { diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index ed151037ab9..241cb8570c2 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -18,8 +18,14 @@ #define KOMODO_NSPV_DEFSH #include +#include "uint256.h" +#include "univalue.h" +#include "script/script.h" +#include "primitives/transaction.h" +#include "amount.h" +#include "main.h" -#define NSPV_PROTOCOL_VERSION 0x00000005 +#define NSPV_PROTOCOL_VERSION 0x00000006 #define NSPV_POLLITERS 200 #define NSPV_POLLMICROS 50000 #define NSPV_MAXVINS 64 @@ -71,7 +77,12 @@ #define NSPV_MAXREQSPERSEC 15 -#define NSPV_MAX_VARINT_SIZE 9 +#ifndef KOMODO_NSPV_FULLNODE +#define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) +#endif // !KOMODO_NSPV_FULLNODE +#ifndef KOMODO_NSPV_SUPERLITE +#define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) +#endif // !KOMODO_NSPV_SUPERLITE int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int32_t height,CTransaction &tx,uint256 &hashblock,int32_t &txheight,int32_t ¤theight,int64_t extradata,uint32_t tiptime,int64_t &rewardsum); UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); @@ -87,6 +98,7 @@ struct NSPV_equihdr uint32_t nTime; uint32_t nBits; uint256 nNonce; + uint64_t nSolutionLen; uint8_t nSolution[1344]; }; @@ -133,20 +145,26 @@ struct NSPV_mempoolresp struct NSPV_ntz { - uint256 blockhash,txid,othertxid; - int32_t height,txidheight; - uint32_t timestamp; + uint256 txid; // notarization txid + uint256 desttxid; // for back notarizations this is notarization txid from KMD/BTC chain + uint256 ntzblockhash; // notarization tx blockhash + int32_t txidheight; // notarization tx height + int32_t ntzheight; // notarized height by this notarization tx + int16_t depth; + //uint256 blockhash, txid, othertxid; + //int32_t height, txidheight; + uint32_t timestamp; // timestamp of the notarization tx block }; struct NSPV_ntzsresp { - struct NSPV_ntz prevntz,nextntz; + struct NSPV_ntz ntz; int32_t reqheight; }; struct NSPV_inforesp { - struct NSPV_ntz notarization; // last notarisation + struct NSPV_ntz ntz; // last notarisation uint256 blockhash; // chain tip blockhash int32_t height; // chain tip height int32_t hdrheight; // requested block height (it will be the tip height if requested height is 0) @@ -158,24 +176,24 @@ struct NSPV_txproof { uint256 txid; int64_t unspentvalue; - int32_t height,vout,txlen,txprooflen; - uint8_t *tx,*txproof; + int32_t height, vout, txlen, txprooflen; + uint8_t *tx, *txproof; uint256 hashblock; }; struct NSPV_ntzproofshared { struct NSPV_equihdr *hdrs; - int32_t prevht,nextht,pad32; - uint16_t numhdrs,pad16; + int32_t nextht /*, pad32*/; + uint16_t numhdrs /*, pad16*/; }; struct NSPV_ntzsproofresp { struct NSPV_ntzproofshared common; - uint256 prevtxid,nexttxid; - int32_t prevtxidht,nexttxidht,prevtxlen,nexttxlen; - uint8_t *prevntz,*nextntz; + uint256 nexttxid; + int32_t nexttxidht, nexttxlen; + uint8_t *nextntz; }; struct NSPV_MMRproof @@ -209,11 +227,37 @@ struct NSPV_remoterpcresp char *json; }; +/*struct NSPV_ntzargs +{ + uint256 txid; // notarization txid + uint256 desttxid; // for back notarizations this is notarization txid from KMD/BTC chain + uint256 blockhash; // notarization tx blockhash + int32_t txidht; // notarization tx height + int32_t ntzheight; // notarized height by this notarization tx +};*/ + extern struct NSPV_inforesp NSPV_inforesult; void NSPV_CCunspents(std::vector>& unspentOutputs, char* coinaddr, bool ccflag); void NSPV_CCindexOutputs(std::vector>& indexOutputs, char* coinaddr, bool ccflag); void NSPV_CCtxids(std::vector& txids, char* coinaddr, bool ccflag, uint8_t evalcode, uint256 filtertxid, uint8_t func); +bool NSPV_SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey,uint32_t nTime); + +UniValue NSPV_getinfo_req(int32_t reqht); +UniValue NSPV_login(char *wifstr); +UniValue NSPV_logout(); +UniValue NSPV_addresstxids(char *coinaddr,int32_t CCflag,int32_t skipcount,int32_t filter); +UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag,int32_t skipcount,int32_t filter); +UniValue NSPV_mempooltxids(char *coinaddr,int32_t CCflag,uint8_t funcid,uint256 txid,int32_t vout); +UniValue NSPV_broadcast(char *hex); +UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); +UniValue NSPV_spentinfo(uint256 txid,int32_t vout); +UniValue NSPV_notarizations(int32_t height); +UniValue NSPV_hdrsproof(int32_t nextheight); +UniValue NSPV_txproof(int32_t vout,uint256 txid,int32_t height); +UniValue NSPV_ccmoduleutxos(char *coinaddr, int64_t amount, uint8_t evalcode, std::string funcids, uint256 filtertxid); + +int32_t bitweight(uint64_t x); extern std::map nspvErrors; diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 4867b9d1bff..51c829095fa 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -58,74 +58,82 @@ static std::map nspv_remote_commands = { { "createtxwithnormalinputs", true }, { "tokenv2addccinputs", true }, { "tokenv2infotokel", true }, { "gettransactionsmany", true }, }; -struct NSPV_ntzargs -{ - uint256 txid,desttxid,blockhash; - int32_t txidht,ntzheight; -}; // search for notary txid starting from 'height' in the backward or forward direction -int32_t NSPV_notarization_find(struct NSPV_ntzargs* args, int32_t height, int32_t dir) +int32_t NSPV_notarization_find(struct NSPV_ntz* ntz, int32_t height, int32_t dir) { int32_t ntzheight = 0; uint256 hashBlock; CTransaction tx; Notarisation nota; char* symbol; - std::vector opret; + std::vector vopret; symbol = (ASSETCHAINS_SYMBOL[0] == 0) ? (char*)"KMD" : ASSETCHAINS_SYMBOL; - memset(args, 0, sizeof(*args)); - //if ( dir > 0 ) - // height += 10; - std::cerr << __func__ << " calling ScanNotarisationsDB for height=" << height << " dir=" << dir << std::endl; + memset(ntz, 0, sizeof(*ntz)); + + // std::cerr << __func__ << " calling ScanNotarisationsDB for height=" << height << " dir=" << dir << std::endl; if (dir < 0) { - if ((args->txidht = ScanNotarisationsDB(height, symbol, 1440, nota)) == 0) + if ((ntz->txidheight = ScanNotarisationsDB(height, symbol, 1440, nota)) == 0) return (-1); } else { - if ((args->txidht = ScanNotarisationsDB2(height, symbol, 1440, nota)) == 0) + if ((ntz->txidheight = ScanNotarisationsDB2(height, symbol, 1440, nota)) == 0) return (-1); } - std::cerr << __func__ << " found nota height=" << nota.second.height << " MoMdepth=" << nota.second.MoMDepth << std::endl; - args->txid = nota.first; + // std::cerr << __func__ << " found nota height=" << nota.second.height << " MoMdepth=" << nota.second.MoMDepth << std::endl; + ntz->txid = nota.first; + ntz->ntzheight = nota.second.height; + ntz->ntzblockhash = nota.second.blockHash; + ntz->desttxid = nota.second.txHash; + ntz->depth = nota.second.MoMDepth; + /* if (!GetTransaction(args->txid, tx, hashBlock, false) || tx.vout.size() < 2) return (-2); - GetOpReturnData(tx.vout[1].scriptPubKey, opret); - if (opret.size() >= 32 * 2 + 4) - args->desttxid = NSPV_opretextract(&args->ntzheight, &args->blockhash, symbol, opret, args->txid); - return (args->ntzheight); + GetOpReturnData(tx.vout[1].scriptPubKey, vopret); + if (vopret.size() >= 32 * 2 + 4) + args->desttxid = NSPV_opretextract(&args->ntzheight, &args->blockhash, symbol, vopret, args->txid); + */ + return ntz->ntzheight; } -// finds notarisation bracket: + +// finds prev notarisation // prev notary txid with notarized height < height // and next notary txid with notarised height >= height -// if not found (chain not notarised returns zeroed bracket) -int32_t NSPV_notarized_bracket(struct NSPV_ntzargs* prev, struct NSPV_ntzargs* next, int32_t height) +// if not found or chain not notarised returns zeroed 'prev' +int32_t NSPV_notarized_prev(struct NSPV_ntz* prev, int32_t height) { - const int BACKWARD = -1, FORWARD = 1; + const int BACKWARD = -1; memset(prev, 0, sizeof(*prev)); - memset(next, 0, sizeof(*next)); // search back int32_t ntzbackwardht = NSPV_notarization_find(prev, height, BACKWARD); - LogPrint("nspv-details", "%s search backward ntz result ntzht.%d vs height.%d, txidht.%d\n", __func__, prev->ntzheight, height, prev->txidht); + LogPrint("nspv-details", "%s search backward ntz result ntzht.%d vs height.%d, txidht.%d\n", __func__, prev->ntzheight, height, prev->txidheight); + return 0; // always okay even if chain non-notarised +} + +// finds next notarisation +// next notary txid with notarised height >= height +// if not found or chain not notarised returns zeroed 'next' +int32_t NSPV_notarized_next(struct NSPV_ntz* next, int32_t height) +{ + const int FORWARD = 1; + memset(next, 0, sizeof(*next)); int32_t forwardht = height; - if (ntzbackwardht > 0 && prev->txidht == height) - forwardht ++; // off 1 for not finding next the same as prev - while(true) { + while(true) { // search until notarized height >= height int32_t ntzforwardht = NSPV_notarization_find(next, forwardht, FORWARD); - LogPrint("nspv-details", "%s search forward ntz result ntzht.%d height.%d (will be new prev if less), txidht.%d\n", __func__, next->ntzheight, height, next->txidht); + LogPrint("nspv-details", "%s search forward ntz result ntzht.%d height.%d, txidht.%d\n", __func__, next->ntzheight, height, next->txidheight); if (ntzforwardht > 0 && ntzforwardht < height) { - *prev = *next; // this is the new prev - forwardht = next->txidht+1; // search next next + forwardht = next->txidheight+1; // search next next } else break; } - return (0); + return 0; // always okay even if chain non-notarised } +/* int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint256 desttxid,int32_t ntzheight) { CBlockIndex *pindex; @@ -140,32 +148,29 @@ int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint ptr->timestamp = pindex->nTime; return(0); } +*/ -int32_t NSPV_getntzsresp(struct NSPV_ntzsresp* ptr, int32_t reqheight) +int32_t NSPV_getntzsresp(struct NSPV_ntzsresp* ntzp, int32_t reqheight) { - struct NSPV_ntzargs prev, next; - - if (NSPV_notarized_bracket(&prev, &next, reqheight) == 0) // get notarization pair, before and after the requested height (zeroed if not found or the chain is not notarised) - { - if (prev.ntzheight != 0) { - if (NSPV_ntzextract(&ptr->prevntz, prev.txid, prev.txidht, prev.desttxid, prev.ntzheight) < 0) - return -1; - } - if (next.ntzheight != 0) { - if (NSPV_ntzextract(&ptr->nextntz, next.txid, next.txidht, next.desttxid, next.ntzheight) < 0) - return -1; - } - return sizeof(*ptr); + if (NSPV_notarized_next(&ntzp->ntz, reqheight) >= 0) { // find notarization txid for which reqheight is in its scope (or it is zeroed if not found or the chain is not notarised) + LOCK(cs_main); + CBlockIndex *pindexNtz = komodo_chainactive(ntzp->ntz.txidheight); + if (pindexNtz != nullptr) + ntzp->ntz.timestamp = pindexNtz->nTime; // return notarization tx block timestamp for season + ntzp->reqheight = reqheight; + return sizeof(*ntzp); } - return -1; + else + return -1; } + int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) { CBlockIndex *pindex; LOCK(cs_main); - if ( (pindex= komodo_chainactive(height)) != 0 ) + if ((pindex = komodo_chainactive(height)) != nullptr) { hdr->nVersion = pindex->nVersion; if ( pindex->pprev == 0 ) @@ -176,8 +181,9 @@ int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) hdr->nTime = pindex->nTime; hdr->nBits = pindex->nBits; hdr->nNonce = pindex->nNonce; - memcpy(hdr->nSolution,&pindex->nSolution[0],sizeof(hdr->nSolution)); - return(sizeof(*hdr) + NSPV_MAX_VARINT_SIZE); + memcpy(hdr->nSolution, pindex->nSolution.data(), sizeof(hdr->nSolution)); + hdr->nSolutionLen = sizeof(hdr->nSolution); + return sizeof(*hdr); } return(-1); } @@ -185,19 +191,17 @@ int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) { int32_t prevMoMheight, len = 0; - CBlockIndex *pindex, *pindex2; - struct NSPV_ntzsresp pair; + CBlockIndex *pindexTip, *pindexNtz; LOCK(cs_main); - if ((pindex = chainActive.LastTip()) != 0) { - ptr->height = pindex->GetHeight(); - ptr->blockhash = pindex->GetBlockHash(); - memset(&pair, 0, sizeof(pair)); - if (NSPV_getntzsresp(&pair, ptr->height - 1) < 0) + if ((pindexTip = chainActive.LastTip()) != nullptr) { + ptr->height = pindexTip->GetHeight(); + ptr->blockhash = pindexTip->GetBlockHash(); + + if (NSPV_notarized_prev(&ptr->ntz, ptr->height) < 0) return (-1); - ptr->notarization = pair.prevntz; // use prev notarization as latest notarization - if ((pindex2 = komodo_chainactive(ptr->notarization.txidheight)) != 0) - ptr->notarization.timestamp = pindex2->nTime; + if ((pindexNtz = komodo_chainactive(ptr->ntz.txidheight)) != 0) + ptr->ntz.timestamp = pindexNtz->nTime; //fprintf(stderr, "timestamp.%i\n", ptr->notarization.timestamp ); if (reqheight == 0) reqheight = ptr->height; @@ -205,7 +209,7 @@ int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) ptr->version = NSPV_PROTOCOL_VERSION; if (NSPV_setequihdr(&ptr->H, reqheight) < 0) return (-1); - return (sizeof(*ptr) + NSPV_MAX_VARINT_SIZE); // add space for nSolution varint length + return sizeof(*ptr); } else return (-1); } @@ -904,56 +908,62 @@ int32_t NSPV_gettxproof(struct NSPV_txproof* ptr, int32_t vout, uint256 txid /*, return (sizeof(*ptr) - sizeof(ptr->tx) - sizeof(ptr->txproof) + ptr->txlen + ptr->txprooflen); } -// get notarisation bracket txns and headers between them -int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp* ptr, uint256 prevntztxid, uint256 nextntztxid) +// get notarization tx and headers for the notarized depth +int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp* ntzproofp, uint256 nextntztxid) { - int32_t i; - uint256 prevHashBlock, nextHashBlock, bhash0, bhash1, desttxid0, desttxid1; + //uint256 prevHashBlock, bhash0, desttxid0; + uint256 nextHashBlock, bhash1, desttxid1; + CTransaction tx; + int16_t dummy, momdepth; + const int32_t DONTVALIDATESIG = 0; LOCK(cs_main); + /* ptr->prevtxid = prevntztxid; ptr->prevntz = NSPV_getrawtx(tx, prevHashBlock, &ptr->prevtxlen, ptr->prevtxid); ptr->prevtxidht = komodo_blockheight(prevHashBlock); - if (NSPV_notarizationextract(0, &ptr->common.prevht, &bhash0, &desttxid0, tx) < 0) { + if (NSPV_notarizationextract(DONTVALIDATESIG, &ptr->common.prevht, &bhash0, &desttxid0, &dummy, tx) < 0) { LogPrintf("%s error: cant decode notarization opreturn ptr->common.prevht.%d bhash0 %s\n", __func__, ptr->common.prevht, bhash0.ToString()); return (-2); } else if (komodo_blockheight(bhash0) != ptr->common.prevht) { LogPrintf("%s error: bhash0 ht.%d not equal to prevht.%d\n", __func__, komodo_blockheight(bhash0), ptr->common.prevht); return (-3); } + */ - ptr->nexttxid = nextntztxid; - ptr->nextntz = NSPV_getrawtx(tx, nextHashBlock, &ptr->nexttxlen, ptr->nexttxid); - ptr->nexttxidht = komodo_blockheight(nextHashBlock); - if (NSPV_notarizationextract(0, &ptr->common.nextht, &bhash1, &desttxid1, tx) < 0) { - LogPrintf("%s error: cant decode notarization opreturn ptr->common.nextht.%d bhash1 %s\n", __func__, ptr->common.nextht, bhash1.ToString()); + ntzproofp->nexttxid = nextntztxid; + ntzproofp->nextntz = NSPV_getrawtx(tx, nextHashBlock, &ntzproofp->nexttxlen, ntzproofp->nexttxid); + ntzproofp->nexttxidht = komodo_blockheight(nextHashBlock); + if (NSPV_notarizationextract(DONTVALIDATESIG, &ntzproofp->common.nextht, &bhash1, &desttxid1, &momdepth, tx) < 0) { + LogPrintf("%s error: cant decode notarization opreturn ptr->common.nextht.%d bhash1 %s\n", __func__, ntzproofp->common.nextht, bhash1.ToString()); return (-5); - } else if (komodo_blockheight(bhash1) != ptr->common.nextht) { - LogPrintf("%s error: bhash1 ht.%d not equal to nextht.%d\n", __func__, komodo_blockheight(bhash1), ptr->common.nextht); + } else if (komodo_blockheight(bhash1) != ntzproofp->common.nextht) { + LogPrintf("%s error: bhash1 ht.%d not equal to nextht.%d\n", __func__, komodo_blockheight(bhash1), ntzproofp->common.nextht); return (-6); } - else if (ptr->common.prevht > ptr->common.nextht || (ptr->common.nextht - ptr->common.prevht) > 1440) { + /*else if (ptr->common.prevht > ptr->common.nextht || (ptr->common.nextht - ptr->common.prevht) > 1440) { LogPrintf("%s error illegal prevht.%d nextht.%d\n", __func__, ptr->common.prevht, ptr->common.nextht); return (-7); - } + }*/ //fprintf(stderr, "%s -> prevht.%d, %s -> nexht.%d\n", ptr->prevtxid.GetHex().c_str(), ptr->common.prevht, ptr->nexttxid.GetHex().c_str(), ptr->common.nextht); - ptr->common.numhdrs = (ptr->common.nextht - ptr->common.prevht); - ptr->common.hdrs = (struct NSPV_equihdr*)calloc(ptr->common.numhdrs, sizeof(*ptr->common.hdrs)); + ntzproofp->common.numhdrs = momdepth; + ntzproofp->common.hdrs = (struct NSPV_equihdr*)calloc(ntzproofp->common.numhdrs, sizeof(*ntzproofp->common.hdrs)); //fprintf(stderr, "prev.%d next.%d allocate numhdrs.%d\n", ptr->common.prevht, ptr->common.nextht, ptr->common.numhdrs); - for (i = 0; i < ptr->common.numhdrs; i++) { + for (int32_t i = 0; i < ntzproofp->common.numhdrs; i++) { //hashBlock = NSPV_hdrhash(&ptr->common.hdrs[i]); //fprintf(stderr,"hdr[%d] %s\n",prevht+i,hashBlock.GetHex().c_str()); - if (NSPV_setequihdr(&ptr->common.hdrs[i], ptr->common.prevht + i + 1) < 0) { - LogPrintf("%s error setting hdr for ht.%d\n", __func__, ptr->common.prevht + i + 1); - free(ptr->common.hdrs); - ptr->common.hdrs = 0; + int32_t ht = ntzproofp->common.nextht - momdepth + 1 + i; + if (NSPV_setequihdr(&ntzproofp->common.hdrs[i], ht) < 0) { + LogPrintf("%s error setting hdr for ht.%d\n", __func__, ht); + free(ntzproofp->common.hdrs); + ntzproofp->common.hdrs = 0; return (-1); } } //fprintf(stderr, "sizeof ptr %ld, common.%ld lens.%d %d\n", sizeof(*ptr), sizeof(ptr->common), ptr->prevtxlen, ptr->nexttxlen); - return (sizeof(*ptr) + (sizeof(*ptr->common.hdrs) + NSPV_MAX_VARINT_SIZE) * ptr->common.numhdrs - sizeof(ptr->common.hdrs) - sizeof(ptr->prevntz) - sizeof(ptr->nextntz) + ptr->prevtxlen + ptr->nexttxlen); + return sizeof(*ntzproofp) + sizeof(*ntzproofp->common.hdrs) * (ntzproofp->common.numhdrs) + ntzproofp->nexttxlen; } int32_t NSPV_getspentinfo(struct NSPV_spentinfo* ptr, uint256 txid, int32_t vout) @@ -1087,7 +1097,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re int32_t skipcount = 0; int32_t maxrecords = 0; uint8_t isCC = 0; - int32_t respLen; + int32_t respEstimated; //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); @@ -1130,22 +1140,24 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re LogPrint("nspv-details", "NSPV_UTXOS address=%s isCC.%d skipcount.%d maxrecords.%d\n", coinaddr, isCC, skipcount, maxrecords); memset(&U, 0, sizeof(U)); - if ((respLen = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, maxrecords)) > 0) { - response.resize(nspvHeaderSize + respLen); + if ((respEstimated = NSPV_getaddressutxos(&U, coinaddr, isCC, skipcount, maxrecords)) > 0) { + response.resize(nspvHeaderSize + respEstimated); response[0] = NSPV_UTXOSRESP; memcpy(&response[1], &requestId, sizeof(requestId)); - if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) <= respLen) { + int32_t respWritten = NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U); + if (respWritten > 0 && respWritten <= respEstimated) { + response.resize(nspvHeaderSize + respWritten); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_UTXOS response: numutxos=%d to node=%d\n", U.numutxos, pfrom->id); } else { - LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", respLen); + LogPrint("nspv", "NSPV_rwutxosresp incorrect written response len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); } NSPV_utxosresp_purge(&U); } else { - LogPrint("nspv", "NSPV_getaddressutxos error respLen.%d\n", respLen); + LogPrint("nspv", "NSPV_getaddressutxos error respEstimated.%d\n", respEstimated); NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); } } @@ -1158,7 +1170,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re int32_t skipcount = 0; int32_t maxrecords = 0; uint8_t isCC = 0; - int32_t respLen; + int32_t respEstimated; //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); @@ -1202,23 +1214,25 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re LogPrint("nspv-details", "NSPV_TXIDS address=%s isCC.%d skipcount.%d maxrecords.%x\n", coinaddr, isCC, skipcount, maxrecords); memset(&T, 0, sizeof(T)); - if ((respLen = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, maxrecords)) > 0) { + if ((respEstimated = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, maxrecords)) > 0) { //fprintf(stderr,"respLen.%d\n",respLen); - response.resize(nspvHeaderSize + respLen); + response.resize(nspvHeaderSize + respEstimated); response[0] = NSPV_TXIDSRESP; memcpy(&response[1], &requestId, sizeof(requestId)); - if (NSPV_rwtxidsresp(IGUANA_WRITE, &response[nspvHeaderSize], &T) <= respLen) { + int32_t respWritten = NSPV_rwtxidsresp(IGUANA_WRITE, &response[nspvHeaderSize], &T); + if (respWritten > 0 && respWritten <= respEstimated) { + response.resize(nspvHeaderSize + respWritten); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_TXIDS response: numtxids=%d to node=%d\n", (int)T.numtxids, pfrom->id); } else { - LogPrint("nspv", "NSPV_rwtxidsresp incorrect response len.%d\n", respLen); + LogPrint("nspv", "NSPV_rwtxidsresp incorrect response written len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); } NSPV_txidsresp_purge(&T); } else { - LogPrint("nspv", "NSPV_getaddresstxids error.%d\n", respLen); + LogPrint("nspv", "NSPV_getaddresstxids error.%d\n", respEstimated); NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); } } @@ -1232,7 +1246,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re uint256 txid; uint8_t funcid, isCC = 0; int8_t addrlen; - int32_t respLen; + int32_t respEstimated; if (requestDataLen > sizeof(isCC) + sizeof(funcid) + sizeof(vout) + sizeof(txid) + sizeof(addrlen)) { uint32_t offset = 0; @@ -1247,23 +1261,25 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re offset += addrlen; LogPrint("nspv-details", "address (%s) isCC.%d funcid.%d %s/v%d len.%d addrlen.%d\n", coinaddr, isCC, funcid, txid.GetHex().c_str(), vout, requestDataLen, addrlen); memset(&M, 0, sizeof(M)); - if ((respLen = NSPV_mempooltxids(&M, coinaddr, isCC, funcid, txid, vout)) > 0) { + if ((respEstimated = NSPV_mempooltxids(&M, coinaddr, isCC, funcid, txid, vout)) > 0) { //fprintf(stderr,"NSPV_mempooltxids respLen.%d\n",respLen); - response.resize(nspvHeaderSize + respLen); + response.resize(nspvHeaderSize + respEstimated); response[0] = NSPV_MEMPOOLRESP; memcpy(&response[1], &requestId, sizeof(requestId)); - if (NSPV_rwmempoolresp(IGUANA_WRITE, &response[nspvHeaderSize], &M) <= respLen) { + int32_t respWritten = NSPV_rwmempoolresp(IGUANA_WRITE, &response[nspvHeaderSize], &M); + if (respWritten > 0 && respWritten <= respEstimated) { + response.resize(nspvHeaderSize + respWritten); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_MEMPOOL response: numtxids=%d to node=%d\n", M.numtxids, pfrom->id); } else { - LogPrint("nspv", "NSPV_rwmempoolresp incorrect response len.%d\n", respLen); + LogPrint("nspv", "NSPV_rwmempoolresp incorrect response written len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); } NSPV_mempoolresp_purge(&M); } else { - LogPrint("nspv", "NSPV_mempooltxids err.%d\n", respLen); + LogPrint("nspv", "NSPV_mempooltxids err.%d\n", respEstimated); NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); } } else { @@ -1282,26 +1298,28 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re struct NSPV_ntzsresp N; int32_t height; if (requestDataLen == sizeof(height)) { - int32_t respLen; + int32_t respEstimated; iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(height), &height); memset(&N, 0, sizeof(N)); - if ((respLen = NSPV_getntzsresp(&N, height)) > 0) { - response.resize(nspvHeaderSize + respLen); + if ((respEstimated = NSPV_getntzsresp(&N, height)) > 0) { + response.resize(nspvHeaderSize + respEstimated); response[0] = NSPV_NTZSRESP; memcpy(&response[1], &requestId, sizeof(requestId)); - if (NSPV_rwntzsresp(IGUANA_WRITE, &response[nspvHeaderSize], &N) <= respLen) { + int32_t respWritten = NSPV_rwntzsresp(IGUANA_WRITE, &response[nspvHeaderSize], &N); + if (respWritten > 0 && respWritten <= respEstimated) { + response.resize(nspvHeaderSize + respWritten); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; - LogPrint("nspv-details", "NSPV_NTZS response: prevntz.txid=%s nextntx.txid=%s node=%d\n", N.prevntz.txid.GetHex().c_str(), N.nextntz.txid.GetHex().c_str(), pfrom->id); + LogPrint("nspv-details", "NSPV_NTZS response: ntz.txid=%s node=%d\n", N.ntz.txid.GetHex(), pfrom->id); } else { - LogPrint("nspv", "NSPV_rwntzsresp incorrect response len.%d\n", respLen); + LogPrint("nspv", "NSPV_rwntzsresp incorrect response written len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); } NSPV_ntzsresp_purge(&N); } else { - LogPrint("nspv", "NSPV_rwntzsresp err.%d\n", respLen); + LogPrint("nspv", "NSPV_rwntzsresp respLen err.%d\n", respEstimated); NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); } } else { @@ -1314,30 +1332,31 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re case NSPV_NTZSPROOF: { struct NSPV_ntzsproofresp P; - uint256 prevntz, nextntz; - if (requestDataLen == sizeof(prevntz) + sizeof(nextntz)) { - int32_t respLen; + uint256 ntztxid; + if (requestDataLen == sizeof(ntztxid)) { + int32_t respEstimated; - iguana_rwbignum(IGUANA_READ, &requestData[0], sizeof(prevntz), (uint8_t*)&prevntz); - iguana_rwbignum(IGUANA_READ, &requestData[sizeof(prevntz)], sizeof(nextntz), (uint8_t*)&nextntz); + iguana_rwbignum(IGUANA_READ, &requestData[0], sizeof(ntztxid), (uint8_t*)&ntztxid); memset(&P, 0, sizeof(P)); - if ((respLen = NSPV_getntzsproofresp(&P, prevntz, nextntz)) > 0) { + if ((respEstimated = NSPV_getntzsproofresp(&P, ntztxid)) > 0) { // fprintf(stderr,"respLen.%d msg prev.%s next.%s\n",respLen,prevntz.GetHex().c_str(),nextntz.GetHex().c_str()); - response.resize(nspvHeaderSize + respLen); + response.resize(nspvHeaderSize + respEstimated); response[0] = NSPV_NTZSPROOFRESP; memcpy(&response[1], &requestId, sizeof(requestId)); - if (NSPV_rwntzsproofresp(IGUANA_WRITE, &response[nspvHeaderSize], &P) <= respLen) { + int32_t respWritten = NSPV_rwntzsproofresp(IGUANA_WRITE, &response[nspvHeaderSize], &P); + if (respWritten > 0) { + response.resize(nspvHeaderSize + respWritten); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; - LogPrint("nspv-details", "NSPV_NTZSPROOF response: prevtxidht=%d nexttxidht=%d node=%d\n", P.prevtxidht, P.nexttxidht, pfrom->id); + LogPrint("nspv-details", "NSPV_NTZSPROOF response: nexttxidht=%d node=%d\n", P.nexttxidht, pfrom->id); } else { - LogPrint("nspv", "NSPV_rwntzsproofresp incorrect response len.%d\n", respLen); + LogPrint("nspv", "NSPV_rwntzsproofresp incorrect response written len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); } NSPV_ntzsproofresp_purge(&P); } else { - LogPrint("nspv", "NSPV_NTZSPROOF err.%d\n", respLen); + LogPrint("nspv", "NSPV_NTZSPROOF respLen err.%d\n", respEstimated); NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); } } else { @@ -1353,31 +1372,33 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re uint256 txid; int32_t height, vout; if (requestDataLen == sizeof(txid) + sizeof(height) + sizeof(vout)) { - int32_t respLen; + int32_t respEstimated; iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(height), &height); iguana_rwnum(IGUANA_READ, &requestData[sizeof(height)], sizeof(vout), &vout); iguana_rwbignum(IGUANA_READ, &requestData[sizeof(height) + sizeof(vout)], sizeof(txid), (uint8_t*)&txid); //fprintf(stderr,"got txid %s/v%d ht.%d\n",txid.GetHex().c_str(),vout,height); memset(&P, 0, sizeof(P)); - if ((respLen = NSPV_gettxproof(&P, vout, txid /*,height*/)) > 0) { - //fprintf(stderr,"respLen.%d\n",respLen); - response.resize(nspvHeaderSize + respLen); + if ((respEstimated = NSPV_gettxproof(&P, vout, txid /*,height*/)) > 0) { + //fprintf(stderr,"respEstimated.%d\n",respEstimated); + response.resize(nspvHeaderSize + respEstimated); response[0] = NSPV_TXPROOFRESP; memcpy(&response[1], &requestId, sizeof(requestId)); - if (NSPV_rwtxproof(IGUANA_WRITE, &response[nspvHeaderSize], &P) <= respLen) { + int32_t respWritten = NSPV_rwtxproof(IGUANA_WRITE, &response[nspvHeaderSize], &P); + if (respWritten > 0 && respWritten <= respEstimated) { + response.resize(nspvHeaderSize + respWritten); //fprintf(stderr,"send response\n"); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_TXPROOF response: txlen=%d txprooflen=%d node=%d\n", P.txlen, P.txprooflen, pfrom->id); } else { - LogPrint("nspv", "NSPV_rwtxproof incorrect response len.%d\n", respLen); + LogPrint("nspv", "NSPV_rwtxproof incorrect response written len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); } NSPV_txproof_purge(&P); } else { - LogPrint("nspv", "gettxproof error.%d\n", respLen); + LogPrint("nspv", "gettxproof error.%d\n", respEstimated); NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); } } else { @@ -1394,27 +1415,29 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re uint256 txid; if (requestDataLen == sizeof(txid) + sizeof(vout)) { - int32_t respLen; + int32_t respEstimated; iguana_rwnum(IGUANA_READ, &requestData[0], sizeof(vout), &vout); iguana_rwbignum(IGUANA_READ, &requestData[sizeof(vout)], sizeof(txid), (uint8_t*)&txid); memset(&S, 0, sizeof(S)); - if ((respLen = NSPV_getspentinfo(&S, txid, vout)) > 0) { - response.resize(nspvHeaderSize + respLen); + if ((respEstimated = NSPV_getspentinfo(&S, txid, vout)) > 0) { + response.resize(nspvHeaderSize + respEstimated); response[0] = NSPV_SPENTINFORESP; memcpy(&response[1], &requestId, sizeof(requestId)); - if (NSPV_rwspentinfo(IGUANA_WRITE, &response[nspvHeaderSize], &S) <= respLen) { + int32_t respWritten = NSPV_rwspentinfo(IGUANA_WRITE, &response[nspvHeaderSize], &S); + if (respWritten > 0 && respWritten <= respEstimated) { + response.resize(nspvHeaderSize + respWritten); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_SPENTINFO response: spent txid=%s vout=%d node=%d\n", S.txid.GetHex().c_str(), S.vout, pfrom->id); } else { - LogPrint("nspv", "NSPV_rwspentinfo incorrect response len.%d\n", respLen); + LogPrint("nspv", "NSPV_rwspentinfo incorrect response written len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); } NSPV_spentinfo_purge(&S); } else { - LogPrint("nspv", "NSPV_getspentinfo error.%d node=%d\n", respLen, pfrom->id); + LogPrint("nspv", "NSPV_getspentinfo error.%d node=%d\n", respEstimated, pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); } } else { @@ -1431,34 +1454,36 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re int32_t txlen; if (requestDataLen > sizeof(txid) + sizeof(txlen)) { int32_t offset = 0; - int32_t respLen; + int32_t respEstimated; offset += iguana_rwbignum(IGUANA_READ, &requestData[offset], sizeof(txid), (uint8_t*)&txid); offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(txlen), &txlen); memset(&B, 0, sizeof(B)); - if (txlen < MAX_TX_SIZE_AFTER_SAPLING && requestDataLen == offset + txlen && (respLen = NSPV_sendrawtransaction(&B, &requestData[offset], txlen)) > 0) { - response.resize(nspvHeaderSize + respLen); + if (txlen < MAX_TX_SIZE_AFTER_SAPLING && requestDataLen == offset + txlen && (respEstimated = NSPV_sendrawtransaction(&B, &requestData[offset], txlen)) > 0) { + response.resize(nspvHeaderSize + respEstimated); response[0] = NSPV_BROADCASTRESP; memcpy(&response[1], &requestId, sizeof(requestId)); - if (NSPV_rwbroadcastresp(IGUANA_WRITE, &response[nspvHeaderSize], &B) <= respLen) { + + int32_t respWritten = NSPV_rwbroadcastresp(IGUANA_WRITE, &response[nspvHeaderSize], &B); + if (respWritten > 0 && respWritten <= respEstimated) { + response.resize(nspvHeaderSize + respWritten); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_BROADCAST response: txid=%s vout=%d to node=%d\n", B.txid.GetHex().c_str(), pfrom->id); } else { - LogPrint("nspv", "NSPV_rwbroadcastresp incorrect response len.%d\n", respLen); + LogPrint("nspv", "NSPV_rwbroadcastresp incorrect response written len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); } NSPV_broadcast_purge(&B); } else { - LogPrint("nspv", "NSPV_BROADCAST either wrong tx len.%d or NSPV_sendrawtransaction error.%d, node=%d\n", txlen, respLen, pfrom->id); + LogPrint("nspv", "NSPV_BROADCAST either wrong tx len.%d or NSPV_sendrawtransaction error.%d, node=%d\n", txlen, respEstimated, pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_BROADCAST); } } else { LogPrint("nspv", "NSPV_BROADCAST bad request len.%d node %d\n", requestDataLen, pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); } - } break; @@ -1467,7 +1492,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re struct NSPV_remoterpcresp R; int32_t offset = 0; int32_t reqJsonLen; - int32_t respJsonLen; + int32_t respEstimated; offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(reqJsonLen), &reqJsonLen); if (reqJsonLen > NSPV_MAXJSONREQUESTSIZE) { LogPrint("nspv", "NSPV_REMOTERPC too big json request len.%d\n", reqJsonLen); @@ -1479,15 +1504,21 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re LogPrint("nspv", "NSPV_REMOTERPC bad request len.%d node %d\n", requestDataLen, pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); } - if ((respJsonLen = NSPV_remoterpc(&R, (char*)&requestData[offset], reqJsonLen)) > 0) { - response.resize(nspvHeaderSize + respJsonLen); + if ((respEstimated = NSPV_remoterpc(&R, (char*)&requestData[offset], reqJsonLen)) > 0) { + response.resize(nspvHeaderSize + respEstimated); response[0] = NSPV_REMOTERPCRESP; memcpy(&response[1], &requestId, sizeof(requestId)); - NSPV_rwremoterpcresp(IGUANA_WRITE, &response[nspvHeaderSize], &R, respJsonLen); - pfrom->PushMessage("nSPV", response); - pfrom->nspvdata[idata].prevtime = timestamp; - pfrom->nspvdata[idata].nreqs++; - LogPrint("nspv-details", "NSPV_REMOTERPCRESP response: method=%s json=%s to node=%d\n", R.method, R.json, pfrom->id); + int32_t respWritten = NSPV_rwremoterpcresp(IGUANA_WRITE, &response[nspvHeaderSize], &R, respEstimated); + if (respWritten > 0 && respWritten <= respEstimated) { + response.resize(nspvHeaderSize + respWritten); + pfrom->PushMessage("nSPV", response); + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; + LogPrint("nspv-details", "NSPV_REMOTERPCRESP response: method=%s json=%s to node=%d\n", R.method, R.json, pfrom->id); + } else { + LogPrint("nspv", "NSPV_rwbroadcastresp incorrect response written len.%d\n", respWritten); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } NSPV_remoterpc_purge(&R); } else { LogPrint("nspv", "NSPV_REMOTERPC could not execute request node %d\n", requestDataLen, pfrom->id); @@ -1506,7 +1537,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re char funcids[27]; uint256 filtertxid; bool errorFormat = false; - int32_t respLen; + int32_t respEstimated; //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); @@ -1554,22 +1585,24 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re } iguana_rwbignum(IGUANA_READ, &requestData[offset], sizeof(filtertxid), (uint8_t*)&filtertxid); memset(&U, 0, sizeof(U)); - if ((respLen = NSPV_getccmoduleutxos(&U, coinaddr, amount, evalcode, funcids, filtertxid)) > 0) { - response.resize(nspvHeaderSize + respLen); + if ((respEstimated = NSPV_getccmoduleutxos(&U, coinaddr, amount, evalcode, funcids, filtertxid)) > 0) { + response.resize(nspvHeaderSize + respEstimated); response[0] = NSPV_CCMODULEUTXOSRESP; memcpy(&response[1], &requestId, sizeof(requestId)); - if (NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U) <= respLen) { + int32_t respWritten = NSPV_rwutxosresp(IGUANA_WRITE, &response[nspvHeaderSize], &U); + if (respWritten > 0 && respWritten <= respEstimated) { + response.resize(nspvHeaderSize + respWritten); pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; LogPrint("nspv-details", "NSPV_CCMODULEUTXOS returned %d utxos to node=%d\n", (int)U.numutxos, pfrom->id); } else { - LogPrint("nspv", "NSPV_rwutxosresp incorrect response len.%d\n", respLen); + LogPrint("nspv", "NSPV_rwutxosresp incorrect response written len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); } NSPV_utxosresp_purge(&U); } else { - LogPrint("nspv", "NSPV_getccmoduleutxos error.%d, node %d\n", respLen, pfrom->id); + LogPrint("nspv", "NSPV_getccmoduleutxos error.%d, node %d\n", respEstimated, pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); } diff --git a/src/komodo_nSPV_superlite.h b/src/komodo_nSPV_superlite.h index fc63b0f82e1..15a0bedf1c8 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -19,6 +19,7 @@ #include +#include "key_io.h" #include "main.h" #include "komodo_defs.h" #include "notarisationdb.h" @@ -116,11 +117,11 @@ struct NSPV_txproof *NSPV_txproof_add(struct NSPV_txproof *ptr) return(&NSPV_txproof_cache[i]); } -struct NSPV_ntzsproofresp *NSPV_ntzsproof_find(uint256 prevtxid,uint256 nexttxid) +struct NSPV_ntzsproofresp *NSPV_ntzsproof_find(uint256 nexttxid) { int32_t i; for (i=0; iprevtxid.GetHex().c_str(),ptr->nexttxid.GetHex().c_str()); + fprintf(stderr,"ADD CACHE ntzsproof %s\n", ptr->nexttxid.GetHex().c_str()); return(&NSPV_ntzsproofresp_cache[i]); } @@ -188,26 +189,26 @@ void komodo_nSPVresp(CNode *pfrom,std::vector response) // received a r NSPV_rwntzsresp(0,&response[1],&NSPV_ntzsresult); if ( NSPV_ntzsresp_find(NSPV_ntzsresult.reqheight) == 0 ) NSPV_ntzsresp_add(&NSPV_ntzsresult); - fprintf(stderr,"got ntzs response %u size.%d %s prev.%d, %s next.%d\n",timestamp,(int32_t)response.size(),NSPV_ntzsresult.prevntz.txid.GetHex().c_str(),NSPV_ntzsresult.prevntz.height,NSPV_ntzsresult.nextntz.txid.GetHex().c_str(),NSPV_ntzsresult.nextntz.height); + fprintf(stderr,"got ntzs response %u size.%d ntz.txid %s ntzed.height.%d\n",timestamp,(int32_t)response.size(), NSPV_ntzsresult.ntz.txid.GetHex().c_str(), NSPV_ntzsresult.ntz.ntzheight); break; case NSPV_NTZSPROOFRESP: NSPV_ntzsproofresp_purge(&NSPV_ntzsproofresult); NSPV_rwntzsproofresp(0,&response[1],&NSPV_ntzsproofresult); - if ( NSPV_ntzsproof_find(NSPV_ntzsproofresult.prevtxid,NSPV_ntzsproofresult.nexttxid) == 0 ) + if ( NSPV_ntzsproof_find(NSPV_ntzsproofresult.nexttxid) == 0 ) NSPV_ntzsproof_add(&NSPV_ntzsproofresult); - fprintf(stderr,"got ntzproof response %u size.%d prev.%d next.%d\n",timestamp,(int32_t)response.size(),NSPV_ntzsproofresult.common.prevht,NSPV_ntzsproofresult.common.nextht); + fprintf(stderr,"got ntzproof response %u size.%d next.%d\n",timestamp,(int32_t)response.size(), NSPV_ntzsproofresult.common.nextht); break; case NSPV_TXPROOFRESP: NSPV_txproof_purge(&NSPV_txproofresult); NSPV_rwtxproof(0,&response[1],&NSPV_txproofresult); if ( NSPV_txproof_find(NSPV_txproofresult.txid) == 0 ) NSPV_txproof_add(&NSPV_txproofresult); - fprintf(stderr,"got txproof response %u size.%d %s ht.%d\n",timestamp,(int32_t)response.size(),NSPV_txproofresult.txid.GetHex().c_str(),NSPV_txproofresult.height); + fprintf(stderr,"got txproof response %u size.%d %s ht.%d\n",timestamp,(int32_t)response.size(), NSPV_txproofresult.txid.GetHex().c_str(),NSPV_txproofresult.height); break; case NSPV_SPENTINFORESP: NSPV_spentinfo_purge(&NSPV_spentresult); NSPV_rwspentinfo(0,&response[1],&NSPV_spentresult); - fprintf(stderr,"got spentinfo response %u size.%d\n",timestamp,(int32_t)response.size()); + fprintf(stderr,"got spentinfo response %u size.%d\n", timestamp,(int32_t)response.size()); break; case NSPV_BROADCASTRESP: NSPV_broadcast_purge(&NSPV_broadcastresult); @@ -340,11 +341,11 @@ UniValue NSPV_spentinfo_json(struct NSPV_spentinfo *ptr) UniValue NSPV_ntz_json(struct NSPV_ntz *ptr) { UniValue result(UniValue::VOBJ); - result.push_back(Pair("notarized_height",(int64_t)ptr->height)); - result.push_back(Pair("notarized_blockhash",ptr->blockhash.GetHex())); + result.push_back(Pair("notarized_height",(int64_t)ptr->ntzheight)); + result.push_back(Pair("notarized_blockhash",ptr->ntzblockhash.GetHex())); result.push_back(Pair("notarization_txid",ptr->txid.GetHex())); result.push_back(Pair("notarization_txidheight",(int64_t)ptr->txidheight)); - result.push_back(Pair("notarization_desttxid",ptr->othertxid.GetHex())); + result.push_back(Pair("notarization_desttxid",ptr->desttxid.GetHex())); return(result); } @@ -385,7 +386,7 @@ UniValue NSPV_getinfo_json(struct NSPV_inforesp *ptr) } result.push_back(Pair("height",(int64_t)ptr->height)); result.push_back(Pair("chaintip",ptr->blockhash.GetHex())); - result.push_back(Pair("notarization",NSPV_ntz_json(&ptr->notarization))); + result.push_back(Pair("notarization",NSPV_ntz_json(&ptr->ntz))); result.push_back(Pair("header",NSPV_header_json(&ptr->H,ptr->hdrheight))); result.push_back(Pair("protocolversion",(int64_t)ptr->version)); result.push_back(Pair("lastpeer",NSPV_lastpeer)); @@ -482,8 +483,7 @@ UniValue NSPV_ntzsresp_json(struct NSPV_ntzsresp *ptr) { UniValue result(UniValue::VOBJ); result.push_back(Pair("result","success")); - result.push_back(Pair("prev",NSPV_ntz_json(&ptr->prevntz))); - result.push_back(Pair("next",NSPV_ntz_json(&ptr->nextntz))); + result.push_back(Pair("ntz",NSPV_ntz_json(&ptr->ntz))); result.push_back(Pair("lastpeer",NSPV_lastpeer)); return(result); } @@ -492,16 +492,12 @@ UniValue NSPV_ntzsproof_json(struct NSPV_ntzsproofresp *ptr) { UniValue result(UniValue::VOBJ); result.push_back(Pair("result","success")); - result.push_back(Pair("prevht",(int64_t)ptr->common.prevht)); result.push_back(Pair("nextht",(int64_t)ptr->common.nextht)); - result.push_back(Pair("prevtxid",ptr->prevtxid.GetHex())); - result.push_back(Pair("prevtxidht",(int64_t)ptr->prevtxidht)); - result.push_back(Pair("prevtxlen",(int64_t)ptr->prevtxlen)); result.push_back(Pair("nexttxid",ptr->nexttxid.GetHex())); result.push_back(Pair("nexttxidht",(int64_t)ptr->nexttxidht)); result.push_back(Pair("nexttxlen",(int64_t)ptr->nexttxlen)); result.push_back(Pair("numhdrs",(int64_t)ptr->common.numhdrs)); - result.push_back(Pair("headers",NSPV_headers_json(ptr->common.hdrs,ptr->common.numhdrs,ptr->common.prevht))); + result.push_back(Pair("headers",NSPV_headers_json(ptr->common.hdrs, ptr->common.numhdrs, ptr->common.nextht))); result.push_back(Pair("lastpeer",NSPV_lastpeer)); //fprintf(stderr,"ntzs_proof %s %d, %s %d\n",ptr->prevtxid.GetHex().c_str(),ptr->common.prevht,ptr->nexttxid.GetHex().c_str(),ptr->common.nextht); return(result); @@ -821,19 +817,18 @@ UniValue NSPV_notarizations(int32_t reqheight) return(NSPV_ntzsresp_json(&N)); } -UniValue NSPV_txidhdrsproof(uint256 prevtxid,uint256 nexttxid) +UniValue NSPV_txidhdrsproof(uint256 nexttxid) { uint8_t msg[512]; int32_t i,iter,len = 0; struct NSPV_ntzsproofresp P,*ptr; - if ( (ptr= NSPV_ntzsproof_find(prevtxid,nexttxid)) != 0 ) + if ( (ptr= NSPV_ntzsproof_find(nexttxid)) != 0 ) { - fprintf(stderr,"FROM CACHE NSPV_txidhdrsproof %s %s\n",ptr->prevtxid.GetHex().c_str(),ptr->nexttxid.GetHex().c_str()); + fprintf(stderr,"FROM CACHE NSPV_txidhdrsproof %s\n", ptr->nexttxid.GetHex().c_str()); NSPV_ntzsproofresp_purge(&NSPV_ntzsproofresult); NSPV_ntzsproofresp_copy(&NSPV_ntzsproofresult,ptr); return(NSPV_ntzsproof_json(ptr)); } NSPV_ntzsproofresp_purge(&NSPV_ntzsproofresult); msg[len++] = NSPV_NTZSPROOF; - len += iguana_rwbignum(1,&msg[len],sizeof(prevtxid),(uint8_t *)&prevtxid); len += iguana_rwbignum(1,&msg[len],sizeof(nexttxid),(uint8_t *)&nexttxid); for (iter=0; iter<3; iter++) if ( NSPV_req(0,msg,len,NODE_NSPV,msg[0]>>1) != 0 ) @@ -841,7 +836,7 @@ UniValue NSPV_txidhdrsproof(uint256 prevtxid,uint256 nexttxid) for (i=0; icommon.nextht-ptr->common.prevht+1) != ptr->common.numhdrs ) + int16_t momdepthprev, momdepthnext; + const int32_t VALIDATESIGS = 1; + + /*if (ptr->common.depth != ptr->common.numhdrs) { fprintf(stderr,"next.%d prev.%d -> %d vs %d\n",ptr->common.nextht,ptr->common.prevht,ptr->common.nextht-ptr->common.prevht+1,ptr->common.numhdrs); return(-2); - } - else if ( NSPV_txextract(tx,ptr->nextntz,ptr->nexttxlen) < 0 ) + } else */ + if ( NSPV_txextract(tx,ptr->nextntz,ptr->nexttxlen) < 0 ) return(-3); else if ( tx.GetHash() != ptr->nexttxid ) return(-4); - else if ( NSPV_notarizationextract(1,&height,&blockhash,&desttxid,tx) < 0 ) + else if ( NSPV_notarizationextract(VALIDATESIGS, &height, &blockhash, &desttxid, &momdepthprev, tx) < 0 ) return(-5); else if ( height != ptr->common.nextht ) return(-6); @@ -50,23 +53,28 @@ int32_t NSPV_validatehdrs(struct NSPV_ntzsproofresp *ptr) if ( blockhash != ptr->common.hdrs[i].hashPrevBlock ) return(-i-13); } - sleep(1); // need this to get past the once per second rate limiter per message + /*sleep(1); // need this to get past the once per second rate limiter per message if ( NSPV_txextract(tx,ptr->prevntz,ptr->prevtxlen) < 0 ) return(-8); else if ( tx.GetHash() != ptr->prevtxid ) return(-9); - else if ( NSPV_notarizationextract(1,&height,&blockhash,&desttxid,tx) < 0 ) + else if ( NSPV_notarizationextract(VALIDATESIGS, &height, &blockhash, &desttxid, &momdepthnext, tx) < 0 ) return(-10); else if ( height != ptr->common.prevht ) return(-11); - else if ( NSPV_hdrhash(&ptr->common.hdrs[0]) != blockhash ) + else */ + if ( NSPV_hdrhash(&ptr->common.hdrs[0]) != blockhash ) return(-12); return(0); } int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int32_t height,CTransaction &tx,uint256 &hashblock,int32_t &txheight,int32_t ¤theight,int64_t extradata,uint32_t tiptime,int64_t &rewardsum) { - struct NSPV_txproof *ptr; int32_t i,offset,retval; int64_t rewards = 0; uint32_t nLockTime; std::vector proof; + struct NSPV_txproof* ptr; + int32_t i, offset, retval; + int64_t rewards = 0; + uint32_t nLockTime; + std::vector proof; retval = skipvalidation != 0 ? 0 : -1; //fprintf(stderr,"NSPV_gettx %s/v%d ht.%d\n",txid.GetHex().c_str(),vout,height); @@ -107,38 +115,48 @@ int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int proof.resize(ptr->txprooflen); memcpy(&proof[0],ptr->txproof,ptr->txprooflen); } - NSPV_notarizations(height); // gets the prev and next notarizations - if ( NSPV_inforesult.notarization.height >= height && (NSPV_ntzsresult.prevntz.height == 0 || NSPV_ntzsresult.prevntz.height >= NSPV_ntzsresult.nextntz.height) ) - { + + NSPV_ntz *ntzp; + if (height > NSPV_inforesult.ntz.ntzheight - NSPV_inforesult.ntz.depth && height <= NSPV_inforesult.ntz.ntzheight) + ntzp = &NSPV_inforesult.ntz; + else if (height > NSPV_ntzsresult.ntz.ntzheight - NSPV_ntzsresult.ntz.depth && height <= NSPV_ntzsresult.ntz.ntzheight) + ntzp = &NSPV_ntzsresult.ntz; + else { fprintf(stderr,"issue manual bracket\n"); - NSPV_notarizations(height-1); - NSPV_notarizations(height+1); - NSPV_notarizations(height); // gets the prev and next notarizations + NSPV_notarizations(height); // gets the notarization for tx height + ntzp = &NSPV_ntzsresult.ntz; + //NSPV_notarizations(height-1); + //NSPV_notarizations(height+1); + //NSPV_notarizations(height); // gets the prev and next notarizations } - if ( NSPV_ntzsresult.prevntz.height != 0 && NSPV_ntzsresult.prevntz.height <= NSPV_ntzsresult.nextntz.height ) + if (ntzp->txidheight != 0 && height > ntzp->ntzheight-ntzp->depth && height <= ntzp->ntzheight) { - fprintf(stderr,">>>>> gettx ht.%d prev.%d next.%d\n",height,NSPV_ntzsresult.prevntz.height, NSPV_ntzsresult.nextntz.height); - offset = (height - NSPV_ntzsresult.prevntz.height); - if ( offset >= 0 && height <= NSPV_ntzsresult.nextntz.height ) + fprintf(stderr,">>>>> gettx ht.%d next ntzht.%d\n", height, ntzp->ntzheight); + offset = height - (ntzp->ntzheight - ntzp->depth) + 1; // pos in headers + + //fprintf(stderr,"call NSPV_txidhdrsproof %s %s\n",NSPV_ntzsresult.prevntz.txid.GetHex().c_str(),NSPV_ntzsresult.nextntz.txid.GetHex().c_str()); + NSPV_txidhdrsproof(ntzp->txid); + //usleep(10000); + if ((retval = NSPV_validatehdrs(&NSPV_ntzsproofresult)) == 0) { - //fprintf(stderr,"call NSPV_txidhdrsproof %s %s\n",NSPV_ntzsresult.prevntz.txid.GetHex().c_str(),NSPV_ntzsresult.nextntz.txid.GetHex().c_str()); - NSPV_txidhdrsproof(NSPV_ntzsresult.prevntz.txid,NSPV_ntzsresult.nextntz.txid); - usleep(10000); - if ( (retval= NSPV_validatehdrs(&NSPV_ntzsproofresult)) == 0 ) + std::vector txids; uint256 proofroot; + proofroot = BitcoinGetProofMerkleRoot(proof,txids); + if ( proofroot != NSPV_ntzsproofresult.common.hdrs[offset].hashMerkleRoot || txids[0] != txid ) { - std::vector txids; uint256 proofroot; - proofroot = BitcoinGetProofMerkleRoot(proof,txids); - if ( proofroot != NSPV_ntzsproofresult.common.hdrs[offset].hashMerkleRoot || txids[0] != txid ) - { - fprintf(stderr,"txid.%s vs txids[0] %s\n",txid.GetHex().c_str(),txids[0].GetHex().c_str()); - fprintf(stderr,"prooflen.%d proofroot.%s vs %s\n",(int32_t)proof.size(),proofroot.GetHex().c_str(),NSPV_ntzsproofresult.common.hdrs[offset].hashMerkleRoot.GetHex().c_str()); - retval = -2003; - } else retval = 0; - } - } else retval = -2005; - } else retval = -2004; + fprintf(stderr,"txid.%s vs txids[0] %s\n",txid.GetHex().c_str(),txids[0].GetHex().c_str()); + fprintf(stderr,"prooflen.%d proofroot.%s vs %s\n",(int32_t)proof.size(),proofroot.GetHex().c_str(),NSPV_ntzsproofresult.common.hdrs[offset].hashMerkleRoot.GetHex().c_str()); + retval = -2003; + } + else + retval = 0; + } + else + retval = -2005; + } + else + retval = -2004; } - return(retval); + return retval; } int32_t NSPV_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *belowp,struct NSPV_utxoresp utxos[],int32_t numunspents,int64_t value) diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 23ed5b7df10..b560e83e169 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -818,7 +818,7 @@ int32_t komodo_is_issuer() int32_t bitweight(uint64_t x) { - int i,wt = 0; + int i, wt = 0; for (i=0; i<64; i++) if ( (1LL << i) & x ) wt++; diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 70b303362a4..8b26e373f3a 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -28,7 +28,7 @@ #include "cc/CCinclude.h" #include "cc/eval.h" #include "key_io.h" - +#include "komodo_nSPV_defs.h" #include using namespace std; @@ -37,12 +37,6 @@ typedef vector valtype; extern uint8_t ASSETCHAINS_TXPOW; extern char NSPV_wifstr[],NSPV_pubkeystr[]; extern int32_t KOMODO_NSPV; -#ifndef KOMODO_NSPV_FULLNODE -#define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) -#endif // !KOMODO_NSPV_FULLNODE -#ifndef KOMODO_NSPV_SUPERLITE -#define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) -#endif // !KOMODO_NSPV_SUPERLITE uint256 SIG_TXHASH; diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 3795a7077ad..f46d90c49ce 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -37,6 +37,7 @@ #include +#include "komodo_nSPV_defs.h" #include "rpcwallet.h" using namespace std; @@ -1007,26 +1008,8 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPubKey& m } extern int32_t KOMODO_NSPV,KOMODO_DEX_P2P; -#ifndef KOMODO_NSPV_FULLNODE -#define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) -#endif // !KOMODO_NSPV_FULLNODE -#ifndef KOMODO_NSPV_SUPERLITE -#define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) -#endif // !KOMODO_NSPV_SUPERLITE uint256 zeroid; -UniValue NSPV_getinfo_req(int32_t reqht); -UniValue NSPV_login(char *wifstr); -UniValue NSPV_logout(); -UniValue NSPV_addresstxids(char *coinaddr,int32_t CCflag,int32_t skipcount,int32_t filter); -UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag,int32_t skipcount,int32_t filter); -UniValue NSPV_mempooltxids(char *coinaddr,int32_t CCflag,uint8_t funcid,uint256 txid,int32_t vout); -UniValue NSPV_broadcast(char *hex); -UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); -UniValue NSPV_spentinfo(uint256 txid,int32_t vout); -UniValue NSPV_notarizations(int32_t height); -UniValue NSPV_hdrsproof(int32_t prevheight,int32_t nextheight); -UniValue NSPV_txproof(int32_t vout,uint256 txid,int32_t height); -UniValue NSPV_ccmoduleutxos(char *coinaddr, int64_t amount, uint8_t evalcode, std::string funcids, uint256 filtertxid); + UniValue komodo_DEXbroadcast(uint64_t *locatorp,uint8_t funcid,char *hexstr,int32_t priority,char *tagA,char *tagB,char *destpub33,char *volA,char *volB); UniValue komodo_DEXlist(uint32_t stopat,int32_t minpriority,char *tagA,char *tagB,char *destpub33,char *minA,char *maxA,char *minB,char *maxB,char *stophashstr); @@ -1419,14 +1402,13 @@ UniValue nspv_notarizations(const UniValue& params, bool fHelp, const CPubKey& m UniValue nspv_hdrsproof(const UniValue& params, bool fHelp, const CPubKey& mypk) { - int32_t prevheight,nextheight; - if ( fHelp || params.size() != 2 ) - throw runtime_error("nspv_hdrsproof prevheight nextheight\n"); + int32_t nextheight; + if ( fHelp || params.size() != 1 ) + throw runtime_error("nspv_hdrsproof nextheight\n"); if ( KOMODO_NSPV_FULLNODE ) throw runtime_error("-nSPV=1 must be set to use nspv\n"); - prevheight = atol((char *)params[0].get_str().c_str()); - nextheight = atol((char *)params[1].get_str().c_str()); - return(NSPV_hdrsproof(prevheight,nextheight)); + nextheight = atol((char *)params[0].get_str().c_str()); + return(NSPV_hdrsproof(nextheight)); } UniValue nspv_txproof(const UniValue& params, bool fHelp, const CPubKey& mypk) From 8a17867f3def1b8bf2ac76356d81a2e79a6f696e Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 19 Nov 2021 13:01:52 +0500 Subject: [PATCH 185/348] comment added in assets cc --- src/cc/CCassetstx_impl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index a98d9abd17a..e321466a2e5 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -426,7 +426,7 @@ UniValue CancelBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uin CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk } else { CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk (for expired orders) } UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, @@ -459,7 +459,7 @@ UniValue CancelSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 txfee = 10000; // add normal inputs only from my mypk (not from any pk in the wallet) to validate the ownership - if (txfee <= ASSETS_MARKER_AMOUNT || AddNormalinputsRemote(mtx, mypk, txfee, 0x10000) > 0) + if (txfee <= ASSETS_MARKER_AMOUNT || AddNormalinputsRemote(mtx, mypk, txfee, 0x10000) > 0) // if txfee <= ASSETS_MARKER_AMOUNT then take txfee from marker { uint256 spendingtxid; int32_t spendingvin, h; @@ -506,7 +506,7 @@ UniValue CancelSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk } else { CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk (for expired orders) } UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, From eba470cca2f3dce0982320ce0823a206a3dec853 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 19 Nov 2021 13:09:46 +0500 Subject: [PATCH 186/348] commented unused py token test code --- src/tui/tui_assets_orders.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index a9ed0ed691d..59712866cd5 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -118,7 +118,6 @@ def run_tokens_create(): # test tokenallbalances: check_tokenallbalances(rpc1, v, {tokenid1: 100, tokenid2: 1000_0000, nft00id1: 1, nft00id2: 1, nftf7id1: 1, nftf7id2: 1, nftf7id3: 1, nftf7id4: 1} ) - ''' # first try transfer tokens to a pk and back, then run assets tests print("starting transfer tests for tokenid version=" + v + "...") run_transfers(rpc1, rpc2, v, tokenid1, tokenid2, 10) @@ -156,7 +155,6 @@ def run_tokens_create(): print("starting MofN tests for nftf7id1...") run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) print("token MofN transfer tests finished okay!") - ''' print("all token/assets tests finished okay!") time.sleep(3) @@ -727,6 +725,7 @@ def check_tokenallbalances(rpc, v, checkbalances) : assert len(results) == len(checkbalances), "not all tokenids have correct amounts in " + rpcname + " results" print('check_tokenallbalances okay!') +''' menuItems = [ {"run token create/transfers and assets orders": run_tokens_create}, {"Exit": exit} @@ -804,12 +803,12 @@ def main(): list(menuItems[int(choice)].values())[0]() except (ValueError, IndexError): pass - +''' if __name__ == "__main__": print("starting assets orders test\n plz first start a chain of three nodes and enter paths for your node config files)") # time.sleep(2) - makeTuiConfig() + # makeTuiConfig() # main() - #run_tokens_create() + run_tokens_create() From ebb43791031c38724631169d67bf26674f270666 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 19 Nov 2021 18:03:08 +0500 Subject: [PATCH 187/348] removed 'tokenv2address' from help, added help msg to tokenv2indexkey --- src/rpc/tokensrpc.cpp | 60 ++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 70ccd0aec2d..55884624f4f 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -35,7 +35,7 @@ using namespace std; -UniValue assetsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) +UniValue assetsindexkey(const UniValue& params, bool fHelp, const CPubKey& mypk) { struct CCcontract_info *cp, C; std::vector pubkey; cp = CCinit(&C, EVAL_ASSETS); @@ -48,7 +48,7 @@ UniValue assetsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) return CCaddress(cp, (char *)"Assets", pubkey); } -UniValue tokenaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) +UniValue tokenindexkey(const UniValue& params, bool fHelp, const CPubKey& mypk) { struct CCcontract_info *cp,C; std::vector pubkey; cp = CCinit(&C, EVAL_TOKENS); @@ -63,54 +63,45 @@ UniValue tokenaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) UniValue tokenv2indexkey(const UniValue& params, bool fHelp, const CPubKey& mypk) { - struct CCcontract_info *cp,C; - vuint8_t vpubkey; + if (fHelp || params.size() != 1) + throw runtime_error("tokenv2indexkey pubkey\n" + "returns address index key for pubkey.\n" + "It can be used with getaddressutxos getaddresstxids rpcs to list tokens outputs on this pubkey\n"); + struct CCcontract_info *cp,C; cp = CCinit(&C, EVAL_TOKENSV2); - if (fHelp || params.size() != 1) - throw runtime_error("tokenv2address pubkey\n"); + if (ensure_CCrequirements(cp->evalcode) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - vpubkey = ParseHex(params[0].get_str().c_str()); + vuint8_t vpubkey = ParseHex(params[0].get_str().c_str()); CPubKey pk = pubkey2pk(vpubkey); if (!pk.IsValid()) throw runtime_error("invalid pubkey\n"); char address[KOMODO_ADDRESS_BUFSIZE]; GetCCaddress(cp, address, pk, true); - return address; } -UniValue tokenv2address(const UniValue& params, bool fHelp, const CPubKey& mypk) +UniValue assetsv2indexkey(const UniValue& params, bool fHelp, const CPubKey& mypk) { struct CCcontract_info *cp,C; - vuint8_t pubkey; - - throw runtime_error("tokenv2address not supported, use tokenv2indexkey\n"); - cp = CCinit(&C, EVAL_TOKENSV2); - if (fHelp || params.size() > 1) - throw runtime_error("tokenv2address [pubkey]\n"); - if (ensure_CCrequirements(cp->evalcode) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - if (params.size() == 1) - pubkey = ParseHex(params[0].get_str().c_str()); - return CCaddress(cp, "Tokensv2", pubkey, true); -} - -UniValue assetsv2address(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - struct CCcontract_info *cp,C; - vuint8_t pubkey; + if (fHelp || params.size() != 1) + throw runtime_error("assetsv2indexkey pubkey\n" + "returns address index key for pubkey.\n" + "It can be used with getaddressutxos getaddresstxids rpcs to list assets cc outputs on this pubkey\n"); cp = CCinit(&C, EVAL_ASSETSV2); - if (fHelp || params.size() > 1) - throw runtime_error("assetsv2address [pubkey]\n"); if (ensure_CCrequirements(cp->evalcode) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - if (params.size() == 1) - pubkey = ParseHex(params[0].get_str().c_str()); - return CCaddress(cp, "Assetsv2", pubkey, true); + vuint8_t vpubkey = ParseHex(params[0].get_str().c_str()); + CPubKey pk = pubkey2pk(vpubkey); + if (!pk.IsValid()) + throw runtime_error("invalid pubkey\n"); + + char address[KOMODO_ADDRESS_BUFSIZE]; + GetCCaddress(cp, address, pk, true); + return address; } UniValue tokenlist(const UniValue& params, bool fHelp, const CPubKey& remotepk) @@ -1171,8 +1162,8 @@ static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- // tokens & assets - { "tokens", "assetsaddress", &assetsaddress, true }, - { "tokens v2", "assetsv2address", &assetsv2address, true }, + { "tokens", "assetsindexkey", &assetsindexkey, true }, + { "tokens v2", "assetsv2indexkey", &assetsv2indexkey, true }, { "tokens", "tokeninfo", &tokeninfo, true }, { "tokens v2", "tokenv2info", &tokenv2info, true }, @@ -1182,8 +1173,7 @@ static const CRPCCommand commands[] = { "tokens v2", "tokenv2orders", &tokenv2orders, true }, { "tokens", "mytokenorders", &mytokenorders, true }, { "tokens v2", "mytokenv2orders", &mytokenv2orders, true }, - { "tokens", "tokenaddress", &tokenaddress, true }, - { "tokens v2", "tokenv2address", &tokenv2address, true }, + { "tokens", "tokenindexkey", &tokenindexkey, true }, { "tokens v2", "tokenv2indexkey", &tokenv2indexkey, true }, { "tokens", "tokenbalance", &tokenbalance, true }, { "tokens v2", "tokenv2balance", &tokenv2balance, true }, From 225144836bae227ff3583cf2f3472ccc4107a546 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 23 Nov 2021 12:44:51 +0500 Subject: [PATCH 188/348] searchforpubkey rpc added --- src/rpc/ccutilsrpc.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index 08282211851..df5852a1f1d 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -228,12 +228,50 @@ UniValue getindexkeyforcc(const UniValue& params, bool fHelp, const CPubKey& rem return ccaddress; } +extern bool fAddressIndex; +// search for pubkey for a given normal address +UniValue searchforpubkey(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() != 1) + { + string msg = "searchforpubkey R-address\n" + "\nSearch for the pubkey for an address by trying to get a spending input for an utxo on this address. AddressIndex is required\n" + "\nArguments:\n" + "address\n\n"; + throw std::runtime_error(msg); + } + if (!fAddressIndex) throw std::runtime_error("address index not enabled"); + std::string address = params[0].get_str(); + const bool NORMAL_OUTPUTS = false; + + std::vector> addressIndex; + SetAddressIndexOutputs(addressIndex, (char*)address.c_str(), NORMAL_OUTPUTS); + for (std::vector>::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++) { + if (it->first.spending) { + CTransaction tx; + uint256 blockHash; + if (myGetTransaction(it->first.txhash, tx, blockHash)) { + if (it->first.index < tx.vin.size()) { + vuint8_t pk, sig; + if (E_UNMARSHAL(vuint8_t(tx.vin[it->first.index].scriptSig.begin(), tx.vin[it->first.index].scriptSig.end()), ss >> sig; ss >> pk)) + return HexStr(pk); + } + } + } + } + if (addressIndex.size() == 0) + throw std::runtime_error("address not found"); + else + throw std::runtime_error("pubkey not found"); +} + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- // cc helpers { "ccutils", "listccunspents", &listccunspents, true }, { "ccutils", "getindexkeyforcc", &getindexkeyforcc, true }, + { "ccutils", "searchforpubkey", &searchforpubkey, true }, { "nspv", "createtxwithnormalinputs", &createtxwithnormalinputs, true }, { "nspv", "gettransactionsmany", &gettransactionsmany, true }, }; From 07337922bf66b6024f6831c5880364866a107aac Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 25 Nov 2021 00:43:28 +0500 Subject: [PATCH 189/348] added opdrop tokens data rules into assets cc --- src/cc/CCassets.h | 2 +- src/cc/CCassetsCore_impl.h | 40 +++++++++++++++++++++++++++++++++++++- src/cc/CCassetsUtils.cpp | 27 ++++++++++++------------- src/cc/assets.cpp | 15 +++++++++++--- 4 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index 285d6a17303..d0bcfbf8a45 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -45,7 +45,7 @@ bool ValidateSwapRemainder(CAmount remaining_units, CAmount remaining_nValue, CA bool SetBidFillamounts(CAmount unit_price, CAmount &received_nValue, CAmount orig_nValue, CAmount &paid_units, CAmount orig_units, CAmount paid_unit_price); bool SetAskFillamounts(CAmount unit_price, CAmount fill_assetoshis, CAmount orig_assetoshis, CAmount paid_nValue); bool SetSwapFillamounts(CAmount unit_price, CAmount &paid, CAmount orig_nValue, CAmount &received, CAmount totalprice); // not implemented -CAmount AssetsGetCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx); +CAmount AssetsGetTxCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx); const char ccassets_log[] = "ccassets"; diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index 50c0d6d75f0..7fcd60ce2ea 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -222,7 +222,7 @@ CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *o } // check no more other vins spending from global addr: - if (AssetsGetCCInputs(eval, cpAssets, unspendableAddr, tx) != vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue) + if (AssetsGetTxCCInputs(eval, cpAssets, unspendableAddr, tx) != vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue) return eval->Invalid("invalid assets cc vins found"), 0LL; if (vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue == 0) @@ -286,6 +286,44 @@ CAmount AssetValidateSellvin(struct CCcontract_info *cpAssets, Eval* eval, CAmou return assetoshis; } +template +bool AssetsValidateTokenId(Eval *eval, struct CCcontract_info *cp, const CTransaction &tx, int32_t v, uint256 assetid) +{ + CScript tokenOpret; + uint256 reftokenid; + uint8_t funcId; + std::string errorStr; + if (T::CheckTokensvout(cp, eval, tx, v, tokenOpret, reftokenid, funcId, errorStr) >= 0) { + if (reftokenid != assetid) + return eval->Invalid("invalid tokenid for tokenask"); + else + return true; + } + return eval->Invalid("invalid token tx"); +} + +template +CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, uint256 tokenid, const CTransaction &tx) +{ + CTransaction vinTx; + uint256 hashBlock; + CAmount inputs = 0LL; + + for (int32_t i = 0; i < tx.vin.size(); i++) + { + if (cpTokens->ismyvin(tx.vin[i].scriptSig)) + { + if (eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock)) + { + if (AssetsValidateTokenId(eval, cpTokens, vinTx, tx.vin[i].prevout.n, tokenid)) { + //std::cerr << __func__ << " adding amount=" << vinTx.vout[tx.vin[i].prevout.n].nValue << " for vin i=" << i << " eval=" << std::hex << (int)cp->evalcode << std::resetiosflags(std::ios::hex) << std::endl; + inputs += vinTx.vout[tx.vin[i].prevout.n].nValue; + } + } + } + } + return inputs; +} #endif // #ifndef CC_ASSETS_CORE_IMPL_H diff --git a/src/cc/CCassetsUtils.cpp b/src/cc/CCassetsUtils.cpp index 0e56a9e3b1f..ebcd762e361 100644 --- a/src/cc/CCassetsUtils.cpp +++ b/src/cc/CCassetsUtils.cpp @@ -270,7 +270,7 @@ bool SetBidFillamounts(CAmount unit_price, CAmount &received_nValue, CAmount ori // received_nValue = orig_nValue; received_nValue = (paid_units * paid_unit_price); // as paid unit_price might be less than original unit_price // remaining_units = 0; - fprintf(stderr, "%s not enough units!\n", __func__); + CCLogPrintF(ccassets_log, CCLOG_DEBUG1, "%s not enough units!\n", __func__); return(false); } //remaining_units = (orig_units - paid_units); @@ -279,8 +279,8 @@ bool SetBidFillamounts(CAmount unit_price, CAmount &received_nValue, CAmount ori //unit_price = (orig_nValue / orig_remaining_units); received_nValue = (paid_units * paid_unit_price); - fprintf(stderr, "%s orig_units.%lld - paid_units.%lld, (orig_value.%lld - received_value.%lld)\n", __func__, - (long long)orig_units, (long long)paid_units, (long long)orig_nValue, (long long)received_nValue); + CCLogPrintF(ccassets_log, CCLOG_DEBUG1, "%s orig_units.%lld - paid_units.%lld, (orig_value.%lld - received_value.%lld)\n", __func__, + (long long)orig_units, (long long)paid_units, (long long)orig_nValue, (long long)received_nValue); if (unit_price > 0 && received_nValue > 0 && received_nValue <= orig_nValue) { CAmount remaining_nValue = (orig_nValue - received_nValue); @@ -288,7 +288,7 @@ bool SetBidFillamounts(CAmount unit_price, CAmount &received_nValue, CAmount ori } else { - fprintf(stderr, "%s incorrect values: unit_price %lld > 0, orig_value.%lld >= received_value.%lld\n", __func__, + CCLogPrintF(ccassets_log, CCLOG_DEBUG1, "%s incorrect values: unit_price %lld > 0, orig_value.%lld >= received_value.%lld\n", __func__, (long long)unit_price, (long long)orig_nValue, (long long)received_nValue); return(false); } @@ -317,11 +317,11 @@ bool SetAskFillamounts(CAmount unit_price, CAmount fill_assetoshis, CAmount orig return(true); }*/ if (orig_assetoshis == 0) { - fprintf(stderr, "%s ask order empty!\n", __func__); + CCLogPrintF(ccassets_log, CCLOG_DEBUG1, "%s ask order empty!\n", __func__); return false; } if (fill_assetoshis == 0) { - fprintf(stderr, "%s ask fill tokens is null!\n", __func__); + CCLogPrintF(ccassets_log, CCLOG_DEBUG1, "%s ask fill tokens is null!\n", __func__); return false; } CAmount paid_unit_price = paid_nValue / fill_assetoshis; @@ -330,18 +330,18 @@ bool SetAskFillamounts(CAmount unit_price, CAmount fill_assetoshis, CAmount orig //remaining_nValue = orig_nValue - unit_price * fill_assetoshis; // dunit_price = ((double)orig_nValue / orig_assetoshis); // fill_assetoshis = (paid_nValue / dunit_price); // back conversion -> could be loss of value - fprintf(stderr, "%s paid_unit_price %lld fill_assetoshis %lld orig_assetoshis %lld unit_price %lld fill_assetoshis %lld\n", __func__, - (long long)paid_unit_price, (long long)fill_assetoshis, (long long)orig_assetoshis, (long long)unit_price, (long long)fill_assetoshis); + CCLogPrintF(ccassets_log, CCLOG_DEBUG1, "%s paid_unit_price %lld fill_assetoshis %lld orig_assetoshis %lld unit_price %lld fill_assetoshis %lld\n", + __func__, (long long)paid_unit_price, (long long)fill_assetoshis, (long long)orig_assetoshis, (long long)unit_price, (long long)fill_assetoshis); if (paid_unit_price > 0 && fill_assetoshis <= orig_assetoshis) { CAmount remaining_assetoshis = (orig_assetoshis - fill_assetoshis); if (remaining_assetoshis == 0) - fprintf(stderr, "%s ask order totally filled!\n", __func__); + CCLogPrintF(ccassets_log, CCLOG_DEBUG1, "%s ask order totally filled!\n", __func__); return ValidateAskRemainder(unit_price, remaining_assetoshis, orig_assetoshis, fill_assetoshis, paid_nValue); } else { - fprintf(stderr, "%s incorrect values paid_unit_price %lld > 0, fill_assetoshis %lld > 0 and <= orig_assetoshis %lld\n", __func__, + CCLogPrintF(ccassets_log, CCLOG_DEBUG1, "%s incorrect values paid_unit_price %lld > 0, fill_assetoshis %lld > 0 and <= orig_assetoshis %lld\n", __func__, (long long)paid_unit_price, (long long)fill_assetoshis, (long long)orig_assetoshis); return(false); } @@ -458,7 +458,7 @@ bool ValidateSwapRemainder(int64_t remaining_price, int64_t remaining_nValue, in } // get tx's vin inputs for cp->evalcode and addr. If addr is null then all inputs are added -CAmount AssetsGetCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx) +CAmount AssetsGetTxCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx) { CTransaction vinTx; uint256 hashBlock; @@ -474,7 +474,7 @@ CAmount AssetsGetCCInputs(Eval *eval, struct CCcontract_info *cp, const char *ad if (eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock)) { char scriptaddr[KOMODO_ADDRESS_BUFSIZE]; - if (addr == NULL || Getscriptaddress(scriptaddr, vinTx.vout[tx.vin[i].prevout.n].scriptPubKey) && strcmp(scriptaddr, addr) == 0) { + if (Getscriptaddress(scriptaddr, vinTx.vout[tx.vin[i].prevout.n].scriptPubKey) && strcmp(scriptaddr, addr) == 0) { //std::cerr << __func__ << " adding amount=" << vinTx.vout[tx.vin[i].prevout.n].nValue << " for vin i=" << i << " eval=" << std::hex << (int)cp->evalcode << std::resetiosflags(std::ios::hex) << std::endl; inputs += vinTx.vout[tx.vin[i].prevout.n].nValue; } @@ -482,4 +482,5 @@ CAmount AssetsGetCCInputs(Eval *eval, struct CCcontract_info *cp, const char *ad } } return inputs; -} \ No newline at end of file +} + diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 8c3bf758fe8..0899a6e40f5 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -380,7 +380,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("vout0 should be originator normal address with remainder for fillbid"); } - vin_tokens = AssetsGetCCInputs(eval, cpTokens, NULL, tx); + vin_tokens = AssetsGetTxTokenInputs(eval, cpTokens, assetid, tx); int32_t myNormalVout = 1; int32_t myTokenVout = 2+r; int32_t tokenRemainderVout; @@ -389,11 +389,13 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const else tokenRemainderVout = 3+r; // no marker + if (!AssetsValidateTokenId(eval, cp, tx, myTokenVout, assetid)) + return eval->Invalid("invalid tokenid in vout for tokenfillbid"); if (tx.vout.size() > tokenRemainderVout && tx.vout[tokenRemainderVout].scriptPubKey.IsPayToCryptoCondition()) // if tokens remainder exists { if (!A::ConstrainVout(tx.vout[myTokenVout], CCVOUT, origTokensCCaddr, 0LL, T::EvalCode())) // tokens to originator cc addr (tokens+nonfungible evalcode) return eval->Invalid("vout" + std::to_string(myTokenVout) + " tokens value should go to originator pubkey for fillbid"); - else if (vin_tokens != tx.vout[myTokenVout].nValue + tx.vout[tokenRemainderVout].nValue) // tokens from cc global address -> token global addr (remainder) + originator cc address + else if (vin_tokens != tx.vout[myTokenVout].nValue + tx.vout[tokenRemainderVout].nValue) // tokens from cc inputs -> bid originator token pk + token remainder anywhere return eval->Invalid("tokens inputs doesnt match tokens vout" + std::to_string(myTokenVout) + "+" + "vout"+std::to_string(tokenRemainderVout) + " for fillbid"); ccvouts += 2; } @@ -402,7 +404,6 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("vout" + std::to_string(myTokenVout) + " should have tokens to originator cc addr for fillbid"); ccvouts ++; } - if (!A::ConstrainVout(tx.vout[myNormalVout], NORMALVOUT, NULL, 0LL, 0)) // amount paid for tokens goes to normal addr (we can't check 'self' address) return eval->Invalid("vout " + std::to_string(myNormalVout) + " should be normal for fillbid"); @@ -453,6 +454,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("too few vouts"); else if (A::ConstrainVout(tx.vout[0], CCVOUT, tokensDualEvalUnspendableCCaddr, 0LL, T::EvalCode()) == false) // tokens sent to global addr return eval->Invalid("invalid vout0 global two eval address for sell"); + else if (!AssetsValidateTokenId(eval, cp, tx, 0, assetid)) + return eval->Invalid("invalid tokenid in output for tokenask"); else if( A::ConstrainVout(tx.vout[1], CCVOUT, markerCCaddress, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr return eval->Invalid("invalid vout1 marker for originator pubkey"); else if (TotalPubkeyNormalInputs(eval, tx, origpk) == 0) // check tx is signed by originator pubkey @@ -489,6 +492,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (A::ConstrainVout(tx.vout[0], CCVOUT, origTokensCCaddr, vin_tokens, T::EvalCode()) == false) // tokens returning to originator cc addr return eval->Invalid("invalid vout0 for cancelask"); + else if (!AssetsValidateTokenId(eval, cp, tx, 0, assetid)) + return eval->Invalid("invalid tokenid in vout0 for cancelask"); // get first ccvin: ccvin = std::find_if(tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin) { return cpAssets->ismyvin(vin.scriptSig); }); @@ -547,8 +552,12 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const CAmount paid_value = r > 0 ? tx.vout[2].nValue + tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner if (!ValidateAskRemainder(unit_price, tx.vout[0].nValue, vin_tokens, tx.vout[1].nValue, paid_value)) return eval->Invalid("mismatched vout0 remainder for fillask"); + else if (!AssetsValidateTokenId(eval, cp, tx, 0, assetid)) + return eval->Invalid("invalid tokenid in vout0 for fillask"); else if (!A::ConstrainVout(tx.vout[1], CCVOUT, NULL, 0LL, T::EvalCode())) // do not check tokens buyer's 'self' cc addr return eval->Invalid("vout1 should be cc for fillask"); + else if (!AssetsValidateTokenId(eval, cp, tx, 1, assetid)) + return eval->Invalid("invalid tokenid in vout1 for fillask"); else if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, origNormalAddr, 0LL, 0)) // coins to originator normal addr return eval->Invalid("vout2 should be cc for fillask"); if (r > 0) { From dc56823e7da09086305a3df5cdcd533ecec73107 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 25 Nov 2021 00:44:06 +0500 Subject: [PATCH 190/348] tests added for assets cc rukes for opdrop token data --- src/test-komodo-cc/test-assets.cpp | 221 ++++++++++++++++++++++++++--- 1 file changed, 203 insertions(+), 18 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index d72d12ae5d1..8d2d638f32d 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -82,8 +82,8 @@ class EvalMock : public Eval static EvalMock eval; -static CTransaction txnormal1, txnormal2, txnormal3, txnormal4, txnormalg, txask1, txask2, txbid1, txbid2, txtokencreate1, txtokencreate2, txtokencreate3, txtokencreateUnused; -static uint256 tokenid1, tokenid2, tokenid3, tokenidUnused; +static uint256 tokenid1, tokenid2, tokenid3, tokenid4, tokenidUnused; +static uint256 askid1, askid2, bidid1; // RJXkCF7mn2DRpUZ77XBNTKCe55M2rJbTcu static CPubKey pk1 = CPubKey(ParseHex("035d3b0f2e98cf0fba19f80880ec7c08d770c6cf04aa5639bc57130d5ac54874db")); @@ -390,6 +390,8 @@ class TestAssetsCC : public ::testing::Test { static void CreateMockTransactions() { + CTransaction txnormal1, txnormal2, txnormal3, txnormal4, txnormalg, txask1, txask2, txbid1, txbid2, + txtokencreate1, txtokencreate2, txtokencreate3, txtokencreate4, txtokencreateUnused; txnormal1 = MakeNormalTx(pk1, 20000); eval.AddTx(txnormal1); @@ -422,18 +424,26 @@ class TestAssetsCC : public ::testing::Test { eval.AddTx(txtokencreate3); tokenid3 = txtokencreate3.GetHash(); + txtokencreate4 = MakeTokenV2CreateTx(pk1, 10); + eval.AddTx(txtokencreate4); + tokenid4 = txtokencreate4.GetHash(); + txtokencreateUnused = MakeTokenV2CreateTx(pk1, 10); eval.AddTx(txtokencreateUnused); tokenidUnused = txtokencreateUnused.GetHash(); txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); eval.AddTx(txask1); + askid1 = txask1.GetHash(); txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); eval.AddTx(txask2); + askid2 = txask2.GetHash(); txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 222); eval.AddTx(txbid1); + bidid1 = txbid1.GetHash(); + //txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2, 222); // test dust @@ -869,15 +879,15 @@ class TestAssetsCC : public ::testing::Test { CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // probe to spend marker - std::cerr << __func__ << " mypk=" << HexStr(mypk) << " origpubkey=" << HexStr(pubkey2pk(origpubkey)) << std::endl; + //std::cerr << __func__ << " mypk=" << HexStr(mypk) << " origpubkey=" << HexStr(pubkey2pk(origpubkey)) << std::endl; if (mypk == pubkey2pk(origpubkey)) { CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk - std::cerr << __func__ << " use mypk" << std::endl; + //std::cerr << __func__ << " use mypk" << std::endl; } else { CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk - std::cerr << __func__ << " use unspendableAssetsPrivkey=" << HexStr(unspendableAssetsPrivkey, unspendableAssetsPrivkey+32) << std::endl; + //std::cerr << __func__ << " use unspendableAssetsPrivkey=" << HexStr(unspendableAssetsPrivkey, unspendableAssetsPrivkey+32) << std::endl; } if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, @@ -1084,6 +1094,31 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } + { + // test: different tokenid in opdrop + CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, mypk, tokenid1, numtokens, 501, 222); // price more than dust + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + CScript opret = TokensV2::EncodeTokenOpRet(tokenid1, { unspendableAssetsPubkey }, {}); + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + + CScript opretCh = TokensV2::EncodeTokenOpRet(tokenid1, { mypk }, {}); + vscript_t vopretCh; + GetOpReturnData(opretCh, vopretCh); + std::vector vDataCh { vopretCh }; + + mtx.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), mtx.vout[0].nValue, unspendableAssetsPubkey, &vData); + mtx.vout[2] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), mtx.vout[2].nValue, mypk, &vDataCh); // cc change + mtx.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx, cpTokens, testKeys[mypk], 10000, + TokensV2::EncodeTokenOpRet(tokenid2, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop.." << std::endl; + EXPECT_TRUE(!TestRunCCEval(mtx) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // fail: can't ask for different tokenid + } + } TEST_F(TestAssetsCC, tokenv2bid_basic) @@ -1121,25 +1156,42 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) UniValue data(UniValue::VOBJ); struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0); eval.SetCurrentHeight(111); //set height - CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, txask1.GetHash(), 2, 0, data); - ASSERT_FALSE(CTransaction(mtx).IsNull()); + for (CAmount fillUnits : { 1, 2 }) { // fill partially and totally + CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, askid1, fillUnits, 0, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + // test: valid tokenv2fillask + EXPECT_TRUE(TestRunCCEval(mtx)); + } - // test: valid tokenv2fillask - EXPECT_TRUE(TestRunCCEval(mtx)); + + CTransaction txask1; + CTransaction txbid1; + CTransaction txask2; + + uint256 hashBlock; + ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, askid1, txask1, hashBlock)); + ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, bidid1, txbid1, hashBlock)); + ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, askid2, txask2, hashBlock)); //vuint8_t ownerpubkey = ParseHex(data["ownerpubkey"].getValStr()); + CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, askid1, 2, 0, data); // test: spend invalid tokenid { CMutableTransaction mtx1(mtx); - mtx1.vin.back() = CTxIn(txask1.GetHash(), ASSETS_GLOBALADDR_VOUT, CScript()); // spend order tx + mtx1.vin.back() = CTxIn(askid1, ASSETS_GLOBALADDR_VOUT, CScript()); // spend order tx vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; + CTransaction txask1; + uint256 hashBlock; + ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, askid1, txask1, hashBlock)); uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); ASSERT_TRUE(funcid != 0); mtx1.vout.pop_back(); @@ -1170,7 +1222,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) // test: spend yet another order { CMutableTransaction mtx2(mtx); - mtx2.vin.push_back( CTxIn(txask2.GetHash(), ASSETS_GLOBALADDR_VOUT, CScript()) ); // spend yet another order tx + mtx2.vin.push_back( CTxIn(askid2, ASSETS_GLOBALADDR_VOUT, CScript()) ); // spend yet another order tx vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; @@ -1191,6 +1243,9 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; + CTransaction txask1; + uint256 hashBlock; + ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, askid1, txask1, hashBlock)); uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); // get orig pk, orig value ASSERT_TRUE(funcid != 0); mtx2.vout.pop_back(); @@ -1221,7 +1276,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) int32_t expiryHeight; uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); - CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, txask1.GetHash(), 2, unit_price-1, data); + CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, askid1, 2, unit_price-1, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: invalid tokenv2fillask with a lower price @@ -1234,13 +1289,60 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) int32_t expiryHeight; uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); - CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, txask1.GetHash(), 2, unit_price+1, data); + CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, askid1, 2, unit_price+1, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2fillask with a bigger price EXPECT_TRUE(TestRunCCEval(mtx)); } + { + for (CAmount fillUnits : { 1, 2 }) { // fill partially and totally + // test: fillask with different tokenid in opdrop + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + CTransaction txask1; + uint256 hashBlock; + ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, askid1, txask1, hashBlock)); + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); + + CMutableTransaction mtx2 = MakeTokenV2FillAskTx(cpAssets, pk2, assetidOpret, askid1, fillUnits, unit_price, data); + + CAmount txfee = 10000; + CAmount otherAmount = TestAddTokenInputs(mtx2, pk2, tokenid3, mtx2.vout[0].nValue); //add tokenid3 + ASSERT_TRUE(otherAmount > 0); + + mtx2.vout.insert(mtx2.vout.begin() + mtx2.vout.size() - 1, mtx2.vout[0]); // copy vout with tokens with assetidOpret back + + CScript opret = TokensV2::EncodeTokenOpRet(tokenid3, { unspendableAssetsPubkey }, {}); // put tokenid3 in opdrop while assetid = tokenid2 + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx2.vout[0] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[0].nValue, unspendableAssetsPubkey, &vData); // replace remainder with tokenid3 + + if (otherAmount > mtx2.vout[0].nValue) { // if tokenid3 change exists + CScript opret = TokensV2::EncodeTokenOpRet(tokenid3, { pk2 }, {}); + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx2.vout.insert(mtx2.vout.begin() + mtx2.vout.size() - 1, + TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), otherAmount - mtx2.vout[0].nValue, pk2, &vData)); // add tokenid3 change + } + + mtx2.vout.pop_back(); // remove opret to replace it in TestFinalizeTx + CCwrapper wrCond1(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), pk2)); // spend my tokens to fill buy + CCAddVintxCond(cpAssets, wrCond1, NULL); //NULL indicates to use myprivkey + + ASSERT_TRUE(TestFinalizeTx(mtx2, cpAssets, testKeys[pk2], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, + { AssetsV2::EncodeAssetOpRet('S', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + std::cerr << __func__ << " test: tokenfillask with different tokenid in opdrop, fillUnuts=" << fillUnits << std::endl; + EXPECT_FALSE(assetidOpret == tokenid3); + EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid3 in opdrop + } + } } @@ -1251,7 +1353,11 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) cpTokens = CCinit(&C, TokensV2::EvalCode()); eval.SetCurrentHeight(111); //set height - CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, txbid1.GetHash(), 2, 0, data); + CTransaction txbid1; + uint256 hashBlock; + ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, bidid1, txbid1, hashBlock)); + + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, bidid1, 2, 0, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2fillbid @@ -1266,7 +1372,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) CAmount unit_price = data["unit_price"].get_int64(); int32_t expiryHeight = data["expiryHeight"].get_int(); - mtx1.vin[1] = CTxIn(txtokencreate3.GetHash(), 1, CScript()); // spend other tokenid3 + mtx1.vin[1] = CTxIn(tokenid3, 1, CScript()); // spend other tokenid3 mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(origpubkey) }, @@ -1313,7 +1419,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) int32_t expiryHeight; uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value - CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, txbid1.GetHash(), 1, unit_price, data); + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, bidid1, 1, unit_price, data); mtx.vout[1].nValue += 1; // imitate lower price ASSERT_FALSE(CTransaction(mtx).IsNull()); @@ -1327,7 +1433,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) int32_t expiryHeight; uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value - CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, txbid1.GetHash(), 1, unit_price-1, data); + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, bidid1, 1, unit_price-1, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2fillbid with lower sell price than requested @@ -1346,6 +1452,40 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) // test: invalid tokenv2fillbid with bigger sell price than requested EXPECT_FALSE(TestRunCCEval(mtx)); // must fail } + { + // test: fillbid with different tokenid in opdrop + vuint8_t origpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value + + CMutableTransaction mtx2 = MakeTokenV2FillBidTx(cpTokens, pk2, assetidOpret, txbid1.GetHash(), 2, 0, data); + + CAmount txfee = 10000; + mtx2.vin[1] = CTxIn(tokenid3, 1, CScript()); // spend other tokenid3 + + CScript opret = TokensV2::EncodeTokenOpRet(tokenid3, { origpubkey }, {}); //send to tokenid3 when assetidOpret = tokenid2 + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx2.vout[2] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[2].nValue, origpubkey, &vData); + + CScript opretCh = TokensV2::EncodeTokenOpRet(tokenid3, { pk2 }, {}); //send to tokenid3 when assetidOpret = tokenid2 + vscript_t vopretCh; + GetOpReturnData(opretCh, vopretCh); + std::vector vDataCh { vopretCh }; + mtx2.vout[3] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[3].nValue, pk2, &vDataCh); // change + + mtx2.vout.pop_back(); // remove opret to replace it in TestFinalizeTx + ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(origpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', unit_price, origpubkey, expiryHeight) }))); + + std::cerr << __func__ << " test: tokenfillbid with different tokenid in opdrop" << std::endl; + EXPECT_FALSE(assetidOpret == tokenid3); + EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid3 in opdrop + } } TEST_F(TestAssetsCC, tokenv2fillbid_royalty) @@ -1418,6 +1558,9 @@ TEST_F(TestAssetsCC, tokenv2cancelask) cpAssets = CCinit(&C, AssetsV2::EvalCode()); cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + CTransaction txask1; + uint256 hashBlock; + ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, askid1, txask1, hashBlock)); for (CTransaction vintx : std::vector{ txask1 }) // TODO add more txasks { @@ -1477,6 +1620,43 @@ TEST_F(TestAssetsCC, tokenv2cancelask) { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); EXPECT_FALSE(TestRunCCEval(mtx6)); // must fail } + { + CMutableTransaction mtx7(mtx); + + CAmount txfee = 10000; + CAmount otherAmount = TestAddTokenInputs(mtx7, origpubkey, tokenid4, mtx7.vout[0].nValue); //add different tokenid + ASSERT_TRUE(otherAmount > 0); + + mtx7.vout.insert(mtx7.vout.begin() + mtx7.vout.size() - 1, mtx7.vout[0]); // copy vout with tokens with assetidOpret back + + CScript opret = TokensV2::EncodeTokenOpRet(tokenid4, { origpubkey }, {}); // put tokenid4 in opdrop while assetid differs + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx7.vout[0] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx7.vout[0].nValue, origpubkey, &vData); // replace remainder with tokenid4 + + std::cerr << __func__ << " tokenid4=" << tokenid4.GetHex() << " assetidOpret=" << assetidOpret.GetHex() << " otherAmount=" << otherAmount << " mtx7.vin.size()=" << mtx7.vin.size() << std::endl; + if (otherAmount > mtx7.vout[0].nValue) { // if tokenid4 change exists + CScript opret = TokensV2::EncodeTokenOpRet(tokenid4, { origpubkey }, {}); + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx7.vout.insert(mtx7.vout.begin() + mtx7.vout.size() - 1, + TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), otherAmount - mtx7.vout[0].nValue, origpubkey, &vData)); // add tokenid4 change + } + + CCwrapper wrCond1(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), origpubkey)); // spend my tokenid4 + CCAddVintxCond(cpAssets, wrCond1, NULL); // NULL indicates to use myprivkey + + mtx7.vout.pop_back(); //remove opret + ASSERT_TRUE(TestFinalizeTx(mtx7, cpAssets, testKeys[origpubkey], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { origpubkey }, + { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(), 0) }))); + + std::cerr << __func__ << " test: tokencancelask with different tokenid in opdrop" << std::endl; + EXPECT_FALSE(assetidOpret == tokenid4); + EXPECT_TRUE(!TestRunCCEval(mtx7) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't cancel with another tokenid in opdrop + } } } @@ -1596,6 +1776,10 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) cpAssets = CCinit(&C, AssetsV2::EvalCode()); cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + CTransaction txbid1; + uint256 hashBlock; + ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, bidid1, txbid1, hashBlock)); + for (CTransaction vintx : std::vector{ txbid1 }) // TODO add more txbid { UniValue data(UniValue::VOBJ); @@ -1829,7 +2013,8 @@ TEST_F(TestAssetsCC, tokenv2create) uint8_t privkeyg[32]; CPubKey pkg = GetUnspendable(cpTokens, privkeyg); - mtx5.vin.push_back(CTxIn(txnormalg.GetHash(), 0)); + ASSERT_TRUE(TestAddNormalInputs(mtx5, pkg, TOKENS_MARKER_VALUE + 10 + txfee) > 0); + //mtx5.vin.push_back(CTxIn(txnormalg.GetHash(), 0)); mtx5.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cpTokens, NULL))); mtx5.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); From 47a76af8243d4c0e277e726ac91e3a52a7410e3d Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 26 Nov 2021 00:07:45 +0500 Subject: [PATCH 191/348] added height activation for asset rules --- src/Makefile.am | 1 + src/cc/CCassetsCore_impl.h | 13 +++++++++++-- src/cc/assets.cpp | 11 ++++++----- src/komodo_utils.h | 6 ++++++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 4fb31dc0f59..712d2f88aec 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -363,6 +363,7 @@ libbitcoin_server_a_SOURCES = \ txdb.cpp \ txmempool.cpp \ validationinterface.cpp \ + cc/CCupgrades.cpp \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index 7fcd60ce2ea..6010fe5c77f 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -18,7 +18,7 @@ #include "CCassets.h" #include "CCtokens.h" - +#include "CCupgrades.h" /* The SetAssetFillamounts() and ValidateAssetRemainder() work in tandem to calculate the vouts for a fill and to validate the vouts, respectively. @@ -302,6 +302,15 @@ bool AssetsValidateTokenId(Eval *eval, struct CCcontract_info *cp, const CTransa return eval->Invalid("invalid token tx"); } +template +bool AssetsValidateTokenId_Activated(Eval *eval, struct CCcontract_info *cpTokens, const CTransaction &tx, int32_t v, uint256 assetid) +{ + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCASSETS_OPDROP_VALIDATE_FIX)) + return AssetsValidateTokenId(eval, cpTokens, tx, v, assetid); + else + return true; +} + template CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, uint256 tokenid, const CTransaction &tx) { @@ -315,7 +324,7 @@ CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, uin { if (eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock)) { - if (AssetsValidateTokenId(eval, cpTokens, vinTx, tx.vin[i].prevout.n, tokenid)) { + if (AssetsValidateTokenId_Activated(eval, cpTokens, vinTx, tx.vin[i].prevout.n, tokenid)) { //std::cerr << __func__ << " adding amount=" << vinTx.vout[tx.vin[i].prevout.n].nValue << " for vin i=" << i << " eval=" << std::hex << (int)cp->evalcode << std::resetiosflags(std::ios::hex) << std::endl; inputs += vinTx.vout[tx.vin[i].prevout.n].nValue; } diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 0899a6e40f5..a2ef0ddc24a 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -18,6 +18,7 @@ #include "CCtokens_impl.h" #include "CCassetsCore_impl.h" #include "CCTokelData.h" +#include "CCupgrades.h" const int32_t CCVOUT = 1; const int32_t NORMALVOUT = 0; @@ -389,7 +390,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const else tokenRemainderVout = 3+r; // no marker - if (!AssetsValidateTokenId(eval, cp, tx, myTokenVout, assetid)) + if (!AssetsValidateTokenId_Activated(eval, cp, tx, myTokenVout, assetid)) return eval->Invalid("invalid tokenid in vout for tokenfillbid"); if (tx.vout.size() > tokenRemainderVout && tx.vout[tokenRemainderVout].scriptPubKey.IsPayToCryptoCondition()) // if tokens remainder exists { @@ -454,7 +455,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("too few vouts"); else if (A::ConstrainVout(tx.vout[0], CCVOUT, tokensDualEvalUnspendableCCaddr, 0LL, T::EvalCode()) == false) // tokens sent to global addr return eval->Invalid("invalid vout0 global two eval address for sell"); - else if (!AssetsValidateTokenId(eval, cp, tx, 0, assetid)) + else if (!AssetsValidateTokenId_Activated(eval, cp, tx, 0, assetid)) return eval->Invalid("invalid tokenid in output for tokenask"); else if( A::ConstrainVout(tx.vout[1], CCVOUT, markerCCaddress, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false ) // marker to originator asset cc addr return eval->Invalid("invalid vout1 marker for originator pubkey"); @@ -492,7 +493,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (A::ConstrainVout(tx.vout[0], CCVOUT, origTokensCCaddr, vin_tokens, T::EvalCode()) == false) // tokens returning to originator cc addr return eval->Invalid("invalid vout0 for cancelask"); - else if (!AssetsValidateTokenId(eval, cp, tx, 0, assetid)) + else if (!AssetsValidateTokenId_Activated(eval, cp, tx, 0, assetid)) return eval->Invalid("invalid tokenid in vout0 for cancelask"); // get first ccvin: @@ -552,11 +553,11 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const CAmount paid_value = r > 0 ? tx.vout[2].nValue + tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner if (!ValidateAskRemainder(unit_price, tx.vout[0].nValue, vin_tokens, tx.vout[1].nValue, paid_value)) return eval->Invalid("mismatched vout0 remainder for fillask"); - else if (!AssetsValidateTokenId(eval, cp, tx, 0, assetid)) + else if (!AssetsValidateTokenId_Activated(eval, cp, tx, 0, assetid)) return eval->Invalid("invalid tokenid in vout0 for fillask"); else if (!A::ConstrainVout(tx.vout[1], CCVOUT, NULL, 0LL, T::EvalCode())) // do not check tokens buyer's 'self' cc addr return eval->Invalid("vout1 should be cc for fillask"); - else if (!AssetsValidateTokenId(eval, cp, tx, 1, assetid)) + else if (!AssetsValidateTokenId_Activated(eval, cp, tx, 1, assetid)) return eval->Invalid("invalid tokenid in vout1 for fillask"); else if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, origNormalAddr, 0LL, 0)) // coins to originator normal addr return eval->Invalid("vout2 should be cc for fillask"); diff --git a/src/komodo_utils.h b/src/komodo_utils.h index b560e83e169..5eef416bbd7 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -18,6 +18,8 @@ #include "komodo_defs.h" #include "cc/CCinclude.h" #include "importcoin.h" +#include "cc/CCupgrades.h" + #include #ifdef _WIN32 @@ -2436,6 +2438,10 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); KOMODO_DPOWCONFS = GetArg("-dpowconfs",dpowconfs); if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"SUPERNET") == 0 || strcmp(ASSETCHAINS_SYMBOL,"DEX") == 0 || strcmp(ASSETCHAINS_SYMBOL,"COQUI") == 0 || strcmp(ASSETCHAINS_SYMBOL,"PIRATE") == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDICE") == 0 ) KOMODO_EXTRASATOSHI = 1; + + if (ASSETCHAINS_CC != 0) + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); + } void komodo_nameset(char *symbol,char *dest,char *source) From 2dadc28cf6ff4e5e8ff0e1efa978cf9af47c9065 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 26 Nov 2021 00:11:43 +0500 Subject: [PATCH 192/348] tests for assets rules height activation --- src/test-komodo-cc/test-assets.cpp | 155 +++++++++++++++++++++++------ 1 file changed, 127 insertions(+), 28 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 8d2d638f32d..1930187fe56 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -3,6 +3,7 @@ #include #include "cc/CCinclude.h" +#include "cc/CCupgrades.h" #include "cc/CCtokens.h" #include "cc/CCtokens_impl.h" @@ -443,11 +444,7 @@ class TestAssetsCC : public ::testing::Test { txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 222); eval.AddTx(txbid1); bidid1 = txbid1.GetHash(); - - - //txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2, 222); // test dust - } static CTransaction MakeNormalTx(CPubKey mypk, CAmount val) @@ -491,7 +488,6 @@ class TestAssetsCC : public ::testing::Test { return mtx; } - static CMutableTransaction MakeTokenV2AskTx(struct CCcontract_info *cpTokens, CPubKey mypk, uint256 tokenid, CAmount numtokens, CAmount unit_price, int32_t expiryHeight) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); @@ -979,6 +975,13 @@ class TestAssetsCC : public ::testing::Test { return mtx; } + virtual void TearDown() + { + // clean up + strcpy(ASSETCHAINS_SYMBOL, ""); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); // select default + } + }; @@ -1096,7 +1099,12 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) } { // test: different tokenid in opdrop - CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, mypk, tokenid1, numtokens, 501, 222); // price more than dust + eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); + + CAmount unit_price = 501; + CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, mypk, tokenid1, numtokens, unit_price, 222); // price more than dust ASSERT_FALSE(CTransaction(mtx).IsNull()); CScript opret = TokensV2::EncodeTokenOpRet(tokenid1, { unspendableAssetsPubkey }, {}); @@ -1168,7 +1176,6 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) EXPECT_TRUE(TestRunCCEval(mtx)); } - CTransaction txask1; CTransaction txbid1; CTransaction txask2; @@ -1298,6 +1305,13 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) { for (CAmount fillUnits : { 1, 2 }) { // fill partially and totally // test: fillask with different tokenid in opdrop + eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + //eval.SetCurrentHeight(1); + + strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); + //strcpy(ASSETCHAINS_SYMBOL, "MYCHAIN_8173645"); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); + vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; @@ -1312,14 +1326,14 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) CAmount txfee = 10000; CAmount otherAmount = TestAddTokenInputs(mtx2, pk2, tokenid3, mtx2.vout[0].nValue); //add tokenid3 ASSERT_TRUE(otherAmount > 0); - mtx2.vout.insert(mtx2.vout.begin() + mtx2.vout.size() - 1, mtx2.vout[0]); // copy vout with tokens with assetidOpret back - - CScript opret = TokensV2::EncodeTokenOpRet(tokenid3, { unspendableAssetsPubkey }, {}); // put tokenid3 in opdrop while assetid = tokenid2 - vscript_t vopret; - GetOpReturnData(opret, vopret); - std::vector vData { vopret }; - mtx2.vout[0] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[0].nValue, unspendableAssetsPubkey, &vData); // replace remainder with tokenid3 + { + CScript opret = TokensV2::EncodeTokenOpRet(tokenid3, { unspendableAssetsPubkey }, {}); // put tokenid3 in opdrop while assetid = tokenid2 + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx2.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), mtx2.vout[0].nValue, unspendableAssetsPubkey, &vData); // replace remainder with tokenid3 + } if (otherAmount > mtx2.vout[0].nValue) { // if tokenid3 change exists CScript opret = TokensV2::EncodeTokenOpRet(tokenid3, { pk2 }, {}); @@ -1343,6 +1357,81 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid3 in opdrop } } + + { + // test: make different tokenid in opdrop in ask and try fillask it + eval.SetCurrentHeight(111); //set height + //eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); + + CAmount numtokens = 2LL; + CPubKey mypk = pk1; + uint256 mytokenid = tokenid1; + CAmount unit_price = 501; + int32_t expiryHeight = CCASSETS_OPDROP_FIX_TOKEL_HEIGHT+222; + + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, mypk, tokenid1, numtokens, unit_price, expiryHeight); // price more than dust + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + { + CScript opret = TokensV2::EncodeTokenOpRet(tokenid1, { unspendableAssetsPubkey }, {}); + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), mtx.vout[0].nValue, unspendableAssetsPubkey, &vData); + } + { + CScript opretCh = TokensV2::EncodeTokenOpRet(tokenid1, { mypk }, {}); + vscript_t vopretCh; + GetOpReturnData(opretCh, vopretCh); + std::vector vDataCh { vopretCh }; + mtx.vout[2] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx.vout[2].nValue, mypk, &vDataCh); // cc change + } + + mtx.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx, cpTokens, testKeys[mypk], 10000, + TokensV2::EncodeTokenOpRet(tokenid2, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))); + std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop, adding.." << std::endl; + EXPECT_TRUE(TestRunCCEval(mtx)); // work for tokel before CCASSETS_OPDROP_FIX_TOKEL_HEIGHT + eval.AddTx(mtx); + uint256 askid = mtx.GetHash(); + + // add fill ask + eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); // after fix activation + + CAmount fillUnits = 1; + CAmount txfee = 10000; + CMutableTransaction mtx2 = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid2, askid, fillUnits, unit_price, data); + { + CScript opret = TokensV2::EncodeTokenOpRet(tokenid1, { unspendableAssetsPubkey }, {}); // put tokenid1 in opdrop while assetid = tokenid2 + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx2.vout[0] = TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), mtx2.vout[0].nValue, unspendableAssetsPubkey, &vData); // replace remainder with tokenid3 + } + { + CScript opret = TokensV2::EncodeTokenOpRet(tokenid1, { pk2 }, {}); + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx2.vout[1] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[1].nValue, pk2, &vData); // purchased tokens + } + + mtx2.vout.pop_back(); // remove opret to replace it in TestFinalizeTx + CCwrapper wrCond1(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), pk2)); // spend my tokens to fill buy + CCAddVintxCond(cpAssets, wrCond1, NULL); //NULL indicates to use myprivkey + + ASSERT_TRUE(TestFinalizeTx(mtx2, cpAssets, testKeys[pk2], 10000, + TokensV2::EncodeTokenOpRet(tokenid2, { pk2 }, + { AssetsV2::EncodeAssetOpRet('S', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))); + + std::cerr << __func__ << " test: tokenfillask with different tokenid in opdrop, fillUnuts=" << fillUnits << std::endl; + EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must work before TOKEL activation height + } } @@ -1454,6 +1543,11 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) } { // test: fillbid with different tokenid in opdrop + //eval.SetCurrentHeight(111); + eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); + vuint8_t origpubkey; CAmount unit_price; uint256 assetidOpret; @@ -1464,18 +1558,20 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) CAmount txfee = 10000; mtx2.vin[1] = CTxIn(tokenid3, 1, CScript()); // spend other tokenid3 - - CScript opret = TokensV2::EncodeTokenOpRet(tokenid3, { origpubkey }, {}); //send to tokenid3 when assetidOpret = tokenid2 - vscript_t vopret; - GetOpReturnData(opret, vopret); - std::vector vData { vopret }; - mtx2.vout[2] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[2].nValue, origpubkey, &vData); - - CScript opretCh = TokensV2::EncodeTokenOpRet(tokenid3, { pk2 }, {}); //send to tokenid3 when assetidOpret = tokenid2 - vscript_t vopretCh; - GetOpReturnData(opretCh, vopretCh); - std::vector vDataCh { vopretCh }; - mtx2.vout[3] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[3].nValue, pk2, &vDataCh); // change + { + CScript opret = TokensV2::EncodeTokenOpRet(tokenid3, { origpubkey }, {}); //send to tokenid3 when assetidOpret = tokenid2 + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx2.vout[2] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[2].nValue, origpubkey, &vData); + } + { + CScript opretCh = TokensV2::EncodeTokenOpRet(tokenid3, { pk2 }, {}); //send to tokenid3 when assetidOpret = tokenid2 + vscript_t vopretCh; + GetOpReturnData(opretCh, vopretCh); + std::vector vDataCh { vopretCh }; + mtx2.vout[3] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[3].nValue, pk2, &vDataCh); // change + } mtx2.vout.pop_back(); // remove opret to replace it in TestFinalizeTx ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk2], txfee, @@ -1484,6 +1580,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) std::cerr << __func__ << " test: tokenfillbid with different tokenid in opdrop" << std::endl; EXPECT_FALSE(assetidOpret == tokenid3); + //EXPECT_TRUE(TestRunCCEval(mtx2)); EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid3 in opdrop } } @@ -1621,6 +1718,10 @@ TEST_F(TestAssetsCC, tokenv2cancelask) EXPECT_FALSE(TestRunCCEval(mtx6)); // must fail } { + eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); + CMutableTransaction mtx7(mtx); CAmount txfee = 10000; @@ -1664,8 +1765,6 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) { CAmount txfee = 10000; eval.SetCurrentHeight(111); //set height - - { struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); From 15f919e912a9d6bf798d944c6c8f232d4d0c3bf3 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 26 Nov 2021 00:12:04 +0500 Subject: [PATCH 193/348] more retires in assets py tests --- src/tui/tui_assets_orders.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 59712866cd5..d61b9c1d28a 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -206,7 +206,7 @@ def call_token_rpc_send_tx(rpc, rpcname, stop_error, *args) : assert False, 'sendrawtransaction no more retries' def call_rpc_retry(rpc, rpcname, stop_error, *args) : - retries = 24 + retries = 36 delay = 10 rpcfunc = getattr(rpc, rpcname) for i in range(retries): From 2ed6bcae3a668f54cdcaa0354d09384d98d6861a Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 26 Nov 2021 12:55:20 +0500 Subject: [PATCH 194/348] extra params deleted from a helper func --- src/cc/CCassets.h | 1 + src/cc/CCassetsCore_impl.h | 31 +++---------------------------- src/cc/CCassetsUtils.cpp | 24 +++++++++++++++++++----- src/cc/assets.cpp | 2 +- 4 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index d0bcfbf8a45..198b5be97c1 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -46,6 +46,7 @@ bool SetBidFillamounts(CAmount unit_price, CAmount &received_nValue, CAmount ori bool SetAskFillamounts(CAmount unit_price, CAmount fill_assetoshis, CAmount orig_assetoshis, CAmount paid_nValue); bool SetSwapFillamounts(CAmount unit_price, CAmount &paid, CAmount orig_nValue, CAmount &received, CAmount totalprice); // not implemented CAmount AssetsGetTxCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx); +CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, const CTransaction &tx); const char ccassets_log[] = "ccassets"; diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index 6010fe5c77f..108f77eefcd 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -103,7 +103,6 @@ CAmount IsAssetvout(struct CCcontract_info *cp, CAmount &remaining_units_out, st template uint8_t GetOrderParams(std::vector &origpubkey_out, CAmount &unit_price, uint256 &assetid, int32_t &expiryHeightOut, const CTransaction &tx) { - uint256 assetid2; uint8_t evalCode, funcid; if (tx.vout.size() > 0 && (funcid = A::DecodeAssetTokenOpRet(tx.vout.back().scriptPubKey, evalCode, assetid, unit_price, origpubkey_out, expiryHeightOut)) != 0) @@ -221,8 +220,8 @@ CAmount AssetValidateCCvin(struct CCcontract_info *cpAssets, Eval* eval, char *o return eval->Invalid("no assets cc vins in previous fillbuy or fillsell tx"), 0LL; } - // check no more other vins spending from global addr: - if (AssetsGetTxCCInputs(eval, cpAssets, unspendableAddr, tx) != vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue) + // check no more other vins spending from global addr (must be only vintx.vout[0]): + if (AssetsGetTxCCInputs(eval, cpAssets, unspendableAddr, tx) != vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue) // gets either cc coins from global or tokens from dual eval global address return eval->Invalid("invalid assets cc vins found"), 0LL; if (vinTx.vout[ASSETS_GLOBALADDR_VOUT].nValue == 0) @@ -278,7 +277,7 @@ CAmount AssetValidateSellvin(struct CCcontract_info *cpAssets, Eval* eval, CAmou if (ccvin == tx.vin.end()) return eval->Invalid("cc vin not found"), 0LL; if ((nValue = AssetValidateCCvin(cpAssets, eval, origCCaddr_out, origaddr_out, expiryHeightOut, tx, ccvin-tx.vin.begin(), vinTxOut)) == 0) - return 0LL; // eval is set already in AssetValidateCCvin + return 0LL; // eval->Invalid is set already in AssetValidateCCvin if ((assetoshis = IsAssetvout(cpAssets, unit_price, origpubkey_out, vinTxOut, ASSETS_GLOBALADDR_VOUT, assetid)) == 0) return eval->Invalid("invalid missing CC vout0 for sellvin"), 0LL; @@ -311,28 +310,4 @@ bool AssetsValidateTokenId_Activated(Eval *eval, struct CCcontract_info *cpToken return true; } -template -CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, uint256 tokenid, const CTransaction &tx) -{ - CTransaction vinTx; - uint256 hashBlock; - CAmount inputs = 0LL; - - for (int32_t i = 0; i < tx.vin.size(); i++) - { - if (cpTokens->ismyvin(tx.vin[i].scriptSig)) - { - if (eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock)) - { - if (AssetsValidateTokenId_Activated(eval, cpTokens, vinTx, tx.vin[i].prevout.n, tokenid)) { - //std::cerr << __func__ << " adding amount=" << vinTx.vout[tx.vin[i].prevout.n].nValue << " for vin i=" << i << " eval=" << std::hex << (int)cp->evalcode << std::resetiosflags(std::ios::hex) << std::endl; - inputs += vinTx.vout[tx.vin[i].prevout.n].nValue; - } - } - } - } - return inputs; -} - - #endif // #ifndef CC_ASSETS_CORE_IMPL_H diff --git a/src/cc/CCassetsUtils.cpp b/src/cc/CCassetsUtils.cpp index ebcd762e361..38037932849 100644 --- a/src/cc/CCassetsUtils.cpp +++ b/src/cc/CCassetsUtils.cpp @@ -457,16 +457,13 @@ bool ValidateSwapRemainder(int64_t remaining_price, int64_t remaining_nValue, in return(true); } -// get tx's vin inputs for cp->evalcode and addr. If addr is null then all inputs are added +// get tx's vin inputs for cp->evalcode and addr CAmount AssetsGetTxCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx) { CTransaction vinTx; uint256 hashBlock; CAmount inputs = 0LL; - //struct CCcontract_info *cpTokens, C; - //cpTokens = CCinit(&C, EVAL_TOKENS); - for (int32_t i = 0; i < tx.vin.size(); i++) { if (cp->ismyvin(tx.vin[i].scriptSig)) @@ -475,7 +472,6 @@ CAmount AssetsGetTxCCInputs(Eval *eval, struct CCcontract_info *cp, const char * { char scriptaddr[KOMODO_ADDRESS_BUFSIZE]; if (Getscriptaddress(scriptaddr, vinTx.vout[tx.vin[i].prevout.n].scriptPubKey) && strcmp(scriptaddr, addr) == 0) { - //std::cerr << __func__ << " adding amount=" << vinTx.vout[tx.vin[i].prevout.n].nValue << " for vin i=" << i << " eval=" << std::hex << (int)cp->evalcode << std::resetiosflags(std::ios::hex) << std::endl; inputs += vinTx.vout[tx.vin[i].prevout.n].nValue; } } @@ -484,3 +480,21 @@ CAmount AssetsGetTxCCInputs(Eval *eval, struct CCcontract_info *cp, const char * return inputs; } +CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, const CTransaction &tx) +{ + CTransaction vinTx; + uint256 hashBlock; + CAmount inputs = 0LL; + + for (int32_t i = 0; i < tx.vin.size(); i++) + { + if (cpTokens->ismyvin(tx.vin[i].scriptSig)) + { + if (eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock)) + { + inputs += vinTx.vout[tx.vin[i].prevout.n].nValue; + } + } + } + return inputs; +} \ No newline at end of file diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index a2ef0ddc24a..00dc8c22973 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -381,7 +381,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("vout0 should be originator normal address with remainder for fillbid"); } - vin_tokens = AssetsGetTxTokenInputs(eval, cpTokens, assetid, tx); + vin_tokens = AssetsGetTxTokenInputs(eval, cpTokens, tx); int32_t myNormalVout = 1; int32_t myTokenVout = 2+r; int32_t tokenRemainderVout; From 6e29083f4b2beae21a61a77c759344a807247e6a Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 26 Nov 2021 12:55:59 +0500 Subject: [PATCH 195/348] removed extra prints in cc test --- src/test-komodo-cc/test-assets.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 1930187fe56..af9e4ec53b7 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -267,15 +267,15 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ if (strcmp(destaddr, globaladdr) == 0) { privkey = cp->CCpriv; cond.reset(MakeCCcond1(cp->evalcode, globalpk)); - std::cerr << __func__ << " vini." << i << " found globaladdress=" << globaladdr << " destaddr=" << destaddr << " strlen=" << strlen(globaladdr) << " evalcode=" << (int)cp->evalcode << std::endl; + //std::cerr << __func__ << " vini." << i << " found globaladdress=" << globaladdr << " destaddr=" << destaddr << " strlen=" << strlen(globaladdr) << " evalcode=" << (int)cp->evalcode << std::endl; } else if (strcmp(destaddr, myccaddr) == 0) { privkey = myprivkey; cond.reset(MakeCCcond1(cp->evalcode, mypk)); - std::cerr << __func__ << " vini." << i << " found myccaddr=" << myccaddr << std::endl; + //std::cerr << __func__ << " vini." << i << " found myccaddr=" << myccaddr << std::endl; } else if (strcmp(destaddr, mytokenaddr) == 0) { privkey = myprivkey; cond.reset(MakeTokensv2CCcond1(cp->evalcode, mypk)); - std::cerr << __func__ << " vini." << i << " found mytokenaddr=" << mytokenaddr << " evalcode=" << (int)cp->evalcode << std::endl; + //std::cerr << __func__ << " vini." << i << " found mytokenaddr=" << mytokenaddr << " evalcode=" << (int)cp->evalcode << std::endl; } else { const uint8_t nullpriv[32] = {'\0'}; // use vector of dest addresses and conds to probe vintxconds @@ -286,7 +286,7 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ CCtoAnon(anonCond.get()); Getscriptaddress(coinaddr, CCPubKey(anonCond.get(), true)); if (strcmp(destaddr, coinaddr) == 0) { - std::cerr << __func__ << " vini." << i << " found vintxprobe=" << coinaddr << " privkey=" << (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) << std::endl; + //std::cerr << __func__ << " vini." << i << " found vintxprobe=" << coinaddr << " privkey=" << (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) << std::endl; if (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) privkey = t.CCpriv; else @@ -369,7 +369,7 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " cc_verify error D" << std::endl; return false; } - std::cerr << __func__ << " cc_verify okay for vin.hash=" << vin.prevout.hash.GetHex() << std::endl; + //std::cerr << __func__ << " cc_verify okay for vin.hash=" << vin.prevout.hash.GetHex() << std::endl; break; } } @@ -383,7 +383,7 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " CheckCryptoCondition error=" << ScriptErrorString(error) << " eval=" << eval.state.GetRejectReason() << std::endl; return false; } - std::cerr << __func__ << " cc_verify okay for vout.nValue=" << vout.nValue << std::endl; + //std::cerr << __func__ << " cc_verify okay for vout.nValue=" << vout.nValue << std::endl; } } return true; @@ -535,7 +535,7 @@ class TestAssetsCC : public ::testing::Test { if(!TestFinalizeTx(mtx, cpTokens, testKeys[mypk], txfee, TokensV2::EncodeTokenOpRet(tokenid, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))) { - std::cerr << __func__ << " cant finalise tx" << std::endl; + std::cerr << __func__ << " cant finalize tx" << std::endl; return CTransaction(); } return mtx; @@ -565,7 +565,7 @@ class TestAssetsCC : public ::testing::Test { if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, TokensV2::EncodeTokenOpRet(tokenid, {}, { AssetsV2::EncodeAssetOpRet('b', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))) { - std::cerr << __func__ << " cant finalise tx" << std::endl; + std::cerr << __func__ << " cant finalize tx" << std::endl; return CTransaction(); } return mtx; @@ -650,7 +650,7 @@ class TestAssetsCC : public ::testing::Test { if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, TokensV2::EncodeTokenOpRet(tokenid, { mypk }, { AssetsV2::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) } ))) { - std::cerr << __func__ << " cant finalise tx" << std::endl; + std::cerr << __func__ << " cant finalize tx" << std::endl; return CTransaction(); } data.pushKV("ownerpubkey", HexStr(ownerpubkey)); @@ -733,7 +733,7 @@ class TestAssetsCC : public ::testing::Test { } vuint8_t ownerpubkey = std::get<0>(tokenData); - std::cerr << __func__ << " bidtx=" << bidtx.GetHash().GetHex() << " " << HexStr(E_MARSHAL(ss << bidtx)) << " vouts=" << bidtx.vout.size() << std::endl; + //std::cerr << __func__ << " bidtx=" << bidtx.GetHash().GetHex() << " " << HexStr(E_MARSHAL(ss << bidtx)) << " vouts=" << bidtx.vout.size() << std::endl; CAmount bid_amount = bidtx.vout[bidvout].nValue; vuint8_t origpubkey; @@ -1354,7 +1354,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) std::cerr << __func__ << " test: tokenfillask with different tokenid in opdrop, fillUnuts=" << fillUnits << std::endl; EXPECT_FALSE(assetidOpret == tokenid3); - EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid3 in opdrop + EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid in opdrop } } From 2ddd6d26a76c0d4d14b60914912aa3f2253bb2a5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 26 Nov 2021 13:01:58 +0500 Subject: [PATCH 196/348] CCupgrades src added --- src/cc/CCupgrades.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++ src/cc/CCupgrades.h | 59 +++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 src/cc/CCupgrades.cpp create mode 100644 src/cc/CCupgrades.h diff --git a/src/cc/CCupgrades.cpp b/src/cc/CCupgrades.cpp new file mode 100644 index 00000000000..e230edd9226 --- /dev/null +++ b/src/cc/CCupgrades.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * Copyright © 2021 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. * + * * + ******************************************************************************/ + +#include +#include "CCupgrades.h" + +namespace CCUpgrades { + + class CUpgradesContainer { + public: + CUpgradesContainer() { + + // default upgrades: always enable all fixes + defaultUpgrades.IsAllEnabled = true; + + // TOKEL + ChainUpgrades tokel; + tokel.setActivationHeight(CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TOKEL_HEIGHT, UPGRADE_ACTIVE); + mChainUpgrades["TOKEL"] = tokel; + + // TKLTEST + ChainUpgrades tkltest; + tkltest.setActivationHeight(CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT, UPGRADE_ACTIVE); + mChainUpgrades["TKLTEST"] = tokel; + + // add more chains here... + // ... + } + + public: + std::map mChainUpgrades; + ChainUpgrades defaultUpgrades; + } ccChainsUpgrades; + + static const ChainUpgrades *pSelectedUpgrades = &ccChainsUpgrades.defaultUpgrades; + + // return ref to chain upgrades list by chain name: + void SelectUpgrades(const std::string &chainName) { + std::map::const_iterator it = ccChainsUpgrades.mChainUpgrades.find(chainName); + if (it != ccChainsUpgrades.mChainUpgrades.end()) { + pSelectedUpgrades = &it->second; + } + else { + pSelectedUpgrades = &ccChainsUpgrades.defaultUpgrades; + } + } + + const ChainUpgrades &GetUpgrades() + { + return *pSelectedUpgrades; + } + + + bool IsUpgradeActive(int32_t nHeight, const ChainUpgrades &chainUpgrades, UPGRADE_ID id) { + if (chainUpgrades.IsAllEnabled) + return true; + else { + std::map::const_iterator it = chainUpgrades.mUpgrades.find(id); + if (it != chainUpgrades.mUpgrades.end()) + return nHeight >= it->second.nActivationHeight ? it->second.status == UPGRADE_ACTIVE : false; + return false; + } + } + +}; // namespace CCUpgrades diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h new file mode 100644 index 00000000000..789450b3834 --- /dev/null +++ b/src/cc/CCupgrades.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Copyright © 2014-2021 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. * + * * + ******************************************************************************/ + +#ifndef CC_UPGRADES_H +#define CC_UPGRADES_H + +#include +#include +#include +#include + +const int32_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 100000; +const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 100000; + +namespace CCUpgrades { + + enum UPGRADE_STATUS { + UPGRADE_ACTIVE = 1, + }; + + enum UPGRADE_ID { + CCASSETS_OPDROP_VALIDATE_FIX = 0x01, + }; + + struct UpgradeInfo { + int32_t nActivationHeight; + UPGRADE_STATUS status; + }; + + class ChainUpgrades { + public: + ChainUpgrades() : IsAllEnabled(false) { } + void setActivationHeight(UPGRADE_ID upgId, int32_t nHeight, UPGRADE_STATUS upgStatus) { + mUpgrades[upgId] = { nHeight, upgStatus }; + } + public: + std::map mUpgrades; + bool IsAllEnabled; + }; + + void SelectUpgrades(const std::string &chainName); + const ChainUpgrades &GetUpgrades(); + bool IsUpgradeActive(int32_t nHeight, const ChainUpgrades &chainUpgrades, UPGRADE_ID upgId); +}; // namespace CCUpgrades + +#endif // #ifndef CC_UPGRADES_H + From 83c6c791d5df3741e3c790b27d3a2510f18b3660 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 26 Nov 2021 13:17:09 +0500 Subject: [PATCH 197/348] upgrade heights set --- src/cc/CCupgrades.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index 789450b3834..b327c2e925f 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -21,8 +21,8 @@ #include #include -const int32_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 100000; -const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 100000; +const int32_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 243159; // 26 Nov + 60 days +const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 158961; // 26 Nov + 14 days namespace CCUpgrades { From e418f6af942df95e594244224f41520d53071200 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 11 Dec 2021 12:30:00 +0500 Subject: [PATCH 198/348] fix tkltest hf height var (does not change the actual height) --- src/cc/CCupgrades.cpp | 5 ++--- src/cc/CCupgrades.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cc/CCupgrades.cpp b/src/cc/CCupgrades.cpp index e230edd9226..11203680b05 100644 --- a/src/cc/CCupgrades.cpp +++ b/src/cc/CCupgrades.cpp @@ -31,9 +31,8 @@ namespace CCUpgrades { mChainUpgrades["TOKEL"] = tokel; // TKLTEST - ChainUpgrades tkltest; - tkltest.setActivationHeight(CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT, UPGRADE_ACTIVE); - mChainUpgrades["TKLTEST"] = tokel; + ChainUpgrades tkltest = tokel; + mChainUpgrades["TKLTEST"] = tkltest; // add more chains here... // ... diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index b327c2e925f..9d886a5af26 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -22,7 +22,7 @@ #include const int32_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 243159; // 26 Nov + 60 days -const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 158961; // 26 Nov + 14 days +//const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 158961; // 26 Nov + 14 days namespace CCUpgrades { From bee65bf34366993f241416a846832152f3764fa5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 14 Dec 2021 12:26:46 +0500 Subject: [PATCH 199/348] not checking -pubkey for certain token rpcs when called over nspv --- src/cc/CCinclude.h | 2 +- src/rpc/crosschain.cpp | 2 +- src/rpc/tokensrpc.cpp | 39 +++++++++++++++++++++------------------ src/wallet/rpcwallet.cpp | 4 ++-- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index f2ee24e4d32..c35050afd60 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -1075,7 +1075,7 @@ void AddSigData2UniValue(UniValue &result, int32_t vini, UniValue& ccjson, std:: /// returns 0 if requirements for cc module with the evalcode is fulfilled. /// @param evalcode eval code for cc module /// @returns 0 if okay or -1 -int32_t ensure_CCrequirements(uint8_t evalcode); +int32_t ensure_CCrequirements(uint8_t evalcode, bool isRemote = false); /// returns true if tx is in active chain /// @param txid txid of tx to check diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index a84be01229c..56fe421c0c5 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -49,7 +49,7 @@ using namespace std; extern std::string ASSETCHAINS_SELFIMPORT; extern uint16_t ASSETCHAINS_CODAPORT, ASSETCHAINS_BEAMPORT; -int32_t ensure_CCrequirements(uint8_t evalcode); +//int32_t ensure_CCrequirements(uint8_t evalcode); bool EnsureWalletIsAvailable(bool avoidException); diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 55884624f4f..4c1382b9311 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -110,7 +110,7 @@ UniValue tokenlist(const UniValue& params, bool fHelp, const CPubKey& remotepk) if (fHelp || params.size() > 0) throw runtime_error("tokenlist\n"); - if (ensure_CCrequirements(EVAL_TOKENS) < 0) + if (ensure_CCrequirements(EVAL_TOKENS, remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); return TokenList(); @@ -127,7 +127,7 @@ UniValue tokenv2list(const UniValue& params, bool fHelp, const CPubKey& remotepk " \"pubkey\" - search tokens created by a specific pubkey\n" " \"address\" - search created on a specific cc address\n"); - if (ensure_CCrequirements(EVAL_TOKENSV2) < 0) + if (ensure_CCrequirements(EVAL_TOKENSV2, remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); UniValue jsonParams; @@ -173,7 +173,7 @@ static UniValue tokeninfotokel(const std::string& name, const UniValue& params, { if (fHelp || params.size() != 1) throw runtime_error(name + " tokenid\n"); - if (ensure_CCrequirements(V::EvalCode()) < 0) + if (ensure_CCrequirements(V::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str()); return TokenInfo(tokenid, ParseTokelVData); @@ -189,7 +189,7 @@ UniValue tokenv2infotokel(const UniValue& params, bool fHelp, const CPubKey& rem } template -UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& mypk) +UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) { uint256 tokenid; const CPubKey emptypk; @@ -198,7 +198,7 @@ UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp throw runtime_error(name + " [tokenid|'*']\n" "returns tokens orders for the tokenid or all available token orders if tokenid is not set\n" "\n"); - if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) + if (ensure_CCrequirements(A::EvalCode(), remotepk.IsValid()) < 0 || ensure_CCrequirements(T::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (params.size() >= 1) { @@ -229,7 +229,7 @@ UniValue mytokenorders(const std::string& name, const UniValue& params, bool fHe "returns all tokens orders for mypubkey\n" // no additional evalcode for mytokenorders - it will return all orders for on mypk: /*"if evalcode is set then returns mypubkey's token orders for non-fungible tokens with this evalcode\n"*/ "\n"); - if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) + if (ensure_CCrequirements(A::EvalCode(), remotepk.IsValid()) < 0 || ensure_CCrequirements(T::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); @@ -255,7 +255,7 @@ static UniValue tokenbalance(const std::string& name, const UniValue& params, bo if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error(name + " tokenid [pubkey]\n"); - if (ensure_CCrequirements(V::EvalCode()) < 0) + if (ensure_CCrequirements(V::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); // LOCK(cs_main); @@ -304,7 +304,7 @@ static UniValue tokenallbalances(const std::string& name, const UniValue& params { if (fHelp || params.size() > 1) throw runtime_error(name + " [pubkey]\n"); - if (ensure_CCrequirements(V::EvalCode()) < 0) + if (ensure_CCrequirements(V::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); // LOCK(cs_main); @@ -345,7 +345,7 @@ static UniValue tokencreate(const UniValue& params, const vuint8_t &vtokenData, //if (fHelp || params.size() > 4 || params.size() < 2) // throw runtime_error(fname + " name supply [description] [tokens data]\n"); - if (ensure_CCrequirements(V::EvalCode()) < 0) + if (ensure_CCrequirements(V::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) @@ -505,7 +505,7 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b "amount - token amount to send in satoshi, int64\n" "Note, that MofN supported only for tokens v2\n\n"); - if (ensure_CCrequirements(V::EvalCode()) < 0) + if (ensure_CCrequirements(V::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) @@ -623,7 +623,7 @@ UniValue tokentransfermany(const std::string& name, const UniValue& params, bool if (fHelp || params.size() < 3) throw runtime_error(name + " tokenid1 tokenid2 ... destpubkey amount \n"); - if (ensure_CCrequirements(V::EvalCode()) < 0) + if (ensure_CCrequirements(V::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); std::vector tokenids; @@ -740,7 +740,7 @@ UniValue tokenbid(const std::string& name, const UniValue& params, bool fHelp, c CCerror.clear(); if (fHelp || params.size() < 3 || params.size() > 4) throw runtime_error(name + " numtokens tokenid price [expiry-height]\n"); - if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) + if (ensure_CCrequirements(A::EvalCode(), remotepk.IsValid()) < 0 || ensure_CCrequirements(T::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) @@ -794,7 +794,7 @@ UniValue tokencancelbid(const std::string& name, const UniValue& params, bool fH if (fHelp || params.size() != 2) throw runtime_error(name + " tokenid bidtxid\n"); - if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) + if (ensure_CCrequirements(A::EvalCode(), remotepk.IsValid()) < 0 || ensure_CCrequirements(T::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) @@ -834,7 +834,7 @@ UniValue tokenfillbid(const std::string& name, const UniValue& params, bool fHel if (fHelp || params.size() != 3 && params.size() != 4) throw runtime_error(name + " tokenid bidtxid fillamount [unit_price]\n"); - if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) + if (ensure_CCrequirements(A::EvalCode(), remotepk.IsValid()) < 0 || ensure_CCrequirements(T::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) @@ -881,7 +881,7 @@ UniValue tokenask(const std::string& name, const UniValue& params, bool fHelp, c CCerror.clear(); if (fHelp || params.size() < 3 || params.size() > 4) throw runtime_error(name + " numtokens tokenid price [expiry-height]\n"); - if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) + if (ensure_CCrequirements(A::EvalCode(), remotepk.IsValid()) < 0 || ensure_CCrequirements(T::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) @@ -937,7 +937,7 @@ UniValue tokenswapask(const UniValue& params, bool fHelp, const CPubKey& remotep CCerror.clear(); if (fHelp || params.size() != 4) throw runtime_error("tokenswapask numtokens tokenid otherid price\n"); - if (ensure_CCrequirements(EVAL_ASSETS) < 0) + if (ensure_CCrequirements(EVAL_ASSETS, remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!EnsureWalletIsAvailable(false)) @@ -1014,7 +1014,7 @@ UniValue tokenfillask(const std::string& name, const UniValue& params, bool fHel if (fHelp || params.size() != 3 && params.size() != 4) throw runtime_error(name + " tokenid asktxid fillunits [unitprice]\n"); - if (ensure_CCrequirements(A::EvalCode()) < 0 || ensure_CCrequirements(T::EvalCode()) < 0) + if (ensure_CCrequirements(A::EvalCode(), remotepk.IsValid()) < 0 || ensure_CCrequirements(T::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) @@ -1058,7 +1058,7 @@ UniValue tokenfillswap(const UniValue& params, bool fHelp, const CPubKey& remote CCerror.clear(); if (fHelp || params.size() != 4 && params.size() != 5) throw runtime_error("tokenfillswap tokenid otherid asktxid fillunits [unitprice]\n"); - if (!remotepk.IsValid() && ensure_CCrequirements(EVAL_ASSETS) < 0) + if (ensure_CCrequirements(EVAL_ASSETS, remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!EnsureWalletIsAvailable(false)) @@ -1130,6 +1130,9 @@ UniValue tokenv2addccinputs(const UniValue& params, bool fHelp, const CPubKey& r throw runtime_error(msg); } + if (ensure_CCrequirements(EVAL_TOKENSV2, remotepk.IsValid()) < 0) + throw runtime_error(CC_REQUIREMENTS_MSG); + uint256 tokenid = Parseuint256(params[0].get_str().c_str()); CPubKey pk = pubkey2pk( ParseHex(params[1].get_str().c_str()) ); CAmount amount = atoll(params[2].get_str().c_str()); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5cd1a5227be..d80b83dcdc0 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5609,7 +5609,7 @@ int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits } -int32_t ensure_CCrequirements(uint8_t evalcode) +int32_t ensure_CCrequirements(uint8_t evalcode, bool isRemote) { CCerror.clear(); if (ASSETCHAINS_CCDISABLES[evalcode] != 0) { @@ -5620,7 +5620,7 @@ int32_t ensure_CCrequirements(uint8_t evalcode) return (-1); } } - if (NOTARY_PUBKEY33[0] == 0) { + if (!isRemote && NOTARY_PUBKEY33[0] == 0) { // do not check local pubkey set for nspv calls fprintf(stderr, "no -pubkey set\n"); return (-1); } else if (GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX) == 0) { From 14cffc37b79dd765ad1dd2e2765d2ecfe8bd12d7 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 20 Dec 2021 13:45:15 +0500 Subject: [PATCH 200/348] added test for incorrect tokens/assets eval threshold --- src/test-komodo-cc/test-assets.cpp | 58 ++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index af9e4ec53b7..c8422ca202f 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -317,6 +317,49 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ return true; } +// make three-eval (token+evalcode+evalcode2) 1of2 pk M-1 eval fake cryptocondition: +CC *TestMakeTokensv2CCcondMofN(uint8_t evalcode1, uint8_t evalcode2, uint8_t M, std::vector pks) +{ + // make 1of2 sigs cond + std::vector condpks; + for (auto const &pk : pks) + condpks.push_back(CCNewSecp256k1(pk)); + + std::vector thresholds; + if (evalcode1 != 0) + thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode1))); + if (evalcode1 != EVAL_TOKENSV2) // if evalCode == EVAL_TOKENSV2, it is actually MakeCCcond1of2()! + thresholds.push_back(CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENSV2))); // this is eval token cc + if (evalcode2 != 0) + thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode2))); // add optional additional evalcode + + thresholds.push_back(CCNewThreshold(M, condpks)); // this is 1 of 2 sigs cc + + uint8_t t = thresholds.size() > 1 ? thresholds.size() - 1 : thresholds.size(); + + return CCNewThreshold(t, thresholds); +} + +// make three-eval (token+evalcode+evalcode2) MofN cc vout: +CTxOut TestMakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, uint8_t M, const std::vector &pks, vscript_t* pvData) +{ + CTxOut vout; + CCwrapper payoutCond( TestMakeTokensv2CCcondMofN(evalcode1, evalcode2, M, pks) ); + if (!CCtoAnon(payoutCond.get())) + return vout; + + vout = CTxOut(nValue, CCPubKey(payoutCond.get(),true)); + + { + std::vector vvData; + if (pvData) + vvData.push_back(*pvData); + + COptCCParams ccp = COptCCParams(COptCCParams::VERSION_2, evalcode1, M, pks.size(), pks, vvData); // ver2 -> add pks + vout.scriptPubKey << ccp.AsVector() << OP_DROP; + } + return vout; +} class TestAssetsCC : public ::testing::Test { @@ -1126,7 +1169,6 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop.." << std::endl; EXPECT_TRUE(!TestRunCCEval(mtx) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // fail: can't ask for different tokenid } - } TEST_F(TestAssetsCC, tokenv2bid_basic) @@ -1395,7 +1437,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) ASSERT_TRUE(TestFinalizeTx(mtx, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(tokenid2, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))); - std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop, adding.." << std::endl; + std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop - should work before HF fix:" << std::endl; EXPECT_TRUE(TestRunCCEval(mtx)); // work for tokel before CCASSETS_OPDROP_FIX_TOKEL_HEIGHT eval.AddTx(mtx); uint256 askid = mtx.GetHash(); @@ -1429,9 +1471,19 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) TokensV2::EncodeTokenOpRet(tokenid2, { pk2 }, { AssetsV2::EncodeAssetOpRet('S', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))); - std::cerr << __func__ << " test: tokenfillask with different tokenid in opdrop, fillUnuts=" << fillUnits << std::endl; + std::cerr << __func__ << " test: tokenfillask with different tokenid in opdrop, fillUnuts=" << fillUnits << " should fail with 'invalid tokenid' error:" << std::endl; EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must work before TOKEL activation height } + { + // test: try to send remainder to 2of3 token/asset eval/secp threshold (must be 3of3) + CMutableTransaction mtx1(mtx); + CScript opret = TokensV2::EncodeTokenOpRet(tokenid1, { unspendableAssetsPubkey }, {}); + vscript_t vopret; + GetOpReturnData(opret, vopret); + mtx1.vout[0] = TestMakeTokensCCMofNvoutMixed(AssetsV2::EvalCode(), TokensV2::EvalCode(), mtx1.vout[0].nValue, 1, { unspendableAssetsPubkey }, &vopret); // replace with 1of2 eval threshold + std::cerr << __func__ << " test: tokenfillask with incorrect eval threshold:" << std::endl; + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid + } } From 1b1a4ded7d2137513387a07effa7a56ec3b371eb Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 2 Jan 2022 14:54:48 +0300 Subject: [PATCH 201/348] tokel assets HF height adjusted + 30 days --- src/cc/CCupgrades.cpp | 3 ++- src/cc/CCupgrades.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cc/CCupgrades.cpp b/src/cc/CCupgrades.cpp index 11203680b05..bad6aa5b0a7 100644 --- a/src/cc/CCupgrades.cpp +++ b/src/cc/CCupgrades.cpp @@ -31,7 +31,8 @@ namespace CCUpgrades { mChainUpgrades["TOKEL"] = tokel; // TKLTEST - ChainUpgrades tkltest = tokel; + ChainUpgrades tkltest; + tkltest.setActivationHeight(CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT, UPGRADE_ACTIVE); mChainUpgrades["TKLTEST"] = tkltest; // add more chains here... diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index 9d886a5af26..4c6dd3770d9 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -21,8 +21,8 @@ #include #include -const int32_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 243159; // 26 Nov + 60 days -//const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 158961; // 26 Nov + 14 days +const int32_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 286359; // 26 Nov + 90 days +const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 243159; // 26 Nov + 60 days namespace CCUpgrades { From ecb9f955e217e2e74b2c9a7b7f31503f14eae302 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 19 Jan 2022 02:06:22 +0500 Subject: [PATCH 202/348] nspv code cleanup --- src/cc/CCutils.cpp | 3 --- src/cc/oracles.cpp | 1 - src/cc/pegs.cpp | 3 ++- src/komodo_nSPV_fullnode.h | 35 +++++------------------------------ src/komodo_nSPV_wallet.h | 1 - src/main.cpp | 8 +------- src/rpc/blockchain.cpp | 6 ------ src/wallet/rpcwallet.cpp | 4 ---- 8 files changed, 8 insertions(+), 53 deletions(-) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 55ec2302222..9a3f55f8972 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -1032,9 +1032,6 @@ bool CClib_Dispatch(const CC* cond, Eval* eval, std::vector paramsNull, return eval->Invalid("cclib CC must have evalcode between 16 and 127"); } -//void OS_randombytes(unsigned char *x,long xlen); -//extern bits256 curve25519_basepoint9(); - int32_t _SuperNET_cipher(uint8_t nonce[crypto_box_NONCEBYTES],uint8_t *cipher,uint8_t *message,int32_t len,bits256 destpub,bits256 srcpriv,uint8_t *buf) { memset(cipher,0,len+crypto_box_ZEROBYTES); diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 194aeced354..18fe528e25f 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -93,7 +93,6 @@ vout.n-1: opreturn with oracletxid, prevbatontxid and data in proper format */ -//extern int32_t komodo_get_current_height(); #define PUBKEY_SPOOFING_FIX_ACTIVATION 1563148800 #define CC_MARKER_VALUE 10000 #define CC_TXFEE 10000 diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 824bad2ce34..118c59a92e4 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -19,6 +19,8 @@ #include "CCPegs.h" #include "../importcoin.h" #include "key_io.h" +#include "komodo_defs.h" + #include @@ -101,7 +103,6 @@ pegs CC is able to create a coin backed (by any supported coin with gateways CC #define CC_MARKER_VALUE 10000 extern uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); -//extern int64_t GetTokenBalance(CPubKey pk, uint256 tokenid); extern int32_t komodo_currentheight(); extern int32_t prices_syntheticvec(std::vector &vec, std::vector synthetic); extern int64_t prices_syntheticprice(std::vector vec, int32_t height, int32_t minmax, int16_t leverage); diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 51c829095fa..72485feeddb 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -72,7 +72,6 @@ int32_t NSPV_notarization_find(struct NSPV_ntz* ntz, int32_t height, int32_t dir symbol = (ASSETCHAINS_SYMBOL[0] == 0) ? (char*)"KMD" : ASSETCHAINS_SYMBOL; memset(ntz, 0, sizeof(*ntz)); - // std::cerr << __func__ << " calling ScanNotarisationsDB for height=" << height << " dir=" << dir << std::endl; if (dir < 0) { if ((ntz->txidheight = ScanNotarisationsDB(height, symbol, 1440, nota)) == 0) return (-1); @@ -80,7 +79,6 @@ int32_t NSPV_notarization_find(struct NSPV_ntz* ntz, int32_t height, int32_t dir if ((ntz->txidheight = ScanNotarisationsDB2(height, symbol, 1440, nota)) == 0) return (-1); } - // std::cerr << __func__ << " found nota height=" << nota.second.height << " MoMdepth=" << nota.second.MoMDepth << std::endl; ntz->txid = nota.first; ntz->ntzheight = nota.second.height; ntz->ntzblockhash = nota.second.blockHash; @@ -353,7 +351,6 @@ class DefaultCCChecker : public BaseCCChecker { isEof = ss.eof(); ); opretTxid = revuint256(opretTxid); - //std::cerr << __func__ << " " << "opretEvalcode=" << opretEvalcode << " opretFuncid=" << (char)opretFuncid << " isCreateTx=" << isCreateTx << " opretTxid=" << opretTxid.GetHex() << std::endl; if( parseOk /*parseOk=true if eof reached*/|| !isEof /*more data means okay*/) { if (evalcode == opretEvalcode && std::find(funcids.begin(), funcids.end(), (char)opretFuncid) != funcids.end() && @@ -413,7 +410,6 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ //} // select all appropriate utxos: - //std::cerr << __func__ << " " << "searching addr=" << coinaddr << std::endl; for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { if (myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index) == 0) @@ -429,8 +425,6 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ // if a checker is set for evalcode use it otherwise use the default checker: if (baseChecker && baseChecker->checkCC(it->first.txhash, tx.vout, nvout, evalcode, funcids, filtertxid) || defaultCCChecker.checkCC(it->first.txhash, tx.vout, nvout, evalcode, funcids, filtertxid)) { - //std::cerr << __func__ << " " << "filtered utxo with amount=" << tx.vout[nvout].nValue << std::endl; - struct CC_utxo utxo; utxo.txid = it->first.txhash; utxo.vout = (int32_t)it->first.index; @@ -441,7 +435,7 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ } } else - std::cerr << __func__ << " " << "ERROR: cant load tx for txid, please reindex" << std::endl; + LogPrint("nspv", "ERROR: cant load tx for txid, please reindex\n"); } } @@ -463,7 +457,7 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ if (CC_vinselect(&abovei, &above, &belowi, &below, utxoSelected.data(), utxoSelected.size(), remains) < 0) { - std::cerr << "error CC_vinselect" << " remains=" << remains << " amount=" << amount << " abovei=" << abovei << " belowi=" << belowi << " ind=" << " utxoSelected.size()=" << utxoSelected.size() << ind << std::endl; + LOGSTREAMFN("nspv", CCLOG_INFO, stream << "error CC_vinselect" << " remains=" << remains << " amount=" << amount << " abovei=" << abovei << " belowi=" << belowi << " ind=" << " utxoSelected.size()=" << utxoSelected.size() << ind << std::endl); return 0; } if (abovei >= 0) // best is 'above' @@ -472,7 +466,7 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ ind = belowi; else { - std::cerr << "error finding unspent" << " remains=" << remains << " amount=" << amount << " abovei=" << abovei << " belowi=" << belowi << " ind=" << " utxoSelected.size()=" << utxoSelected.size() << ind << std::endl; + LOGSTREAMFN("nspv", CCLOG_INFO, stream << "error finding unspent" << " remains=" << remains << " amount=" << amount << " abovei=" << abovei << " belowi=" << belowi << " ind=" << " utxoSelected.size()=" << utxoSelected.size() << ind << std::endl); return 0; } @@ -536,7 +530,6 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is ptr->skipcount = skipcount; ptr->txids = nullptr; - //std::cerr << __func__ << " coinaddr=" << coinaddr << std::endl; if (txids.size() >= 0 && skipcount < txids.size()) { ptr->txids = (struct NSPV_txidresp*)calloc(txids.size() - skipcount, sizeof(ptr->txids[0])); for (std::vector>::const_iterator it = txids.begin() + skipcount; @@ -546,21 +539,6 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is ptr->txids[ind].satoshis = (int64_t)it->second; ptr->txids[ind].height = (int64_t)it->first.blockHeight; - /* - CTransaction tx; - uint256 hashBlock; - myGetTransaction(it->first.txhash, tx, hashBlock); - char a[64]; - Getscriptaddress(a, tx.vout[it->first.index].scriptPubKey); - - int32_t type = 0; - uint160 hashBytes; - CBitcoinAddress address(a); - if (address.GetIndexKey(hashBytes, type, isCC) == 0) - std::cerr << __func__ << " txhash=" << it->first.txhash.ToString() << " index=" << " cant find indexkey" << std::endl; - else - std::cerr << __func__ << " txhash=" << it->first.txhash.ToString() << " index=" << it->first.index << " address=" << a << " hashBytes=" << HexStr(hashBytes) << " amount=" << it->second << std::endl; - */ ind++; } } @@ -568,10 +546,6 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is ptr->numtxids = ind; len = (int32_t)(sizeof(*ptr) + sizeof(ptr->txids[0]) * ptr->numtxids - sizeof(ptr->txids)); return (len); - /*if (ptr->txids != nullptr) - free(ptr->txids); - memset(ptr, 0, sizeof(*ptr)); - return (0);*/ } // get txids from addressindex or mempool by different criteria @@ -757,7 +731,8 @@ int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n) { request.read(json,n); jreq.parse(request); - strcpy(ptr->method,jreq.strMethod.c_str()); + strncpy(ptr->method, jreq.strMethod.c_str(), sizeof(ptr->method)-1); + ptr->method[sizeof(ptr->method)-1] = '\0'; len+=sizeof(ptr->method); std::map::iterator it = nspv_remote_commands.find(jreq.strMethod); if (it==nspv_remote_commands.end()) diff --git a/src/komodo_nSPV_wallet.h b/src/komodo_nSPV_wallet.h index 21e6bff1390..b460abac792 100644 --- a/src/komodo_nSPV_wallet.h +++ b/src/komodo_nSPV_wallet.h @@ -24,7 +24,6 @@ // nSPV wallet uses superlite functions (and some komodod built in functions) to implement nSPV_spend -//extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); int32_t NSPV_validatehdrs(struct NSPV_ntzsproofresp *ptr) { diff --git a/src/main.cpp b/src/main.cpp index 7d114992d6e..5ddcb4e43ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -80,14 +80,8 @@ using namespace std; #define TMPFILE_START 100000000 CCriticalSection cs_main; -//extern uint8_t NOTARY_PUBKEY33[33]; -//extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI; int32_t KOMODO_NEWBLOCKS; -//int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); -//void komodo_broadcast(CBlock *pblock,int32_t limit); -//bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); -//void komodo_setactivation(int32_t height); -//void komodo_pricesupdate(int32_t height,CBlock *pblock); + BlockMap mapBlockIndex; CChain chainActive; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 0fb2f67dce4..c766aa8687c 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -51,12 +51,6 @@ using namespace std; -//extern int32_t KOMODO_INSYNC; -//extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -//void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -//int32_t komodo_notarized_height(int32_t *prevMoMheightp, uint256 *hashp, uint256 *txidp); - - double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) { // Floating point number that is a multiple of the minimum difficulty, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d80b83dcdc0..94ff3319d92 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5513,10 +5513,6 @@ UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& m } -//#include "script/sign.h" -//int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); -//extern std::string NOTARY_PUBKEY; - int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void *pTr) { set setAddress; uint8_t *script,utxosig[128]; uint256 utxotxid; uint64_t utxovalue; int32_t i,siglen=0,nMinDepth = 0,nMaxDepth = 9999999; vector vecOutputs; uint32_t utxovout,eligible,earliest = 0; CScript best_scriptPubKey; bool fNegative,fOverflow; From 32cbb2cd9cbb0c0eaa0c74a24daa01127eb8d093 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 9 Feb 2022 17:02:15 +0500 Subject: [PATCH 203/348] added filtering json parameters to tokenorders rpc; locks optimised in tokenlist --- src/cc/CCassetstx_impl.h | 183 +++++++++++++++++++++++++++++---------- src/cc/CCtokens.cpp | 57 +++++++----- src/rpc/tokensrpc.cpp | 32 +++++-- 3 files changed, 198 insertions(+), 74 deletions(-) diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index e321466a2e5..b832d37a1df 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -21,10 +21,30 @@ #include "CCTokelData.h" template -UniValue AssetOrders(uint256 refassetid, CPubKey pk) +UniValue AssetOrders(uint256 refassetid, const CPubKey &mypk, const UniValue ¶ms) { UniValue result(UniValue::VARR); const char *funcname = __func__; + const bool CC_OUTPUTS_TRUE = true; + + int32_t beginHeight = 0; + int32_t endHeight = 0; + CPubKey checkPK = mypk; + std::string checkAddr; + if (params.exists("beginHeight")) + beginHeight = atoi(params["beginHeight"].getValStr().c_str()); + if (params.exists("endHeight")) + endHeight = atoi(params["endHeight"].getValStr().c_str()); + if (params.exists("pubkey")) + checkPK = pubkey2pk(ParseHex(params["pubkey"].getValStr().c_str())); + + if (beginHeight > 0 || endHeight > 0) + { + if (endHeight <= 0) { + LOCK(cs_main); + endHeight = chainActive.Height(); // if beginheight set but endHeight unset then set endHeight to the tip + } + } struct CCcontract_info *cpAssets, assetsC; struct CCcontract_info *cpTokens, tokensC; @@ -32,9 +52,9 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) cpAssets = CCinit(&assetsC, A::EvalCode()); cpTokens = CCinit(&tokensC, T::EvalCode()); - auto addOrders = [&](struct CCcontract_info *cp, const CAddressUnspentKey &key) + auto addOrders = [&](struct CCcontract_info *cp, uint256 ordertxid) { - uint256 txid, hashBlock, assetid; + uint256 hashBlock, assetid; CAmount unit_price; vscript_t origpubkey; CTransaction ordertx; @@ -42,10 +62,9 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) char origaddr[KOMODO_ADDRESS_BUFSIZE], origtokenaddr[KOMODO_ADDRESS_BUFSIZE]; int32_t expiryHeight; - txid = key.txhash; - LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " checking txid=" << txid.GetHex() << std::endl); - if (!myGetTransaction(txid, ordertx, hashBlock)) { - LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname <<" could not load order txid=" << txid.GetHex() << std::endl); + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " checking txid=" << ordertxid.GetHex() << std::endl); + if (!myGetTransaction(ordertxid, ordertx, hashBlock)) { + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname <<" could not load order txid=" << ordertxid.GetHex() << std::endl); return; } @@ -53,32 +72,36 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) { LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " checking ordertx.vout.size()=" << ordertx.vout.size() << " funcid=" << (char)(funcid ? funcid : ' ') << " assetid=" << assetid.GetHex() << std::endl); - if (!pk.IsValid() && (refassetid == zeroid || assetid == refassetid) || // tokenorders - pk.IsValid() && pk == pubkey2pk(origpubkey)) // mytokenorders + if ((!checkPK.IsValid() || checkPK == pubkey2pk(origpubkey)) && (refassetid.IsNull() || assetid == refassetid)) { uint256 spenttxid; - uint256 init_txid = txid; + uint256 init_txid = ordertxid; int32_t spentvin; int32_t height; // try to get unspent partially filled order (if it is a search by global assets address) - while(CCgetspenttxid(spenttxid, spentvin, height, init_txid, ASSETS_GLOBALADDR_VOUT) == 0 && IsTxidInActiveChain(spenttxid)) { + while(CCgetspenttxid(spenttxid, spentvin, height, init_txid, ASSETS_GLOBALADDR_VOUT) == 0) + { + { + LOCK(cs_main); + if (!IsTxidInActiveChain(spenttxid)) break; + } init_txid = spenttxid; } - if (init_txid != txid) { + if (init_txid != ordertxid) { // if it is a filled order load it - txid = init_txid; - if (!myGetTransaction(txid, ordertx, hashBlock)) { - LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " could not load order txid=" << txid.GetHex() << std::endl); + ordertxid = init_txid; + if (!myGetTransaction(ordertxid, ordertx, hashBlock)) { + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " could not load order txid=" << ordertxid.GetHex() << std::endl); return; } if ((funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, unit_price, origpubkey, expiryHeight)) == 0) { - LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " could not decode order txid=" << txid.GetHex() << std::endl); + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " could not decode order txid=" << ordertxid.GetHex() << std::endl); return; } } if (ordertx.vout.size() < 2) { - LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " txid skipped " << txid.GetHex() << std::endl); + LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " txid skipped " << ordertxid.GetHex() << std::endl); return; } @@ -86,7 +109,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) std::string funcidstr(1, (char)funcid); item.push_back(Pair("funcid", funcidstr)); - item.push_back(Pair("txid", txid.GetHex())); + item.push_back(Pair("txid", ordertxid.GetHex())); if (funcid == 'b' || funcid == 'B') { item.push_back(Pair("bidamount", ValueFromAmount(ordertx.vout[0].nValue))); @@ -95,6 +118,8 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) { item.push_back(Pair("askamount", ordertx.vout[0].nValue)); } + else + return; if (origpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { GetCCaddress(cp, origaddr, pubkey2pk(origpubkey), A::IsMixed()); @@ -117,51 +142,119 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk) item.push_back(Pair("price", ValueFromAmount(unit_price))); } } + { + LOCK(cs_main); + CBlockIndex *pindex = komodo_getblockindex(hashBlock); + if (pindex) + item.push_back(Pair("blockHeight", pindex->GetHeight())); + } if (expiryHeight > 0) item.push_back(Pair("ExpiryHeight", expiryHeight)); if (ordertx.vout[0].nValue > 0LL) // do not add totally filled orders result.push_back(item); - LOGSTREAM(ccassets_log, CCLOG_DEBUG1, stream << funcname << " added order funcId=" << (char)(funcid ? funcid : ' ') << " key.index=" << key.index << " ordertx.vout[key.index].nValue=" << ordertx.vout[key.index].nValue << " tokenid=" << assetid.GetHex() << std::endl); + LOGSTREAM(ccassets_log, CCLOG_DEBUG1, stream << funcname << " added order funcId=" << (char)(funcid ? funcid : ' ') << " orderid=" << ordertxid.GetHex() << " tokenid=" << assetid.GetHex() << std::endl); } } }; - if (!pk.IsValid()) // get tokenorders (all orders) + if (!checkPK.IsValid()) // get tokenorders (all orders) { - // tokenbids: - std::vector > unspentOutputsCoins; - char assetsGlobalAddr[KOMODO_ADDRESS_BUFSIZE]; - GetCCaddress(cpAssets, assetsGlobalAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); - SetCCunspents(unspentOutputsCoins, assetsGlobalAddr, true); - for (std::vector >::const_iterator itCoins = unspentOutputsCoins.begin(); - itCoins != unspentOutputsCoins.end(); - itCoins++) - addOrders(cpAssets, itCoins->first); - - // tokenasks: - std::vector > unspentOutputsTokens; - char tokensAssetsGlobalAddr[KOMODO_ADDRESS_BUFSIZE]; - GetTokensCCaddress(cpAssets, tokensAssetsGlobalAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); - SetCCunspents(unspentOutputsTokens, tokensAssetsGlobalAddr, true); - for (std::vector >::const_iterator itTokens = unspentOutputsTokens.begin(); - itTokens != unspentOutputsTokens.end(); - itTokens++) - addOrders(cpAssets, itTokens->first); + if (beginHeight > 0 || endHeight > 0) + { + // tokenbids (using addressindex sorted by height): + std::vector> addressIndexOutputsCoins; + char assetsGlobalAddr[KOMODO_ADDRESS_BUFSIZE]; + GetCCaddress(cpAssets, assetsGlobalAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); + SetAddressIndexOutputs(addressIndexOutputsCoins, assetsGlobalAddr, CC_OUTPUTS_TRUE, beginHeight, endHeight); + LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "SetAddressIndexOutputs addressIndexOutputsCoins.size()=" << addressIndexOutputsCoins.size() << std::endl); + for (const auto &outputsCoins : addressIndexOutputsCoins) + { + if (!outputsCoins.first.spending) { + bool isTxidInActiveChain = false; + { + LOCK(cs_main); + isTxidInActiveChain = IsTxidInActiveChain(outputsCoins.first.txhash); + } + if (isTxidInActiveChain) + addOrders(cpAssets, outputsCoins.first.txhash); + } + } + + // tokenasks (using addressindex sorted by height): + std::vector> addressIndexOutputsTokens; + char tokensAssetsGlobalAddr[KOMODO_ADDRESS_BUFSIZE]; + GetTokensCCaddress(cpAssets, tokensAssetsGlobalAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); + SetAddressIndexOutputs(addressIndexOutputsTokens, tokensAssetsGlobalAddr, CC_OUTPUTS_TRUE, beginHeight, endHeight); + LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "SetAddressIndexOutputs addressIndexOutputsTokens.size()=" << addressIndexOutputsTokens.size() << std::endl); + for (const auto &outputsTokens : addressIndexOutputsTokens) + { + if (!outputsTokens.first.spending) { + bool isTxidInActiveChain = false; + { + LOCK(cs_main); + isTxidInActiveChain = IsTxidInActiveChain(outputsTokens.first.txhash); + } + if (isTxidInActiveChain) + addOrders(cpAssets, outputsTokens.first.txhash); + } + } + } + else + { + // tokenbids: + std::vector > unspentOutputsCoins; + char assetsGlobalAddr[KOMODO_ADDRESS_BUFSIZE]; + GetCCaddress(cpAssets, assetsGlobalAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); + SetCCunspents(unspentOutputsCoins, assetsGlobalAddr, CC_OUTPUTS_TRUE); + for (const auto & unspentCoins : unspentOutputsCoins) + { + bool isTxidInActiveChain = false; + { + LOCK(cs_main); + isTxidInActiveChain = IsTxidInActiveChain(unspentCoins.first.txhash); + } + if (isTxidInActiveChain) + addOrders(cpAssets, unspentCoins.first.txhash); + } + + // tokenasks: + std::vector > unspentOutputsTokens; + char tokensAssetsGlobalAddr[KOMODO_ADDRESS_BUFSIZE]; + GetTokensCCaddress(cpAssets, tokensAssetsGlobalAddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); + SetCCunspents(unspentOutputsTokens, tokensAssetsGlobalAddr, CC_OUTPUTS_TRUE); + for (const auto & unspentTokens : unspentOutputsTokens) + { + bool isTxidInActiveChain = false; + { + LOCK(cs_main); + isTxidInActiveChain = IsTxidInActiveChain(unspentTokens.first.txhash); + } + if (isTxidInActiveChain) + addOrders(cpAssets, unspentTokens.first.txhash); + } + } } else { // mytokenorders, use marker on my pk : std::vector > unspentsMyAddr; char assetsMyAddr[KOMODO_ADDRESS_BUFSIZE]; - GetCCaddress1of2(cpAssets, assetsMyAddr, pk, GetUnspendable(cpAssets, NULL), A::IsMixed()); + GetCCaddress1of2(cpAssets, assetsMyAddr, checkPK, GetUnspendable(cpAssets, NULL), A::IsMixed()); SetCCunspents(unspentsMyAddr, assetsMyAddr, true); - for (std::vector >::const_iterator itOrders = unspentsMyAddr.begin(); - itOrders != unspentsMyAddr.end(); - itOrders++) - addOrders(cpAssets, itOrders->first); + for (const auto & orders : unspentsMyAddr) + { + bool isTxidInActiveChain = false; + { + LOCK(cs_main); + isTxidInActiveChain = IsTxidInActiveChain(orders.first.txhash); + } + // also check begin/end heights: + if (isTxidInActiveChain && (beginHeight <= 0 || orders.second.blockHeight >= beginHeight) && (endHeight <= 0 || orders.second.blockHeight <= endHeight)) + addOrders(cpAssets, orders.first.txhash); + } } - return(result); + return result; } // rpc tokenbid implementation, locks 'bidamount' coins for the 'pricetotal' of tokens diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index c615b81a065..ca26e19b7d7 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -883,31 +883,30 @@ UniValue TokenV2List(const UniValue ¶ms) std::string name, description; std::vector oprets; - if (IsTxidInActiveChain(tokenid)) - { - if (DecodeTokenCreateOpRetV2(opreturn, origpubkey, name, description, oprets) != 0) { - if (checkPK.IsValid()) { - if (checkPK == pubkey2pk(origpubkey)) - result.push_back(tokenid.GetHex()); - } - else if (!checkAddr.empty()) { - char origaddr[KOMODO_ADDRESS_BUFSIZE]; - Getscriptaddress(origaddr, TokensV2::MakeCC1vout(EVAL_TOKENSV2, 0LL, pubkey2pk(origpubkey)).scriptPubKey); - if (checkAddr == origaddr) - result.push_back(tokenid.GetHex()); - } - else + if (DecodeTokenCreateOpRetV2(opreturn, origpubkey, name, description, oprets) != 0) { + if (checkPK.IsValid()) { + if (checkPK == pubkey2pk(origpubkey)) result.push_back(tokenid.GetHex()); } - else { - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "DecodeTokenCreateOpRetV2 failed for tokenid=" << tokenid.GetHex() << " opreturn.size=" << opreturn.size() << std::endl); + else if (!checkAddr.empty()) { + char origaddr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(origaddr, TokensV2::MakeCC1vout(EVAL_TOKENSV2, 0LL, pubkey2pk(origpubkey)).scriptPubKey); + if (checkAddr == origaddr) + result.push_back(tokenid.GetHex()); } + else + result.push_back(tokenid.GetHex()); + } + else { + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "DecodeTokenCreateOpRetV2 failed for tokenid=" << tokenid.GetHex() << " opreturn.size=" << opreturn.size() << std::endl); } }; if (beginHeight > 0 || endHeight > 0) { - if (endHeight <= 0) + if (endHeight <= 0) { + LOCK(cs_main); endHeight = chainActive.Height(); + } std::vector> addressIndexOutputs; SetAddressIndexOutputs(addressIndexOutputs, cp->unspendableCCaddr, CC_OUTPUTS_TRUE, beginHeight, endHeight); LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "SetAddressIndexOutputs addressIndexOutputs.size()=" << addressIndexOutputs.size() << std::endl); @@ -917,8 +916,12 @@ UniValue TokenV2List(const UniValue ¶ms) if (!it.first.spending && myGetTransaction(it.first.txhash, creationtx, hashBlock) && creationtx.vout.size() > 0) { - LOCK(cs_main); - if (IsBlockHashInActiveChain(hashBlock)) + bool isBlockHashInActiveChain = false; + { + LOCK(cs_main); + isBlockHashInActiveChain = IsBlockHashInActiveChain(hashBlock); + } + if (isBlockHashInActiveChain) addTokenId(it.first.txhash, creationtx.vout.back().scriptPubKey); } } @@ -932,8 +935,12 @@ UniValue TokenV2List(const UniValue ¶ms) SetCCunspentsCCIndex(unspentOutputs, cp->unspendableCCaddr, zeroid); // find by burnable validated cc addr marker LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " cp->unspendableCCaddr=" << cp->unspendableCCaddr << " SetCCunspentsCCIndex unspentOutputs.size()=" << unspentOutputs.size() << std::endl); for (const auto &it : unspentOutputs) { - LOCK(cs_main); - if (IsTxidInActiveChain(it.first.creationid)) + bool isTxidInActiveChain = false; + { + LOCK(cs_main); + isTxidInActiveChain = IsTxidInActiveChain(it.first.creationid); + } + if (isTxidInActiveChain) addTokenId(it.first.creationid, it.second.opreturn); } } @@ -948,8 +955,12 @@ UniValue TokenV2List(const UniValue ¶ms) uint256 hashBlock; if (myGetTransaction(it.first.txhash, creationtx, hashBlock) && creationtx.vout.size() > 0) { - LOCK(cs_main); - if (IsBlockHashInActiveChain(hashBlock)) + bool isBlockHashInActiveChain = false; + { + LOCK(cs_main); + isBlockHashInActiveChain = IsBlockHashInActiveChain(hashBlock); + } + if (isBlockHashInActiveChain) addTokenId(it.first.txhash, creationtx.vout.back().scriptPubKey); } } diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 4c1382b9311..a6d44cffdf3 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -191,13 +191,18 @@ UniValue tokenv2infotokel(const UniValue& params, bool fHelp, const CPubKey& rem template UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) { + const static std::set acceptable = { "beginHeight", "endHeight", "pubkey"}; uint256 tokenid; const CPubKey emptypk; - if (fHelp || params.size() > 1) - throw runtime_error(name + " [tokenid|'*']\n" + if (fHelp || params.size() > 2) + throw runtime_error(name + " [tokenid|'*'] [json-params]\n" "returns tokens orders for the tokenid or all available token orders if tokenid is not set\n" - "\n"); + "json-params - optional json object with params limiting orders to output:\n" + " { \"beginHeight\": number \"endHeight\": number, \"pubkey\": hexstring }\n" + " \"beginHeight\", \"endHeight\" - height interval where to search orders, if beginHeight omitted the first block is used, if endHeight omitted the chain tip is used" + " \"pubkey\" - search orders created by a specific pubkey\n\n"); + if (ensure_CCrequirements(A::EvalCode(), remotepk.IsValid()) < 0 || ensure_CCrequirements(T::EvalCode(), remotepk.IsValid()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (params.size() >= 1) @@ -205,11 +210,26 @@ UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp if (params[0].get_str() != "*") { tokenid = Parseuint256((char *)params[0].get_str().c_str()); - if (tokenid == zeroid) + if (tokenid.IsNull()) throw runtime_error("incorrect tokenid\n"); } } - return AssetOrders(tokenid, emptypk); + UniValue jsonParams; + if (params.size() >= 2) + { + if (params[1].getType() == UniValue::VOBJ) + jsonParams = params[1].get_array(); + else if (params[1].getType() == UniValue::VSTR) // json in quoted string '{...}' + jsonParams.read(params[1].get_str().c_str()); + if (jsonParams.getType() != UniValue::VOBJ) + throw runtime_error("parameter 2 must be a json object"); + + // check unused params: + for (int i = 0; i < jsonParams.getKeys().size(); i ++) + if (acceptable.count(jsonParams.getKeys()[i]) == 0) + throw runtime_error(std::string("invalid json param") + jsonParams.getKeys()[i]); + } + return AssetOrders(tokenid, emptypk, jsonParams); } UniValue tokenorders(const UniValue& params, bool fHelp, const CPubKey& remotepk) @@ -235,7 +255,7 @@ UniValue mytokenorders(const std::string& name, const UniValue& params, bool fHe CPubKey mypk; SET_MYPK_OR_REMOTE(mypk, remotepk); - return AssetOrders(zeroid, mypk); + return AssetOrders(zeroid, mypk, NullUniValue); } UniValue mytokenorders(const UniValue& params, bool fHelp, const CPubKey& remotepk) From 98ac2fec71f5573d07c2fa5be9914fc5e31951c3 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 00:50:40 +0500 Subject: [PATCH 204/348] add --enable-debug support to build --- Makefile.am | 3 +++ configure.ac | 3 ++- depends/hosts/darwin.mk | 4 ++-- depends/hosts/linux.mk | 4 ++-- depends/hosts/mingw32.mk | 6 +++--- zcutil/build-mac-dtest.sh | 33 +++++++++++++++++--------------- zcutil/build-mac.sh | 31 ++++++++++++++++-------------- zcutil/build-win-dtest.sh | 29 +++++++++++++--------------- zcutil/build-win.sh | 17 +++++++---------- zcutil/build.sh | 40 +++++++++++++++++++++++---------------- 10 files changed, 91 insertions(+), 79 deletions(-) diff --git a/Makefile.am b/Makefile.am index 51d0430aca4..298ce8fe824 100644 --- a/Makefile.am +++ b/Makefile.am @@ -344,3 +344,6 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-man clean-local: rm -rf test_bitcoin.coverage/ zcash-gtest.coverage/ total.coverage/ + +clean-all: clean-local + $(MAKE) -C src clean-all \ No newline at end of file diff --git a/configure.ac b/configure.ac index 98d3b098ffc..977bcc45c91 100644 --- a/configure.ac +++ b/configure.ac @@ -199,7 +199,8 @@ AC_LANG_PUSH([C++]) AX_CHECK_COMPILE_FLAG([-Werror],[CXXFLAG_WERROR="-Werror"],[CXXFLAG_WERROR=""]) if test "x$enable_debug" = xyes; then - CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER" +dnl CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER" + CPPFLAGS="$CPPFLAGS -DDEBUG" if test "x$GCC" = xyes; then CFLAGS="$CFLAGS -g3 -O0" fi diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index 7be744aebc0..10999dac006 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -8,10 +8,10 @@ darwin_CXX=g++-8 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysro darwin_CFLAGS=-pipe darwin_CXXFLAGS=$(darwin_CFLAGS) -darwin_release_CFLAGS=-O1 +darwin_release_CFLAGS=-g -O1 darwin_release_CXXFLAGS=$(darwin_release_CFLAGS) -darwin_debug_CFLAGS=-O1 +darwin_debug_CFLAGS=-g -O0 darwin_debug_CXXFLAGS=$(darwin_debug_CFLAGS) darwin_native_toolchain=native_cctools diff --git a/depends/hosts/linux.mk b/depends/hosts/linux.mk index 31748d66226..a141178a3dd 100644 --- a/depends/hosts/linux.mk +++ b/depends/hosts/linux.mk @@ -1,10 +1,10 @@ linux_CFLAGS=-pipe linux_CXXFLAGS=$(linux_CFLAGS) -linux_release_CFLAGS=-O1 +linux_release_CFLAGS=-g -O2 linux_release_CXXFLAGS=$(linux_release_CFLAGS) -linux_debug_CFLAGS=-O1 +linux_debug_CFLAGS=-g -O0 linux_debug_CXXFLAGS=$(linux_debug_CFLAGS) linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC diff --git a/depends/hosts/mingw32.mk b/depends/hosts/mingw32.mk index b217bfdb547..1f74eec23ae 100644 --- a/depends/hosts/mingw32.mk +++ b/depends/hosts/mingw32.mk @@ -1,12 +1,12 @@ mingw32_CC=x86_64-w64-mingw32-gcc-posix mingw32_CXX=x86_64-w64-mingw32-g++-posix mingw32_CFLAGS=-pipe -std=c11 -mingw32_CXXFLAGS=$(mingw32_CFLAGS) -std=c++11 +mingw32_CXXFLAGS=-pipe -std=c++11 -mingw32_release_CFLAGS=-O1 +mingw32_release_CFLAGS=-g -O2 mingw32_release_CXXFLAGS=$(mingw32_release_CFLAGS) -mingw32_debug_CFLAGS=-O1 +mingw32_debug_CFLAGS=-g -O0 mingw32_debug_CXXFLAGS=$(mingw32_debug_CFLAGS) mingw32_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC diff --git a/zcutil/build-mac-dtest.sh b/zcutil/build-mac-dtest.sh index d73bbe2d2ce..e1a5ece470f 100755 --- a/zcutil/build-mac-dtest.sh +++ b/zcutil/build-mac-dtest.sh @@ -18,11 +18,13 @@ Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov ] [ MAKEARGS... ] - Build Zcash and most of its transitive dependencies from - source. MAKEARGS are applied to both dependencies and Zcash itself. If - --enable-lcov is passed, Zcash is configured to add coverage +$0 [ --enable-lcov ] [ --enable-debug ] [ MAKEARGS... ] + Build Komodo and most of its transitive dependencies from + source. MAKEARGS are applied to both dependencies and Komodo itself. + If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. + If --enable-debug is passed, Komodo is built with debugging information. It + must be passed after the previous arguments, if present. EOF exit 0 fi @@ -37,24 +39,25 @@ then shift fi +# If --enable-debug is the next argument, enable debugging +DEBUGGING_ARG='' +if [ "x${1:-}" = 'x--enable-debug' ] +then + DEBUG=1 + export DEBUG + DEBUGGING_ARG='--enable-debug' + shift +fi + TRIPLET=`./depends/config.guess` PREFIX="$(pwd)/depends/$TRIPLET" # make dependences make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 -#BUILD CCLIB -# WD=$PWD -# cd src/cc -# echo $PWD -# ./makecustom -# cd $WD -# cclib building now added to src/Makefile.am - - ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64 -DTESTMODE" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ -./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" +CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ +./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$DEBUGGING_ARG" make "$@" V=1 NO_GTEST=1 STATIC=1 diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index 9dd86537007..825b49d8eb3 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -23,11 +23,13 @@ Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov ] [ MAKEARGS... ] - Build Zcash and most of its transitive dependencies from - source. MAKEARGS are applied to both dependencies and Zcash itself. If - --enable-lcov is passed, Zcash is configured to add coverage +$0 [ --enable-lcov ] [ --enable-debug ] [ MAKEARGS... ] + Build Komodo and most of its transitive dependencies from + source. MAKEARGS are applied to both dependencies and Komodo itself. + If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. + If --enable-debug is passed, Komodo is built with debugging information. It + must be passed after the previous arguments, if present. EOF exit 0 fi @@ -42,24 +44,25 @@ then shift fi +# If --enable-debug is the next argument, enable debugging +DEBUGGING_ARG='' +if [ "x${1:-}" = 'x--enable-debug' ] +then + DEBUG=1 + export DEBUG + DEBUGGING_ARG='--enable-debug' + shift +fi + TRIPLET=`./depends/config.guess` PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 -# cclib building now added to src/Makefile.am -#BUILD CCLIB -# WD=$PWD -# cd src/cc -# echo $PWD -# echo Making cclib... -# ./makecustom -# cd $WD - ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ -./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" \ +./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" "$DEBUGGING_ARG" \ --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' diff --git a/zcutil/build-win-dtest.sh b/zcutil/build-win-dtest.sh index 2cf85e7bcee..48557bc5e58 100755 --- a/zcutil/build-win-dtest.sh +++ b/zcutil/build-win-dtest.sh @@ -2,27 +2,24 @@ export HOST=x86_64-w64-mingw32 CXX=x86_64-w64-mingw32-g++-posix CC=x86_64-w64-mingw32-gcc-posix -PREFIX="$(pwd)/depends/$HOST" set -eu -o pipefail - set -x -cd "$(dirname "$(readlink -f "$0")")/.." -# make dependences -cd depends/ && make HOST=$HOST V=1 NO_QT=1 -cd ../ +UTIL_DIR="$(dirname "$(readlink -f "$0")")" +BASE_DIR="$(dirname "$(readlink -f "$UTIL_DIR")")" +PREFIX="$BASE_DIR/depends/$HOST" -#BUILD CCLIB -# WD=$PWD -# cd src/cc -# echo $PWD -# ./makecustom -# cd $WD -# cclib building now added to src/Makefile.am +cd $BASE_DIR/depends +make HOST=$HOST NO_QT=1 "$@" +cd $BASE_DIR ./autogen.sh -CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" CPPFLAGS=-DTESTMODE ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared +CONFIG_SITE=$PWD/depends/$HOST/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" CPPFLAGS=-DTESTMODE ./configure --prefix="${PREFIX}" --host=$HOST --enable-static --disable-shared sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure -cd src/ -CC="${CC} -g " CXX="${CXX} -g " make V=1 komodod.exe komodo-cli.exe komodo-tx.exe + +cd $BASE_DIR/src/cryptoconditions +CC="${CC} -g " CXX="${CXX} -g " make V=1 +cd $BASE_DIR + +CC="${CC} -g " CXX="${CXX} -g " make V=1 src/komodod.exe src/komodo-cli.exe src/komodo-tx.exe diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index b89271e4833..297fb9d7b20 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -6,23 +6,20 @@ PREFIX="$(pwd)/depends/$HOST" set -eu -o pipefail -set -x -cd "$(dirname "$(readlink -f "$0")")/.." +UTIL_DIR="$(dirname "$(readlink -f "$0")")" +BASE_DIR="$(dirname "$(readlink -f "$UTIL_DIR")")" +PREFIX="$BASE_DIR/depends/$HOST" # make dependences cd depends/ && make HOST=$HOST V=1 NO_QT=1 cd ../ -# note: cclib building now added to src/Makefile.am -#BUILD CCLIB -# WD=$PWD -# cd src/cc -# echo $PWD -# ./makecustom -# cd $WD +cd $BASE_DIR/depends +make HOST=$HOST NO_QT=1 "$@" +cd $BASE_DIR ./autogen.sh -CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared \ +CONFIG_SITE=$BASE_DIR/depends/$HOST/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix=$PREFIX --host=$HOST --enable-static --disable-shared \ --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' diff --git a/zcutil/build.sh b/zcutil/build.sh index 2c1a9c66e86..5b0399ef654 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -44,15 +44,15 @@ then Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [ MAKEARGS... ] - Build Zcash and most of its transitive dependencies from - source. MAKEARGS are applied to both dependencies and Zcash itself. - If --enable-lcov is passed, Zcash is configured to add coverage +$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [ --enable-debug ] [ MAKEARGS... ] + Build Komodo and most of its transitive dependencies from + source. MAKEARGS are applied to both dependencies and Komodo itself. + If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. - If --disable-tests is passed instead, the Zcash tests are not built. - If --disable-mining is passed, Zcash is configured to not build any mining + If --disable-tests is passed instead, the Komodo tests are not built. + If --disable-mining is passed, Komodo is configured to not build any mining code. It must be passed after the test arguments, if present. - If --enable-proton is passed, Zcash is configured to build the Apache Qpid Proton + If --enable-proton is passed, Komodo is configured to build the Apache Qpid Proton library required for AMQP support. This library is not built by default. It must be passed after the test/mining arguments, if present. EOF @@ -92,6 +92,22 @@ then shift fi +# If --enable-debug is the next argument, enable debugging +DEBUGGING_ARG='' +if [ "x${1:-}" = 'x--enable-debug' ] +then + DEBUG=1 + export DEBUG + DEBUGGING_ARG='--enable-debug' + shift +fi + +if [[ -z "${VERBOSE-}" ]]; then + VERBOSITY="--enable-silent-rules" +else + VERBOSITY="--disable-silent-rules" +fi + eval "$MAKE" --version as --version ld -v @@ -99,17 +115,9 @@ ld -v HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh -CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' \ +CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$DEBUGGING_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' \ --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' -# cclib building now added to src/Makefile.am: -#BUILD CCLIB -#WD=$PWD -#cd src/cc -#echo $PWD -#./makecustom -#cd $WD - "$MAKE" "$@" V=1 From a0ed0840188085b03c27620ea1feb18996ff4bbc Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 00:51:36 +0500 Subject: [PATCH 205/348] addrman constructor refactored --- src/addrman.h | 12 +++++++----- src/init.cpp | 2 -- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/addrman.h b/src/addrman.h index 7816f06b0fc..1385ac8090f 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -499,9 +499,9 @@ friend class CAddrManTest; Check(); } - void Clear() +private: + void Clear_() { - LOCK(cs); std::vector().swap(vRandom); nKey = GetRandHash(); for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) { @@ -522,14 +522,16 @@ friend class CAddrManTest; mapAddr.clear(); } +public: CAddrMan() { - // Clear(); // causes boost: mutex lock failed in pthread_mutex_lock: Invalid argument exception because of static init concurrency (static dd_mutex has not been constructed yet) + Clear_(); // use unlocked version bcz locked one caused boost: mutex lock failed in pthread_mutex_lock: Invalid argument exception because of static init concurrency (static dd_mutex has not been constructed yet) } - void Init() + void Clear() { - Clear(); + LOCK(cs); + Clear_(); } ~CAddrMan() diff --git a/src/init.cpp b/src/init.cpp index 190b09ab5ba..b2c796224e1 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -938,8 +938,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (setProcDEPPol != NULL) setProcDEPPol(PROCESS_DEP_ENABLE); #endif - addrman.Init(); // call clear addr table - if (!SetupNetworking()) return InitError("Error: Initializing networking failed"); From ac06d3f32180964d5fcd5a3ce3d873341ac631b5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 00:53:53 +0500 Subject: [PATCH 206/348] added komodo_globals.h to cli to prevent ld nStakedDecemberHardfork undef when no opt --- src/bitcoin-cli.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index e38cf348d26..9c3041faab1 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -24,6 +24,7 @@ #include "rpc/protocol.h" #include "util.h" #include "utilstrencodings.h" +#include "komodo_globals.h" #include #include @@ -31,8 +32,8 @@ #include #include #include "support/events.h" -uint16_t BITCOIND_RPCPORT = 7771; -char ASSETCHAINS_SYMBOL[65]; +//uint16_t BITCOIND_RPCPORT = 7771; +//char ASSETCHAINS_SYMBOL[65]; #include From c6a8c0c1841a26e996da55997960c7d58c54f065 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 00:58:36 +0500 Subject: [PATCH 207/348] lib cryptoconditions extenstions: new secp256k1hash cond, dontfulfill flag, eval param --- src/cryptoconditions/Makefile.am | 38 +- .../include/cryptoconditions.h | 10 +- src/cryptoconditions/src/anon.c | 13 +- src/cryptoconditions/src/asn/Condition.c | 18 +- src/cryptoconditions/src/asn/Condition.h | 10 +- src/cryptoconditions/src/asn/ConditionTypes.c | 2 +- src/cryptoconditions/src/asn/ConditionTypes.h | 9 +- .../src/asn/CryptoConditions.asn | 15 +- .../src/asn/EvalFulfillment.c | 16 +- .../src/asn/EvalFulfillment.h | 9 +- src/cryptoconditions/src/asn/Fulfillment.c | 18 +- src/cryptoconditions/src/asn/Fulfillment.h | 11 +- .../asn/Secp256k1hashFingerprintContents.c | 84 ++++ .../asn/Secp256k1hashFingerprintContents.h | 37 ++ .../src/asn/Secp256k1hashFulfillment.c | 120 ++++++ .../src/asn/Secp256k1hashFulfillment.h | 38 ++ src/cryptoconditions/src/cryptoconditions.c | 46 ++- src/cryptoconditions/src/ed25519.c | 6 + src/cryptoconditions/src/eval.c | 93 ++++- src/cryptoconditions/src/include/ripemd160.c | 342 ++++++++++++++++ src/cryptoconditions/src/include/ripemd160.h | 22 ++ src/cryptoconditions/src/prefix.c | 4 + src/cryptoconditions/src/preimage.c | 5 + src/cryptoconditions/src/secp256k1.c | 21 +- src/cryptoconditions/src/secp256k1hash.c | 364 ++++++++++++++++++ src/cryptoconditions/src/threshold.c | 17 +- 26 files changed, 1286 insertions(+), 82 deletions(-) create mode 100644 src/cryptoconditions/src/asn/Secp256k1hashFingerprintContents.c create mode 100644 src/cryptoconditions/src/asn/Secp256k1hashFingerprintContents.h create mode 100644 src/cryptoconditions/src/asn/Secp256k1hashFulfillment.c create mode 100644 src/cryptoconditions/src/asn/Secp256k1hashFulfillment.h create mode 100644 src/cryptoconditions/src/include/ripemd160.c create mode 100644 src/cryptoconditions/src/include/ripemd160.h create mode 100644 src/cryptoconditions/src/secp256k1hash.c diff --git a/src/cryptoconditions/Makefile.am b/src/cryptoconditions/Makefile.am index 263cb4f8d53..7db566e035c 100644 --- a/src/cryptoconditions/Makefile.am +++ b/src/cryptoconditions/Makefile.am @@ -1,30 +1,27 @@ -lib_LTLIBRARIES=libcryptoconditions.la -noinst_LTLIBRARIES=$(CRYPTOCONDITIONS_CORE) +noinst_LIBRARIES=libcryptoconditions_core.a SUBDIRS = src/include/secp256k1 -include_HEADERS = include/cryptoconditions.h +# optimisation off to allow better gdb/lldb +CFLAGS = -g -O0 -# Have a separate build target for cryptoconditions that does not contain secp256k1 +# use to debug: +# CPPFLAGS = -DEMIT_ASN_DEBUG=1 -libcryptoconditions_la_SOURCES = include/cryptoconditions.h -libcryptoconditions_la_LIBADD = $(CRYPTOCONDITIONS_CORE) $(LIBSECP256K1) +include_HEADERS = include/cryptoconditions.h src/internal.h -AM_CFLAGS = -I$(top_srcdir)/src/asn -I$(top_srcdir)/include -I$(top_srcdir)/src/include \ - -Wall -Wno-pointer-sign -Wno-discarded-qualifiers +# Have a separate build target for cryptoconditions that does not contain secp256k1 LIBSECP256K1=src/include/secp256k1/libsecp256k1.la $(LIBSECP256K1): $(wildcard src/secp256k1/*) - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) -march:x86-64 -g + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) -march:x86-64 -g -O0 -CRYPTOCONDITIONS_CORE=libcryptoconditions_core.la - -libcryptoconditions_core_la_SOURCES = \ - include/cryptoconditions.h \ +libcryptoconditions_core_a_SOURCES = \ src/cryptoconditions.c \ src/utils.c \ src/include/cJSON.c \ src/include/sha256.c \ + src/include/ripemd160.c \ src/include/ed25519/src/keypair.c \ src/include/ed25519/src/seed.c \ src/include/ed25519/src/verify.c \ @@ -51,7 +48,9 @@ libcryptoconditions_core_la_SOURCES = \ src/asn/Ed25519FingerprintContents.c \ src/asn/EvalFulfillment.c \ src/asn/Secp256k1FingerprintContents.c \ + src/asn/Secp256k1hashFingerprintContents.c \ src/asn/Secp256k1Fulfillment.c \ + src/asn/Secp256k1hashFulfillment.c \ src/asn/INTEGER.c \ src/asn/NativeEnumerated.c \ src/asn/NativeInteger.c \ @@ -75,18 +74,21 @@ libcryptoconditions_core_la_SOURCES = \ src/asn/per_decoder.c \ src/asn/per_encoder.c \ src/asn/per_opentype.c +libcryptoconditions_core_a_CPPFLAGS=-I. -I./src/include -I./src/asn test: bash -c '[ -d .env ] || virtualenv .env -p python3' .env/bin/pip install pytest + gdb -batch -ex run -ex bt --args .env/bin/python -m pytest -s -x -v 2>&1 | grep -v ^"No stack."$ test-debug-interactive: gdb -ex run --args python3 -m pytest -s -x -v asn: - cd src/asn; \ - mv asn_system.h asn_system.bak; \ - rm *.c *.h; \ - asn1c CryptoConditions.asn; \ - mv asn_system.bak asn_system.h +# run asn1c in a dedicated directory, use exactly the same asn1c version, when asn1c is done copy generated files manually into asn subdir +# cd src/asn; \ +# mv asn_system.h asn_system.bak; \ +# rm *.c *.h; \ +# asn1c CryptoConditions.asn; \ +# mv asn_system.bak asn_system.h diff --git a/src/cryptoconditions/include/cryptoconditions.h b/src/cryptoconditions/include/cryptoconditions.h index ebfeb5c1281..5c88470a2f4 100644 --- a/src/cryptoconditions/include/cryptoconditions.h +++ b/src/cryptoconditions/include/cryptoconditions.h @@ -37,6 +37,7 @@ enum CCTypeId { CC_Threshold = 2, CC_Ed25519 = 4, CC_Secp256k1 = 5, + CC_Secp256k1hash = 6, CC_Eval = 15 }; @@ -55,7 +56,7 @@ typedef struct CC { struct CCType *type; union { // public key types - struct { uint8_t *publicKey, *signature; }; + struct { uint8_t *publicKey, *signature; uint8_t *publicKeyHash; }; // preimage struct { uint8_t *preimage; size_t preimageLength; }; // threshold @@ -64,11 +65,12 @@ typedef struct CC { struct { uint8_t *prefix; size_t prefixLength; struct CC *subcondition; size_t maxMessageLength; }; // eval - struct { uint8_t *code; size_t codeLength; }; + struct { uint8_t *code; size_t codeLength; uint8_t *param; size_t paramLength; int includeParamInFP; }; // anon struct { uint8_t fingerprint[32]; uint32_t subtypes; unsigned long cost; struct CCType *conditionType; }; }; + int dontFulfill; } CC; /* @@ -94,7 +96,9 @@ int cc_visit(CC *cond, struct CCVisitor visitor); int cc_signTreeEd25519(CC *cond, const uint8_t *privateKey, const uint8_t *msg, const size_t msgLength); int cc_signTreeSecp256k1Msg32(CC *cond, const uint8_t *privateKey, const uint8_t *msg32); +int cc_signTreeSecp256k1HashMsg32(CC *cond, const unsigned char *privateKey, const unsigned char *msg32); int cc_secp256k1VerifyTreeMsg32(const CC *cond, const uint8_t *msg32); +int cc_secp256k1HashVerifyTreeMsg32(const CC *cond, const unsigned char *msg32); size_t cc_conditionBinary(const CC *cond, uint8_t *buf); size_t cc_fulfillmentBinary(const CC *cond, uint8_t *buf, size_t bufLength); size_t cc_fulfillmentBinaryMixedMode(const CC *cond, uint8_t *buf, size_t bufLength); @@ -116,7 +120,7 @@ uint32_t cc_typeMask(const CC *cond); int cc_isAnon(const CC *cond); struct CC* cc_anon(const CC *cond); void cc_free(struct CC *cond); -struct CC* cc_copy(CC *cond); +struct CC* cc_copy(const CC *cond); #ifdef __cplusplus } diff --git a/src/cryptoconditions/src/anon.c b/src/cryptoconditions/src/anon.c index dabcdcb20d2..196f420e361 100644 --- a/src/cryptoconditions/src/anon.c +++ b/src/cryptoconditions/src/anon.c @@ -59,7 +59,7 @@ static CC* anonFromJSON(const cJSON *params, char *err) { size_t len; cJSON *fingerprint_item = cJSON_GetObjectItem(params, "fingerprint"); if (!cJSON_IsString(fingerprint_item)) { - strcpy(err, "fingerprint must be a number"); + strcpy(err, "fingerprint must be a string"); return NULL; } unsigned char *fing = base64_decode(fingerprint_item->valuestring, &len); @@ -78,10 +78,20 @@ static CC* anonFromJSON(const cJSON *params, char *err) { strcpy(err, "subtypes must be a number"); return NULL; } + CCType *realType = NULL; + cJSON *asnType_item = cJSON_GetObjectItem(params, "asnType"); + if (asnType_item) { + if (!cJSON_IsNumber(asnType_item)) { + strcpy(err, "asnType must be a number"); + return NULL; + } + realType = getTypeByAsnEnum(asnType_item->valueint); + } CC* cond=cc_new(CC_Anon); memcpy(cond->fingerprint,fing,len); cond->cost = (long) cost_item->valuedouble; cond->subtypes = subtypes_item->valueint; + cond->conditionType = realType; return cond; } @@ -91,6 +101,7 @@ static void anonToJSON(const CC *cond, cJSON *params) { free(b64); cJSON_AddItemToObject(params, "cost", cJSON_CreateNumber(cond->cost)); cJSON_AddItemToObject(params, "subtypes", cJSON_CreateNumber(cond->subtypes)); + cJSON_AddItemToObject(params, "asnType", cJSON_CreateNumber((int)cond->conditionType->asnType)); } diff --git a/src/cryptoconditions/src/asn/Condition.c b/src/cryptoconditions/src/asn/Condition.c index 49ec83e3b5a..7def6dc3aba 100644 --- a/src/cryptoconditions/src/asn/Condition.c +++ b/src/cryptoconditions/src/asn/Condition.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.28 (http://lionet.info/asn1c) * From ASN.1 module "Crypto-Conditions" - * found in "CryptoConditions.asn" + * found in "./CryptoConditions-pkhash.asn" */ #include "Condition.h" @@ -61,6 +61,15 @@ static asn_TYPE_member_t asn_MBR_Condition_1[] = { 0, "secp256k1Sha256" }, + { ATF_NOFLAGS, 0, offsetof(struct Condition, choice.secp256k1hashSha256), + (ASN_TAG_CLASS_CONTEXT | (6 << 2)), + -1, /* IMPLICIT tag at current level */ + &asn_DEF_SimpleSha256Condition, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "secp256k1hashSha256" + }, { ATF_NOFLAGS, 0, offsetof(struct Condition, choice.evalSha256), (ASN_TAG_CLASS_CONTEXT | (15 << 2)), -1, /* IMPLICIT tag at current level */ @@ -78,7 +87,8 @@ static const asn_TYPE_tag2member_t asn_MAP_Condition_tag2el_1[] = { { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 }, /* rsaSha256 */ { (ASN_TAG_CLASS_CONTEXT | (4 << 2)), 4, 0, 0 }, /* ed25519Sha256 */ { (ASN_TAG_CLASS_CONTEXT | (5 << 2)), 5, 0, 0 }, /* secp256k1Sha256 */ - { (ASN_TAG_CLASS_CONTEXT | (15 << 2)), 6, 0, 0 } /* evalSha256 */ + { (ASN_TAG_CLASS_CONTEXT | (6 << 2)), 6, 0, 0 }, /* secp256k1hashSha256 */ + { (ASN_TAG_CLASS_CONTEXT | (15 << 2)), 7, 0, 0 } /* evalSha256 */ }; static asn_CHOICE_specifics_t asn_SPC_Condition_specs_1 = { sizeof(struct Condition), @@ -86,7 +96,7 @@ static asn_CHOICE_specifics_t asn_SPC_Condition_specs_1 = { offsetof(struct Condition, present), sizeof(((struct Condition *)0)->present), asn_MAP_Condition_tag2el_1, - 7, /* Count of tags in the map */ + 8, /* Count of tags in the map */ 0, -1 /* Extensions start */ }; @@ -108,7 +118,7 @@ asn_TYPE_descriptor_t asn_DEF_Condition = { 0, /* No tags (count) */ 0, /* No PER visible constraints */ asn_MBR_Condition_1, - 7, /* Elements count */ + 8, /* Elements count */ &asn_SPC_Condition_specs_1 /* Additional specs */ }; diff --git a/src/cryptoconditions/src/asn/Condition.h b/src/cryptoconditions/src/asn/Condition.h index 2396c01523e..8a9e76cd948 100644 --- a/src/cryptoconditions/src/asn/Condition.h +++ b/src/cryptoconditions/src/asn/Condition.h @@ -1,19 +1,19 @@ /* * Generated by asn1c-0.9.28 (http://lionet.info/asn1c) * From ASN.1 module "Crypto-Conditions" - * found in "CryptoConditions.asn" + * found in "./CryptoConditions-pkhash.asn" */ #ifndef _Condition_H_ #define _Condition_H_ -#include "asn_application.h" +#include /* Including external dependencies */ #include "SimpleSha256Condition.h" #include "CompoundSha256Condition.h" -#include "constr_CHOICE.h" +#include #ifdef __cplusplus extern "C" { @@ -28,6 +28,7 @@ typedef enum Condition_PR { Condition_PR_rsaSha256, Condition_PR_ed25519Sha256, Condition_PR_secp256k1Sha256, + Condition_PR_secp256k1hashSha256, Condition_PR_evalSha256 } Condition_PR; @@ -41,6 +42,7 @@ typedef struct Condition { SimpleSha256Condition_t rsaSha256; SimpleSha256Condition_t ed25519Sha256; SimpleSha256Condition_t secp256k1Sha256; + SimpleSha256Condition_t secp256k1hashSha256; SimpleSha256Condition_t evalSha256; } choice; @@ -56,4 +58,4 @@ extern asn_TYPE_descriptor_t asn_DEF_Condition; #endif #endif /* _Condition_H_ */ -#include "asn_internal.h" +#include diff --git a/src/cryptoconditions/src/asn/ConditionTypes.c b/src/cryptoconditions/src/asn/ConditionTypes.c index 16ca9d19c4f..dbcded60e94 100644 --- a/src/cryptoconditions/src/asn/ConditionTypes.c +++ b/src/cryptoconditions/src/asn/ConditionTypes.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.28 (http://lionet.info/asn1c) * From ASN.1 module "Crypto-Conditions" - * found in "CryptoConditions.asn" + * found in "./CryptoConditions-pkhash.asn" */ #include "ConditionTypes.h" diff --git a/src/cryptoconditions/src/asn/ConditionTypes.h b/src/cryptoconditions/src/asn/ConditionTypes.h index 595dd0aad60..61481af9423 100644 --- a/src/cryptoconditions/src/asn/ConditionTypes.h +++ b/src/cryptoconditions/src/asn/ConditionTypes.h @@ -1,17 +1,17 @@ /* * Generated by asn1c-0.9.28 (http://lionet.info/asn1c) * From ASN.1 module "Crypto-Conditions" - * found in "CryptoConditions.asn" + * found in "./CryptoConditions-pkhash.asn" */ #ifndef _ConditionTypes_H_ #define _ConditionTypes_H_ -#include "asn_application.h" +#include /* Including external dependencies */ -#include "BIT_STRING.h" +#include #ifdef __cplusplus extern "C" { @@ -25,6 +25,7 @@ typedef enum ConditionTypes { ConditionTypes_rsaSha256 = 3, ConditionTypes_ed25519Sha256 = 4, ConditionTypes_secp256k1Sha256 = 5, + ConditionTypes_secp256k1hashSha256 = 6, ConditionTypes_evalSha256 = 15 } e_ConditionTypes; @@ -46,4 +47,4 @@ xer_type_encoder_f ConditionTypes_encode_xer; #endif #endif /* _ConditionTypes_H_ */ -#include "asn_internal.h" +#include diff --git a/src/cryptoconditions/src/asn/CryptoConditions.asn b/src/cryptoconditions/src/asn/CryptoConditions.asn index 42a3c88f174..94bdaa5857b 100644 --- a/src/cryptoconditions/src/asn/CryptoConditions.asn +++ b/src/cryptoconditions/src/asn/CryptoConditions.asn @@ -11,6 +11,7 @@ Crypto-Conditions DEFINITIONS AUTOMATIC TAGS ::= BEGIN rsaSha256 [3] SimpleSha256Condition, ed25519Sha256 [4] SimpleSha256Condition, secp256k1Sha256 [5] SimpleSha256Condition, + secp256k1hashSha256 [6] SimpleSha256Condition, evalSha256 [15] SimpleSha256Condition } @@ -32,6 +33,7 @@ Crypto-Conditions DEFINITIONS AUTOMATIC TAGS ::= BEGIN rsaSha256 (3), ed25519Sha256 (4), secp256k1Sha256 (5), + secp256k1hashSha256 (6), evalSha256 (15) } @@ -44,6 +46,7 @@ Crypto-Conditions DEFINITIONS AUTOMATIC TAGS ::= BEGIN rsaSha256 [3] RsaSha256Fulfillment, ed25519Sha256 [4] Ed25519Sha512Fulfillment, secp256k1Sha256 [5] Secp256k1Fulfillment, + secp256k1hashSha256 [6] Secp256k1hashFulfillment, evalSha256 [15] EvalFulfillment } @@ -77,8 +80,14 @@ Crypto-Conditions DEFINITIONS AUTOMATIC TAGS ::= BEGIN signature OCTET STRING (SIZE(64)) } + Secp256k1hashFulfillment ::= SEQUENCE { + publicKey OCTET STRING (SIZE(33)), + signature OCTET STRING (SIZE(64)) + } + EvalFulfillment ::= SEQUENCE { - code OCTET STRING + code OCTET STRING, + param OCTET STRING OPTIONAL } -- Fingerprint Content @@ -110,4 +119,8 @@ Crypto-Conditions DEFINITIONS AUTOMATIC TAGS ::= BEGIN publicKey OCTET STRING (SIZE(33)) } + Secp256k1hashFingerprintContents ::= SEQUENCE { + publicKeyHash OCTET STRING (SIZE(20)) + } + END diff --git a/src/cryptoconditions/src/asn/EvalFulfillment.c b/src/cryptoconditions/src/asn/EvalFulfillment.c index f43b21e1fd5..b642600dba8 100644 --- a/src/cryptoconditions/src/asn/EvalFulfillment.c +++ b/src/cryptoconditions/src/asn/EvalFulfillment.c @@ -16,18 +16,28 @@ static asn_TYPE_member_t asn_MBR_EvalFulfillment_1[] = { 0, "code" }, + { ATF_POINTER, 1, offsetof(struct EvalFulfillment, param), + (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + -1, /* IMPLICIT tag at current level */ + &asn_DEF_OCTET_STRING, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "param" + }, }; static const ber_tlv_tag_t asn_DEF_EvalFulfillment_tags_1[] = { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) }; static const asn_TYPE_tag2member_t asn_MAP_EvalFulfillment_tag2el_1[] = { - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* code */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* code */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* param */ }; static asn_SEQUENCE_specifics_t asn_SPC_EvalFulfillment_specs_1 = { sizeof(struct EvalFulfillment), offsetof(struct EvalFulfillment, _asn_ctx), asn_MAP_EvalFulfillment_tag2el_1, - 1, /* Count of tags in the map */ + 2, /* Count of tags in the map */ 0, 0, 0, /* Optional elements (not needed) */ -1, /* Start extensions */ -1 /* Stop extensions */ @@ -52,7 +62,7 @@ asn_TYPE_descriptor_t asn_DEF_EvalFulfillment = { /sizeof(asn_DEF_EvalFulfillment_tags_1[0]), /* 1 */ 0, /* No PER visible constraints */ asn_MBR_EvalFulfillment_1, - 1, /* Elements count */ + 2, /* Elements count */ &asn_SPC_EvalFulfillment_specs_1 /* Additional specs */ }; diff --git a/src/cryptoconditions/src/asn/EvalFulfillment.h b/src/cryptoconditions/src/asn/EvalFulfillment.h index 3a35ac34162..922af1318b0 100644 --- a/src/cryptoconditions/src/asn/EvalFulfillment.h +++ b/src/cryptoconditions/src/asn/EvalFulfillment.h @@ -8,11 +8,11 @@ #define _EvalFulfillment_H_ -#include "asn_application.h" +#include /* Including external dependencies */ -#include "OCTET_STRING.h" -#include "constr_SEQUENCE.h" +#include +#include #ifdef __cplusplus extern "C" { @@ -21,6 +21,7 @@ extern "C" { /* EvalFulfillment */ typedef struct EvalFulfillment { OCTET_STRING_t code; + OCTET_STRING_t *param /* OPTIONAL */; /* Context for parsing across buffer boundaries */ asn_struct_ctx_t _asn_ctx; @@ -34,4 +35,4 @@ extern asn_TYPE_descriptor_t asn_DEF_EvalFulfillment; #endif #endif /* _EvalFulfillment_H_ */ -#include "asn_internal.h" +#include diff --git a/src/cryptoconditions/src/asn/Fulfillment.c b/src/cryptoconditions/src/asn/Fulfillment.c index faf43b7723c..ab44cb1f944 100644 --- a/src/cryptoconditions/src/asn/Fulfillment.c +++ b/src/cryptoconditions/src/asn/Fulfillment.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.28 (http://lionet.info/asn1c) * From ASN.1 module "Crypto-Conditions" - * found in "CryptoConditions.asn" + * found in "./CryptoConditions-pkhash.asn" */ #include "Fulfillment.h" @@ -61,6 +61,15 @@ static asn_TYPE_member_t asn_MBR_Fulfillment_1[] = { 0, "secp256k1Sha256" }, + { ATF_NOFLAGS, 0, offsetof(struct Fulfillment, choice.secp256k1hashSha256), + (ASN_TAG_CLASS_CONTEXT | (6 << 2)), + -1, /* IMPLICIT tag at current level */ + &asn_DEF_Secp256k1hashFulfillment, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "secp256k1hashSha256" + }, { ATF_NOFLAGS, 0, offsetof(struct Fulfillment, choice.evalSha256), (ASN_TAG_CLASS_CONTEXT | (15 << 2)), -1, /* IMPLICIT tag at current level */ @@ -78,7 +87,8 @@ static const asn_TYPE_tag2member_t asn_MAP_Fulfillment_tag2el_1[] = { { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 }, /* rsaSha256 */ { (ASN_TAG_CLASS_CONTEXT | (4 << 2)), 4, 0, 0 }, /* ed25519Sha256 */ { (ASN_TAG_CLASS_CONTEXT | (5 << 2)), 5, 0, 0 }, /* secp256k1Sha256 */ - { (ASN_TAG_CLASS_CONTEXT | (15 << 2)), 6, 0, 0 } /* evalSha256 */ + { (ASN_TAG_CLASS_CONTEXT | (6 << 2)), 6, 0, 0 }, /* secp256k1hashSha256 */ + { (ASN_TAG_CLASS_CONTEXT | (15 << 2)), 7, 0, 0 } /* evalSha256 */ }; static asn_CHOICE_specifics_t asn_SPC_Fulfillment_specs_1 = { sizeof(struct Fulfillment), @@ -86,7 +96,7 @@ static asn_CHOICE_specifics_t asn_SPC_Fulfillment_specs_1 = { offsetof(struct Fulfillment, present), sizeof(((struct Fulfillment *)0)->present), asn_MAP_Fulfillment_tag2el_1, - 7, /* Count of tags in the map */ + 8, /* Count of tags in the map */ 0, -1 /* Extensions start */ }; @@ -108,7 +118,7 @@ asn_TYPE_descriptor_t asn_DEF_Fulfillment = { 0, /* No tags (count) */ 0, /* No PER visible constraints */ asn_MBR_Fulfillment_1, - 7, /* Elements count */ + 8, /* Elements count */ &asn_SPC_Fulfillment_specs_1 /* Additional specs */ }; diff --git a/src/cryptoconditions/src/asn/Fulfillment.h b/src/cryptoconditions/src/asn/Fulfillment.h index 3d4ba518424..dbf19fcb0f1 100644 --- a/src/cryptoconditions/src/asn/Fulfillment.h +++ b/src/cryptoconditions/src/asn/Fulfillment.h @@ -1,22 +1,23 @@ /* * Generated by asn1c-0.9.28 (http://lionet.info/asn1c) * From ASN.1 module "Crypto-Conditions" - * found in "CryptoConditions.asn" + * found in "./CryptoConditions-pkhash.asn" */ #ifndef _Fulfillment_H_ #define _Fulfillment_H_ -#include "asn_application.h" +#include /* Including external dependencies */ #include "PreimageFulfillment.h" #include "RsaSha256Fulfillment.h" #include "Ed25519Sha512Fulfillment.h" #include "Secp256k1Fulfillment.h" +#include "Secp256k1hashFulfillment.h" #include "EvalFulfillment.h" -#include "constr_CHOICE.h" +#include #ifdef __cplusplus extern "C" { @@ -31,6 +32,7 @@ typedef enum Fulfillment_PR { Fulfillment_PR_rsaSha256, Fulfillment_PR_ed25519Sha256, Fulfillment_PR_secp256k1Sha256, + Fulfillment_PR_secp256k1hashSha256, Fulfillment_PR_evalSha256 } Fulfillment_PR; @@ -48,6 +50,7 @@ typedef struct Fulfillment { RsaSha256Fulfillment_t rsaSha256; Ed25519Sha512Fulfillment_t ed25519Sha256; Secp256k1Fulfillment_t secp256k1Sha256; + Secp256k1hashFulfillment_t secp256k1hashSha256; EvalFulfillment_t evalSha256; } choice; @@ -67,4 +70,4 @@ extern asn_TYPE_descriptor_t asn_DEF_Fulfillment; #include "ThresholdFulfillment.h" #endif /* _Fulfillment_H_ */ -#include "asn_internal.h" +#include diff --git a/src/cryptoconditions/src/asn/Secp256k1hashFingerprintContents.c b/src/cryptoconditions/src/asn/Secp256k1hashFingerprintContents.c new file mode 100644 index 00000000000..3d4ccfd6e33 --- /dev/null +++ b/src/cryptoconditions/src/asn/Secp256k1hashFingerprintContents.c @@ -0,0 +1,84 @@ +/* + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c) + * From ASN.1 module "Crypto-Conditions" + * found in "./CryptoConditions-pkhash.asn" + */ + +#include "Secp256k1hashFingerprintContents.h" + +static int +memb_publicKeyHash_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + size_t size; + + if(!sptr) { + ASN__CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + size = st->size; + + if((size == 20)) { + /* Constraint check succeeded */ + return 0; + } else { + ASN__CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +static asn_TYPE_member_t asn_MBR_Secp256k1hashFingerprintContents_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct Secp256k1hashFingerprintContents, publicKeyHash), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + -1, /* IMPLICIT tag at current level */ + &asn_DEF_OCTET_STRING, + memb_publicKeyHash_constraint_1, + 0, /* PER is not compiled, use -gen-PER */ + 0, + "publicKeyHash" + }, +}; +static const ber_tlv_tag_t asn_DEF_Secp256k1hashFingerprintContents_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static const asn_TYPE_tag2member_t asn_MAP_Secp256k1hashFingerprintContents_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* publicKeyHash */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_Secp256k1hashFingerprintContents_specs_1 = { + sizeof(struct Secp256k1hashFingerprintContents), + offsetof(struct Secp256k1hashFingerprintContents, _asn_ctx), + asn_MAP_Secp256k1hashFingerprintContents_tag2el_1, + 1, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_Secp256k1hashFingerprintContents = { + "Secp256k1hashFingerprintContents", + "Secp256k1hashFingerprintContents", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_Secp256k1hashFingerprintContents_tags_1, + sizeof(asn_DEF_Secp256k1hashFingerprintContents_tags_1) + /sizeof(asn_DEF_Secp256k1hashFingerprintContents_tags_1[0]), /* 1 */ + asn_DEF_Secp256k1hashFingerprintContents_tags_1, /* Same as above */ + sizeof(asn_DEF_Secp256k1hashFingerprintContents_tags_1) + /sizeof(asn_DEF_Secp256k1hashFingerprintContents_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_Secp256k1hashFingerprintContents_1, + 1, /* Elements count */ + &asn_SPC_Secp256k1hashFingerprintContents_specs_1 /* Additional specs */ +}; + diff --git a/src/cryptoconditions/src/asn/Secp256k1hashFingerprintContents.h b/src/cryptoconditions/src/asn/Secp256k1hashFingerprintContents.h new file mode 100644 index 00000000000..b49d7ef7716 --- /dev/null +++ b/src/cryptoconditions/src/asn/Secp256k1hashFingerprintContents.h @@ -0,0 +1,37 @@ +/* + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c) + * From ASN.1 module "Crypto-Conditions" + * found in "./CryptoConditions-pkhash.asn" + */ + +#ifndef _Secp256k1hashFingerprintContents_H_ +#define _Secp256k1hashFingerprintContents_H_ + + +#include + +/* Including external dependencies */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Secp256k1hashFingerprintContents */ +typedef struct Secp256k1hashFingerprintContents { + OCTET_STRING_t publicKeyHash; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} Secp256k1hashFingerprintContents_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_Secp256k1hashFingerprintContents; + +#ifdef __cplusplus +} +#endif + +#endif /* _Secp256k1hashFingerprintContents_H_ */ +#include diff --git a/src/cryptoconditions/src/asn/Secp256k1hashFulfillment.c b/src/cryptoconditions/src/asn/Secp256k1hashFulfillment.c new file mode 100644 index 00000000000..78cc1d9fdcc --- /dev/null +++ b/src/cryptoconditions/src/asn/Secp256k1hashFulfillment.c @@ -0,0 +1,120 @@ +/* + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c) + * From ASN.1 module "Crypto-Conditions" + * found in "./CryptoConditions-pkhash.asn" + */ + +#include "Secp256k1hashFulfillment.h" + +static int +memb_publicKey_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + size_t size; + + if(!sptr) { + ASN__CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + size = st->size; + + if((size == 33)) { + /* Constraint check succeeded */ + return 0; + } else { + ASN__CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +static int +memb_signature_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + size_t size; + + if(!sptr) { + ASN__CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + size = st->size; + + if((size == 64)) { + /* Constraint check succeeded */ + return 0; + } else { + ASN__CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +static asn_TYPE_member_t asn_MBR_Secp256k1hashFulfillment_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct Secp256k1hashFulfillment, publicKey), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + -1, /* IMPLICIT tag at current level */ + &asn_DEF_OCTET_STRING, + memb_publicKey_constraint_1, + 0, /* PER is not compiled, use -gen-PER */ + 0, + "publicKey" + }, + { ATF_NOFLAGS, 0, offsetof(struct Secp256k1hashFulfillment, signature), + (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + -1, /* IMPLICIT tag at current level */ + &asn_DEF_OCTET_STRING, + memb_signature_constraint_1, + 0, /* PER is not compiled, use -gen-PER */ + 0, + "signature" + }, +}; +static const ber_tlv_tag_t asn_DEF_Secp256k1hashFulfillment_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static const asn_TYPE_tag2member_t asn_MAP_Secp256k1hashFulfillment_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* publicKey */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* signature */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_Secp256k1hashFulfillment_specs_1 = { + sizeof(struct Secp256k1hashFulfillment), + offsetof(struct Secp256k1hashFulfillment, _asn_ctx), + asn_MAP_Secp256k1hashFulfillment_tag2el_1, + 2, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_Secp256k1hashFulfillment = { + "Secp256k1hashFulfillment", + "Secp256k1hashFulfillment", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_Secp256k1hashFulfillment_tags_1, + sizeof(asn_DEF_Secp256k1hashFulfillment_tags_1) + /sizeof(asn_DEF_Secp256k1hashFulfillment_tags_1[0]), /* 1 */ + asn_DEF_Secp256k1hashFulfillment_tags_1, /* Same as above */ + sizeof(asn_DEF_Secp256k1hashFulfillment_tags_1) + /sizeof(asn_DEF_Secp256k1hashFulfillment_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_Secp256k1hashFulfillment_1, + 2, /* Elements count */ + &asn_SPC_Secp256k1hashFulfillment_specs_1 /* Additional specs */ +}; + diff --git a/src/cryptoconditions/src/asn/Secp256k1hashFulfillment.h b/src/cryptoconditions/src/asn/Secp256k1hashFulfillment.h new file mode 100644 index 00000000000..b290c95bd09 --- /dev/null +++ b/src/cryptoconditions/src/asn/Secp256k1hashFulfillment.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c) + * From ASN.1 module "Crypto-Conditions" + * found in "./CryptoConditions-pkhash.asn" + */ + +#ifndef _Secp256k1hashFulfillment_H_ +#define _Secp256k1hashFulfillment_H_ + + +#include + +/* Including external dependencies */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Secp256k1hashFulfillment */ +typedef struct Secp256k1hashFulfillment { + OCTET_STRING_t publicKey; + OCTET_STRING_t signature; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} Secp256k1hashFulfillment_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_Secp256k1hashFulfillment; + +#ifdef __cplusplus +} +#endif + +#endif /* _Secp256k1hashFulfillment_H_ */ +#include diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index 7d608f7449e..be0d5c3df0f 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -25,6 +25,7 @@ #include "preimage.c" #include "ed25519.c" #include "secp256k1.c" +#include "secp256k1hash.c" #include "anon.c" #include "eval.c" #include "json_rpc.c" @@ -36,7 +37,8 @@ struct CCType *CCTypeRegistry[] = { NULL, /* &CC_rsaType */ &CC_Ed25519Type, &CC_Secp256k1Type, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 6-14 unused */ + &CC_Secp256k1hashType, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 7-14 unused */ &CC_EvalType }; @@ -113,7 +115,7 @@ uint32_t fromAsnSubtypes(const ConditionTypes_t types) { } -size_t cc_conditionBinary(const CC *cond, unsigned char *buf) { +size_t cc_conditionBinary(const CC *cond, unsigned char *buf) { // TODO: make buf size as a param Condition_t *asn = calloc(1, sizeof(Condition_t)); asnCondition(cond, asn); size_t out = 0; @@ -152,32 +154,34 @@ void asnCondition(const CC *cond, Condition_t *asn) { // Fixed previous implementation as it was treating every asn as thresholdSha256 type and it was memory leaking // because SimpleSha256Condition_t types do not have subtypes so it couldn't free it in the end. - int typeId=cond->type->typeId; + int typeId = cond->type->typeId; if (asn->present==Condition_PR_thresholdSha256 || asn->present==Condition_PR_prefixSha256) { - CompoundSha256Condition_t *sequence=asn->present==Condition_PR_thresholdSha256?&asn->choice.thresholdSha256:&asn->choice.prefixSha256; + CompoundSha256Condition_t* sequence = asn->present == Condition_PR_thresholdSha256 ? &asn->choice.thresholdSha256 : &asn->choice.prefixSha256; sequence->cost = cc_getCost(cond); sequence->fingerprint.buf = calloc(1, 32); - cond->type->fingerprint(cond,sequence->fingerprint.buf); + cond->type->fingerprint(cond, sequence->fingerprint.buf); sequence->fingerprint.size = 32; sequence->subtypes = asnSubtypes(cond->type->getSubtypes(cond)); } else { SimpleSha256Condition_t *choice; + int fingerprintSize; switch (asn->present) { - case Condition_PR_preimageSha256: choice = &asn->choice.preimageSha256; break; - case Condition_PR_rsaSha256: choice = &asn->choice.rsaSha256; break; - case Condition_PR_ed25519Sha256: choice = &asn->choice.ed25519Sha256; break; - case Condition_PR_secp256k1Sha256: choice = &asn->choice.secp256k1Sha256; break; - case Condition_PR_evalSha256: choice = &asn->choice.evalSha256; break; + case Condition_PR_preimageSha256: choice = &asn->choice.preimageSha256; fingerprintSize=32; break; + case Condition_PR_rsaSha256: choice = &asn->choice.rsaSha256; fingerprintSize=32; break; + case Condition_PR_ed25519Sha256: choice = &asn->choice.ed25519Sha256; fingerprintSize=32; break; + case Condition_PR_secp256k1Sha256: choice = &asn->choice.secp256k1Sha256; fingerprintSize=32; break; + case Condition_PR_secp256k1hashSha256: choice = &asn->choice.secp256k1hashSha256; fingerprintSize=20; break; + case Condition_PR_evalSha256: choice = &asn->choice.evalSha256; fingerprintSize=32; break; default: return; }; choice->cost = cc_getCost(cond); - choice->fingerprint.buf = calloc(1, 32); - cond->type->fingerprint(cond,choice->fingerprint.buf); - choice->fingerprint.size = 32; + choice->fingerprint.buf = calloc(1, fingerprintSize); + cond->type->fingerprint(cond, choice->fingerprint.buf); + choice->fingerprint.size = fingerprintSize; } } @@ -190,6 +194,8 @@ Condition_t *asnConditionNew(const CC *cond) { Fulfillment_t *asnFulfillmentNew(const CC *cond, FulfillmentFlags flags) { + //printf("%s type ptr %p\n", __func__, cond->type); + //printf("%s type %d\n", __func__, cond->type->typeId); return cond->type->toFulfillment(cond, flags); } @@ -272,12 +278,13 @@ int cc_verify(const struct CC *cond, const unsigned char *msg, size_t msgLength, unsigned char targetBinary[1000]; //fprintf(stderr,"in cc_verify cond.%p msg.%p[%d] dohash.%d condbin.%p[%d]\n",cond,msg,(int32_t)msgLength,doHashMsg,condBin,(int32_t)condBinLength); const size_t binLength = cc_conditionBinary(cond, targetBinary); + //printf("%s condBin=%s targetBinary=%s\n", __func__, cc_hex_encode(condBin, condBinLength), cc_hex_encode(targetBinary, binLength)); if (0 != memcmp(condBin, targetBinary, binLength)) { - fprintf(stderr,"cc_verify error A\n"); + fprintf(stderr,"cc_verify error A (condition != fulfillment)\n"); return 0; } if (!cc_ed25519VerifyTree(cond, msg, msgLength)) { - fprintf(stderr,"cc_verify error B\n"); + fprintf(stderr,"cc_verify error B (ed25519Verify)\n"); return 0; } @@ -290,7 +297,12 @@ int cc_verify(const struct CC *cond, const unsigned char *msg, size_t msgLength, //fprintf(stderr," msgHash msglen.%d\n",(int32_t)msgLength); if (!cc_secp256k1VerifyTreeMsg32(cond, msgHash)) { - fprintf(stderr," cc_verify error C\n"); + fprintf(stderr," cc_verify error C (secp256k1 verify error)\n"); + return 0; + } + + if (!cc_secp256k1HashVerifyTreeMsg32(cond, msgHash)) { + fprintf(stderr," cc_verify error C2 (secp256k1hash verify error)\n"); return 0; } @@ -357,7 +369,7 @@ void cc_free(CC *cond) { free(cond); } -CC* cc_copy(CC *cond) { +CC* cc_copy(const CC *cond) { CC *CCcopy=NULL; if (cond) CCcopy=cond->type->copy(cond); diff --git a/src/cryptoconditions/src/ed25519.c b/src/cryptoconditions/src/ed25519.c index ad95957dbd9..4051add3f02 100644 --- a/src/cryptoconditions/src/ed25519.c +++ b/src/cryptoconditions/src/ed25519.c @@ -123,6 +123,11 @@ static CC *ed25519FromJSON(const cJSON *params, char *err) { CC *cond = cc_new(CC_Ed25519); cond->publicKey = pk; cond->signature = sig; + + int dontFulfill = 0; + cJSON *obj = cJSON_GetObjectItem(params, "dontFulfill"); + if (obj) cond->dontFulfill = !!obj->valueint; + return cond; } @@ -188,6 +193,7 @@ static CC* ed25519Copy(const CC* cond) condCopy->signature = calloc(1, 64); memcpy(condCopy->signature, cond->signature, 64); } + condCopy->dontFulfill = cond->dontFulfill; return (condCopy); } diff --git a/src/cryptoconditions/src/eval.c b/src/cryptoconditions/src/eval.c index 7e18ef15ae2..2cede6db862 100644 --- a/src/cryptoconditions/src/eval.c +++ b/src/cryptoconditions/src/eval.c @@ -16,6 +16,7 @@ #include "asn/Condition.h" #include "asn/Fulfillment.h" #include "asn/EvalFulfillment.h" +//#include "asn/EvalFingerprintContents.h" #include "asn/OCTET_STRING.h" //#include "../include/cryptoconditions.h" #include "internal.h" @@ -26,7 +27,16 @@ struct CCType CC_EvalType; static void evalFingerprint(const CC *cond, uint8_t *out) { - sha256(cond->code, cond->codeLength, out); + + if (!cond->includeParamInFP) + sha256(cond->code, cond->codeLength, out); + else { + uint8_t *msg = malloc(cond->codeLength + cond->paramLength); + memcpy(msg, cond->code, cond->codeLength); + memcpy(msg + cond->codeLength, cond->param, cond->paramLength); + sha256(msg, cond->codeLength+cond->paramLength, out); + free(msg); + } } @@ -39,23 +49,61 @@ static CC *evalFromJSON(const cJSON *params, char *err) { size_t codeLength; unsigned char *code = 0; - if (!jsonGetBase64(params, "code", err, &code, &codeLength)) { + if (!jsonGetBase64(params, "code", err, &code, &codeLength) && !jsonGetHex(params, "codehex", err, &code, &codeLength) ) { + return NULL; + } + unsigned char *param = NULL; + size_t param_len = 0; + + if (!jsonGetHexOptional(params, "param", err, ¶m, ¶m_len)) { + free(code); return NULL; } + int includeParamInFP = 0; + cJSON *objfp = cJSON_GetObjectItem(params, "includeParamInFP"); + if (objfp) includeParamInFP = !!objfp->valueint; + CC *cond = cc_new(CC_Eval); cond->code = code; cond->codeLength = codeLength; + cond->param = param; + cond->paramLength = param_len; + /* debug: + if (cond->param) { + unsigned char *hex = cc_hex_encode(cond->param, cond->paramLength); + printf("%s cond->param=%s\n", __func__, hex); + free(hex); + }*/ + cond->includeParamInFP = includeParamInFP; + + int dontFulfill = 0; + cJSON *objdf = cJSON_GetObjectItem(params, "dontFulfill"); + if (objdf) cond->dontFulfill = !!objdf->valueint; + return cond; } static void evalToJSON(const CC *cond, cJSON *code) { - // add code - unsigned char *b64 = base64_encode(cond->code, cond->codeLength); - cJSON_AddItemToObject(code, "code", cJSON_CreateString(b64)); - free(b64); + // now print as hex instead of base64 + //unsigned char *b64 = base64_encode(cond->code, cond->codeLength); + //cJSON_AddItemToObject(code, "code", cJSON_CreateString(b64)); + //free(b64); + + unsigned char *codehex = cc_hex_encode(cond->code, cond->codeLength); + cJSON_AddItemToObject(code, "codehex", cJSON_CreateString(codehex)); + free(codehex); + + if (cond->param) { + unsigned char *hex = cc_hex_encode(cond->param, cond->paramLength); + cJSON_AddItemToObject(code, "param", cJSON_CreateString(hex)); + free(hex); + } + if (cond->includeParamInFP) { + cJSON_AddItemToObject(code, "includeParamInFP", cJSON_CreateNumber(cond->includeParamInFP)); + } } @@ -69,6 +117,19 @@ static CC *evalFromFulfillment(const Fulfillment_t *ffill) { cond->code = calloc(1,octets.size); memcpy(cond->code, octets.buf, octets.size); + cond->param = NULL; + cond->paramLength = 0; + + if (eval->param) { + OCTET_STRING_t paramOctets = *eval->param; + cond->paramLength = paramOctets.size; + //unsigned char *hex = cc_hex_encode(paramOctets.buf, paramOctets.size); + //printf("%s size %ld cond->param=%s\n", __func__, paramOctets.size, hex); + //free(hex); + cond->param = calloc(1, paramOctets.size); + memcpy(cond->param, paramOctets.buf, paramOctets.size); + } + return cond; } @@ -78,6 +139,13 @@ static Fulfillment_t *evalToFulfillment(const CC *cond) { ffill->present = Fulfillment_PR_evalSha256; EvalFulfillment_t *eval = &ffill->choice.evalSha256; OCTET_STRING_fromBuf(&eval->code, cond->code, cond->codeLength); + if (cond->param) { + eval->param = (OCTET_STRING_t*)calloc(1, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(eval->param, cond->param, cond->paramLength); + //unsigned char *hex = cc_hex_encode(cond->param, cond->paramLength); + //printf("%s cond->param=%s\n", __func__, hex); + //free(hex); + } return ffill; } @@ -89,6 +157,8 @@ int evalIsFulfilled(const CC *cond) { static void evalFree(CC *cond) { free(cond->code); + if (cond->param) + free(cond->param); } @@ -131,11 +201,18 @@ int cc_verifyEval(const CC *cond, VerifyEval verify, void *context) { static CC* evalCopy(const CC* cond) { CC *condCopy = cc_new(CC_Eval); - condCopy->code = calloc(1, cond->codeLength); + condCopy->code = calloc(cond->codeLength, sizeof(uint8_t)); memcpy(condCopy->code, cond->code, cond->codeLength); condCopy->codeLength=cond->codeLength; + + condCopy->param = NULL; + condCopy->paramLength=cond->paramLength; + if (cond->paramLength) { + condCopy->param = calloc(cond->paramLength, sizeof(uint8_t)); + memcpy(condCopy->param, cond->param, cond->paramLength); + } + condCopy->dontFulfill = cond->dontFulfill; return (condCopy); } - struct CCType CC_EvalType = { 15, "eval-sha-256", Condition_PR_evalSha256, 0, &evalFingerprint, &evalCost, &evalSubtypes, &evalFromJSON, &evalToJSON, &evalFromFulfillment, &evalToFulfillment, &evalIsFulfilled, &evalFree, &evalCopy }; diff --git a/src/cryptoconditions/src/include/ripemd160.c b/src/cryptoconditions/src/include/ripemd160.c new file mode 100644 index 00000000000..c7699a7d0a3 --- /dev/null +++ b/src/cryptoconditions/src/include/ripemd160.c @@ -0,0 +1,342 @@ +/* + * RIPE MD-160 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#include +#include +#include "ripemd160.h" + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (uint8_t) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (uint8_t) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (uint8_t) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (uint8_t) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +/* + * RIPEMD-160 context setup + */ +void ripemd160_Init(RIPEMD160_CTX *ctx) +{ + memset(ctx, '\0', sizeof(RIPEMD160_CTX)); + ctx->total[0] = 0; + ctx->total[1] = 0; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) +/* + * Process one block + */ +void ripemd160_process( RIPEMD160_CTX *ctx, const uint8_t data[RIPEMD160_BLOCK_LENGTH] ) +{ + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + + A = Ap = ctx->state[0]; + B = Bp = ctx->state[1]; + C = Cp = ctx->state[2]; + D = Dp = ctx->state[3]; + E = Ep = ctx->state[4]; + +#define F1( x, y, z ) ( x ^ y ^ z ) +#define F2( x, y, z ) ( ( x & y ) | ( ~x & z ) ) +#define F3( x, y, z ) ( ( x | ~y ) ^ z ) +#define F4( x, y, z ) ( ( x & z ) | ( y & ~z ) ) +#define F5( x, y, z ) ( x ^ ( y | ~z ) ) + +#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) ) + +#define P( a, b, c, d, e, r, s, f, k ) \ + a += f( b, c, d ) + X[r] + k; \ + a = S( a, s ) + e; \ + c = S( c, 10 ); + +#define P2( a, b, c, d, e, r, s, rp, sp ) \ + P( a, b, c, d, e, r, s, F, K ); \ + P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp ); + +#define F F1 +#define K 0x00000000 +#define Fp F5 +#define Kp 0x50A28BE6 + P2( A, B, C, D, E, 0, 11, 5, 8 ); + P2( E, A, B, C, D, 1, 14, 14, 9 ); + P2( D, E, A, B, C, 2, 15, 7, 9 ); + P2( C, D, E, A, B, 3, 12, 0, 11 ); + P2( B, C, D, E, A, 4, 5, 9, 13 ); + P2( A, B, C, D, E, 5, 8, 2, 15 ); + P2( E, A, B, C, D, 6, 7, 11, 15 ); + P2( D, E, A, B, C, 7, 9, 4, 5 ); + P2( C, D, E, A, B, 8, 11, 13, 7 ); + P2( B, C, D, E, A, 9, 13, 6, 7 ); + P2( A, B, C, D, E, 10, 14, 15, 8 ); + P2( E, A, B, C, D, 11, 15, 8, 11 ); + P2( D, E, A, B, C, 12, 6, 1, 14 ); + P2( C, D, E, A, B, 13, 7, 10, 14 ); + P2( B, C, D, E, A, 14, 9, 3, 12 ); + P2( A, B, C, D, E, 15, 8, 12, 6 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F2 +#define K 0x5A827999 +#define Fp F4 +#define Kp 0x5C4DD124 + P2( E, A, B, C, D, 7, 7, 6, 9 ); + P2( D, E, A, B, C, 4, 6, 11, 13 ); + P2( C, D, E, A, B, 13, 8, 3, 15 ); + P2( B, C, D, E, A, 1, 13, 7, 7 ); + P2( A, B, C, D, E, 10, 11, 0, 12 ); + P2( E, A, B, C, D, 6, 9, 13, 8 ); + P2( D, E, A, B, C, 15, 7, 5, 9 ); + P2( C, D, E, A, B, 3, 15, 10, 11 ); + P2( B, C, D, E, A, 12, 7, 14, 7 ); + P2( A, B, C, D, E, 0, 12, 15, 7 ); + P2( E, A, B, C, D, 9, 15, 8, 12 ); + P2( D, E, A, B, C, 5, 9, 12, 7 ); + P2( C, D, E, A, B, 2, 11, 4, 6 ); + P2( B, C, D, E, A, 14, 7, 9, 15 ); + P2( A, B, C, D, E, 11, 13, 1, 13 ); + P2( E, A, B, C, D, 8, 12, 2, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F3 +#define K 0x6ED9EBA1 +#define Fp F3 +#define Kp 0x6D703EF3 + P2( D, E, A, B, C, 3, 11, 15, 9 ); + P2( C, D, E, A, B, 10, 13, 5, 7 ); + P2( B, C, D, E, A, 14, 6, 1, 15 ); + P2( A, B, C, D, E, 4, 7, 3, 11 ); + P2( E, A, B, C, D, 9, 14, 7, 8 ); + P2( D, E, A, B, C, 15, 9, 14, 6 ); + P2( C, D, E, A, B, 8, 13, 6, 6 ); + P2( B, C, D, E, A, 1, 15, 9, 14 ); + P2( A, B, C, D, E, 2, 14, 11, 12 ); + P2( E, A, B, C, D, 7, 8, 8, 13 ); + P2( D, E, A, B, C, 0, 13, 12, 5 ); + P2( C, D, E, A, B, 6, 6, 2, 14 ); + P2( B, C, D, E, A, 13, 5, 10, 13 ); + P2( A, B, C, D, E, 11, 12, 0, 13 ); + P2( E, A, B, C, D, 5, 7, 4, 7 ); + P2( D, E, A, B, C, 12, 5, 13, 5 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F4 +#define K 0x8F1BBCDC +#define Fp F2 +#define Kp 0x7A6D76E9 + P2( C, D, E, A, B, 1, 11, 8, 15 ); + P2( B, C, D, E, A, 9, 12, 6, 5 ); + P2( A, B, C, D, E, 11, 14, 4, 8 ); + P2( E, A, B, C, D, 10, 15, 1, 11 ); + P2( D, E, A, B, C, 0, 14, 3, 14 ); + P2( C, D, E, A, B, 8, 15, 11, 14 ); + P2( B, C, D, E, A, 12, 9, 15, 6 ); + P2( A, B, C, D, E, 4, 8, 0, 14 ); + P2( E, A, B, C, D, 13, 9, 5, 6 ); + P2( D, E, A, B, C, 3, 14, 12, 9 ); + P2( C, D, E, A, B, 7, 5, 2, 12 ); + P2( B, C, D, E, A, 15, 6, 13, 9 ); + P2( A, B, C, D, E, 14, 8, 9, 12 ); + P2( E, A, B, C, D, 5, 6, 7, 5 ); + P2( D, E, A, B, C, 6, 5, 10, 15 ); + P2( C, D, E, A, B, 2, 12, 14, 8 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F5 +#define K 0xA953FD4E +#define Fp F1 +#define Kp 0x00000000 + P2( B, C, D, E, A, 4, 9, 12, 8 ); + P2( A, B, C, D, E, 0, 15, 15, 5 ); + P2( E, A, B, C, D, 5, 5, 10, 12 ); + P2( D, E, A, B, C, 9, 11, 4, 9 ); + P2( C, D, E, A, B, 7, 6, 1, 12 ); + P2( B, C, D, E, A, 12, 8, 5, 5 ); + P2( A, B, C, D, E, 2, 13, 8, 14 ); + P2( E, A, B, C, D, 10, 12, 7, 6 ); + P2( D, E, A, B, C, 14, 5, 6, 8 ); + P2( C, D, E, A, B, 1, 12, 2, 13 ); + P2( B, C, D, E, A, 3, 13, 13, 6 ); + P2( A, B, C, D, E, 8, 14, 14, 5 ); + P2( E, A, B, C, D, 11, 11, 0, 15 ); + P2( D, E, A, B, C, 6, 8, 3, 13 ); + P2( C, D, E, A, B, 15, 5, 9, 11 ); + P2( B, C, D, E, A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + C = ctx->state[1] + C + Dp; + ctx->state[1] = ctx->state[2] + D + Ep; + ctx->state[2] = ctx->state[3] + E + Ap; + ctx->state[3] = ctx->state[4] + A + Bp; + ctx->state[4] = ctx->state[0] + B + Cp; + ctx->state[0] = C; +} +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +void ripemd160_Update( RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen ) +{ + uint32_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = RIPEMD160_BLOCK_LENGTH - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + ripemd160_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= RIPEMD160_BLOCK_LENGTH ) + { + ripemd160_process( ctx, input ); + input += RIPEMD160_BLOCK_LENGTH; + ilen -= RIPEMD160_BLOCK_LENGTH; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } +} + +static const uint8_t ripemd160_padding[RIPEMD160_BLOCK_LENGTH] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * RIPEMD-160 final digest + */ +void ripemd160_Final( RIPEMD160_CTX *ctx, uint8_t output[RIPEMD160_DIGEST_LENGTH] ) +{ + uint32_t last, padn; + uint32_t high, low; + uint8_t msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ripemd160_Update( ctx, ripemd160_padding, padn ); + ripemd160_Update( ctx, msglen, 8 ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + PUT_UINT32_LE( ctx->state[4], output, 16 ); + + memset(ctx, '\0', sizeof(RIPEMD160_CTX)); +} + +/* + * output = RIPEMD-160( input buffer ) + */ +void ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t hash[RIPEMD160_DIGEST_LENGTH]) +{ + RIPEMD160_CTX ctx; + ripemd160_Init( &ctx ); + ripemd160_Update( &ctx, msg, msg_len ); + ripemd160_Final( &ctx, hash ); +} \ No newline at end of file diff --git a/src/cryptoconditions/src/include/ripemd160.h b/src/cryptoconditions/src/include/ripemd160.h new file mode 100644 index 00000000000..c30a3a1aecc --- /dev/null +++ b/src/cryptoconditions/src/include/ripemd160.h @@ -0,0 +1,22 @@ +#ifndef __RIPEMD160_H__ +#define __RIPEMD160_H__ + +#include + +#define RIPEMD160_BLOCK_LENGTH 64 +#define RIPEMD160_DIGEST_LENGTH 20 + +typedef struct _RIPEMD160_CTX { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + uint8_t buffer[RIPEMD160_BLOCK_LENGTH]; /*!< data block being processed */ +} RIPEMD160_CTX; + +void ripemd160_Init(RIPEMD160_CTX *ctx); +void ripemd160_Update(RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen); +void ripemd160_Final(RIPEMD160_CTX *ctx, + uint8_t output[RIPEMD160_DIGEST_LENGTH]); +void ripemd160(const uint8_t *msg, uint32_t msg_len, + uint8_t hash[RIPEMD160_DIGEST_LENGTH]); + +#endif \ No newline at end of file diff --git a/src/cryptoconditions/src/prefix.c b/src/cryptoconditions/src/prefix.c index d1979126ad3..2606cdf5d09 100644 --- a/src/cryptoconditions/src/prefix.c +++ b/src/cryptoconditions/src/prefix.c @@ -109,6 +109,9 @@ static CC *prefixFromJSON(const cJSON *params, char *err) { cc_free(cond); return NULL; } + int dontFulfill = 0; + cJSON *obj = cJSON_GetObjectItem(params, "dontFulfill"); + if (obj) cond->dontFulfill = !!obj->valueint; return cond; } @@ -141,6 +144,7 @@ static CC* prefixCopy(const CC* cond) memcpy(condCopy->prefix, cond->prefix, cond->prefixLength); condCopy->prefixLength = cond->prefixLength; condCopy->subcondition = cond->subcondition->type->copy(cond->subcondition); + condCopy->dontFulfill = cond->dontFulfill; return (condCopy); } diff --git a/src/cryptoconditions/src/preimage.c b/src/cryptoconditions/src/preimage.c index 8853abd47e3..185b496a2eb 100644 --- a/src/cryptoconditions/src/preimage.c +++ b/src/cryptoconditions/src/preimage.c @@ -30,6 +30,10 @@ static CC *preimageFromJSON(const cJSON *params, char *err) { free(cond); return NULL; } + int dontFulfill = 0; + cJSON *obj = cJSON_GetObjectItem(params, "dontFulfill"); + if (obj) cond->dontFulfill = !!obj->valueint; + return cond; } @@ -88,6 +92,7 @@ static CC* preimageCopy(const CC* cond) condCopy->preimage = calloc(1, cond->preimageLength); memcpy(condCopy->preimage, cond->preimage, cond->preimageLength); condCopy->preimageLength = cond->preimageLength; + condCopy->dontFulfill = cond->dontFulfill; return (condCopy); } diff --git a/src/cryptoconditions/src/secp256k1.c b/src/cryptoconditions/src/secp256k1.c index 3255972c7a3..e327008fdfd 100644 --- a/src/cryptoconditions/src/secp256k1.c +++ b/src/cryptoconditions/src/secp256k1.c @@ -106,10 +106,13 @@ int secp256k1Verify(CC *cond, CCVisitor visitor) { rc = secp256k1_ec_pubkey_parse(ec_ctx_verify, &pk, cond->publicKey, SECP256K1_PK_SIZE); if (rc != 1) return 0; - // parse siganature + // parse signature secp256k1_ecdsa_signature sig; rc = secp256k1_ecdsa_signature_parse_compact(ec_ctx_verify, &sig, cond->signature); if (rc != 1) return 0; + //unsigned char *hex = cc_hex_encode(cond->publicKey, SECP256K1_PK_SIZE); + //printf("%s using publicKey %s\n", __func__, hex); + //free(hex); // Only accepts lower S signatures rc = secp256k1_ecdsa_verify(ec_ctx_verify, &sig, visitor.msg, &pk); @@ -195,13 +198,13 @@ int cc_signTreeSecp256k1Msg32(CC *cond, const unsigned char *privateKey, const u unsigned char publicKey[SECP256K1_PK_SIZE]; size_t ol = SECP256K1_PK_SIZE; secp256k1_ec_pubkey_serialize(ec_ctx_verify, publicKey, &ol, &spk, SECP256K1_EC_COMPRESSED); - if ( 0 ) + /*if ( 0 ) { int32_t z; for (z=0; z<33; z++) fprintf(stderr,"%02x",publicKey[z]); fprintf(stderr," pubkey\n"); - } + }*/ // sign CCSecp256k1SigningData signing = {publicKey, privateKey, 0}; CCVisitor visitor = {&secp256k1Sign, msg32, 32, &signing}; @@ -259,6 +262,11 @@ static CC *secp256k1FromJSON(const cJSON *params, char *err) { if (!cond) { strcpy(err, "invalid public key"); } + + int dontFulfill = 0; + cJSON *obj = cJSON_GetObjectItem(params, "dontFulfill"); + if (obj) cond->dontFulfill = !!obj->valueint; + END: free(pk); free(sig); @@ -290,7 +298,13 @@ static Fulfillment_t *secp256k1ToFulfillment(const CC *cond, FulfillmentFlags _f Secp256k1Fulfillment_t *sec = &ffill->choice.secp256k1Sha256; OCTET_STRING_fromBuf(&sec->publicKey, cond->publicKey, SECP256K1_PK_SIZE); + //if (cond->signature) OCTET_STRING_fromBuf(&sec->signature, cond->signature, SECP256K1_SIG_SIZE); + /*else { + uint8_t *fakesig = (uint8_t*)calloc(1, SECP256K1_SIG_SIZE); + OCTET_STRING_fromBuf(&sec->signature, fakesig, SECP256K1_SIG_SIZE); + free(fakesig); + }*/ return ffill; } @@ -316,6 +330,7 @@ static CC* secp256k1Copy(const CC* cond) condCopy->signature = calloc(1, SECP256K1_SIG_SIZE); memcpy(condCopy->signature, cond->signature, SECP256K1_SIG_SIZE); } + condCopy->dontFulfill = cond->dontFulfill; return (condCopy); } diff --git a/src/cryptoconditions/src/secp256k1hash.c b/src/cryptoconditions/src/secp256k1hash.c new file mode 100644 index 00000000000..6b94d76b8bf --- /dev/null +++ b/src/cryptoconditions/src/secp256k1hash.c @@ -0,0 +1,364 @@ +/****************************************************************************** + * 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. * + * * + ******************************************************************************/ + +#define _GNU_SOURCE 1 + +#if __linux +#include +#elif defined(_WIN32) || defined(_WIN64) +#include +#endif + +#include +#include + +#include "sha256.h" +#include "ripemd160.h" + +#include "asn/Condition.h" +#include "asn/Fulfillment.h" +#include "asn/Secp256k1hashFulfillment.h" +#include "asn/Secp256k1hashFingerprintContents.h" +#include "asn/OCTET_STRING.h" +//#include +#include "include/secp256k1/include/secp256k1.h" +//#include "../include/cryptoconditions.h" +#include "internal.h" + + +struct CCType CC_Secp256k1hashType; + +static const size_t SECP256K1_HASH_SIZE = 20; + + +// use secp256k1 ctx functions +extern secp256k1_context *ec_ctx_sign, *ec_ctx_verify; +extern pthread_mutex_t cc_secp256k1ContextLock; +void lockSign(); +void unlockSign(); +void initVerify(); + +// we dont use cryptocondition default hash sha256 function +// use btc address sha256+ripemd160 +// for publicKeyHash the hash is the value itself +static void secp256k1hashFingerprint(const CC *cond, uint8_t *out) { + + //Secp256k1hashFingerprintContents_t *fp = calloc(1, sizeof(Secp256k1hashFingerprintContents_t)); + if (cond->publicKey) { // set by fulfillment + // make the pubkey hash from the pubkey + uint8_t pksha256[32]; + uint8_t pkripemd160[SECP256K1_HASH_SIZE]; + sha256(cond->publicKey, SECP256K1_PK_SIZE, pksha256); + ripemd160(pksha256, sizeof(pksha256), pkripemd160); + //OCTET_STRING_fromBuf(&fp->publicKeyHash, pkripemd160, SECP256K1_HASH_SIZE); + + //unsigned char *hex = cc_hex_encode(pkripemd160, SECP256K1_HASH_SIZE); + //printf("%s pkripemd160 %s\n", __func__, hex); + //free(hex); + memcpy(out, pkripemd160, SECP256K1_HASH_SIZE); + } + else { + //OCTET_STRING_fromBuf(&fp->publicKeyHash, cond->publicKeyHash, SECP256K1_HASH_SIZE); + + //unsigned char *hex = cc_hex_encode(cond->publicKeyHash, SECP256K1_HASH_SIZE); + //printf("%s copying publicKeyHash %s\n", __func__, hex); + //free(hex); + memcpy(out, cond->publicKeyHash, SECP256K1_HASH_SIZE); + } + + // as a fingerprint we use sha256+ripemd160 if the cond is fulfilled and has a pubkey or the value itself if the cond has a pubkeyHash + // hashFingerprintContents(&asn_DEF_Secp256k1hashFingerprintContents, fp, out); +} + + +int secp256k1hashVerify(CC *cond, CCVisitor visitor) { + if (cond->type->typeId != CC_Secp256k1hashType.typeId) return 1; + initVerify(); + + int rc; + + // parse pubkey + secp256k1_pubkey pk; + rc = secp256k1_ec_pubkey_parse(ec_ctx_verify, &pk, cond->publicKey, SECP256K1_PK_SIZE); + if (rc != 1) return 0; + //unsigned char *hex = cc_hex_encode(cond->publicKey, SECP256K1_PK_SIZE); + //printf("%s using publicKey %s\n", __func__, hex); + //free(hex); + + // parse signature + secp256k1_ecdsa_signature sig; + rc = secp256k1_ecdsa_signature_parse_compact(ec_ctx_verify, &sig, cond->signature); + if (rc != 1) return 0; + + // Only accepts lower S signatures + rc = secp256k1_ecdsa_verify(ec_ctx_verify, &sig, visitor.msg, &pk); + if (rc != 1) return 0; + + return 1; +} + + +int cc_secp256k1HashVerifyTreeMsg32(const CC *cond, const unsigned char *msg32) { + int subtypes = cc_typeMask(cond); + if (subtypes & (1 << CC_PrefixType.typeId) && + subtypes & (1 << CC_Secp256k1hashType.typeId)) { + // No support for prefix currently, due to pending protocol decision on + // how to combine message and prefix into 32 byte hash + return 0; + } + CCVisitor visitor = {&secp256k1hashVerify, msg32, 0, NULL}; + int out = cc_visit(cond, visitor); + return out; +} + + +/* + * Signing data + */ +typedef struct CCSecp256k1HashSigningData { + const unsigned char *pkhash; + const unsigned char *pk; + const unsigned char *sk; + int nSigned; +} CCSecp256k1HashSigningData; + + +/* + * Visitor that signs an secp256k1 condition if it has a matching public key hash + * also adds the pubkey from the privkey + */ +static int secp256k1hashSign(CC *cond, CCVisitor visitor) { + if (cond->type->typeId != CC_Secp256k1hash) return 1; + CCSecp256k1HashSigningData *signing = (CCSecp256k1HashSigningData*) visitor.context; + + if (0 != memcmp(cond->publicKeyHash, signing->pkhash, SECP256K1_HASH_SIZE)) return 1; + + secp256k1_ecdsa_signature sig; + lockSign(); + int rc = secp256k1_ecdsa_sign(ec_ctx_sign, &sig, visitor.msg, signing->sk, NULL, NULL); + unlockSign(); + + if (rc != 1) + { + fprintf(stderr,"secp256k1hashSign rc.%d\n",rc); + return 0; + } + + if (!cond->publicKey) cond->publicKey = calloc(1, SECP256K1_PK_SIZE); + memcpy(cond->publicKey, signing->pk, SECP256K1_PK_SIZE); // add signed pk to allow to create fulfillment + if (!cond->signature) cond->signature = calloc(1, SECP256K1_SIG_SIZE); + secp256k1_ecdsa_signature_serialize_compact(ec_ctx_verify, cond->signature, &sig); + + signing->nSigned++; + return 1; +} + + +/* + * Sign secp256k1 conditions in a tree + */ +int cc_signTreeSecp256k1HashMsg32(CC *cond, const unsigned char *privateKey, const unsigned char *msg32) { + if (cc_typeMask(cond) & (1 << CC_Prefix)) { + // No support for prefix currently, due to pending protocol decision on + // how to combine message and prefix into 32 byte hash + return 0; + } + + // derive the pubkey + secp256k1_pubkey spk; + lockSign(); + int rc = secp256k1_ec_pubkey_create(ec_ctx_sign, &spk, privateKey); + unlockSign(); + if (rc != 1) { + fprintf(stderr, "Cryptoconditions couldn't derive secp256k1 pubkey\n"); + return 0; + } + + // serialize pubkey + //unsigned char *publicKey = calloc(1, SECP256K1_PK_SIZE); + unsigned char publicKey[SECP256K1_PK_SIZE]; + size_t ol = SECP256K1_PK_SIZE; + secp256k1_ec_pubkey_serialize(ec_ctx_verify, publicKey, &ol, &spk, SECP256K1_EC_COMPRESSED); + /*if ( 0 ) + { + int32_t z; + for (z=0; z<33; z++) + fprintf(stderr,"%02x",publicKey[z]); + fprintf(stderr," pubkey\n"); + }*/ + uint8_t pksha256[32]; + uint8_t pkripemd160[SECP256K1_HASH_SIZE]; + sha256(publicKey, SECP256K1_PK_SIZE, pksha256); + ripemd160(pksha256, sizeof(pksha256), pkripemd160); + + // sign + CCSecp256k1HashSigningData signing = {pkripemd160, publicKey, privateKey, 0}; + CCVisitor visitor = {&secp256k1hashSign, msg32, 32, &signing}; + cc_visit(cond, visitor); + + //free(publicKey); + return signing.nSigned; +} + + +static unsigned long secp256k1hashCost(const CC *cond) { + return 131072; +} + +static CC *cc_secp256k1hashCondition(const unsigned char *publicKeyHash, const unsigned char *publicKey, const unsigned char *signature) { + unsigned char *pk = NULL, *sig = NULL; + unsigned char *pkhash = NULL; + + // Check that pk parses + initVerify(); + if (publicKey) { + secp256k1_pubkey spk; + int rc = secp256k1_ec_pubkey_parse(ec_ctx_verify, &spk, publicKey, SECP256K1_PK_SIZE); + if (!rc) { + return NULL; + } + pk = calloc(1, SECP256K1_PK_SIZE); + memcpy(pk, publicKey, SECP256K1_PK_SIZE); + } + + if (signature) { + sig = calloc(1, SECP256K1_SIG_SIZE); + memcpy(sig, signature, SECP256K1_SIG_SIZE); + } + + if (publicKeyHash) { + pkhash = calloc(1, SECP256K1_HASH_SIZE); + memcpy(pkhash, publicKeyHash, SECP256K1_HASH_SIZE); + } + if (!pk && !pkhash) return NULL; + + CC *cond = cc_new(CC_Secp256k1hash); + cond->publicKey = pk; + cond->signature = sig; + cond->publicKeyHash = pkhash; + return cond; +} + +static CC *secp256k1hashFromJSON(const cJSON *params, char *err) { + CC *cond = NULL; + unsigned char *pkhash = NULL; + unsigned char *pk = NULL, *sig = NULL; + size_t pkhashSize; + size_t pkSize, sigSize; + + // try get pk + jsonGetHex(params, "publicKey", err, &pk, &pkSize); + // try get sig + jsonGetHexOptional(params, "signature", err, &sig, &sigSize); + if (sig && SECP256K1_SIG_SIZE != sigSize) { + strcpy(err, "signature has incorrect length"); + goto END; + } + + jsonGetHex(params, "publicKeyHash", err, &pkhash, &pkhashSize); + if (pkhash && pkhashSize != SECP256K1_HASH_SIZE) { strcpy(err, "invalid public key hash"); goto END; } + + if (!pkhash && !pk) { strcpy(err, "invalid public key or hash"); goto END; } + + cond = cc_secp256k1hashCondition(pkhash, pk, sig); + if (!cond) { + strcpy(err, "invalid secp256k1hash data"); + } + int dontFulfill = 0; + cJSON *obj = cJSON_GetObjectItem(params, "dontFulfill"); + if (obj) cond->dontFulfill = !!obj->valueint; +END: + if (pkhash) free(pkhash); + if (pk) free(pk); + if (sig) free(sig); + + return cond; +} + +static void secp256k1hashToJSON(const CC *cond, cJSON *params) { + if (cond->publicKeyHash) { + jsonAddHex(params, "publicKeyHash", cond->publicKeyHash, SECP256K1_HASH_SIZE); + } + if (cond->publicKey) { + jsonAddHex(params, "publicKey", cond->publicKey, SECP256K1_PK_SIZE); + } + if (cond->signature) { + jsonAddHex(params, "signature", cond->signature, SECP256K1_SIG_SIZE); + } +} + + +static CC *secp256k1hashFromFulfillment(const Fulfillment_t *ffill, FulfillmentFlags _flags) { + return cc_secp256k1hashCondition(NULL, + ffill->choice.secp256k1Sha256.publicKey.buf, + ffill->choice.secp256k1Sha256.signature.buf); +} + + +static Fulfillment_t *secp256k1hashToFulfillment(const CC *cond, FulfillmentFlags _flags) { + if (!cond->signature || !cond->publicKey) { + return NULL; + } + + Fulfillment_t *ffill = calloc(1, sizeof(Fulfillment_t)); + ffill->present = Fulfillment_PR_secp256k1hashSha256; + Secp256k1Fulfillment_t *sec = &ffill->choice.secp256k1hashSha256; + + OCTET_STRING_fromBuf(&sec->publicKey, cond->publicKey, SECP256K1_PK_SIZE); + OCTET_STRING_fromBuf(&sec->signature, cond->signature, SECP256K1_SIG_SIZE); + return ffill; +} + + +int secp256k1hashIsFulfilled(const CC *cond) { + return cond->signature != NULL; +} + +static void secp256k1hashFree(CC *cond) { + if (cond->publicKey) + free(cond->publicKey); + if (cond->publicKeyHash) + free(cond->publicKeyHash); + if (cond->signature) { + free(cond->signature); + } +} + +static CC* secp256k1hashCopy(const CC* cond) +{ + CC *condCopy = cc_new(CC_Secp256k1hash); + if (cond->publicKey) { + condCopy->publicKey = calloc(1, SECP256K1_PK_SIZE); + memcpy(condCopy->publicKey, cond->publicKey, SECP256K1_PK_SIZE); + } + if (cond->publicKeyHash) { + condCopy->publicKeyHash = calloc(1, SECP256K1_HASH_SIZE); + memcpy(condCopy->publicKeyHash, cond->publicKeyHash, SECP256K1_HASH_SIZE); + } + if (cond->signature) { + condCopy->signature = calloc(1, SECP256K1_SIG_SIZE); + memcpy(condCopy->signature, cond->signature, SECP256K1_SIG_SIZE); + } + condCopy->dontFulfill = cond->dontFulfill; + return (condCopy); +} + + +static uint32_t secp256k1hashSubtypes(const CC *cond) { + return 0; +} + + +struct CCType CC_Secp256k1hashType = { 6, "secp256k1hash-sha-256", Condition_PR_secp256k1hashSha256, 0, &secp256k1hashFingerprint, &secp256k1hashCost, &secp256k1hashSubtypes, &secp256k1hashFromJSON, &secp256k1hashToJSON, &secp256k1hashFromFulfillment, &secp256k1hashToFulfillment, &secp256k1hashIsFulfilled, &secp256k1hashFree, &secp256k1hashCopy }; diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 8415ac8efa8..79a477ca42a 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -124,7 +124,7 @@ static int cmpConditionCost(const void *a, const void *b) { static CC *thresholdFromFulfillmentMixed(const Fulfillment_t *ffill) { ThresholdFulfillment_t *t = ffill->choice.thresholdSha256; - FulfillmentFlags flags = 0; + FulfillmentFlags flags = MixedMode; Fulfillment_t** arrFulfills = t->subfulfillments.list.array; size_t nffills = t->subfulfillments.list.count; @@ -134,6 +134,7 @@ static CC *thresholdFromFulfillmentMixed(const Fulfillment_t *ffill) { if (nffills == 0) { free(cond); + fprintf(stderr, "%s nffills == 0\n", __func__); return NULL; } @@ -172,12 +173,12 @@ static CC *thresholdFromFulfillmentMixed(const Fulfillment_t *ffill) { return NULL; } } - return cond; } static CC *thresholdFromFulfillment(const Fulfillment_t *ffill, FulfillmentFlags flags) { + //printf("%s flags & MixedMode %d\n", __func__, (flags & MixedMode)); if (flags & MixedMode) return thresholdFromFulfillmentMixed(ffill); ThresholdFulfillment_t *t = ffill->choice.thresholdSha256; @@ -194,6 +195,7 @@ static CC *thresholdFromFulfillment(const Fulfillment_t *ffill, FulfillmentFlags if (!subconditions[i]) { for (int j=0; jsize; i++) { CC *sub = cond->subconditions[i]; + //printf("%s sub->type=%d sub->dontFulfill=%d\n", __func__, sub->type->typeId, sub->dontFulfill); if (fulfillment = asnFulfillmentNew(sub, flags)) { + //printf("%s sub->type=%d added as ffill\n", __func__, sub->type->typeId); asn_set_add(&tf->subfulfillments, fulfillment); } else { + //printf("%s sub->type=%d added as cond\n", __func__, sub->type->typeId); asn_set_add(&tf->subconditions, asnConditionNew(sub)); } } @@ -234,6 +239,7 @@ static Fulfillment_t *thresholdToFulfillmentMixed(const CC *cond, FulfillmentFla static Fulfillment_t *thresholdToFulfillment(const CC *cond, FulfillmentFlags flags) { + //printf("%s flags & MixedMode %d\n", __func__, (flags & MixedMode)); if (flags & MixedMode) return thresholdToFulfillmentMixed(cond, flags); Fulfillment_t *fulfillment; @@ -249,7 +255,7 @@ static Fulfillment_t *thresholdToFulfillment(const CC *cond, FulfillmentFlags fl for (int i=0; isize; i++) { CC *sub = subconditions[i]; - if (needed && (fulfillment = asnFulfillmentNew(sub, flags))) { + if (needed && !sub->dontFulfill && (fulfillment = asnFulfillmentNew(sub, flags))) { asn_set_add(&tf->subfulfillments, fulfillment); needed--; } else { @@ -289,6 +295,10 @@ static CC *thresholdFromJSON(const cJSON *params, char *err) { cond->size = cJSON_GetArraySize(subfulfillments_item); cond->subconditions = calloc(cond->size, sizeof(CC*)); + int dontFulfill = 0; + cJSON *obj = cJSON_GetObjectItem(params, "dontFulfill"); + if (obj) cond->dontFulfill = !!obj->valueint; + cJSON *sub; for (int i=0; isize; i++) { sub = cJSON_GetArrayItem(subfulfillments_item, i); @@ -344,6 +354,7 @@ static CC* thresholdCopy(const CC* cond) for (int i=0; isize; i++) { condCopy->subconditions[i]=cond->subconditions[i]->type->copy(cond->subconditions[i]); } + condCopy->dontFulfill = cond->dontFulfill; return (condCopy); } From d8f2e18a5bf3072df4ae66667906c53abfd87537 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 00:59:39 +0500 Subject: [PATCH 208/348] cryptoconditions lib static link --- src/Makefile.am | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 712d2f88aec..e24d5ac0679 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,5 @@ -DIST_SUBDIRS = secp256k1 univalue cryptoconditions +DIST_SUBDIRS = secp256k1 univalue +SUBDIRS = cryptoconditions AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) AM_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) @@ -48,7 +49,7 @@ LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBVERUS_CRYPTO=crypto/libverus_crypto.a LIBVERUS_PORTABLE_CRYPTO=crypto/libverus_portable_crypto.a LIBSECP256K1=secp256k1/libsecp256k1.la -LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.la +LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.a LIBSNARK=snark/libsnark.a LIBUNIVALUE=univalue/libunivalue.la LIBZCASH=libzcash.a From e07c35270aeecd742c456e67b2f9d48cf2ddb619 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 01:11:13 +0500 Subject: [PATCH 209/348] added cryptoconditions new secp256k1hash cond support to scriptPubKey as new 'M'+1 prefix (cc subversion 1) --- src/cc/CCtx.cpp | 72 ++++++++++++++++---------- src/cc/CCupgrades.cpp | 23 ++++++--- src/cc/CCupgrades.h | 13 +++-- src/cc/CCutilbits.cpp | 11 ---- src/cc/CCutils.cpp | 91 +++++++++++++++++++++++++++------ src/main.cpp | 21 +++++--- src/main.h | 1 + src/script/cc.cpp | 98 ++++++++++++++++++++++++++---------- src/script/cc.h | 28 +++++++++-- src/script/interpreter.cpp | 10 ++-- src/script/script.cpp | 54 ++++++++++++++++---- src/script/script.h | 1 + src/script/serverchecker.cpp | 4 +- src/script/serverchecker.h | 2 +- 14 files changed, 310 insertions(+), 119 deletions(-) diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 7c1f2fe6531..a38fdfa7fc0 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -502,8 +502,10 @@ UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info if (vintx.vout[utxovout].scriptPubKey.IsPayToCryptoCondition() == 0) { if (KOMODO_NSPV_FULLNODE) { if (!remote) { - if (SignTx(mtx, i, vintx.vout[utxovout].nValue, vintx.vout[utxovout].scriptPubKey) == 0) + if (SignTx(mtx, i, vintx.vout[utxovout].nValue, vintx.vout[utxovout].scriptPubKey) == 0) { fprintf(stderr, "%s signing error for normal vini.%d\n", __func__, i); + return sigDataNull; + } } else { // if no myprivkey for mypk it means remote call from nspv superlite client // add sigData for superlite client @@ -521,6 +523,7 @@ UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info fprintf(stderr, "%s NSPV signing error for vini.%d\n", __func__, i); } } else { + bool bdontsign = false; Getscriptaddress(destaddr, vintx.vout[utxovout].scriptPubKey); if (strcmp(destaddr, globaladdr) == 0) { privkey = cp->CCpriv; @@ -533,50 +536,65 @@ UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info cond.reset(MakeTokensv2CCcond1(cp->evalcode, mypk)); } else { const uint8_t nullpriv[32] = {'\0'}; + const uint8_t dontsign[32] = { 0xff }; // use vector of dest addresses and conds to probe vintxconds for (auto& t : cp->CCvintxprobes) { - char coinaddr[KOMODO_ADDRESS_BUFSIZE]; if (t.CCwrapped.get() != NULL) { - CCwrapper anonCond = t.CCwrapped; - CCtoAnon(anonCond.get()); - Getscriptaddress(coinaddr, CCPubKey(anonCond.get(), true)); - if (strcmp(destaddr, coinaddr) == 0) { - if (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) - privkey = t.CCpriv; - else - privkey = myprivkey; - cond = t.CCwrapped; - break; + //CCwrapper anonCond = t.CCwrapped; + //CCtoAnon(anonCond.get()); // now in CCPubKey() + for (CC_SUBVER ccSubVer = CC_MIXED_MODE_SUBVER_0; ccSubVer <= CC_MIXED_MODE_SUBVER_MAX; ccSubVer = (CC_SUBVER)(ccSubVer+1)) + { + char coinaddr[KOMODO_ADDRESS_BUFSIZE]; + //Getscriptaddress(coinaddr, CCPubKey(anonCond.get(), ccSubVer)); + Getscriptaddress(coinaddr, CCPubKey(t.CCwrapped.get(), ccSubVer)); + if (strcmp(destaddr, coinaddr) == 0) { + if (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) == 0) + privkey = myprivkey; + else if (memcmp(t.CCpriv, dontsign, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) == 0) + bdontsign = true; + else + privkey = t.CCpriv; + + cond = t.CCwrapped; + break; + } } + if (cond.get() != nullptr) break; // found cond } } } - if (cond.get() == NULL) { + if (cond.get() == nullptr) { fprintf(stderr, "%s vini.%d has CC signing error: could not find matching cond, address.(%s) %s\n", __func__, i, destaddr, EncodeHexTx(mtx).c_str()); memset(myprivkey, 0, sizeof(myprivkey)); return sigDataNull; } - if (!remote) // we have privkey in the wallet + if (bdontsign) { + mtx.vin[i].scriptSig = CCSig(cond.get()); // no signing cond + //std::cerr << __func__ << " using 'dont sign' vin" << i << std::endl; + } + else if (!remote) // we have privkey in the wallet { uint256 sighash = SignatureHash(CCPubKey(cond.get()), mtx, i, SIGHASH_ALL, utxovalues[i], consensusBranchId, &txdata); - if (cc_signTreeSecp256k1Msg32(cond.get(), privkey, sighash.begin()) != 0) { - std::string strcond; - cJSON *params = cc_conditionToJSON(cond.get()); - if (params) { - char *out = cJSON_PrintUnformatted(params); - cJSON_Delete(params); - if (out) { - strcond = out; - cJSON_free(out); - } - } + if (cc_signTreeSecp256k1Msg32(cond.get(), privkey, sighash.begin()) != 0 || + cc_signTreeSecp256k1HashMsg32(cond.get(), privkey, sighash.begin()) != 0) { - UniValue unicond(UniValue::VOBJ); - unicond.read(strcond); mtx.vin[i].scriptSig = CCSig(cond.get()); if (!IsCCInput(mtx.vin[i].scriptSig)) { // if fulfillment could not be serialised treat as signature threshold not reached // return partially signed condition: + std::string strcond; + cJSON *params = cc_conditionToJSON(cond.get()); + if (params) { + char *out = cJSON_PrintUnformatted(params); + cJSON_Delete(params); + if (out) { + strcond = out; + cJSON_free(out); + } + } + + UniValue unicond(UniValue::VOBJ); + unicond.read(strcond); UniValue elem(UniValue::VOBJ); elem.push_back(Pair("vin", i)); elem.push_back(Pair("ccaddress", destaddr)); diff --git a/src/cc/CCupgrades.cpp b/src/cc/CCupgrades.cpp index bad6aa5b0a7..9e220597360 100644 --- a/src/cc/CCupgrades.cpp +++ b/src/cc/CCupgrades.cpp @@ -19,21 +19,28 @@ namespace CCUpgrades { class CUpgradesContainer { + private: + void addUpgradeActive(const std::string &chainName, UPGRADE_ID upgradeId, int32_t nHeight) + { + ChainUpgrades oUpgrade; + oUpgrade.setActivationHeight(upgradeId, nHeight, UPGRADE_ACTIVE); + mChainUpgrades[chainName] = oUpgrade; + } public: CUpgradesContainer() { // default upgrades: always enable all fixes defaultUpgrades.IsAllEnabled = true; - // TOKEL - ChainUpgrades tokel; - tokel.setActivationHeight(CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TOKEL_HEIGHT, UPGRADE_ACTIVE); - mChainUpgrades["TOKEL"] = tokel; + // CCASSETS_OPDROP_VALIDATE_FIX activation + addUpgradeActive("TOKEL", CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + addUpgradeActive("TKLTEST", CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT); - // TKLTEST - ChainUpgrades tkltest; - tkltest.setActivationHeight(CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT, UPGRADE_ACTIVE); - mChainUpgrades["TKLTEST"] = tkltest; + // CCMIXEDMODE_SUBVER_1 activation + addUpgradeActive("TOKEL", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT); + addUpgradeActive("TKLTEST", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT); + addUpgradeActive("DIMXY24", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT); + addUpgradeActive("TKLTEST2", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT); // add more chains here... // ... diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index 4c6dd3770d9..c07ed75374e 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -21,17 +21,24 @@ #include #include -const int32_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 286359; // 26 Nov + 90 days -const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 243159; // 26 Nov + 60 days - namespace CCUpgrades { + // asset chain activation heights + const int32_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 286359; // 26 Nov + 90 days + const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 243159; // 26 Nov + 60 days + + const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT = 0; // TBD + const int32_t CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT = 0; // TBD + const int32_t CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT = 10000000; // TBD + const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 10000000; // TBD + enum UPGRADE_STATUS { UPGRADE_ACTIVE = 1, }; enum UPGRADE_ID { CCASSETS_OPDROP_VALIDATE_FIX = 0x01, + CCMIXEDMODE_SUBVER_1 = 0x02, // new cc secp256k1 cond type and eval param }; struct UpgradeInfo { diff --git a/src/cc/CCutilbits.cpp b/src/cc/CCutilbits.cpp index 13041873a25..240093fdd7b 100644 --- a/src/cc/CCutilbits.cpp +++ b/src/cc/CCutilbits.cpp @@ -147,14 +147,3 @@ bool IsRemoteRPCCall() { return is_remote_rpc_call; } - -bool CCtoAnon(const CC* cond) -{ - for (int i = 0; i < cond->size; i++) - if (cc_typeId(cond->subconditions[i]) == CC_Threshold) { - CCwrapper tmp(cond->subconditions[i]); - cond->subconditions[i] = cc_anon(tmp.get()); - return (true); - } - return (false); -} \ No newline at end of file diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 9a3f55f8972..969febe3692 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -141,8 +141,8 @@ CTxOut MakeCC1voutMixed(uint8_t evalcode,CAmount nValue, CPubKey pk, std::vector { CTxOut vout; CCwrapper payoutCond(MakeCCcond1(evalcode,pk)); - if (!CCtoAnon(payoutCond.get())) return (vout); - vout = CTxOut(nValue,CCPubKey(payoutCond.get(),true)); + //if (!CCtoAnon(payoutCond.get())) return (vout); + vout = CTxOut(nValue,CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); if ( vData ) { vout.scriptPubKey << *vData << OP_DROP; @@ -154,8 +154,8 @@ CTxOut MakeCC1of2voutMixed(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey p { CTxOut vout; CCwrapper payoutCond(MakeCCcond1of2(evalcode,pk1,pk2)); - if (!CCtoAnon(payoutCond.get())) return (vout); - vout = CTxOut(nValue,CCPubKey(payoutCond.get(),true)); + //if (!CCtoAnon(payoutCond.get())) return (vout); + vout = CTxOut(nValue,CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); if ( vData ) { vout.scriptPubKey << *vData << OP_DROP; @@ -391,8 +391,8 @@ bool _GetCCaddress(char *destaddr,uint8_t evalcode,CPubKey pk,bool mixed) destaddr[0] = 0; if (payoutCond.get() != 0 ) { - if (mixed) CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr,CCPubKey(payoutCond.get(),mixed)); + //if (mixed) CCtoAnon(payoutCond.get()); + Getscriptaddress(destaddr,CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); } return(destaddr[0] != 0); } @@ -416,9 +416,9 @@ static bool _GetTokensCCaddress(char *destaddr, uint8_t evalcode1, uint8_t evalc destaddr[0] = 0; if (payoutCond != nullptr) { - if (mixed) - CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), mixed)); + //if (mixed) + // CCtoAnon(payoutCond.get()); + Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); } return(destaddr[0] != 0); } @@ -438,8 +438,8 @@ bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubK destaddr[0] = 0; if ( payoutCond.get() != 0 ) { - if (mixed) CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr,CCPubKey(payoutCond.get(),mixed)); + //if (mixed) CCtoAnon(payoutCond.get()); + Getscriptaddress(destaddr,CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); } return(destaddr[0] != 0); } @@ -455,9 +455,9 @@ bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey destaddr[0] = 0; if (payoutCond != nullptr) { - if (mixed) - CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), mixed)); + //if (mixed) + // CCtoAnon(payoutCond.get()); + Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); } return(destaddr[0] != 0); } @@ -843,7 +843,7 @@ CPubKey check_signing_pubkey(CScript scriptSig) auto findEval = [](CC *cond, struct CCVisitor _) { bool r = false; - if (cc_typeId(cond) == CC_Secp256k1) { + if (!cc_anon(cond) && cc_typeId(cond) == CC_Secp256k1) { *(CPubKey*)_.context=buf2pk(cond->publicKey); r = true; } @@ -1597,3 +1597,64 @@ bool IsTxidInActiveChain(uint256 txid) } return false; } + +// decode CC mixed mode to UniValue and specially process anon sec256hash +UniValue CCDecodeMixedMode(const CC *cond) +{ + UniValue result(UniValue::VOBJ); + + auto decodeCond = [](const CC *cond) -> UniValue + { + UniValue uCond(UniValue::VOBJ); + uCond.pushKV("type", cc_typeName(cond)); + if (!cc_isAnon(cond)) + { + uCond.pushKV("isAnon", "no"); + if (cc_typeId(cond) == CC_Eval) + uCond.pushKV("EvalCode", EvalToStr(cond->code[0])); + else if(cc_typeId(cond) == CC_Threshold) { + uCond.pushKV("threshold", cond->size); + uCond.pushKV("subconditions", CCDecodeMixedMode(cond)); + } + } + else + { + uCond.pushKV("isAnon", "yes"); + + if (cc_typeId(cond) == CC_Secp256k1hash) { + std::string fingerprintHex = HexStr(cond->fingerprint, cond->fingerprint + sizeof(uint160)); + std::cerr << __func__ << " fingerprintHex=" << fingerprintHex << std::endl; + CKeyID keyid(uint160(vuint8_t(cond->fingerprint, cond->fingerprint + sizeof(uint160)))); + CBitcoinAddress addr; + addr.Set(keyid); + std::cerr << __func__ << " keyid=" << keyid.ToString() << " addr=" << addr.ToString() << std::endl; + + uCond.pushKV("destination", addr.ToString()); + } + else { + uCond.pushKV("fingerprint", HexStr(cond->fingerprint, cond->fingerprint + sizeof(cond->fingerprint))); + if (cc_typeId(cond) == CC_Threshold) + uCond.pushKV("subtypes", (int64_t)cond->subtypes); + } + } + return uCond; + }; + + if (cc_typeId(cond) == CC_Threshold) { + UniValue uThreshold(UniValue::VOBJ); + UniValue uSubConds(UniValue::VARR); + for (int i = 0; i < cond->size; i ++) { + UniValue uSubCond = decodeCond(cond->subconditions[i]); + uSubConds.push_back(uSubCond); + } + uThreshold.pushKV("type", cc_typeName(cond)); + uThreshold.pushKV("size", cond->size); + uThreshold.pushKV("subconditions", uSubConds); + return uThreshold; + } + else + { + UniValue uCond = decodeCond(cond); + return uCond; + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5ddcb4e43ca..1a568f17413 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2110,7 +2110,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString()); } - if (!ContextualCheckOutputs(tx, state, true, txdata, evalcodeChecker)) + if (!ContextualCheckOutputs(tx, state, true, txdata, chainActive.LastTip()->GetHeight() + 1, evalcodeChecker)) return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ContextualCheckOutputs failed %s", hash.ToString()); if (flag != 0) KOMODO_CONNECTING = -1; @@ -2794,12 +2794,12 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { - if (vout != 0) { + if (vout != 0) { //check cc output ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, evalcodeChecker, *txdata); - if (checker.CheckCryptoCondition(scriptPubKey.GetCCV2SPK(), &error) != 1) { - return ::error("CScriptCheck(): %s:%d CC validation failed: %s", ptxTo->GetHash().ToString(), n, ScriptErrorString(error)); + if (checker.CheckCryptoConditionSpk(scriptPubKey.GetCCV2SPK(), &error) != 1) { + return ::error("CScriptCheck(): %s:%d CC output validation failed: %s", ptxTo->GetHash().ToString(), n, ScriptErrorString(error)); } - } else { + } else { // check cc input const CScript& scriptSig = ptxTo->vin[n].scriptSig; ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, evalcodeChecker, *txdata); if (!VerifyScript(scriptSig, scriptPubKey, nFlags, checker, consensusBranchId, &error)) { @@ -2999,6 +2999,7 @@ bool ContextualCheckOutputs( CValidationState &state, bool fScriptChecks, PrecomputedTransactionData& txdata, + int32_t nHeight, std::shared_ptr evalcodeChecker, std::vector *pvChecks) { @@ -3009,8 +3010,14 @@ bool ContextualCheckOutputs( { for (unsigned int i = 0; i < tx.vout.size(); i++) { - if (tx.vout[i].scriptPubKey.IsPayToCCV2() ) + int subversion; + if (tx.vout[i].scriptPubKey.IsPayToCCV2(subversion) ) { + // check if secp256hash and eval param in action: + if (subversion >= CC_MIXED_MODE_SECHASH_SUBVER_1 && !CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + { + return state.DoS(100,false, REJECT_INVALID, std::string("cc v2 subversion 1 or more not yet enabled")); + } CScriptCheck check(tx.vout[i].scriptPubKey, tx.vout[i].nValue, tx, i, evalcodeChecker, &txdata); if (pvChecks) { @@ -3861,7 +3868,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin { // check tx outputs including coinbases std::vector vChecks; - if (!ContextualCheckOutputs(tx, state, fExpensiveChecks, txdata[i], evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) + if (!ContextualCheckOutputs(tx, state, fExpensiveChecks, txdata[i], pindex->GetHeight(), evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) return false; control.Add(vChecks); } diff --git a/src/main.h b/src/main.h index c1df8670ede..1b58ea4759f 100644 --- a/src/main.h +++ b/src/main.h @@ -744,6 +744,7 @@ bool ContextualCheckOutputs( CValidationState &state, bool fScriptChecks, PrecomputedTransactionData& txdata, + int32_t nHeight, std::shared_ptr evalcodeChecker, std::vector *pvChecks = NULL); diff --git a/src/script/cc.cpp b/src/script/cc.cpp index efbfb757a22..ad3744cb8e9 100644 --- a/src/script/cc.cpp +++ b/src/script/cc.cpp @@ -23,26 +23,38 @@ bool IsCryptoConditionsEnabled() } -bool IsSupportedCryptoCondition(const CC *cond) +bool IsSupportedCryptoCondition(const CC *cond, CC_SUBVER ccSubVersion) { int mask = cc_typeMask(cond); + int CCEnabledTypesVersioned = CCEnabledTypes; + if (ccSubVersion >= CC_MIXED_MODE_SECHASH_SUBVER_1) CCEnabledTypesVersioned |= (1 << CC_Secp256k1hash); + if (mask & ~CCEnabledTypesVersioned) return false; + + // Also require that the condition have at least one signable node + int CCSigningNodesVersioned = CCSigningNodes; + if (ccSubVersion >= CC_MIXED_MODE_SECHASH_SUBVER_1) CCSigningNodesVersioned = 0; // allow non signed conds - if (mask & ~CCEnabledTypes) return false; + // TODO: allow non signed conds for ver >= 1 in June 2022? + // if (ccSubVersion < CC_MIXED_MODE_SECHASH_SUBVER_1 && !(mask & CCSigningNodes)) return false; - // Also require that the condition have at least one signable node - if (!(mask & CCSigningNodes)) return false; + // TODO: check for eval params enabled if ccSubVersion >= CC_MIXED_MODE_SECHASH_SUBVER_1 + // ... return true; } -bool IsSignedCryptoCondition(const CC *cond) +bool IsSignedCryptoCondition(const CC *cond, CC_SUBVER ccSubVersion) { if (!cc_isFulfilled(cond)) return false; - if (1 << cc_typeId(cond) & CCSigningNodes) return true; + //if (ccSubVersion >= CC_MIXED_MODE_SECHASH_SUBVER_1) return true; // TODO enable unsigned conds in this June 2022 or not? + + int CCSigningNodesVersioned = CCSigningNodes; + if (ccSubVersion >= CC_MIXED_MODE_SECHASH_SUBVER_1) CCSigningNodesVersioned |= (1 << CC_Secp256k1hash); // allow new secp hash cond + if (1 << cc_typeId(cond) & CCSigningNodesVersioned) return true; if (cc_typeId(cond) == CC_Threshold) for (int i=0; isize; i++) - if (IsSignedCryptoCondition(cond->subconditions[i])) return true; + if (IsSignedCryptoCondition(cond->subconditions[i], ccSubVersion)) return true; return false; } @@ -62,17 +74,28 @@ CC* CCNewThreshold(int t, std::vector v) cond->size = v.size(); cond->subconditions = (CC**) calloc(v.size(), sizeof(CC*)); memcpy(cond->subconditions, v.data(), v.size() * sizeof(CC*)); + cond->dontFulfill = 0; return cond; } - +#include "utilstrencodings.h" CC* CCNewSecp256k1(CPubKey k) { CC *cond = cc_new(CC_Secp256k1); cond->publicKey = CopyPubKey(k); + cond->dontFulfill = 0; return cond; } +CC* CCNewSecp256k1Hash(CKeyID k) +{ + CC *cond = cc_new(CC_Secp256k1hash); + cond->publicKeyHash = (uint8_t*)calloc(1, k.size()); + //std::cerr << __func__ << " CKeyID=" << HexStr(k.begin(), k.begin()+k.size()) << " CKeyID.ToString=" << k.ToString() << std::endl; + memcpy(cond->publicKeyHash, k.begin(), k.size()); + cond->dontFulfill = 0; + return cond; +} CC* CCNewEval(std::vector code) { @@ -83,23 +106,32 @@ CC* CCNewEval(std::vector code) return cond; } - -CScript CCPubKey(const CC *cond, bool mixed) +// make cryptocondition ScriptPubKey +CScript CCPubKey(const CC *cond, CC_SUBVER ccSubVersion) { - unsigned char buf[1000]; size_t len; - if (mixed) - { - buf[0]='M'; - len = cc_fulfillmentBinaryMixedMode(cond, buf+1,999)+1; + unsigned char buf[MAX_FULFILLMENT_SIZE]; + size_t len; + + if (ccSubVersion >= CC_MIXED_MODE_SUBVER_0) { + buf[0] = (uint8_t)CC_MIXED_MODE_PREFIX + ccSubVersion; + CC *condCopy = cc_copy(cond); + // make 1st level thresholds as anon for subver 0 + // for later versions save as the mixed-mode fulfillment + if (ccSubVersion == CC_MIXED_MODE_SUBVER_0) + CCtoAnon(condCopy); + size_t maxFfilSize = (ccSubVersion == CC_MIXED_MODE_SUBVER_0 ? MAX_FULFILLMENT_SPK_SIZE_V0 : MAX_FULFILLMENT_SIZE); + len = cc_fulfillmentBinaryMixedMode(condCopy, buf+1, maxFfilSize-1) + 1; + cc_free(condCopy); } - else len = cc_conditionBinary(cond, buf); + else + len = cc_conditionBinary(cond, buf); return CScript() << std::vector(buf, buf+len) << OP_CHECKCRYPTOCONDITION; } CScript CCSig(const CC *cond) { - unsigned char buf[10000]; - size_t len = cc_fulfillmentBinary(cond, buf, 10000); + unsigned char buf[MAX_FULFILLMENT_SIZE]; + size_t len = cc_fulfillmentBinary(cond, buf, MAX_FULFILLMENT_SIZE); auto ffill = std::vector(buf, buf+len); ffill.push_back(1); // SIGHASH_ALL return CScript() << ffill; @@ -107,8 +139,8 @@ CScript CCSig(const CC *cond) std::vector CCSigVec(const CC *cond) { - unsigned char buf[10000]; - size_t len = cc_fulfillmentBinary(cond, buf, 10000); + unsigned char buf[MAX_FULFILLMENT_SIZE]; + size_t len = cc_fulfillmentBinary(cond, buf, MAX_FULFILLMENT_SIZE); auto ffill = std::vector(buf, buf+len); ffill.push_back(1); // SIGHASH_ALL return ffill; @@ -142,6 +174,21 @@ CC* CCPrune(CC *cond) return cc_readFulfillmentBinary(ffillBin.data(), ffillBin.size()-1); } +// make 1st level thresholds anonymous to have compact spks +bool CCtoAnon(const CC* cond) +{ + if (cc_typeId(cond) == CC_Threshold) { + for (int i = 0; i < cond->size; i++) { + if (cc_typeId(cond->subconditions[i]) == CC_Threshold) { + CC* saved = cond->subconditions[i]; + cond->subconditions[i] = cc_anon(saved); + cc_free(saved); + return (true); + } + } + } + return (false); +} bool GetPushData(const CScript &sig, std::vector &data) { @@ -164,15 +211,12 @@ bool GetOpReturnData(const CScript &sig, std::vector &data) } -const uint8_t CC_MIXED_MODE_PREFIX = 'M'; - - struct CC* cc_readConditionBinaryMaybeMixed(const uint8_t *condBin, size_t condBinLength) { if (condBinLength == 0) return NULL; - return condBin[0] == CC_MIXED_MODE_PREFIX ? + return CC_MixedModeSubVersion(condBin[0]) >= CC_MIXED_MODE_SUBVER_0 ? cc_readFulfillmentBinaryMixedMode(condBin+1, condBinLength-1) : cc_readConditionBinary(condBin, condBinLength); } @@ -181,11 +225,11 @@ struct CC* cc_readConditionBinaryMaybeMixed(const uint8_t *condBin, size_t condB int cc_verifyMaybeMixed(const struct CC *cond, const uint256 sigHash, const uint8_t *condBin, size_t condBinLength, VerifyEval verifyEval, void *evalContext) { - if (condBinLength == 0) return false; + if (condBinLength == 0) return 0; uint8_t condBuf[1000]; - if (condBin[0] == CC_MIXED_MODE_PREFIX) { + if (CC_MixedModeSubVersion(condBin[0]) >= CC_MIXED_MODE_SUBVER_0) { CC* condMixed = cc_readFulfillmentBinaryMixedMode(condBin+1, condBinLength-1); - if (!condMixed) return false; + if (!condMixed) return 0; condBinLength = cc_conditionBinary(condMixed, condBuf); condBin = condBuf; cc_free(condMixed); diff --git a/src/script/cc.h b/src/script/cc.h index 985afa8f289..c4c0e19f91f 100644 --- a/src/script/cc.h +++ b/src/script/cc.h @@ -26,6 +26,20 @@ extern uint32_t ASSETCHAINS_CC; bool IsCryptoConditionsEnabled(); +const uint8_t CC_MIXED_MODE_PREFIX = 'M'; +enum CC_SUBVER : int { + CC_OLD_V1_SUBVER = -1, + CC_MIXED_MODE_SUBVER_0 = 0, + CC_MIXED_MODE_SECHASH_SUBVER_1 = 1, + CC_MIXED_MODE_SUBVER_MAX = CC_MIXED_MODE_SECHASH_SUBVER_1, +}; + + +inline CC_SUBVER CC_MixedModeSubVersion(int c) { return (c >= CC_MIXED_MODE_PREFIX) ? (CC_SUBVER)(c - CC_MIXED_MODE_PREFIX) : CC_OLD_V1_SUBVER; } + +const size_t MAX_FULFILLMENT_SIZE = 10000; +const size_t MAX_FULFILLMENT_SPK_SIZE_V0 = 1000; + // Limit acceptable condition types // Prefix not enabled because no current use case, ambiguity on how to combine with secp256k1 // RSA not enabled because no current use case, not implemented @@ -33,21 +47,22 @@ const int CCEnabledTypes = 1 << CC_Secp256k1 | \ 1 << CC_Threshold | \ 1 << CC_Eval | \ 1 << CC_Preimage | \ - 1 << CC_Ed25519; + 1 << CC_Ed25519 | \ + 1 << CC_Secp256k1hash; -const int CCSigningNodes = 1 << CC_Ed25519 | 1 << CC_Secp256k1; +const int CCSigningNodes = 1 << CC_Ed25519 | 1 << CC_Secp256k1 | 1 << CC_Secp256k1hash; /* * Check if the server can accept the condition based on it's structure / types */ -bool IsSupportedCryptoCondition(const CC *cond); +bool IsSupportedCryptoCondition(const CC *cond, CC_SUBVER ccSubVersion); /* * Check if crypto condition is signed. Can only accept signed conditions. */ -bool IsSignedCryptoCondition(const CC *cond); +bool IsSignedCryptoCondition(const CC *cond, CC_SUBVER ccSubVersion); /* @@ -56,13 +71,14 @@ bool IsSignedCryptoCondition(const CC *cond); CC* CCNewPreimage(std::vector preimage); CC* CCNewEval(std::vector code); CC* CCNewSecp256k1(CPubKey k); +CC* CCNewSecp256k1Hash(CKeyID k); CC* CCNewThreshold(int t, std::vector v); /* * Turn a condition into a scriptPubKey */ -CScript CCPubKey(const CC *cond,bool mixed=false); +CScript CCPubKey(const CC *cond, CC_SUBVER ccSubVersion = CC_OLD_V1_SUBVER); /* @@ -91,6 +107,8 @@ std::string CCShowStructure(CC *cond); */ CC* CCPrune(CC *cond); +// Make first level threshold subconds anonymous +bool CCtoAnon(const CC *cond); /* * Get PUSHDATA from a script diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index d103e37ad6a..d6308e20df7 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1373,8 +1373,10 @@ int TransactionSignatureChecker::CheckCryptoCondition( int error = cc_readFulfillmentBinaryExt((unsigned char*)ffillBin.data(), ffillBin.size()-1, &cond); if (error || !cond) return -1; - if (!IsSupportedCryptoCondition(cond)) return 0; - if (!IsSignedCryptoCondition(cond)) return 0; + CC_SUBVER ccSubVersion = CC_MixedModeSubVersion(scriptCode[0]); + + if (!IsSupportedCryptoCondition(cond, ccSubVersion)) return 0; + if (!IsSignedCryptoCondition(cond, ccSubVersion)) return 0; uint256 sighash; int nHashType = ffillBin.back(); @@ -1388,10 +1390,10 @@ int TransactionSignatureChecker::CheckCryptoCondition( return ((TransactionSignatureChecker*)checker)->CheckEvalCondition(cond); }; - //fprintf(stderr,"non-checker path\n"); + fprintf(stderr,"%s non-checker path\n", __func__); int out = cc_verifyMaybeMixed( cond, sighash, condBin.data(), condBin.size(), eval, (void*)this); - //fprintf(stderr,"out.%d from cc_verify\n",(int32_t)out); + fprintf(stderr,"%s out.%d from cc_verify\n", __func__, (int32_t)out); cc_free(cond); return out; } diff --git a/src/script/script.cpp b/src/script/script.cpp index b0838429a7e..796f2c81dd9 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -355,16 +355,41 @@ bool CScript::GetOpretData(std::vector>& vData) const else return false; } +// validate mixed and non mixed-mode cc spk script opcode and data +static bool IsCCOpcodeValid(opcodetype opcode, const vector &data) +{ + if (data.size() > 0) + { + if (data[0] < CC_MIXED_MODE_PREFIX && opcode > OP_0 && opcode < OP_PUSHDATA1) // pre mixed mode (cc_conditionBinary always < 76 bytes) + return true; + else if (data[0] == CC_MIXED_MODE_PREFIX && opcode > OP_0 && opcode <= OP_PUSHDATA1) // for mixed mode subver 'M'+0 enable longer data upto 255 b + return true; + else if (data[0] > CC_MIXED_MODE_PREFIX && opcode > OP_0 && opcode <= OP_PUSHDATA2) { // for mixed mode subver >= 'M'+1 enable even longer data upto 65K b + return true; + } + } + return false; +} + bool CScript::IsPayToCryptoCondition(CScript *pCCSubScript, std::vector>& vParams) const { const_iterator pc = begin(); vector data; opcodetype opcode,opcode1; - if (this->GetOp(pc, opcode, data)) - // Sha256 conditions are <76 bytes - if (data.size()>0 && (data[0]=='M' || (data[0]!='M' && opcode > OP_0 && opcode < OP_PUSHDATA1))) - //if (opcode > OP_0 && opcode < OP_PUSHDATA1) + if (this->GetOp(pc, opcode, data)) + { + // Pre mixed mode check: + // Sha256 conditions are <76 bytes (for cc pre mixed mode) + // if (opcode > OP_0 && opcode < OP_PUSHDATA1) + + // Original mixed mode condition field's length check. It actually disables long mixed mode conds for cc subversions 'M'+1 and on: + // if (data.size()>0 && (data[0]=='M' || (data[0]!='M' && opcode > OP_0 && opcode < OP_PUSHDATA1))) + + // new function that checks both non mixed and new mixed mode cc script opcode and data + if (IsCCOpcodeValid(opcode, data)) + { if (this->GetOp(pc, opcode1, data)) + { if (opcode1 == OP_CHECKCRYPTOCONDITION) { const_iterator pcCCEnd = pc; @@ -375,6 +400,9 @@ bool CScript::IsPayToCryptoCondition(CScript *pCCSubScript, std::vector data; @@ -398,10 +426,15 @@ bool CScript::IsPayToCCV2() const if (!this->IsPayToCryptoCondition()) return (false); if (this->GetOp(pc, opcode, data)) { - if (data[0]==CC_MIXED_MODE_PREFIX) return (true); + if (CC_MixedModeSubVersion(data[0]) >= CC_MIXED_MODE_SUBVER_0) return (true); } return (false); } +bool CScript::IsPayToCCV2() const +{ + int subversion; + return IsPayToCCV2(subversion); +} const std::vector CScript::GetCCV2SPK() const { @@ -412,7 +445,7 @@ const std::vector CScript::GetCCV2SPK() const if (!this->IsPayToCryptoCondition()) return (std::vector()); if (this->GetOp(pc, opcode, data)) { - if (data[0]==CC_MIXED_MODE_PREFIX) return data; + if (CC_MixedModeSubVersion(data[0]) >= CC_MIXED_MODE_SUBVER_0) return data; } return (std::vector()); } @@ -444,10 +477,13 @@ bool CScript::MayAcceptCryptoCondition() const vector data; opcodetype opcode; if (!this->GetOp(pc, opcode, data)) return false; - if (!(opcode > OP_0 && opcode < OP_PUSHDATA1)) return false; + if (!IsCCOpcodeValid(opcode, data)) return false; + CC *cond = cc_readConditionBinaryMaybeMixed(data.data(), data.size()); if (!cond) return false; - bool out = IsSupportedCryptoCondition(cond); + + CC_SUBVER ccSubVersion = CC_MixedModeSubVersion((*this)[0]); + bool out = IsSupportedCryptoCondition(cond, ccSubVersion); cc_free(cond); return out; } diff --git a/src/script/script.h b/src/script/script.h index 64bf21a6d0f..8d1a096ef12 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -596,6 +596,7 @@ class CScript : public CScriptBase bool IsPayToCryptoCondition(CScript *ccSubScript) const; bool IsPayToCryptoCondition() const; bool IsPayToCCV2() const; // check scriptPubKey is cryptocondition version 2 + bool IsPayToCCV2(int &subversion) const; // check scriptPubKey is cryptocondition version 2 const std::vector GetCCV2SPK() const; bool SpkHasEvalcodeCCV2(uint8_t eval) const; bool IsCoinImport() const; diff --git a/src/script/serverchecker.cpp b/src/script/serverchecker.cpp index 73c404e6d48..d1975358680 100644 --- a/src/script/serverchecker.cpp +++ b/src/script/serverchecker.cpp @@ -122,10 +122,10 @@ int ServerTransactionSignatureChecker::CheckEvalCondition(const CC *cond) const return RunCCEval(cond, *txTo, nIn, evalcodeChecker); } -int ServerTransactionSignatureChecker::CheckCryptoCondition(const std::vector &condBin, ScriptError *serror) const +int ServerTransactionSignatureChecker::CheckCryptoConditionSpk(const std::vector &condBin, ScriptError *serror) const { CC* condMixed; - if (condBin[0] == CC_MIXED_MODE_PREFIX) + if (CC_MixedModeSubVersion(condBin[0]) >= CC_MIXED_MODE_SUBVER_0) { condMixed = cc_readFulfillmentBinaryMixedMode((unsigned char*)condBin.data()+1, condBin.size()-1); if (serror) *serror = SCRIPT_ERR_PUBKEYTYPE; diff --git a/src/script/serverchecker.h b/src/script/serverchecker.h index 454222a9b1b..61aa1618261 100644 --- a/src/script/serverchecker.h +++ b/src/script/serverchecker.h @@ -40,7 +40,7 @@ class ServerTransactionSignatureChecker : public TransactionSignatureChecker bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; int CheckEvalCondition(const CC *cond) const; - int CheckCryptoCondition(const std::vector &condBin, ScriptError *serror) const; + int CheckCryptoConditionSpk(const std::vector &condBin, ScriptError *serror) const; }; #endif // BITCOIN_SCRIPT_SERVERCHECKER_H From f0f02e094ec788c2ef975f3113731e33a619ee6c Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 01:13:01 +0500 Subject: [PATCH 210/348] unused code delete, copyright year updated --- src/cc/CCtokens.cpp | 124 +------------------------------------------- 1 file changed, 2 insertions(+), 122 deletions(-) diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index ca26e19b7d7..489b4eccb02 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2022 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -641,29 +641,6 @@ CAmount TokensV2::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const return(0); // normal or non-token2 vout } - -/*static CPubKey GetTokenOriginatorPubKey(CScript scriptPubKey) { - - uint8_t funcId; - uint256 tokenid; - std::vector voutTokenPubkeys; - std::vector oprets; - - if ((funcId = DecodeTokenOpRetV1(scriptPubKey, tokenid, voutTokenPubkeys, oprets)) != 0) { - CTransaction tokenbasetx; - uint256 hashBlock; - - if (myGetTransaction(tokenid, tokenbasetx, hashBlock) && tokenbasetx.vout.size() > 0) { - vscript_t vorigpubkey; - std::string name, desc; - std::vector oprets; - if (DecodeTokenCreateOpRetV1(tokenbasetx.vout.back().scriptPubKey, vorigpubkey, name, desc, oprets) != 0) - return pubkey2pk(vorigpubkey); - } - } - return CPubKey(); //return invalid pubkey -}*/ - // old token tx validation entry point // NOTE: opreturn decode v1 functions (DecodeTokenCreateOpRetV1 DecodeTokenOpRetV1) understands both old and new opreturn versions bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) @@ -693,84 +670,6 @@ static bool report_validation_error(const std::string &func, Eval* eval, const C return !eval->state.IsValid() ? false/*error state already set*/ : eval->Invalid(errorStr) /* set error state and exit*/; } -// checking creation txns is available with cryptocondition v2 mixed mode -// therefore do not forget to check that the creation tx does not have cc inputs! -/* -static bool CheckTokensV2CreateTx(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx) -{ - std::vector vpksdummy; - std::vector oprets; - vuint8_t vorigpk; - std::string name, description; - uint256 tokenid; - - // check it is a create tx - int32_t createNum = 0; - int32_t transferNum = 0; - for(int32_t i = 0; i < tx.vout.size(); i ++) - { - if (tx.vout[i].scriptPubKey.IsPayToCryptoCondition() && tx.vout[i].scriptPubKey.SpkHasEvalcodeCCV2(EVAL_TOKENSV2)) - { - CScript opret; - bool isLastVoutOpret; - if (!(opret = GetCCDropAsOpret(tx.vout[v].scriptPubKey)).empty()) - { - isLastVoutOpret = false; - } - else - { - isLastVoutOpret = true; - opret = tx.vout.back().scriptPubKey; - } - - uint8_t funcid = TokensV2::DecodeTokenOpRet(opret, tokenid, vpksdummy, oprets); - if (IsTokenCreateFuncid(funcid)) { - createNum ++; - if (createNum > 1) - return report_validation_error(__func__, eval, tx, "can't have more than 1 create vout"); - - TokensV2::DecodeTokenCreateOpRet(opret, vorigpk, name, description, oprets); - - // check this is really creator - CPubKey origpk = pubkey2pk(vorigpk); - if (TotalPubkeyNormalInputs(eval, tx, origpk) == 0) - return report_validation_error(__func__, eval, tx, "no vins with creator pubkey"); - } - else if(IsTokenTransferFuncid(funcid)) - transferNum ++; - } - } - - if (createNum > 0 && transferNum > 0) - return report_validation_error(__func__, eval, tx, "can't have both create and transfer vouts"); - - if (createNum == 0 && transferNum == 0) - { - // if no OP_DROP vouts check the last vout opreturn: - if (IsTokenCreateFuncid(TokensV2::DecodeTokenOpRet(tx.vout.back().scriptPubKey, tokenid, vpksdummy, oprets))) - { - TokensV2::DecodeTokenCreateOpRet(tx.vout.back().scriptPubKey, vorigpk, name, description, oprets); - - // check this is really creator - CPubKey origpk = pubkey2pk(vorigpk); - if (TotalPubkeyNormalInputs(eval, tx, origpk) == 0) - return report_validation_error(__func__, eval, tx, "no vins with creator pubkey"); - createNum ++; - } - } - - // check that creation tx does not have my cc vins - if (createNum > 0) { - bool hasMyccvin = false; - std::for_each (tx.vin.begin(), tx.vin.end(), [&](const CTxIn &vin){ cp->ismyvin(vin.scriptSig) ? hasMyccvin = true : hasMyccvin = hasMyccvin; }); - if (hasMyccvin) - return report_validation_error(__func__, eval, tx, "creation tx can't have token vins"); - return true; - } - return false; -} -*/ - // token 2 cc validation entry point bool Tokensv2Validate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) { @@ -782,13 +681,6 @@ bool Tokensv2Validate(struct CCcontract_info *cp, Eval* eval, const CTransaction return eval->Invalid("only one opreturn supported"); std::string errorStr; - - // these checks now are in TokensExactAmounts - //if (CheckTokensV2CreateTx(cp, eval, tx)) //found create tx and it is valid - // return true; - //if (eval->state.IsInvalid()) // create tx is invalid - // return false; - // check token vouts (token txns could have multiple tokenids for multiple token transfer) if (!TokensExactAmounts(true, cp, eval, tx, errorStr)) return report_validation_error(__func__, eval, tx, errorStr); @@ -845,18 +737,6 @@ UniValue TokenList() return(result); } -/*bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, std::string &errorStr) -{ - return TokensExactAmounts(goDeeper, cp, eval, tx, errorStr); -}*/ - -// some v2 wrappers for template functions - -/*std::string CreateTokenLocal2(CAmount txfee, CAmount tokensupply, std::string name, std::string description, vscript_t nonfungibleData) -{ - return CreateTokenLocal(txfee, tokensupply, name, description, nonfungibleData); -}*/ - UniValue TokenV2List(const UniValue ¶ms) { UniValue result(UniValue::VARR); @@ -968,4 +848,4 @@ UniValue TokenV2List(const UniValue ¶ms) } return(result); -} \ No newline at end of file +} From ca363f25ecca5e7d3685a0e1fbeaab3033723c0d Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 01:17:03 +0500 Subject: [PATCH 211/348] support for Raddress as desination added to tokenv2transfer --- src/cc/CCtokens.h | 40 +++- src/cc/CCtokens_impl.h | 150 ++++++++++----- src/cc/CCtokenutils.cpp | 129 +++++++++++-- src/rpc/tokensrpc.cpp | 409 +++++++++++++++++++++++++++------------- 4 files changed, 532 insertions(+), 196 deletions(-) diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h index 60acdbb4eac..09a2231889e 100644 --- a/src/cc/CCtokens.h +++ b/src/cc/CCtokens.h @@ -206,6 +206,10 @@ CC *MakeTokensv2CCcond1of2(uint8_t evalcode, uint8_t evalcode2, CPubKey pk1, CPu /// @returns cryptocondition object. Must be disposed with cc_free function when not used any more CC *MakeTokensv2CCcondMofN(uint8_t evalcode1, uint8_t evalcode2, uint8_t M, std::vector pks); +/// same for CTxDestination which may be either CPubKey or CKeyID +CC *MakeTokensv2CCcondMofNDest(uint8_t evalcode1, uint8_t evalcode2, uint8_t M, std::vector dests); + + /// Creates a token transaction output with a cryptocondition that allows to spend it by one key. /// The resulting vout will have two eval codes (EVAL_TOKENSV2 and evalcode parameter value). /// The returned output should be added to a transaction vout array. @@ -272,9 +276,19 @@ CTxOut MakeTokensCC1of2voutMixed(uint8_t evalcode, uint8_t evalcode2, CAmount nV /// @see CCcontract_info CTxOut MakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, uint8_t M, const std::vector & pks, vscript_t* pvData = nullptr); +/// same as @see MakeTokensCCMofNvoutMixed but for CPubKeys or CKeyIDs +CTxOut MakeTokensCCMofNDestVoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, uint8_t M, const std::vector &dests, vscript_t* pvData); + UniValue TokenList(); UniValue TokenV2List(const UniValue ¶ms); +/// @private +std::vector GetTokenV1IndexKeys(const CPubKey &pk); +/// @private +std::vector GetTokenV2IndexKeys(const CPubKey &pk); +/// @private +std::vector GetTokenV2Conds(const CPubKey &pk); + inline bool IsTokenCreateFuncid(uint8_t funcid) { return funcid == 'c'; } inline bool IsTokenTransferFuncid(uint8_t funcid) { return funcid == 't'; } @@ -360,12 +374,26 @@ class TokensV1 { return ::MakeTokensCC1vout(evalcode1, evalcode2, nValue, pks[0], pvvData); else return CTxOut(); - } + } + + static CTxOut MakeTokensCCMofNDestVout(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, uint8_t M, const std::vector &dests, std::vector* pvvData = NULL) + { + // convert to pubkey (no other dest support in cc v1) + std::vector pks; + for (auto const &dest : dests) + if (dest.which() == TX_PUBKEY) + pks.push_back(boost::get(dest)); + return MakeTokensCCMofNvout(evalcode1, evalcode2, nValue, M, pks, pvvData); + } static UniValue FinalizeCCTx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, CAmount txfee, CScript opret) { return ::FinalizeCCTxExt(remote, changeFlag, cp, mtx, mypk, txfee, opret); } + static std::vector GetTokenIndexKeys(const CPubKey &pk) + { + return ::GetTokenV1IndexKeys(pk); + } }; // tokens 2 specific functions @@ -443,10 +471,20 @@ class TokensV2 { { return ::MakeTokensCCMofNvoutMixed(evalcode1, evalcode2, nValue, M, pks, (pvvData != nullptr ? &(*pvvData)[0] : nullptr)); } + static CTxOut MakeTokensCCMofNDestVout(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, uint8_t M, const std::vector &dests, std::vector* pvvData = NULL) + { + return ::MakeTokensCCMofNDestVoutMixed(evalcode1, evalcode2, nValue, M, dests, (pvvData != nullptr ? &(*pvvData)[0] : nullptr)); + } + static UniValue FinalizeCCTx(bool remote, uint32_t changeFlag, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, CAmount txfee, CScript opret) { return ::FinalizeCCV2Tx(remote, changeFlag, cp, mtx, mypk, txfee, opret); } + + static std::vector GetTokenIndexKeys(const CPubKey &pk) + { + return ::GetTokenV2IndexKeys(pk); + } }; /// @private diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 0c429b9f706..8d71f4fed79 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -18,6 +18,8 @@ // templates for either tokens or tokens2 functions' implementation +#include "key_io.h" + #include "CCtokens.h" #include "CCassets.h" #include "CCassetsCore_impl.h" @@ -164,10 +166,15 @@ CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, c template CAmount AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, const CPubKey &pk, uint256 tokenid, CAmount total, int32_t maxinputs, bool useMempool) { - char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; - - GetTokensCCaddress(cp, tokenaddr, pk, V::IsMixed()); - return AddTokenCCInputs(cp, mtx, tokenaddr, tokenid, total, maxinputs, useMempool); + CAmount inputs = 0LL; + + std::vector tokenindexkeys = V::GetTokenIndexKeys(pk); + // get inputs from token indexkeys: + for (std::string &tokenindexkey : tokenindexkeys) { + inputs += AddTokenCCInputs(cp, mtx, tokenindexkey.c_str(), tokenid, total, maxinputs, useMempool); + if (total > 0 && inputs >= total) return inputs; // if total == 0 this just getting the balance + } + return inputs; } template @@ -183,7 +190,7 @@ UniValue TokenBeginTransferTx(CMutableTransaction &mtx, struct CCcontract_info * txfee = 10000; mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CAmount normalInputs = AddNormalinputs(mtx, mypk, txfee, 3, isRemote); + CAmount normalInputs = AddNormalinputs(mtx, mypk, txfee, 0x1000, isRemote); if (normalInputs < 0) { return MakeResultError("cannot find normal inputs"); @@ -285,21 +292,21 @@ UniValue TokenFinalizeTransferTx(CMutableTransaction &mtx, struct CCcontract_inf // tokenid - token creation tx id // tokenaddr - address where unspent token inputs to search // probeconds - vector of pair of vintx cond and privkey (if null then global priv key will be used) to pick vintx token vouts to sign mtx vins -// destpubkeys - if size=1 then it is the dest pubkey, if size=2 then the dest address is 1of2 addr +// destinations - addresses or pubkeys where to send tokens // total - token amount to transfer // returns: signed transfer tx in hex template -UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokenid, const char *tokenaddr, std::vector> probeconds, uint8_t M, std::vector destpubkeys, CAmount total, bool useMempool) +UniValue TokenTransferExtDest(const CPubKey &remotepk, CAmount txfee, uint256 tokenid, const std::vector &tokenaddrs, std::vector> probeconds, uint8_t M, std::vector destinations, CAmount total, bool useMempool) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CAmount CCchange = 0, inputs = 0; - struct CCcontract_info *cp, C; if (total < 0) { CCerror = strprintf("negative total"); LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << CCerror << "=" << total << std::endl); return NullUniValue; } + + struct CCcontract_info *cp, C; cp = CCinit(&C, V::EvalCode()); if (txfee == 0) @@ -311,40 +318,59 @@ UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokeni CCerror = "mypk is not set or invalid"; return NullUniValue; } + std::vector destpubkeys; + for (auto const &dest : destinations) + if (dest.which() == TX_PUBKEY) + destpubkeys.push_back(boost::get(dest)); // CAmount normalInputs = AddNormalinputs(mtx, mypk, txfee, 0x10000, isRemote); // note: wallet scanning for inputs is slower than index scanning CAmount normalInputs = AddNormalinputsRemote(mtx, mypk, txfee, 0x10000, useMempool); if (normalInputs > 0) { - if ((inputs = AddTokenCCInputs(cp, mtx, tokenaddr, tokenid, total, CC_MAXVINS, useMempool)) >= total) // NOTE: AddTokenCCInputs might set cp->additionalEvalCode which is used in FinalizeCCtx! + CAmount CCchange = 0, CCinputs = 0; + for (const auto &addr : tokenaddrs) { + CAmount outputs = AddTokenCCInputs(cp, mtx, addr.c_str(), tokenid, total, CC_MAXVINS, useMempool); + if (outputs > 0) + CCinputs += outputs; + if (CCinputs >= total) + break; + } + + if (CCinputs >= total) { - if (inputs > total) - CCchange = (inputs - total); + if (CCinputs > total) + CCchange = (CCinputs - total); - if (destpubkeys.size() == 0) { + if (destinations.size() == 0) { CCerror = "no dest pubkeys"; return NullUniValue; } if (V::EvalCode() == EVAL_TOKENS) { - if (destpubkeys.size() > 2) { + if (destinations.size() > 2) { CCerror = "no more than 2 dest pubkeys supported"; return NullUniValue; } } if (V::EvalCode() == EVAL_TOKENSV2) { - if (destpubkeys.size() > 128) { + if (destinations.size() > 128) { CCerror = "no more than 128 dest pubkeys supported"; return NullUniValue; } } - mtx.vout.push_back(V::MakeTokensCCMofNvout(V::EvalCode(), 0, total, M, destpubkeys)); + mtx.vout.push_back(V::MakeTokensCCMofNDestVout(V::EvalCode(), 0, total, M, destinations)); // add optional custom probe conds to non-usual sign vins for (const auto &p : probeconds) CCAddVintxCond(cp, p.first, p.second); + + if (V::EvalCode() == EVAL_TOKENSV2) { + // probes for spending from mypk + for (const auto &mycond : GetTokenV2Conds(mypk)) + CCAddVintxCond(cp, mycond, nullptr); + } if (V::EvalCode() == EVAL_TOKENSV2) { // if this is multisig - build and add multisig probes: @@ -385,7 +411,7 @@ UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokeni } else { - if (inputs == 0LL) + if (CCinputs == 0LL) CCerror = strprintf("no token inputs"); else CCerror = strprintf("insufficient token inputs"); @@ -399,26 +425,46 @@ UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokeni return NullUniValue; } -// transfer tokens from mypk to another pubkey -// param additionalEvalCode2 allows transfer of dual-eval non-fungible tokens +// old style call, convert pubkeys to destinations +template +UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokenid, const std::vector &tokenaddrs, std::vector> probeconds, uint8_t M, const std::vector &destpks, CAmount total, bool useMempool) +{ + std::vector destinations; + for (auto const &pk : destpks) + destinations.push_back(pk); + return TokenTransferExtDest(remotepk, txfee, tokenid, tokenaddrs, probeconds, M, destinations, total, useMempool); +} + +// transfer tokens from mypk to a destination template -std::string TokenTransfer(CAmount txfee, uint256 tokenid, uint8_t M, const std::vector &destpubkeys, CAmount total) +std::string TokenTransferDest(CAmount txfee, uint256 tokenid, uint8_t M, const std::vector &destinations, CAmount total) { - char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; CPubKey mypk = pubkey2pk(Mypubkey()); struct CCcontract_info *cp, C; cp = CCinit(&C, V::EvalCode()); TokenDataTuple tokenData; - vscript_t vextraData; + vuint8_t vextraData; GetTokenData(NULL, tokenid, tokenData, vextraData); - GetTokensCCaddress(cp, tokenaddr, mypk, V::IsMixed()); + //vuint8_t vextraData = std::get<4>(tokenData); - UniValue sigData = TokenTransferExt(CPubKey(), txfee, tokenid, tokenaddr, {}, M, destpubkeys, total, true); + std::vector tokenindexkeys = V::GetTokenIndexKeys(mypk); + UniValue sigData = TokenTransferExtDest(CPubKey(), txfee, tokenid, tokenindexkeys, {}, M, destinations, total, true); return ResultGetTx(sigData); } +// old style call, convert pubkeys to destinations +template +std::string TokenTransfer(CAmount txfee, uint256 tokenid, uint8_t M, const std::vector &destpks, CAmount total) +{ + std::vector destinations; + for (auto const &pk : destpks) + destinations.push_back(pk); + return TokenTransferDest(txfee, tokenid, M, destinations, total); +} + + // returns token creation signed raw tx // params: txfee amount, token amount, token name and description, optional NFT data, optional eval code of a cc to validate NFT template @@ -551,13 +597,12 @@ UniValue GetAllTokenBalances(CPubKey pk, bool useMempool) struct CCcontract_info *cp, C; cp = CCinit(&C, V::EvalCode()); - char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; - GetTokensCCaddress(cp, tokenaddr, pk, V::IsMixed()); + std::vector tokenindexkeys = V::GetTokenIndexKeys(pk); std::map mapBalances; // make lambda to use it for either index kind: - auto add_token_amount = [&](uint256 txhash, int32_t index, CAmount satoshis) -> void + auto add_token_amount = [&](const char *tokenindexkey, uint256 txhash, int32_t index, CAmount satoshis) -> void { CTransaction tx; uint256 hashBlock; @@ -569,7 +614,7 @@ UniValue GetAllTokenBalances(CPubKey pk, bool useMempool) { char destaddr[KOMODO_ADDRESS_BUFSIZE]; Getscriptaddress(destaddr, tx.vout[index].scriptPubKey); - if (strcmp(destaddr, tokenaddr) != 0) + if (strcmp(destaddr, tokenindexkey) != 0) return; LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << funcname << "()" << " checking tx vout destaddress=" << destaddr << " amount=" << tx.vout[index].nValue << std::endl); @@ -589,30 +634,33 @@ UniValue GetAllTokenBalances(CPubKey pk, bool useMempool) } }; // auto add_token_amount - if (fUnspentCCIndex) + for (std::string &tokenindexkey : tokenindexkeys) { - std::vector > unspentOutputs; - - SetCCunspentsCCIndex(unspentOutputs, tokenaddr); - if (useMempool) - AddCCunspentsCCIndexMempool(unspentOutputs, tokenaddr); - - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspent ccindex found unspentOutputs=" << unspentOutputs.size() << std::endl); - for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) - add_token_amount(it->first.txhash, it->first.index, it->second.satoshis); - } - else - { - std::vector > unspentOutputs; - - if (useMempool) - SetCCunspentsWithMempool(unspentOutputs, (char*)tokenaddr, CC_INPUTS_TRUE); + if (fUnspentCCIndex) + { + std::vector > unspentOutputs; + + SetCCunspentsCCIndex(unspentOutputs, tokenindexkey.c_str()); + if (useMempool) + AddCCunspentsCCIndexMempool(unspentOutputs, tokenindexkey.c_str()); + + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspent ccindex found unspentOutputs=" << unspentOutputs.size() << std::endl); + for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) + add_token_amount(tokenindexkey.c_str(), it->first.txhash, it->first.index, it->second.satoshis); + } else - SetCCunspents(unspentOutputs, (char*)tokenaddr, CC_INPUTS_TRUE); - - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspent index found unspentOutputs=" << unspentOutputs.size() << std::endl); - for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) - add_token_amount(it->first.txhash, it->first.index, it->second.satoshis); + { + std::vector > unspentOutputs; + + if (useMempool) + SetCCunspentsWithMempool(unspentOutputs, (char*)tokenindexkey.c_str(), CC_INPUTS_TRUE); + else + SetCCunspents(unspentOutputs, (char*)tokenindexkey.c_str(), CC_INPUTS_TRUE); + + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << " unspent index found unspentOutputs=" << unspentOutputs.size() << std::endl); + for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) + add_token_amount(tokenindexkey.c_str(), it->first.txhash, it->first.index, it->second.satoshis); + } } for(auto const &m : mapBalances) { @@ -1062,7 +1110,7 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c if (tokenoshis != 0) { - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << indentStr << funcname << "()" << " adding vintx.vout for tx.vin[" << i << "] tokenoshis=" << tokenoshis << std::endl); + LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << funcname << "()" << " adding vintx.vout for tx.vin[" << i << "] tokenoshis=" << tokenoshis << std::endl); mapinputs[reftokenid] += tokenoshis; } } diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index c01024eb330..c85e717fc78 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -17,6 +17,7 @@ // make token cryptoconditions and vouts // This code was moved to a separate source file to enable linking libcommon.so (with importcoin.cpp which depends on some token functions) +#include "key_io.h" #include "CCtokens.h" CScript EncodeTokenCreateOpRetV1(const std::vector &origpubkey, const std::string &name, const std::string &description, const std::vector &oprets) @@ -369,13 +370,21 @@ CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vect // token v2 'mixed' vouts: -// make three-eval (token+evalcode+evalcode2) 1of2 cryptocondition: -CC *MakeTokensv2CCcondMofN(uint8_t evalcode1, uint8_t evalcode2, uint8_t M, std::vector pks) +// make three-eval (token+evalcode+evalcode2) 1of2 cryptocondition with pubkeys or keyids: +CC *MakeTokensv2CCcondMofNDest(uint8_t evalcode1, uint8_t evalcode2, uint8_t M, std::vector dests) { - // make 1of2 sigs cond - std::vector condpks; - for (auto const &pk : pks) - condpks.push_back(CCNewSecp256k1(pk)); + // make MofN sigs cond with destinations + std::vector conddests; + for (auto const &dest : dests) { + CC *ccSig; + if (dest.which() == TX_PUBKEY) + ccSig = CCNewSecp256k1(boost::get(dest)); + else if (dest.which() == TX_PUBKEYHASH) + ccSig = CCNewSecp256k1Hash(boost::get(dest)); + else + return nullptr; + conddests.push_back(ccSig); + } std::vector thresholds; if (evalcode1 != 0) @@ -384,10 +393,23 @@ CC *MakeTokensv2CCcondMofN(uint8_t evalcode1, uint8_t evalcode2, uint8_t M, std: thresholds.push_back(CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENSV2))); // this is eval token cc if (evalcode2 != 0) thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode2))); // add optional additional evalcode - thresholds.push_back(CCNewThreshold(M, condpks)); // this is 1 of 2 sigs cc + thresholds.push_back(CCNewThreshold(M, conddests)); // this is 1 of 2 sigs cc return CCNewThreshold(thresholds.size(), thresholds); } + +// make three-eval (token+evalcode+evalcode2) 1of2 cryptocondition with pubkeys: +CC *MakeTokensv2CCcondMofN(uint8_t evalcode1, uint8_t evalcode2, uint8_t M, std::vector pks) +{ + // convert pks to dests + std::vector dests; + for (auto const &pk : pks) + dests.push_back(pk); + // make MofN sigs cond + return MakeTokensv2CCcondMofNDest(evalcode1, evalcode2, M, dests); +} + + // overload to make two-eval (token+evalcode) 1of2 cryptocondition: CC *MakeTokensv2CCcond1of2(uint8_t evalcode, CPubKey pk1, CPubKey pk2) { return MakeTokensv2CCcondMofN(evalcode, 0, 1, { pk1, pk2 }); @@ -409,21 +431,28 @@ CC *MakeTokensv2CCcond1(uint8_t evalcode, CPubKey pk) { return MakeTokensv2CCcondMofN(evalcode, 0, 1, { pk }); } -// make three-eval (token+evalcode+evalcode2) MofN cc vout: -CTxOut MakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, uint8_t M, const std::vector &pks, vscript_t* pvData) +CTxOut MakeTokensCCMofNDestVoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, uint8_t M, const std::vector &dests, vscript_t* pvData) { CTxOut vout; - CCwrapper payoutCond( MakeTokensv2CCcondMofN(evalcode1, evalcode2, M, pks) ); - if (!CCtoAnon(payoutCond.get())) - return vout; + CCwrapper payoutCond( MakeTokensv2CCcondMofNDest(evalcode1, evalcode2, M, dests) ); + //if (!CCtoAnon(payoutCond.get())) + // return vout; - vout = CTxOut(nValue, CCPubKey(payoutCond.get(),true)); + bool hasSecHash = std::find_if(dests.begin(), dests.end(), [](const CTxDestination &dest){ return dest.which() == TX_PUBKEYHASH; }) != dests.end(); + + vout = CTxOut(nValue, CCPubKey(payoutCond.get(), hasSecHash ? CC_MIXED_MODE_SECHASH_SUBVER_1 : CC_MIXED_MODE_SUBVER_0) ); { std::vector vvData; if (pvData) vvData.push_back(*pvData); + // convert to pubkeys to show them in opdrop + std::vector pks; + for (auto const &dest : dests) + if (dest.which() == TX_PUBKEY) + pks.push_back(boost::get(dest)); + COptCCParams ccp = COptCCParams(COptCCParams::VERSION_2, evalcode1, M, pks.size(), pks, vvData); // ver2 -> add pks vout.scriptPubKey << ccp.AsVector() << OP_DROP; } @@ -432,6 +461,16 @@ CTxOut MakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount n return vout; } +// make three-eval (token+evalcode+evalcode2) MofN cc vout: +CTxOut MakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, uint8_t M, const std::vector &pks, vscript_t* pvData) +{ + // convert pks to dests + std::vector dests; + for (auto const &pk : pks) + dests.push_back(pk); + return MakeTokensCCMofNDestVoutMixed(evalcode1, evalcode2, nValue, M, dests, pvData); +} + // make three-eval (token+evalcode+evalcode2) cc vout: CTxOut MakeTokensCC1voutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmount nValue, CPubKey pk, vscript_t* pvData) { @@ -490,3 +529,67 @@ uint8_t DecodeTokenOpretVersion(const CScript &scriptPubKey) } return version; } + +// get token indexkey for pubkey for old tokens: +std::vector GetTokenV1IndexKeys(const CPubKey &pk) +{ + std::vector tokenindexkeys; + char tokenindexkeyPK[KOMODO_ADDRESS_BUFSIZE]; + struct CCcontract_info *cp, C; + cp = CCinit(&C, EVAL_TOKENS); + + GetTokensCCaddress(cp, tokenindexkeyPK, pk, false); + tokenindexkeys.push_back(tokenindexkeyPK); + + return tokenindexkeys; +} + +std::vector GetTokenV2Conds(const CPubKey &pk) +{ + std::vector tokenconds; + // get token cond from the pubkey: + char tokenindexkeyPK[KOMODO_ADDRESS_BUFSIZE]; + struct CCcontract_info *cp, C; + cp = CCinit(&C, EVAL_TOKENSV2); + + CCwrapper tokenCondPK( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { pk }) ); + tokenconds.push_back(tokenCondPK); + + // get token conds from the Raddress + char normaladdr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(normaladdr, CScript() << vuint8_t(pk.begin(), pk.end()) << OP_CHECKSIG); + CTxDestination dest = DecodeDestination(normaladdr); // get normal dest + for (CC_SUBVER ccSubVersion = CC_MIXED_MODE_SUBVER_0; ccSubVersion <= CC_MIXED_MODE_SUBVER_MAX; ccSubVersion = (CC_SUBVER)(ccSubVersion + 1)) { + CCwrapper tokenCond( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { dest }) ); // use cc creator for destinations + tokenconds.push_back(tokenCond); + } + return tokenconds; +} + +// get all token indexkeys for pubkey for tokens mixed mode: +std::vector GetTokenV2IndexKeys(const CPubKey &pk) +{ + std::vector tokenindexkeys; + // get all addresses from pubkey: + char tokenindexkeyPK[KOMODO_ADDRESS_BUFSIZE]; + struct CCcontract_info *cp, C; + cp = CCinit(&C, EVAL_TOKENSV2); + + GetTokensCCaddress(cp, tokenindexkeyPK, pk, true); + std::cerr << __func__ << " tokenindexkeyPK=" << tokenindexkeyPK << std::endl; + tokenindexkeys.push_back(tokenindexkeyPK); + + // get inputs from Raddress + char normaladdr[KOMODO_ADDRESS_BUFSIZE]; + char tokenindexkeyR[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(normaladdr, CScript() << vuint8_t(pk.begin(), pk.end()) << OP_CHECKSIG); + CTxDestination dest = DecodeDestination(normaladdr); // get normal dest + for (CC_SUBVER ccSubVersion = CC_MIXED_MODE_SUBVER_0; ccSubVersion <= CC_MIXED_MODE_SUBVER_MAX; ccSubVersion = (CC_SUBVER)(ccSubVersion + 1)) { + CCwrapper tokenCond( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { dest }) ); // use cc creator for destinations + //if (!CCtoAnon(tokenCond.get())) { std::cerr << __func__ << " CCtoAnon failed" << std::endl; continue; } // now in CCPubKey() + Getscriptaddress(tokenindexkeyR, CCPubKey(tokenCond.get(), ccSubVersion)); + //std::cerr << __func__ << " CCPubKey=" << CCPubKey(tokenCond.get(), ccSubVersion).ToString() << " tokenindexkeyR=" << tokenindexkeyR << std::endl; + tokenindexkeys.push_back(tokenindexkeyR); + } + return tokenindexkeys; +} \ No newline at end of file diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index a6d44cffdf3..02c79447ed6 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -20,6 +20,7 @@ #include "amount.h" #include "rpc/server.h" #include "rpc/protocol.h" +#include "key_io.h" #include "../wallet/crypter.h" #include "../wallet/rpcwallet.h" @@ -65,7 +66,7 @@ UniValue tokenv2indexkey(const UniValue& params, bool fHelp, const CPubKey& mypk { if (fHelp || params.size() != 1) throw runtime_error("tokenv2indexkey pubkey\n" - "returns address index key for pubkey.\n" + "returns tokens index keys for pubkey.\n" "It can be used with getaddressutxos getaddresstxids rpcs to list tokens outputs on this pubkey\n"); struct CCcontract_info *cp,C; @@ -78,9 +79,11 @@ UniValue tokenv2indexkey(const UniValue& params, bool fHelp, const CPubKey& mypk if (!pk.IsValid()) throw runtime_error("invalid pubkey\n"); - char address[KOMODO_ADDRESS_BUFSIZE]; - GetCCaddress(cp, address, pk, true); - return address; + UniValue result(UniValue::VARR); + std::vector tokenindexkeys = TokensV2::GetTokenIndexKeys(pk); + for (auto const tokenindexkey : tokenindexkeys) + result.push_back(tokenindexkey); + return result; } UniValue assetsv2indexkey(const UniValue& params, bool fHelp, const CPubKey& mypk) @@ -289,7 +292,8 @@ static UniValue tokenbalance(const std::string& name, const UniValue& params, bo else vpubkey = Mypubkey(); - CAmount balance = GetTokenBalance(pubkey2pk(vpubkey), tokenid, false); + CPubKey pk = pubkey2pk(vpubkey); + CAmount balance = GetTokenBalance(pk, tokenid, false); if (CCerror.empty()) { char destaddr[KOMODO_ADDRESS_BUFSIZE]; @@ -297,8 +301,11 @@ static UniValue tokenbalance(const std::string& name, const UniValue& params, bo cp = CCinit(&C, V::EvalCode()); result.push_back(Pair("result", "success")); - if (GetCCaddress(cp, destaddr, pubkey2pk(vpubkey), V::IsMixed()) != 0) - result.push_back(Pair("CCaddress", destaddr)); + + std::vector tokenindexkeys = V::GetTokenIndexKeys(pk); + UniValue uIndexkeys(UniValue::VARR); + for (auto const &tokenindexkey : tokenindexkeys) uIndexkeys.push_back(tokenindexkey); + result.push_back(Pair("CCIndexKeys", uIndexkeys)); result.push_back(Pair("tokenid", params[0].get_str())); result.push_back(Pair("balance", (int64_t)balance)); @@ -515,110 +522,53 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b CCerror.clear(); - if (fHelp || (params.size() != 3 && params.size() != 1)) - throw runtime_error(name + " tokenid destpubkey amount\n" + - name + " '{ \"tokenid\":\"\", \"ccaddressMofN\":\"
\", \"destpubkeys\": [ \"\", \"\", ... ], \"M\": , \"amount\": }'\n" - "tokenid - token creation id\n" - "ccaddressMofN - optional cc address of MofN utxos to spend, if not present spending is from mypk\n" - "destpubkey, destpubkey1 ... destpubkeyN - destination pubkeys (max = 128)\n" - "M - required min of signatures, integer\n\n" - "amount - token amount to send in satoshi, int64\n" - "Note, that MofN supported only for tokens v2\n\n"); + if (fHelp || params.size() != 3) + throw runtime_error( + name + " tokenid destination amount\n" + "To spend 1of1 token utxo and send to 1of1 destination. Params:\n" + " tokenid - token creation id\n" + " destination - destination pubkey or R-address\n" + " amount - token amount to send, in satoshi\n\n"); - if (ensure_CCrequirements(V::EvalCode(), remotepk.IsValid()) < 0) + if (ensure_CCrequirements(V::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) throw runtime_error("wallet is required"); - LOCK2(cs_main, pwalletMain->cs_wallet); // remote call not supported yet + LOCK2(cs_main, pwalletMain->cs_wallet); // remote call not supported, only local wallet + + uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str()); + if( tokenid.IsNull() ) + return MakeResultError("invalid tokenid"); - if (params.size() == 3) - { - uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str()); - if( tokenid == zeroid ) - return MakeResultError("invalid tokenid"); + std::vector dests; + + CTxDestination dest; + vuint8_t vpubkey(ParseHex(params[1].get_str())); + if (vpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE && CPubKey(vpubkey).IsValid()) + dest = CPubKey(vpubkey); + else + dest = DecodeDestination(params[1].get_str()); + if (dest.which() == TX_PUBKEYHASH && !CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + return MakeResultError("destination as address not active yet"); + if (dest.which() != TX_PUBKEYHASH && dest.which() != TX_PUBKEY) + return MakeResultError("invalid destination pubkey or address"); - std::vector pks; - vuint8_t vpubkey(ParseHex(params[1].get_str().c_str())); - if (vpubkey.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) - return MakeResultError("invalid destpubkey"); - pks.push_back(pubkey2pk(vpubkey)); - - CAmount amount = atoll(params[2].get_str().c_str()); - if( amount <= 0 ) - return MakeResultError("amount must be positive"); - hex = TokenTransfer(0, tokenid, 1, pks, amount); - RETURN_IF_ERROR(CCerror); - if (!hex.empty()) - return MakeResultSuccess(hex); - else - return MakeResultError("could not create transfer token transaction"); - } + // after subver_1 upgrade only addresses always will be used as destination, pubkeys are converted to addresses + if (dest.which() == TX_PUBKEY && CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + dests.push_back(boost::get(dest).GetID()); else - { - if (V::EvalCode() != EVAL_TOKENSV2) - return MakeResultError("MofN transfer is supported only for tokens v2\n"); - - UniValue jsonParams(UniValue::VOBJ); - if (params[0].getType() == UniValue::VOBJ) - jsonParams = params[0].get_obj(); - else if (params[0].getType() == UniValue::VSTR) // json in quoted string '{...}' - jsonParams.read(params[0].get_str().c_str()); - if (jsonParams.getType() != UniValue::VOBJ) - return MakeResultError("parameter 1 must be object\n"); - - uint256 tokenid = Parseuint256(jsonParams["tokenid"].get_str().c_str()); - if( tokenid == zeroid ) - return MakeResultError("invalid tokenid"); - - std::string ccaddressMofN; - if (!jsonParams["ccaddressMofN"].isNull()) { - ccaddressMofN = jsonParams["ccaddressMofN"].get_str(); - if (!CBitcoinAddress(ccaddressMofN).IsValid()) - return MakeResultError("invalid ccaddressMofN\n"); - } + dests.push_back(dest); // address or pubkey - std::vector pks; - UniValue udestpks = jsonParams["destpubkeys"]; - if (!udestpks.isArray()) - return MakeResultError("destpubkeys must be an array\n"); - - if (udestpks.size() > 128) - return MakeResultError("destpubkeys num is limited by 128\n"); - - for (int i = 0; i < udestpks.size(); i ++) { - vuint8_t vpubkey(ParseHex(udestpks[i].get_str().c_str())); - if (vpubkey.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) - return MakeResultError(std::string("invalid destpubkey #") + std::to_string(i+1)); - pks.push_back(CPubKey(vpubkey)); - } - int M = jsonParams["M"].get_int(); - if (M > 128) - return MakeResultError("M is limited by 128\n"); - if (M > pks.size()) - return MakeResultError("M could not be more than dest pubkeys\n"); - - CAmount amount = jsonParams["amount"].get_int64(); - if( amount <= 0 ) - return MakeResultError("amount must be positive"); - - if (ccaddressMofN.empty()) { - hex = TokenTransfer(0, tokenid, M, pks, amount); - RETURN_IF_ERROR(CCerror); - if (!hex.empty()) - return MakeResultSuccess(hex); - else - return MakeResultError("could not create transfer token transaction"); - } - else { - UniValue transferred = TokenTransferExt(CPubKey(), 0, tokenid, ccaddressMofN.c_str(), {}, (uint8_t)M, pks, amount, false); - RETURN_IF_ERROR(CCerror); - if (!ResultGetTx(transferred).empty()) - return transferred; - else - return MakeResultError("could not create transfer token transaction"); - } - } + CAmount amount = atoll(params[2].get_str().c_str()); + if( amount <= 0 ) + return MakeResultError("amount must be positive"); + hex = TokenTransferDest(0, tokenid, 1, dests, amount); + RETURN_IF_ERROR(CCerror); + if (!hex.empty()) + return MakeResultSuccess(hex); + else + return MakeResultError("could not create transfer token transaction"); } UniValue tokentransfer(const UniValue& params, bool fHelp, const CPubKey& remotepk) @@ -711,44 +661,95 @@ UniValue tokenv2transfermany(const UniValue& params, bool fHelp, const CPubKey& return tokentransfermany("tokenv2transfermany", params, fHelp, remotepk); } -UniValue tokenconvert(const UniValue& params, bool fHelp, const CPubKey& mypk) + +UniValue tokenv2transferMofN(const UniValue& params, bool fHelp, const CPubKey& remotepk) { - UniValue result(UniValue::VOBJ); std::string hex; int32_t evalcode; int64_t amount; uint256 tokenid; + UniValue result(UniValue::VOBJ); + std::string hex; + CCerror.clear(); - if (fHelp || params.size() != 4) - throw runtime_error("tokenconvert evalcode tokenid pubkey amount\n"); - if (ensure_CCrequirements(EVAL_ASSETS) < 0) + + if (fHelp || params.size() != 1) + throw runtime_error( + std::string(__func__) + " '{ \"tokenid\":\"\", \"ccaddressMofN\":\"
\", \"destpubkeys\": [ \"\", \"\", ... ], \"M\": , \"amount\": }'\n" + "To spend MofN token utxo and send to MofN destination pubkeys. Params:\n" + " tokenid - token creation id\n" + " ccaddressMofN - optional cc address of MofN utxos to spend, if not present spending is from mypk\n" + " destpubkey, destpubkey1 ... destpubkeyN - destination pubkeys (max = 128)\n" + " M - required min number of signatures\n" + " amount - token amount to send, in satoshi\n" + "Note, that MofN supported only for tokens v2\n\n"); + + if (ensure_CCrequirements(TokensV2::EvalCode()) < 0) throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - if (!EnsureWalletIsAvailable(false)) - throw runtime_error("wallet is required"); - LOCK2(cs_main, pwalletMain->cs_wallet); - evalcode = atoi(params[0].get_str().c_str()); - tokenid = Parseuint256((char *)params[1].get_str().c_str()); - std::vector pubkey(ParseHex(params[2].get_str().c_str())); - //amount = atol(params[3].get_str().c_str()); - amount = atoll(params[3].get_str().c_str()); // dimxy changed to prevent loss of significance - if( tokenid == zeroid ) + + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) + throw runtime_error("wallet is required"); + + LOCK2(cs_main, pwalletMain->cs_wallet); // remote rpc call not supported, only local wallet + + UniValue jsonParams(UniValue::VOBJ); + if (params[0].getType() == UniValue::VOBJ) + jsonParams = params[0].get_obj(); + else if (params[0].getType() == UniValue::VSTR) // json in quoted string '{...}' + jsonParams.read(params[0].get_str().c_str()); + if (jsonParams.getType() != UniValue::VOBJ) + return MakeResultError("parameter 1 must be object\n"); + + uint256 tokenid = Parseuint256(jsonParams["tokenid"].get_str().c_str()); + if( tokenid == zeroid ) return MakeResultError("invalid tokenid"); + + std::string ccaddressMofN; + if (!jsonParams["ccaddressMofN"].isNull()) { + ccaddressMofN = jsonParams["ccaddressMofN"].get_str(); + if (!CBitcoinAddress(ccaddressMofN).IsValid()) + return MakeResultError("invalid ccaddressMofN\n"); + } - if( amount <= 0 ) - return MakeResultError("amount must be positive"); + std::vector pks; + UniValue udestpks = jsonParams["destpubkeys"]; + if (!udestpks.isArray()) + return MakeResultError("destpubkeys must be an array\n"); + + if (udestpks.size() > 128) + return MakeResultError("destpubkeys num is limited by 128\n"); - return MakeResultError("deprecated"); + for (int i = 0; i < udestpks.size(); i ++) { + vuint8_t vpubkey(ParseHex(udestpks[i].get_str().c_str())); + if (vpubkey.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) + return MakeResultError(std::string("invalid destpubkey #") + std::to_string(i+1)); + pks.push_back(CPubKey(vpubkey)); + } + int M = jsonParams["M"].get_int(); + if (M > 128) + return MakeResultError("M is limited by 128\n"); + if (M > pks.size()) + return MakeResultError("M could not be more than dest pubkeys\n"); -/* hex = AssetConvert(0,tokenid,pubkey,amount,evalcode); - if (amount > 0) { - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else ERR_RESULT("couldnt convert tokens"); - } else { - ERR_RESULT("amount must be positive"); + CAmount amount = jsonParams["amount"].get_int64(); + if( amount <= 0 ) + return MakeResultError("amount must be positive"); + + if (ccaddressMofN.empty()) { + hex = TokenTransfer(0, tokenid, M, pks, amount); + RETURN_IF_ERROR(CCerror); + if (!hex.empty()) + return MakeResultSuccess(hex); + else + return MakeResultError("could not create transfer token transaction"); } - return(result); */ + else { + UniValue transferred = TokenTransferExt(CPubKey(), 0, tokenid, { ccaddressMofN }, {}, (uint8_t)M, pks, amount, false); + RETURN_IF_ERROR(CCerror); + if (!ResultGetTx(transferred).empty()) + return transferred; + else + return MakeResultError("could not create transfer token transaction"); + } } + template UniValue tokenbid(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) { @@ -1181,6 +1182,149 @@ UniValue tokenv2addccinputs(const UniValue& params, bool fHelp, const CPubKey& r return result; } + +// cc tx creation helper rpc (test) +UniValue CreateCCEvalTx(const CPubKey &mypk, CAmount txfee, const UniValue &txjson) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpEvals, C; + + CAmount inputs = 0LL; + CAmount outputs = 0LL; + + + cpEvals = CCinit(&C, EVAL_TOKENSV2); + if (txfee == 0) + txfee = 10000; + + UniValue jvins = txjson[std::string("vins")]; + if (!jvins.isArray()) { CCerror = "no or incorrect 'vins' array"; return NullUniValue; } + UniValue jvouts = txjson[std::string("vouts")]; + if (!jvouts.isArray()) { CCerror = "no or incorrect 'vouts' array"; return NullUniValue; } + + for (int i = 0; i < jvins.size(); i ++) { + uint256 vintxid = Parseuint256(jvins[i][std::string("hash")].get_str().c_str()); + //std::cerr << __func__ << " getting n" << std::endl; + int32_t vini = jvins[i][std::string("n")].get_int(); + //std::cerr << __func__ << " got n" << std::endl; + uint256 hashBlock; + CTransaction vintx; + if (!myGetTransaction(vintxid, vintx, hashBlock)) { CCerror = "could not load vin tx:" + vintxid.GetHex(); return NullUniValue; } + inputs += vintx.vout[vini].nValue; + + mtx.vin.push_back(CTxIn(vintxid, vini)); + } + + for (int i = 0; i < jvouts.size(); i ++) { + UniValue uniAmount; + if (!(uniAmount = jvouts[i][std::string("nValue")]).empty()) { CCerror = "no nValue in vout"; return NullUniValue; } + //std::cerr << __func__ << " getting nValue " << uniAmount.write() << std::endl; + CAmount nValue = uniAmount.get_int64(); + //std::cerr << __func__ << " got nValue" << std::endl; + UniValue uniDest; + UniValue uniCC; + bool hasPkh = false, hasCC = false; + + if (!(uniDest = jvouts[i][std::string("Destination")]).isNull()) { + CTxDestination dest = DecodeDestination(uniDest.get_str()); + //if (dest.which() != TX_PUBKEYHASH) { CCerror = "only address destinations supported"; return NullUniValue; } + CScript script = GetScriptForDestination(dest); + if (script.empty()) { CCerror = "could not get script for normal destination"; return NullUniValue; } + mtx.vout.push_back(CTxOut(nValue, script)); + hasPkh = true; + } + else if (!(uniCC = jvouts[i][std::string("cc")]).isNull()) { + std::string ccstr = uniCC.write(); + char ccerr[128]; + CC *cond = cc_conditionFromJSONString(ccstr.c_str(), ccerr); + if (!cond) { CCerror = strprintf("could parse cc: %s", ccerr); return NullUniValue; } + + CScript script; + if (!jvouts[i]["opdrop"].isNull()) { + script = CCPubKey(cond, CC_OLD_V1_SUBVER); + std::vector vvopdrop = { ParseHex(jvouts[i]["opdrop"].get_str()) }; + COptCCParams ccp = COptCCParams(COptCCParams::VERSION_2, EVAL_TOKENSV2, 1, 1, { CPubKey(ParseHex(jvouts[i]["pubkey"].get_str())) }, vvopdrop); + script << ccp.AsVector() << OP_DROP; + } + else + script = CCPubKey(cond, CC_MIXED_MODE_SECHASH_SUBVER_1); // use subver 1 + if (script.empty()) { CCerror = "could not get script for cc"; return NullUniValue; } + mtx.vout.push_back(CTxOut(nValue, script)); + hasCC = true; + } + else { + CCerror = strprintf("invalid destination type for vout %d", i); return NullUniValue; + } + if (hasPkh && hasCC) { CCerror = "could not have both normal and cc destinations for one vout"; return NullUniValue; } + outputs += mtx.vout[i].nValue; + } + + if (inputs < outputs + txfee) { + if (AddNormalinputs(mtx, mypk, outputs + txfee - inputs, 0x10000) <= 0) { CCerror = "could not get normal inputs"; return NullUniValue; } + } + + const uint8_t nullpriv[32] = {'\0'}; + const uint8_t dontsign[32] = { 0xff }; + + // parse probe conds: + UniValue jvinccs = txjson[std::string("vinccs")]; + if (!jvinccs.isArray()) { CCerror = "no or incorrect 'vinccs' array"; return NullUniValue; } + for (int i = 0; i < jvinccs.size(); i ++) { + UniValue uniCC; + if (!(uniCC = jvinccs[i][std::string("cc")]).isNull()) { + std::string ccstr = uniCC.write(); + char ccerr[128]; + CCwrapper wrcond( cc_conditionFromJSONString(ccstr.c_str(), ccerr) ); + if (!wrcond.get()) { CCerror = strprintf("could parse vin cc: %s", ccerr); ; return NullUniValue; } + //std::cerr << __func__ << " getting sign" << std::endl; + bool bSign = jvinccs[i][std::string("sign")].get_bool(); + //std::cerr << __func__ << " got sign" << std::endl; + CCAddVintxCond(cpEvals, wrcond, bSign ? nullpriv : dontsign); // add a probe cond how to spend vintx cc utxo + } + } + + UniValue sigData = FinalizeCCV2Tx(false, FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpEvals, mtx, mypk, txfee, CScript()); + if (!ResultHasTx(sigData)) + return MakeResultError("Could not finalize tx"); + return sigData; +} + +UniValue createccevaltx(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + UniValue result(UniValue::VOBJ); + + if (fHelp || params.size() != 1) + throw std::runtime_error(std::string(__func__) + " 'json'\n" + "create and sign transaction with cc evals. The param is a json object with tx vin vout props:\n" + "'{ \"vins\": [...], \"vouts\": [...], \"vinccs\": [...] }'\n" + "'vins' - vin array in the format: '\"vins\":[{\"hash\": prev-tx-hash, \"n\": prev-utxo-n }, {...}]'\n" + "'vouts' - vout array in the format: '\"vouts\":[{\"nValue\": satoshis, \"Destination\": address-or-pubkey, \"cc\": condition-in-json }, {...}]'\n" + "'vinccs' - array of cc used for spending cc utxos, the format is: '\"vinccs\": [{ \"cc\": condition-in-json, \"sign\": true/false }, {..}]'\n\n"); + if (ensure_CCrequirements(EVAL_TOKENSV2) < 0) + throw std::runtime_error(CC_REQUIREMENTS_MSG); + + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) + throw std::runtime_error("wallet is required"); + CONDITIONAL_LOCK2(cs_main, pwalletMain->cs_wallet, !remotepk.IsValid()); + + UniValue jsonParams(UniValue::VOBJ); + if (params[0].getType() == UniValue::VOBJ) + jsonParams = params[0].get_obj(); + else if (params[0].getType() == UniValue::VSTR) // json in quoted string '{...}' + jsonParams.read(params[0].get_str().c_str()); + if (jsonParams.getType() != UniValue::VOBJ) + return MakeResultError("parameter must be an object\n"); + + CPubKey mypk; + SET_MYPK_OR_REMOTE(mypk, remotepk); + + result = CreateCCEvalTx(mypk, 0, jsonParams); + RETURN_IF_ERROR(CCerror); + return result; +} + + + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- @@ -1208,6 +1352,7 @@ static const CRPCCommand commands[] = { "tokens v2", "tokenv2transfer", &tokenv2transfer, true }, { "tokens", "tokentransfermany", &tokentransfermany, true }, { "tokens v2", "tokenv2transfermany", &tokenv2transfermany, true }, + { "tokens v2", "tokenv2transferMofN", &tokenv2transferMofN, true }, { "tokens", "tokenbid", &tokenbid, true }, { "tokens", "tokencancelbid", &tokencancelbid, true }, { "tokens", "tokenfillbid", &tokenfillbid, true }, @@ -1223,13 +1368,15 @@ static const CRPCCommand commands[] = { "tokens v2", "tokenv2cancelask", &tokenv2cancelask, true }, { "tokens v2", "tokenv2fillask", &tokenv2fillask, true }, //{ "tokens", "tokenfillswap", &tokenfillswap, true }, - { "tokens", "tokenconvert", &tokenconvert, true }, + //{ "tokens", "tokenconvert", &tokenconvert, true }, { "ccutils", "addccv2signature", &addccv2signature, true }, { "tokens", "tokencreatetokel", &tokencreatetokel, true }, { "tokens v2", "tokenv2createtokel", &tokenv2createtokel, true }, { "tokens", "tokeninfotokel", &tokeninfotokel, true }, { "tokens v2", "tokenv2infotokel", &tokenv2infotokel, true }, { "nspv", "tokenv2addccinputs", &tokenv2addccinputs, true }, + { "nspv", "createccevaltx", &createccevaltx, true }, + }; void RegisterTokensRPCCommands(CRPCTable &tableRPC) From 009be86278f3ec76937889173f04c20ffd3811b2 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 01:18:20 +0500 Subject: [PATCH 212/348] test assets cc FinalizeCCTx fixed for cc subver_1 --- src/test-komodo-cc/test-assets.cpp | 55 ++++++++++++++++++------------ 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index c8422ca202f..97453076212 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -258,6 +258,7 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ } } else { + bool bdontsign = false; char destaddr[KOMODO_ADDRESS_BUFSIZE]; if (!Getscriptaddress(destaddr, vintx.vout[mtx.vin[i].prevout.n].scriptPubKey)) { std::cerr << __func__ << " vini." << i << " could not Getscriptaddress for scriptPubKey=" << vintx.vout[mtx.vin[i].prevout.n].scriptPubKey.ToString() << std::endl; @@ -278,22 +279,32 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ //std::cerr << __func__ << " vini." << i << " found mytokenaddr=" << mytokenaddr << " evalcode=" << (int)cp->evalcode << std::endl; } else { const uint8_t nullpriv[32] = {'\0'}; + const uint8_t dontsign[32] = { 0xff }; // use vector of dest addresses and conds to probe vintxconds for (auto& t : cp->CCvintxprobes) { char coinaddr[KOMODO_ADDRESS_BUFSIZE]; if (t.CCwrapped.get() != NULL) { - CCwrapper anonCond = t.CCwrapped; - CCtoAnon(anonCond.get()); - Getscriptaddress(coinaddr, CCPubKey(anonCond.get(), true)); - if (strcmp(destaddr, coinaddr) == 0) { - //std::cerr << __func__ << " vini." << i << " found vintxprobe=" << coinaddr << " privkey=" << (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) << std::endl; - if (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) != 0) - privkey = t.CCpriv; - else - privkey = myprivkey; - cond = t.CCwrapped; - break; + //CCwrapper anonCond = t.CCwrapped; + //CCtoAnon(anonCond.get()); + //Getscriptaddress(coinaddr, CCPubKey(anonCond.get(), CC_MIXED_MODE_SUBVER_0)); + for (CC_SUBVER ccSubVer = CC_MIXED_MODE_SUBVER_0; ccSubVer <= CC_MIXED_MODE_SUBVER_MAX; ccSubVer = (CC_SUBVER)(ccSubVer+1)) + { + char coinaddr[KOMODO_ADDRESS_BUFSIZE]; + //Getscriptaddress(coinaddr, CCPubKey(anonCond.get(), ccSubVer)); + Getscriptaddress(coinaddr, CCPubKey(t.CCwrapped.get(), ccSubVer)); + if (strcmp(destaddr, coinaddr) == 0) { + if (memcmp(t.CCpriv, nullpriv, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) == 0) + privkey = myprivkey; + else if (memcmp(t.CCpriv, dontsign, sizeof(t.CCpriv) / sizeof(t.CCpriv[0])) == 0) + bdontsign = true; + else + privkey = t.CCpriv; + + cond = t.CCwrapped; + break; + } } + if (cond.get() != nullptr) break; // found cond } } } @@ -345,10 +356,10 @@ CTxOut TestMakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmou { CTxOut vout; CCwrapper payoutCond( TestMakeTokensv2CCcondMofN(evalcode1, evalcode2, M, pks) ); - if (!CCtoAnon(payoutCond.get())) - return vout; + //if (!CCtoAnon(payoutCond.get())) + // return vout; - vout = CTxOut(nValue, CCPubKey(payoutCond.get(),true)); + vout = CTxOut(nValue, CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); { std::vector vvData; @@ -421,7 +432,7 @@ class TestAssetsCC : public ::testing::Test { ScriptError error; - bool bCheck = checker.CheckCryptoCondition(vout.scriptPubKey.GetCCV2SPK(), &error); + bool bCheck = checker.CheckCryptoConditionSpk(vout.scriptPubKey.GetCCV2SPK(), &error); if (!bCheck) { std::cerr << __func__ << " CheckCryptoCondition error=" << ScriptErrorString(error) << " eval=" << eval.state.GetRejectReason() << std::endl; return false; @@ -1142,7 +1153,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) } { // test: different tokenid in opdrop - eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + eval.SetCurrentHeight(CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); @@ -1347,7 +1358,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) { for (CAmount fillUnits : { 1, 2 }) { // fill partially and totally // test: fillask with different tokenid in opdrop - eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + eval.SetCurrentHeight(CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); //eval.SetCurrentHeight(1); strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); @@ -1403,7 +1414,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) { // test: make different tokenid in opdrop in ask and try fillask it eval.SetCurrentHeight(111); //set height - //eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + //eval.SetCurrentHeight(CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); @@ -1411,7 +1422,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) CPubKey mypk = pk1; uint256 mytokenid = tokenid1; CAmount unit_price = 501; - int32_t expiryHeight = CCASSETS_OPDROP_FIX_TOKEL_HEIGHT+222; + int32_t expiryHeight = CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT+222; struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); @@ -1443,7 +1454,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) uint256 askid = mtx.GetHash(); // add fill ask - eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); // after fix activation + eval.SetCurrentHeight(CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); // after fix activation CAmount fillUnits = 1; CAmount txfee = 10000; @@ -1596,7 +1607,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) { // test: fillbid with different tokenid in opdrop //eval.SetCurrentHeight(111); - eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + eval.SetCurrentHeight(CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); @@ -1770,7 +1781,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask) EXPECT_FALSE(TestRunCCEval(mtx6)); // must fail } { - eval.SetCurrentHeight(CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + eval.SetCurrentHeight(CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); From 9dffa5978d87b157dc0eb53ff8f40b8268eb4d29 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 01:21:57 +0500 Subject: [PATCH 213/348] decode condition added to decoderawtransaction --- src/cc/CCinclude.h | 5 +++-- src/rpc/rawtransaction.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index c35050afd60..6946edb54f6 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -610,8 +610,6 @@ CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk, std::vector>* vData = NULL); -bool CCtoAnon(const CC *cond); - CTxOut MakeCC1voutMixed(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector *vData = NULL); CTxOut MakeCC1of2voutMixed(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector *vData = NULL); @@ -1090,6 +1088,9 @@ bool SubcallCCValidate(Eval* eval, uint8_t evalcode, const CTransaction& ctx, in extern bool fUnspentCCIndex; // if unspent cc index enabled +/// decode condition to UniValue for decoderawtransaction +UniValue CCDecodeMixedMode(const CC *cond); + /// @private forward decl struct CLockedInMemoryUtxos; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d20807e5331..0413dc2974e 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -41,6 +41,8 @@ #endif #include "komodo_defs.h" +#include "cc/CCinclude.h" + #include #include #include @@ -71,6 +73,16 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud a.push_back(EncodeDestination(addr)); } out.push_back(Pair("addresses", a)); + + // add cc decoded + if (scriptPubKey.IsPayToCCV2()) { + std::vector ccdata = scriptPubKey.GetCCV2SPK(); + CC* cond = cc_readConditionBinaryMaybeMixed(ccdata.data(), ccdata.size()); + if (cond) { + out.push_back(Pair("condition", CCDecodeMixedMode(cond))); + cc_free(cond); + } + } } UniValue TxJoinSplitToJSON(const CTransaction& tx) { From 2b55ddfc4e0cda80c7f003c903eec99e33fb27a2 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 01:25:18 +0500 Subject: [PATCH 214/348] nspv tx.nLockTime set for CLTV --- src/rpc/ccutilsrpc.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index df5852a1f1d..8f8e3890f13 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -120,6 +120,7 @@ UniValue createtxwithnormalinputs(const UniValue& params, bool fHelp, const CPub } CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + mtx.nLockTime = komodo_next_tx_locktime(); std::vector vintxns; CAmount added = AddNormalinputsRemote(mtx, usedpk, amount, CC_MAXVINS, &vintxns); if (added < amount) @@ -222,10 +223,22 @@ UniValue getindexkeyforcc(const UniValue& params, bool fHelp, const CPubKey& rem else throw std::runtime_error(std::string("is-mixed must be true or false")); - CScript spk = CCPubKey(cc.get(), ismixed); - char ccaddress[KOMODO_ADDRESS_BUFSIZE]; - Getscriptaddress(ccaddress, spk); - return ccaddress; + UniValue result(UniValue::VARR); + if (ismixed) { + for (CC_SUBVER ccSubVer = CC_MIXED_MODE_SUBVER_0; ccSubVer <= CC_MIXED_MODE_SUBVER_MAX; ccSubVer = (CC_SUBVER)(ccSubVer+1)) { + CScript spk = CCPubKey(cc.get(), ccSubVer); + char ccaddress[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(ccaddress, spk); + result.push_back(ccaddress); + } + } + else { + CScript spk = CCPubKey(cc.get(), CC_OLD_V1_SUBVER); + char ccaddress[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(ccaddress, spk); + result.push_back(ccaddress); + } + return result; } extern bool fAddressIndex; From 0ab88b35b03654a7102a8353ce8d56803a3503c9 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 01:52:54 +0500 Subject: [PATCH 215/348] debug print disabled --- src/script/interpreter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index d6308e20df7..d560ff9fe95 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1390,10 +1390,10 @@ int TransactionSignatureChecker::CheckCryptoCondition( return ((TransactionSignatureChecker*)checker)->CheckEvalCondition(cond); }; - fprintf(stderr,"%s non-checker path\n", __func__); + //fprintf(stderr,"%s non-checker path\n", __func__); int out = cc_verifyMaybeMixed( cond, sighash, condBin.data(), condBin.size(), eval, (void*)this); - fprintf(stderr,"%s out.%d from cc_verify\n", __func__, (int32_t)out); + //fprintf(stderr,"%s out.%d from cc_verify\n", __func__, (int32_t)out); cc_free(cond); return out; } From 0b38429b26e30ef0ec6517efab9ab012bbacb5a6 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 01:53:32 +0500 Subject: [PATCH 216/348] AddNormalInputs set vin sequence non-final to allow CLTV --- src/cc/CCtx.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index a38fdfa7fc0..f4a91682e09 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -1209,7 +1209,7 @@ CAmount AddNormalinputsLocal(CMutableTransaction& mtx, CPubKey mypk, CAmount tot return (0); } up = &utxos[ind]; - mtx.vin.push_back(CTxIn(up->txid, up->vout, CScript())); + mtx.vin.push_back(CTxIn(up->txid, up->vout, CScript(), (4294967295U-1))); // for TOKEL sequence non-final to allow CLTV spending totalinputs += up->nValue; remains -= up->nValue; utxos[ind] = utxos[--n]; @@ -1327,7 +1327,7 @@ CAmount AddNormalinputsRemote(CMutableTransaction& mtx, CPubKey mypk, CAmount to return (0); } up = &utxos[ind]; - mtx.vin.push_back(CTxIn(up->txid, up->vout, CScript())); + mtx.vin.push_back(CTxIn(up->txid, up->vout, CScript(), (4294967295U-1))); // for TOKEL sequence non-final to allow CLTV spending totalinputs += up->nValue; remains -= up->nValue; utxos[ind] = utxos[--n]; From 47b188e25a9aa3e3f64fd2b8c3760ef15497ec30 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 20:47:21 +0500 Subject: [PATCH 217/348] fixed check_signing_pubkey cc_isAnon use --- src/cc/CCutils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 969febe3692..89f6583b56e 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -843,7 +843,7 @@ CPubKey check_signing_pubkey(CScript scriptSig) auto findEval = [](CC *cond, struct CCVisitor _) { bool r = false; - if (!cc_anon(cond) && cc_typeId(cond) == CC_Secp256k1) { + if (!cc_isAnon(cond) && cc_typeId(cond) == CC_Secp256k1) { *(CPubKey*)_.context=buf2pk(cond->publicKey); r = true; } @@ -1640,7 +1640,7 @@ UniValue CCDecodeMixedMode(const CC *cond) return uCond; }; - if (cc_typeId(cond) == CC_Threshold) { + if (!cc_isAnon(cond) && cc_typeId(cond) == CC_Threshold) { UniValue uThreshold(UniValue::VOBJ); UniValue uSubConds(UniValue::VARR); for (int i = 0; i < cond->size; i ++) { From 3bfb6fd329703f82c8d6eb39b583e094227f9af8 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 20:52:15 +0500 Subject: [PATCH 218/348] Added current height to Eval object --- src/cc/eval.cpp | 8 ++++++-- src/cc/eval.h | 8 +++++++- src/main.cpp | 23 ++++++++++++----------- src/main.h | 21 ++++++++++++++------- src/miner.cpp | 6 +++--- src/script/script.cpp | 6 +++--- src/script/serverchecker.cpp | 2 +- src/script/serverchecker.h | 5 +++-- src/test-komodo/test_coinimport.cpp | 4 ++-- src/test-komodo/test_cryptoconditions.cpp | 2 +- src/test-komodo/test_eval_bet.cpp | 2 +- 11 files changed, 53 insertions(+), 34 deletions(-) diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index dbf05ae232a..908584a3e33 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -34,9 +34,10 @@ Eval* EVAL_TEST = 0; struct CCcontract_info CCinfos[0x100]; extern pthread_mutex_t KOMODO_CC_mutex; -bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, std::shared_ptr evalcodeChecker) +bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, int32_t nHeight, std::shared_ptr evalcodeChecker) { EvalRef eval; + eval->SetCurrentHeight(nHeight); pthread_mutex_lock(&KOMODO_CC_mutex); bool out = eval->Dispatch(cond, tx, nIn, evalcodeChecker); pthread_mutex_unlock(&KOMODO_CC_mutex); @@ -103,6 +104,9 @@ bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn,s cp->didinit = 1; } + if (GetCurrentHeight() <= 0) + return Invalid("current chain height not set for eval object"); + switch ( ecode ) { case EVAL_IMPORTPAYOUT: @@ -149,7 +153,7 @@ bool Eval::GetTxConfirmed(const uint256 &hash, CTransaction &txOut, CBlockIndex unsigned int Eval::GetCurrentHeight() const { - return chainActive.Height(); + return nCurrentHeight; } bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const diff --git a/src/cc/eval.h b/src/cc/eval.h index 42f8676d682..ee4a06a69fe 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -79,6 +79,7 @@ class CCheckCCEvalCodes; class Eval { public: + Eval() : nCurrentHeight(0) {} CValidationState state; bool Invalid(std::string s) { return state.Invalid(false, 0, s); } @@ -111,6 +112,7 @@ class Eval virtual bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const; virtual bool GetTxConfirmed(const uint256 &hash, CTransaction &txOut, CBlockIndex &block) const; virtual unsigned int GetCurrentHeight() const; + void SetCurrentHeight(int32_t nHeightIn) { nCurrentHeight = nHeightIn; } virtual bool GetSpendsConfirmed(uint256 hash, std::vector &spends) const; virtual bool GetBlock(uint256 hash, CBlockIndex& blockIdx) const; virtual int32_t GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const; @@ -118,6 +120,10 @@ class Eval virtual bool CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const; virtual uint32_t GetAssetchainsCC() const; virtual std::string GetAssetchainsSymbol() const; + +private: + int32_t nCurrentHeight; + }; @@ -138,7 +144,7 @@ class EvalRef : public EvalRef_ -bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, std::shared_ptr evalcodeChecker); +bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, int32_t nHeight, std::shared_ptr evalcodeChecker); /* diff --git a/src/main.cpp b/src/main.cpp index 1a568f17413..205276ba990 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2079,7 +2079,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // This is done last to help prevent CPU exhaustion denial-of-service attacks. PrecomputedTransactionData txdata(tx); std::shared_ptr evalcodeChecker(new CCheckCCEvalCodes()); - if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, evalcodeChecker)) + if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, chainActive.LastTip()->GetHeight() + 1, evalcodeChecker)) { //fprintf(stderr,"accept failure.9\n"); LogPrint("mempool-tx", "%s ConnectInputs failed for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); @@ -2103,7 +2103,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } //fprintf(stderr,"addmempool 7\n"); - if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, evalcodeChecker)) + if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, chainActive.LastTip()->GetHeight() + 1, evalcodeChecker)) { if (flag != 0) KOMODO_CONNECTING = -1; @@ -2795,13 +2795,13 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { if (vout != 0) { //check cc output - ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, evalcodeChecker, *txdata); + ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, nHeight, evalcodeChecker, *txdata); if (checker.CheckCryptoConditionSpk(scriptPubKey.GetCCV2SPK(), &error) != 1) { return ::error("CScriptCheck(): %s:%d CC output validation failed: %s", ptxTo->GetHash().ToString(), n, ScriptErrorString(error)); } } else { // check cc input const CScript& scriptSig = ptxTo->vin[n].scriptSig; - ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, evalcodeChecker, *txdata); + ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, nHeight, evalcodeChecker, *txdata); if (!VerifyScript(scriptSig, scriptPubKey, nFlags, checker, consensusBranchId, &error)) { return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), n, ScriptErrorString(error)); } @@ -2826,14 +2826,14 @@ namespace Consensus { // are the JoinSplit's requirements met? if (!inputs.HaveJoinSplitRequirements(tx)) return state.Invalid(error("CheckInputs(): %s JoinSplit requirements not met", tx.GetHash().ToString())); - +std::cerr << __func__ << " nSpendHeight=" << nSpendHeight << std::endl; CAmount nValueIn = 0; CAmount nFees = 0; for (unsigned int i = 0; i < tx.vin.size(); i++) { if (tx.IsPegsImport() && i==0) { - nValueIn=GetCoinImportValue(tx); + nValueIn=GetCoinImportValue(tx, nSpendHeight); continue; } const COutPoint &prevout = tx.vin[i].prevout; @@ -2927,6 +2927,7 @@ bool ContextualCheckInputs( PrecomputedTransactionData& txdata, const Consensus::Params& consensusParams, uint32_t consensusBranchId, + int32_t nHeight, std::shared_ptr evalcodeChecker, std::vector *pvChecks) { @@ -2954,7 +2955,7 @@ bool ContextualCheckInputs( assert(coins); // Verify signature - CScriptCheck check(*coins, tx, i, flags, cacheStore, consensusBranchId, evalcodeChecker, &txdata); + CScriptCheck check(*coins, tx, i, flags, cacheStore, consensusBranchId, nHeight, evalcodeChecker, &txdata); if (pvChecks) { pvChecks->push_back(CScriptCheck()); check.swap(pvChecks->back()); @@ -2967,7 +2968,7 @@ bool ContextualCheckInputs( // avoid splitting the network between upgraded and // non-upgraded nodes. CScriptCheck check2(*coins, tx, i, - flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, consensusBranchId, evalcodeChecker, &txdata); + flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, consensusBranchId, nHeight, evalcodeChecker, &txdata); if (check2()) return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); } @@ -2987,7 +2988,7 @@ bool ContextualCheckInputs( if (tx.IsCoinImport() || tx.IsPegsImport()) { LOCK(cs_main); - ServerTransactionSignatureChecker checker(&tx, 0, 0, false, NULL,txdata); + ServerTransactionSignatureChecker checker(&tx, 0, 0, false, nHeight, NULL, txdata); return VerifyCoinImport(tx.vin[0].scriptSig, checker, state); } @@ -3018,7 +3019,7 @@ bool ContextualCheckOutputs( { return state.DoS(100,false, REJECT_INVALID, std::string("cc v2 subversion 1 or more not yet enabled")); } - CScriptCheck check(tx.vout[i].scriptPubKey, tx.vout[i].nValue, tx, i, evalcodeChecker, &txdata); + CScriptCheck check(tx.vout[i].scriptPubKey, tx.vout[i].nValue, tx, i, nHeight, evalcodeChecker, &txdata); if (pvChecks) { pvChecks->push_back(CScriptCheck()); @@ -3862,7 +3863,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin //fprintf(stderr, "tx.%s nFees.%li interest.%li\n", tx.GetHash().ToString().c_str(), stakeTxValue, interest); std::vector vChecks; - if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) + if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, pindex->GetHeight(), evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) return false; } diff --git a/src/main.h b/src/main.h index 1b58ea4759f..02e55bf5714 100644 --- a/src/main.h +++ b/src/main.h @@ -736,8 +736,13 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma * instead of being performed inline. */ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, - unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, - const Consensus::Params& consensusParams, uint32_t consensusBranchId, std::shared_ptr evalcodeChecker, + unsigned int flags, + bool cacheStore, + PrecomputedTransactionData& txdata, + const Consensus::Params& consensusParams, + uint32_t consensusBranchId, + int32_t nHeight, + std::shared_ptr evalcodeChecker, std::vector *pvChecks = NULL); bool ContextualCheckOutputs( const CTransaction& tx, @@ -812,18 +817,19 @@ class CScriptCheck unsigned int nFlags; bool cacheStore; uint32_t consensusBranchId; + int32_t nHeight; ScriptError error; PrecomputedTransactionData *txdata; std::shared_ptr evalcodeChecker; bool vout; public: - CScriptCheck(): amount(0), ptxTo(0), n(0), nFlags(0), cacheStore(false), consensusBranchId(0), error(SCRIPT_ERR_UNKNOWN_ERROR), vout(false) {} - CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nIn, unsigned int nFlagsIn, bool cacheIn, uint32_t consensusBranchIdIn, std::shared_ptr evalcodeCheckerIn,PrecomputedTransactionData* txdataIn) : + CScriptCheck(): amount(0), ptxTo(0), n(0), nFlags(0), cacheStore(false), consensusBranchId(0), nHeight(0), error(SCRIPT_ERR_UNKNOWN_ERROR), vout(false) {} + CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nIn, unsigned int nFlagsIn, bool cacheIn, uint32_t consensusBranchIdIn, int32_t nHeightIn, std::shared_ptr evalcodeCheckerIn,PrecomputedTransactionData* txdataIn) : scriptPubKey(CCoinsViewCache::GetSpendFor(&txFromIn, txToIn.vin[nIn])), amount(txFromIn.vout[txToIn.vin[nIn].prevout.n].nValue), - ptxTo(&txToIn), n(nIn), nFlags(nFlagsIn), cacheStore(cacheIn), consensusBranchId(consensusBranchIdIn), error(SCRIPT_ERR_UNKNOWN_ERROR), evalcodeChecker(evalcodeCheckerIn),txdata(txdataIn), vout(false) { } - CScriptCheck(const CScript& scriptPubKeyIn, const CAmount& amountIn, const CTransaction& txToIn, unsigned int nIn, std::shared_ptr evalcodeCheckerIn,PrecomputedTransactionData* txdataIn) : - scriptPubKey(scriptPubKeyIn), amount(amountIn), ptxTo(&txToIn), n(nIn), nFlags(0), cacheStore(false), consensusBranchId(0), + ptxTo(&txToIn), n(nIn), nFlags(nFlagsIn), cacheStore(cacheIn), consensusBranchId(consensusBranchIdIn), nHeight(nHeightIn), error(SCRIPT_ERR_UNKNOWN_ERROR), evalcodeChecker(evalcodeCheckerIn),txdata(txdataIn), vout(false) { } + CScriptCheck(const CScript& scriptPubKeyIn, const CAmount& amountIn, const CTransaction& txToIn, unsigned int nIn, int32_t nHeightIn, std::shared_ptr evalcodeCheckerIn,PrecomputedTransactionData* txdataIn) : + scriptPubKey(scriptPubKeyIn), amount(amountIn), ptxTo(&txToIn), n(nIn), nFlags(0), cacheStore(false), consensusBranchId(0), nHeight(nHeightIn), error(SCRIPT_ERR_UNKNOWN_ERROR), evalcodeChecker(evalcodeCheckerIn), txdata(txdataIn), vout(true) { } bool operator()(); @@ -835,6 +841,7 @@ class CScriptCheck std::swap(nFlags, check.nFlags); std::swap(cacheStore, check.cacheStore); std::swap(consensusBranchId, check.consensusBranchId); + std::swap(nHeight, check.nHeight); std::swap(error, check.error); std::swap(txdata, check.txdata); std::swap(vout,check.vout); diff --git a/src/miner.cpp b/src/miner.cpp index e7f8a74aa75..1cc7d4ac187 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -321,7 +321,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 std::vector TMP_NotarisationNotaries; if (tx.IsCoinImport()) { - CAmount nValueIn = GetCoinImportValue(tx); // burn amount + CAmount nValueIn = GetCoinImportValue(tx, nHeight); // burn amount nTotalIn += nValueIn; dPriority += (double)nValueIn * 1000; // flat multiplier... max = 1e16. } else { @@ -334,7 +334,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 { if (tx.IsPegsImport() && txin.prevout.n==10e8) { - CAmount nValueIn = GetCoinImportValue(tx); // burn amount + CAmount nValueIn = GetCoinImportValue(tx, nHeight); // burn amount nTotalIn += nValueIn; dPriority += (double)nValueIn * 1000; // flat multiplier... max = 1e16. continue; @@ -566,7 +566,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 CValidationState state; PrecomputedTransactionData txdata(tx); std::shared_ptr evalcodeChecker(new CCheckCCEvalCodes()); - if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, evalcodeChecker)) + if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, nHeight, evalcodeChecker)) { //fprintf(stderr,"context failure\n"); continue; diff --git a/src/script/script.cpp b/src/script/script.cpp index 796f2c81dd9..465872b8bf2 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -360,11 +360,11 @@ static bool IsCCOpcodeValid(opcodetype opcode, const vector &data { if (data.size() > 0) { - if (data[0] < CC_MIXED_MODE_PREFIX && opcode > OP_0 && opcode < OP_PUSHDATA1) // pre mixed mode (cc_conditionBinary always < 76 bytes) + if (opcode > OP_0 && opcode < OP_PUSHDATA1) // pre mixed mode (cc_conditionBinary always < 76 bytes) or small mixed mode return true; - else if (data[0] == CC_MIXED_MODE_PREFIX && opcode > OP_0 && opcode <= OP_PUSHDATA1) // for mixed mode subver 'M'+0 enable longer data upto 255 b + else if (data[0] == CC_MIXED_MODE_PREFIX /*&& opcode > OP_0 && opcode <= OP_PUSHDATA1*/) // for mixed mode subver 'M'+0 enable longer data upto 255 b return true; - else if (data[0] > CC_MIXED_MODE_PREFIX && opcode > OP_0 && opcode <= OP_PUSHDATA2) { // for mixed mode subver >= 'M'+1 enable even longer data upto 65K b + else if (data[0] == CC_MIXED_MODE_PREFIX+1 /*&& opcode > OP_0 && opcode <= OP_PUSHDATA2*/) { // for mixed mode subver >= 'M'+1 enable even longer data upto 65K b return true; } } diff --git a/src/script/serverchecker.cpp b/src/script/serverchecker.cpp index d1975358680..6070692c695 100644 --- a/src/script/serverchecker.cpp +++ b/src/script/serverchecker.cpp @@ -119,7 +119,7 @@ bool ServerTransactionSignatureChecker::VerifySignature(const std::vector &condBin, ScriptError *serror) const diff --git a/src/script/serverchecker.h b/src/script/serverchecker.h index 61aa1618261..f198b8e4d03 100644 --- a/src/script/serverchecker.h +++ b/src/script/serverchecker.h @@ -33,10 +33,11 @@ class ServerTransactionSignatureChecker : public TransactionSignatureChecker private: bool store; std::shared_ptr evalcodeChecker; + int32_t nHeight; public: - ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn, std::shared_ptr evalcodeCheckerIn, const PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nIn, amount, txdataIn), store(storeIn), evalcodeChecker(evalcodeCheckerIn) {} - ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nIn, amount), store(storeIn) {} + ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn, int32_t nHeightIn, std::shared_ptr evalcodeCheckerIn, const PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nIn, amount, txdataIn), store(storeIn), nHeight(nHeightIn), evalcodeChecker(evalcodeCheckerIn) {} + ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nIn, amount), store(storeIn), nHeight(0) {} bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; int CheckEvalCondition(const CC *cond) const; diff --git a/src/test-komodo/test_coinimport.cpp b/src/test-komodo/test_coinimport.cpp index a0f92d8cae3..9411b721010 100644 --- a/src/test-komodo/test_coinimport.cpp +++ b/src/test-komodo/test_coinimport.cpp @@ -71,7 +71,7 @@ class TestCoinImport : public ::testing::Test, public Eval { { CTransaction importTx(mtx); PrecomputedTransactionData txdata(importTx); - ServerTransactionSignatureChecker checker(&importTx, 0, 0, false, NULL, txdata); + ServerTransactionSignatureChecker checker(&importTx, 0, 0, false, 1, NULL, txdata); CValidationState verifystate; if (!VerifyCoinImport(importTx.vin[0].scriptSig, checker, verifystate)) printf("TestRunCCEval: %s\n", verifystate.GetRejectReason().data()); @@ -251,7 +251,7 @@ TEST_F(TestCoinImport, DISABLED_testMomomCheckFail) TEST_F(TestCoinImport, testGetCoinImportValue) { - ASSERT_EQ(100, GetCoinImportValue(importTx)); + ASSERT_EQ(100, GetCoinImportValue(importTx, 1)); } } /* namespace TestCoinImport */ diff --git a/src/test-komodo/test_cryptoconditions.cpp b/src/test-komodo/test_cryptoconditions.cpp index 050b0ea7943..f56ab66a071 100644 --- a/src/test-komodo/test_cryptoconditions.cpp +++ b/src/test-komodo/test_cryptoconditions.cpp @@ -88,7 +88,7 @@ static bool CCVerify(const CMutableTransaction &mtxTo, const CC *cond) { ScriptError error; CTransaction txTo(mtxTo); PrecomputedTransactionData txdata(txTo); - auto checker = ServerTransactionSignatureChecker(&txTo, 0, amount, false, NULL, txdata); + auto checker = ServerTransactionSignatureChecker(&txTo, 0, amount, false, 1, NULL, txdata); return VerifyScript(CCSig(cond), CCPubKey(cond), 0, checker, 0, &error); }; diff --git a/src/test-komodo/test_eval_bet.cpp b/src/test-komodo/test_eval_bet.cpp index b527c63765f..1f6ba6e38ca 100644 --- a/src/test-komodo/test_eval_bet.cpp +++ b/src/test-komodo/test_eval_bet.cpp @@ -43,7 +43,7 @@ int TestCC(CMutableTransaction &mtxTo, unsigned int nIn, CC *cond) ScriptError error; CTransaction txTo(mtxTo); PrecomputedTransactionData txdata(txTo); - auto checker = ServerTransactionSignatureChecker(&txTo, nIn, amount, false, NULL, txdata); + auto checker = ServerTransactionSignatureChecker(&txTo, nIn, amount, false, 1, NULL, txdata); return VerifyScript(txTo.vin[nIn].scriptSig, CCPubKey(cond), 0, checker, 0, &error); } From 8e2cb01011f4d1aadcf526963093f015e593aadd Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 20:53:10 +0500 Subject: [PATCH 219/348] fixed cc mixed mode subversion getting function --- src/script/cc.cpp | 5 +++++ src/script/cc.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/script/cc.cpp b/src/script/cc.cpp index ad3744cb8e9..18023086c2d 100644 --- a/src/script/cc.cpp +++ b/src/script/cc.cpp @@ -236,3 +236,8 @@ int cc_verifyMaybeMixed(const struct CC *cond, const uint256 sigHash, } return cc_verify(cond, sigHash.begin(), 32, 0, condBin, condBinLength, verifyEval, evalContext); } + +CC_SUBVER CC_MixedModeSubVersion(int c) +{ + return (c >= CC_MIXED_MODE_PREFIX && c <= CC_MIXED_MODE_PREFIX + CC_MIXED_MODE_SUBVER_MAX) ? (CC_SUBVER)(c - CC_MIXED_MODE_PREFIX) : CC_OLD_V1_SUBVER; +} diff --git a/src/script/cc.h b/src/script/cc.h index c4c0e19f91f..31c5c4a94ba 100644 --- a/src/script/cc.h +++ b/src/script/cc.h @@ -35,7 +35,7 @@ enum CC_SUBVER : int { }; -inline CC_SUBVER CC_MixedModeSubVersion(int c) { return (c >= CC_MIXED_MODE_PREFIX) ? (CC_SUBVER)(c - CC_MIXED_MODE_PREFIX) : CC_OLD_V1_SUBVER; } +CC_SUBVER CC_MixedModeSubVersion(int c); const size_t MAX_FULFILLMENT_SIZE = 10000; const size_t MAX_FULFILLMENT_SPK_SIZE_V0 = 1000; From a27c1d83b0bdc302743b802cdc669035706ffaaa Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 20:58:22 +0500 Subject: [PATCH 220/348] added valid burn pubkey via activation height --- src/cc/CCinclude.h | 4 ++++ src/cc/CCtokens.cpp | 8 +++++--- src/cc/CCtokens_impl.h | 3 +++ src/cc/gamescc.cpp | 2 +- src/cc/import.cpp | 12 +++++++++++- src/cc/rogue_rpc.cpp | 2 +- src/coins.cpp | 4 ++-- src/importcoin.cpp | 13 +++++++++++-- src/importcoin.h | 2 +- src/rpc/crosschain.cpp | 6 +++--- 10 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 6946edb54f6..b2a954ffd77 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -75,7 +75,11 @@ Details. #include "../unspentccindex.h" #include "rpc/server.h" +// invalid burn pubkey stop using it #define CC_BURNPUBKEY "02deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead" //!< 'dead' pubkey in hex for burning tokens (if tokens are sent to it, they become 'burned') +// valid burn pubkey, start support in June 2022 +#define CC_BURNPUBKEY_FIXED "02deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaa" + /// \cond INTERNAL #define CC_MAXVINS 1024 #define CC_REQUIREMENTS_MSG (KOMODO_NSPV_SUPERLITE?"to use CC contracts you need to nspv_login first\n":"to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n") diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 489b4eccb02..68372952d2c 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -29,13 +29,15 @@ thread_local uint32_t tokenValIndentSize = 0; // for debug logging // helper funcs: +// extract and compare addresses bool IsEqualDestinations(const CScript &spk1, const CScript &spk2) { char addr1[KOMODO_ADDRESS_BUFSIZE]; char addr2[KOMODO_ADDRESS_BUFSIZE]; - Getscriptaddress(addr1, spk1); - Getscriptaddress(addr2, spk2); - return strcmp(addr1, addr2) == 0; + if (Getscriptaddress(addr1, spk1) && Getscriptaddress(addr2, spk2)) + return strcmp(addr1, addr2) == 0; + else + return false; } // remove token->unspendablePk (it is only for marker usage) diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 8d71f4fed79..66896bcc6da 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -938,6 +938,9 @@ static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 } vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey + CAmount burnedAmount = 0; diff --git a/src/cc/gamescc.cpp b/src/cc/gamescc.cpp index e3c33be98d7..c2e31587aa8 100644 --- a/src/cc/gamescc.cpp +++ b/src/cc/gamescc.cpp @@ -1232,7 +1232,7 @@ UniValue games_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY)); + burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED)); gamespk = GetUnspendable(cp,0); games_univalue(result,"register",-1,-1); playertxid = tokenid = zeroid; diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 74344e951a4..2c45f3aba6b 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -23,6 +23,8 @@ #include "cc/CCinclude.h" #include "cc/CCtokens.h" #include "cc/CCImportGateway.h" +#include "cc/CCUpgrades.h" + #include "key_io.h" #define CODA_BURN_ADDRESS "KPrrRoPfHOnNpZZQ6laHXdQDkSQDkVHaN0V+LizLlHxz7NaA59sBAAAA" @@ -546,11 +548,19 @@ bool CheckMigration(Eval *eval, const CTransaction &importTx, const CTransaction if (!hasTokenVin) return eval->Invalid("burn-tx-has-no-token-vins"); + std::vector vDeadPubkeys; + vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey + // calc outputs for burn tx CAmount ccBurnOutputs = 0; for (auto v : burnTx.vout) if (v.scriptPubKey.IsPayToCryptoCondition() && - CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(nonfungibleEvalCode, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY)))) // burned to dead pubkey + std::find_if(vDeadPubkeys.begin(), vDeadPubkeys.end(), [v, nonfungibleEvalCode](const CPubKey &burnpk) { + return IsEqualDestinations(v.scriptPubKey, CCPubKey(CCwrapper(MakeTokensCCcond1(nonfungibleEvalCode, burnpk)).get() )); + } ) != vDeadPubkeys.end()) + //CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(nonfungibleEvalCode, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED)))) // burned to dead pubkey ccBurnOutputs += v.nValue; // calc outputs for import tx diff --git a/src/cc/rogue_rpc.cpp b/src/cc/rogue_rpc.cpp index fbd5ba8add8..bc46631e306 100644 --- a/src/cc/rogue_rpc.cpp +++ b/src/cc/rogue_rpc.cpp @@ -855,7 +855,7 @@ UniValue rogue_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY)); + burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED)); roguepk = GetUnspendable(cp,0); rogue_univalue(result,"register",-1,-1); playertxid = tokenid = zeroid; diff --git a/src/coins.cpp b/src/coins.cpp index 77a46d38b90..57363c8bc39 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -596,14 +596,14 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTr if ( interestp != 0 ) *interestp = 0; if ( tx.IsCoinImport() ) - return GetCoinImportValue(tx); + return GetCoinImportValue(tx, nHeight); if ( tx.IsCoinBase() != 0 ) return 0; for (unsigned int i = 0; i < tx.vin.size(); i++) { if (tx.IsPegsImport() && i==0) { - nResult = GetCoinImportValue(tx); + nResult = GetCoinImportValue(tx, nHeight); continue; } value = GetOutputFor(tx.vin[i]).nValue; diff --git a/src/importcoin.cpp b/src/importcoin.cpp index 1b0224685a5..7a41f11bd01 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -314,7 +314,7 @@ bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &pegstxid,uint256 &tokeni /* * Required by main */ -CAmount GetCoinImportValue(const CTransaction &tx) +CAmount GetCoinImportValue(const CTransaction &tx, int32_t nHeight) { ImportProof proof; CTransaction burnTx; std::vector payouts; bool isNewImportTx = false; @@ -345,11 +345,20 @@ CAmount GetCoinImportValue(const CTransaction &tx) if (!vnonfungibleOpret.empty()) nonfungibleEvalCode = vnonfungibleOpret.begin()[0]; + std::vector vDeadPubkeys; + vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); + if (CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey + // calc outputs for burn tx int64_t ccBurnOutputs = 0; for (auto v : burnTx.vout) if (v.scriptPubKey.IsPayToCryptoCondition() && - CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(nonfungibleEvalCode, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY)))) // burned to dead pubkey + std::find_if(vDeadPubkeys.begin(), vDeadPubkeys.end(), [v, nonfungibleEvalCode](const CPubKey &burnpk) { + return IsEqualDestinations(v.scriptPubKey, CCPubKey(CCwrapper(MakeTokensCCcond1(nonfungibleEvalCode, burnpk)).get() )); + } ) != vDeadPubkeys.end()) + + //CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(nonfungibleEvalCode, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED)))) // burned to dead pubkey ccBurnOutputs += v.nValue; return ccBurnOutputs + burnTx.vout.back().nValue; // total token burned value diff --git a/src/importcoin.h b/src/importcoin.h index 16dc49150d1..690fe118e87 100644 --- a/src/importcoin.h +++ b/src/importcoin.h @@ -92,7 +92,7 @@ class ImportProof { -CAmount GetCoinImportValue(const CTransaction &tx); +CAmount GetCoinImportValue(const CTransaction &tx, int32_t nHeight); CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride = 0); CTransaction MakePegsImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride = 0); diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index 56fe421c0c5..617c54b0b13 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -397,14 +397,14 @@ UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const mtx.vout.clear(); // remove payouts // now make burn transaction: - mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, burnAmount, pubkey2pk(ParseHex(CC_BURNPUBKEY)))); // burn tokens + mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, burnAmount, pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED)))); // burn tokens int64_t change = inputs - txfee; if (change != 0) mtx.vout.push_back(CTxOut(change, CScript() << ParseHex(HexStr(myPubKey)) << OP_CHECKSIG)); // make change here to prevent it from making in FinalizeCCtx std::vector voutTokenPubkeys; - voutTokenPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); // maybe we do not need this because ccTokens has the const for burn pubkey + voutTokenPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // maybe we do not need this because ccTokens has the const for burn pubkey int64_t ccChange = ccInputs - burnAmount; if (ccChange != 0) @@ -1412,7 +1412,7 @@ UniValue getwalletburntransactions(const UniValue& params, bool fHelp, const CPu int64_t burnAmount = 0; for (auto v : pwtx->vout) if (v.scriptPubKey.IsPayToCryptoCondition() && - CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(EVAL_TOKENS, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY)))) // burned to dead pubkey + CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(EVAL_TOKENS, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED)))) // burned to dead pubkey burnAmount += v.nValue; entry.push_back(Pair("burnedAmount", ValueFromAmount(burnAmount))); From d98542342eb18788381980cb382db2be6cf0b824 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 21:00:30 +0500 Subject: [PATCH 221/348] fixed addUpgradeActive in CCupgrades --- src/cc/CCupgrades.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cc/CCupgrades.cpp b/src/cc/CCupgrades.cpp index 9e220597360..0037c20404b 100644 --- a/src/cc/CCupgrades.cpp +++ b/src/cc/CCupgrades.cpp @@ -22,9 +22,7 @@ namespace CCUpgrades { private: void addUpgradeActive(const std::string &chainName, UPGRADE_ID upgradeId, int32_t nHeight) { - ChainUpgrades oUpgrade; - oUpgrade.setActivationHeight(upgradeId, nHeight, UPGRADE_ACTIVE); - mChainUpgrades[chainName] = oUpgrade; + mChainUpgrades[chainName].setActivationHeight(upgradeId, nHeight, UPGRADE_ACTIVE); } public: CUpgradesContainer() { From b8fea1bd774a861925262bba76a07feffe4f9f8e Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 21:14:02 +0500 Subject: [PATCH 222/348] test-assets use Eval base Set/GetCurrentHeight() --- src/test-komodo-cc/test-assets.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 97453076212..181cb57a5e2 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -57,10 +57,6 @@ class EvalMock : public Eval } } const std::map & getTxs() { return txs; } - void SetCurrentHeight(int h) - { - currentHeight = h; - } virtual bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const { @@ -75,10 +71,6 @@ class EvalMock : public Eval } return false; } - virtual unsigned int GetCurrentHeight() const - { - return currentHeight; - } }; static EvalMock eval; @@ -397,7 +389,7 @@ class TestAssetsCC : public ::testing::Test { { CTransaction tx(mtx); PrecomputedTransactionData txdata(tx); - ServerTransactionSignatureChecker checker(&tx, 0, 0, false, NULL, txdata); + ServerTransactionSignatureChecker checker(&tx, 0, 0, false, eval.GetCurrentHeight(), NULL, txdata); CValidationState verifystate; VerifyEval verifyEval = [] (CC *cond, void *checker) { //fprintf(stderr,"checker.%p\n",(TransactionSignatureChecker*)checker); @@ -1177,7 +1169,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) ASSERT_TRUE(TestFinalizeTx(mtx, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(tokenid2, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); - std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop.." << std::endl; + std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop.." << " GetRejectReason=" << eval.state.GetRejectReason() << std::endl; EXPECT_TRUE(!TestRunCCEval(mtx) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // fail: can't ask for different tokenid } } From 8899020ff425fc2f8412dff518e11c9bd1df36e1 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 21:14:39 +0500 Subject: [PATCH 223/348] set TKLTEST2 activation ht for token Raddress --- src/cc/CCupgrades.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index c07ed75374e..1685352bbe4 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -27,10 +27,10 @@ namespace CCUpgrades { const int32_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 286359; // 26 Nov + 90 days const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 243159; // 26 Nov + 60 days - const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT = 0; // TBD - const int32_t CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT = 0; // TBD - const int32_t CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT = 10000000; // TBD - const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 10000000; // TBD + const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT = 100000000; // TBD + const int32_t CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT = 100000000; // TBD + const int32_t CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT = 100000000; // TBD + const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 57544; // 25 apr 2022 4:10p.m enum UPGRADE_STATUS { UPGRADE_ACTIVE = 1, From 7141137c210e30d216b4a20aae4668249a585a56 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 25 Apr 2022 21:36:51 +0500 Subject: [PATCH 224/348] eliminate extra indexkey --- src/cc/CCtokenutils.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index c85e717fc78..e54378ec814 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -570,25 +570,23 @@ std::vector GetTokenV2Conds(const CPubKey &pk) std::vector GetTokenV2IndexKeys(const CPubKey &pk) { std::vector tokenindexkeys; - // get all addresses from pubkey: - char tokenindexkeyPK[KOMODO_ADDRESS_BUFSIZE]; - struct CCcontract_info *cp, C; - cp = CCinit(&C, EVAL_TOKENSV2); - GetTokensCCaddress(cp, tokenindexkeyPK, pk, true); - std::cerr << __func__ << " tokenindexkeyPK=" << tokenindexkeyPK << std::endl; - tokenindexkeys.push_back(tokenindexkeyPK); - - // get inputs from Raddress + // get indexkey from pubkey: + CTxDestination pkdest = pk; + + // get indexkey from Raddress char normaladdr[KOMODO_ADDRESS_BUFSIZE]; char tokenindexkeyR[KOMODO_ADDRESS_BUFSIZE]; Getscriptaddress(normaladdr, CScript() << vuint8_t(pk.begin(), pk.end()) << OP_CHECKSIG); CTxDestination dest = DecodeDestination(normaladdr); // get normal dest - for (CC_SUBVER ccSubVersion = CC_MIXED_MODE_SUBVER_0; ccSubVersion <= CC_MIXED_MODE_SUBVER_MAX; ccSubVersion = (CC_SUBVER)(ccSubVersion + 1)) { - CCwrapper tokenCond( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { dest }) ); // use cc creator for destinations + + std::vector dests{ pkdest, dest }; + + int i = 0; + for (CC_SUBVER ccSubVersion = CC_MIXED_MODE_SUBVER_0; i < dests.size() && ccSubVersion <= CC_MIXED_MODE_SUBVER_MAX; ccSubVersion = (CC_SUBVER)(ccSubVersion + 1), i ++) { + CCwrapper tokenCond( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { dests[i] }) ); //if (!CCtoAnon(tokenCond.get())) { std::cerr << __func__ << " CCtoAnon failed" << std::endl; continue; } // now in CCPubKey() Getscriptaddress(tokenindexkeyR, CCPubKey(tokenCond.get(), ccSubVersion)); - //std::cerr << __func__ << " CCPubKey=" << CCPubKey(tokenCond.get(), ccSubVersion).ToString() << " tokenindexkeyR=" << tokenindexkeyR << std::endl; tokenindexkeys.push_back(tokenindexkeyR); } return tokenindexkeys; From db8bf5a5b42604f8fb90b5c6b37756e9b89e5a37 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 26 Apr 2022 22:04:32 +0500 Subject: [PATCH 225/348] extra loggin removed --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 205276ba990..dae4617f671 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2826,7 +2826,6 @@ namespace Consensus { // are the JoinSplit's requirements met? if (!inputs.HaveJoinSplitRequirements(tx)) return state.Invalid(error("CheckInputs(): %s JoinSplit requirements not met", tx.GetHash().ToString())); -std::cerr << __func__ << " nSpendHeight=" << nSpendHeight << std::endl; CAmount nValueIn = 0; CAmount nFees = 0; for (unsigned int i = 0; i < tx.vin.size(); i++) From d22fe00caac80dd2a5aeada802fbcebcde6cda69 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 26 Apr 2022 22:05:53 +0500 Subject: [PATCH 226/348] fixed token transfer MofN rpc --- src/cc/CCtokens_impl.h | 87 +++++++++++++++++++++-------------------- src/cc/CCtokenutils.cpp | 43 +++++++------------- src/rpc/tokensrpc.cpp | 26 ++++++++---- 3 files changed, 77 insertions(+), 79 deletions(-) diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 66896bcc6da..5bb44025307 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -199,11 +199,11 @@ UniValue TokenBeginTransferTx(CMutableTransaction &mtx, struct CCcontract_info * } template -UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info *cp, const CPubKey &remotepk, uint256 tokenid, const char *tokenaddr, std::vector destpubkeys, const std::pair &probecond, CAmount amount, bool useMempool) +UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info *cp, const CPubKey &remotepk, uint256 tokenid, const std::vector &tokenaddrs, std::vector destpubkeys, const std::vector< std::pair > &probeconds, CAmount total, bool useMempool) { - if (amount < 0) { + if (total < 0) { CCerror = strprintf("negative amount"); - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << CCerror << "=" << amount << std::endl); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << CCerror << "=" << total << std::endl); MakeResultError("negative amount"); } @@ -214,49 +214,50 @@ UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info * return MakeResultError("my pubkey not set"); } - CAmount inputs; - if ((inputs = AddTokenCCInputs(cp, mtx, tokenaddr, tokenid, amount, CC_MAXVINS, useMempool)) > 0) // NOTE: AddTokenCCInputs might set cp->additionalEvalCode which is used in FinalizeCCtx! - { - if (inputs < amount) { - CCerror = strprintf("insufficient token inputs"); - LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << CCerror << std::endl); - return MakeResultError("insufficient token inputs"); - } + CAmount CCinputs = 0LL; + for (const auto &addr : tokenaddrs) { + CAmount CCinputsOne = AddTokenCCInputs(cp, mtx, addr.c_str(), tokenid, total, CC_MAXVINS, useMempool); + if (CCinputsOne > 0) + CCinputs += CCinputsOne; + if (CCinputs >= total) + break; + } - if (probecond.first != nullptr) - { - // add probe cc and kogs priv to spend from kogs global pk - CCAddVintxCond(cp, probecond.first, probecond.second); - } + if (CCinputs < total) { + CCerror = strprintf("insufficient token inputs"); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << CCerror << std::endl); + return MakeResultError("insufficient token inputs"); + } - CScript opret = V::EncodeTokenOpRet(tokenid, destpubkeys, {}); + for(auto const &probecond : probeconds) + CCAddVintxCond(cp, probecond.first, probecond.second); + + CScript opret = V::EncodeTokenOpRet(tokenid, destpubkeys, {}); + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + if (destpubkeys.size() == 1) + mtx.vout.push_back(V::MakeTokensCC1vout(V::EvalCode(), total, destpubkeys[0], &vData)); + else if (destpubkeys.size() == 2) + mtx.vout.push_back(V::MakeTokensCC1of2vout(V::EvalCode(), total, destpubkeys[0], destpubkeys[1], &vData)); + else + { + CCerror = "zero or unsupported destination pk count"; + return MakeResultError("zero or unsupported destination pubkey count"); + } + + CAmount CCchange = 0L; + if (CCinputs > total) + CCchange = (CCinputs - total); + if (CCchange != 0LL) { + CScript opret = V::EncodeTokenOpRet(tokenid, {mypk}, {}); vscript_t vopret; GetOpReturnData(opret, vopret); std::vector vData { vopret }; - if (destpubkeys.size() == 1) - mtx.vout.push_back(V::MakeTokensCC1vout(V::EvalCode(), amount, destpubkeys[0], &vData)); - else if (destpubkeys.size() == 2) - mtx.vout.push_back(V::MakeTokensCC1of2vout(V::EvalCode(), amount, destpubkeys[0], destpubkeys[1], &vData)); - else - { - CCerror = "zero or unsupported destination pk count"; - return MakeResultError("zero or unsupported destination pubkey count"); - } - - CAmount CCchange = 0L; - if (inputs > amount) - CCchange = (inputs - amount); - if (CCchange != 0) { - CScript opret = V::EncodeTokenOpRet(tokenid, {mypk}, {}); - vscript_t vopret; - GetOpReturnData(opret, vopret); - std::vector vData { vopret }; - mtx.vout.push_back(V::MakeTokensCC1vout(V::EvalCode(), CCchange, mypk, &vData)); - } - - return MakeResultSuccess(""); + mtx.vout.push_back(V::MakeTokensCC1vout(V::EvalCode(), CCchange, mypk, &vData)); } - return MakeResultError("could not find token inputs"); + + return MakeResultSuccess(""); } @@ -330,9 +331,9 @@ UniValue TokenTransferExtDest(const CPubKey &remotepk, CAmount txfee, uint256 to { CAmount CCchange = 0, CCinputs = 0; for (const auto &addr : tokenaddrs) { - CAmount outputs = AddTokenCCInputs(cp, mtx, addr.c_str(), tokenid, total, CC_MAXVINS, useMempool); - if (outputs > 0) - CCinputs += outputs; + CAmount CCinputsOne = AddTokenCCInputs(cp, mtx, addr.c_str(), tokenid, total, CC_MAXVINS, useMempool); + if (CCinputsOne > 0) + CCinputs += CCinputsOne; if (CCinputs >= total) break; } diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index e54378ec814..a1273841723 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -544,23 +544,19 @@ std::vector GetTokenV1IndexKeys(const CPubKey &pk) return tokenindexkeys; } +// get conds from pubkey: std::vector GetTokenV2Conds(const CPubKey &pk) { std::vector tokenconds; - // get token cond from the pubkey: - char tokenindexkeyPK[KOMODO_ADDRESS_BUFSIZE]; - struct CCcontract_info *cp, C; - cp = CCinit(&C, EVAL_TOKENSV2); - - CCwrapper tokenCondPK( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { pk }) ); - tokenconds.push_back(tokenCondPK); - - // get token conds from the Raddress char normaladdr[KOMODO_ADDRESS_BUFSIZE]; Getscriptaddress(normaladdr, CScript() << vuint8_t(pk.begin(), pk.end()) << OP_CHECKSIG); - CTxDestination dest = DecodeDestination(normaladdr); // get normal dest - for (CC_SUBVER ccSubVersion = CC_MIXED_MODE_SUBVER_0; ccSubVersion <= CC_MIXED_MODE_SUBVER_MAX; ccSubVersion = (CC_SUBVER)(ccSubVersion + 1)) { - CCwrapper tokenCond( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { dest }) ); // use cc creator for destinations + std::vector dests{ CTxDestination(pk), DecodeDestination(normaladdr) }; + +// for (CC_SUBVER ccSubVersion = CC_MIXED_MODE_SUBVER_0; i < dests.size() && ccSubVersion <= CC_MIXED_MODE_SUBVER_MAX; ccSubVersion = (CC_SUBVER)(ccSubVersion + 1), i ++) { + for (int i = 0; i < dests.size(); i ++) { + CCwrapper tokenCond( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { dests[i] }) ); + //if (!CCtoAnon(tokenCond.get())) { std::cerr << __func__ << " CCtoAnon failed" << std::endl; continue; } // now in CCPubKey() + if (tokenCond == nullptr) continue; tokenconds.push_back(tokenCond); } return tokenconds; @@ -571,23 +567,12 @@ std::vector GetTokenV2IndexKeys(const CPubKey &pk) { std::vector tokenindexkeys; - // get indexkey from pubkey: - CTxDestination pkdest = pk; - - // get indexkey from Raddress - char normaladdr[KOMODO_ADDRESS_BUFSIZE]; - char tokenindexkeyR[KOMODO_ADDRESS_BUFSIZE]; - Getscriptaddress(normaladdr, CScript() << vuint8_t(pk.begin(), pk.end()) << OP_CHECKSIG); - CTxDestination dest = DecodeDestination(normaladdr); // get normal dest - - std::vector dests{ pkdest, dest }; - - int i = 0; - for (CC_SUBVER ccSubVersion = CC_MIXED_MODE_SUBVER_0; i < dests.size() && ccSubVersion <= CC_MIXED_MODE_SUBVER_MAX; ccSubVersion = (CC_SUBVER)(ccSubVersion + 1), i ++) { - CCwrapper tokenCond( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { dests[i] }) ); - //if (!CCtoAnon(tokenCond.get())) { std::cerr << __func__ << " CCtoAnon failed" << std::endl; continue; } // now in CCPubKey() - Getscriptaddress(tokenindexkeyR, CCPubKey(tokenCond.get(), ccSubVersion)); - tokenindexkeys.push_back(tokenindexkeyR); + std::vector tokenconds = GetTokenV2Conds(pk); + for (auto const &cond : tokenconds) { + char tokenindexkey[KOMODO_ADDRESS_BUFSIZE]; + CC_SUBVER ccSubVersion = (cc_typeMask(cond.get()) & (1 << CC_Secp256k1hash)) ? CC_MIXED_MODE_SECHASH_SUBVER_1 : CC_MIXED_MODE_SUBVER_0; + Getscriptaddress(tokenindexkey, CCPubKey(cond.get(), ccSubVersion)); + tokenindexkeys.push_back(tokenindexkey); } return tokenindexkeys; } \ No newline at end of file diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 02c79447ed6..93e9e7dc905 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -627,22 +627,34 @@ UniValue tokentransfermany(const std::string& name, const UniValue& params, bool if (ResultIsError(beginResult)) return beginResult; - for (const auto &tokenid : tokenids) - { + uint8_t mypriv[32]; + Myprivkey(mypriv); + std::vector srctokenaddrs; + std::vector> probes; + if (V::IsMixed() == EVAL_TOKENS) { CCwrapper probeCond; probeCond.reset( MakeCCcond1(V::EvalCode(), mypk) ); - - uint8_t mypriv[32]; - Myprivkey(mypriv); - char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; GetTokensCCaddress(cpTokens, tokenaddr, mypk, V::IsMixed()); + srctokenaddrs.push_back(tokenaddr); + probes.push_back({probeCond, mypriv}); + + } + else { + std::vector pkconds = GetTokenV2Conds(mypk); + srctokenaddrs = GetTokenV2IndexKeys(mypk); + for(auto const &cond : pkconds) + probes.push_back({cond, mypriv}); + } - UniValue addtxResult = TokenAddTransferVout(mtx, cpTokens, remotepk, tokenid, tokenaddr, { destpk }, {probeCond, mypriv}, amount, false); + for (const auto &tokenid : tokenids) + { + UniValue addtxResult = TokenAddTransferVout(mtx, cpTokens, remotepk, tokenid, srctokenaddrs, { destpk }, probes, amount, false); memset(mypriv, '\0', sizeof(mypriv)); if (ResultIsError(addtxResult)) return MakeResultError( ResultGetError(addtxResult) + " " + tokenid.GetHex() ); } + memset(mypriv, '\0', sizeof(mypriv)); UniValue sigData = TokenFinalizeTransferTx(mtx, cpTokens, remotepk, txfee, CScript()); RETURN_IF_ERROR(CCerror); if (ResultHasTx(sigData) > 0) From a1b8c90a26e4b486b99a0b98c51993e935882597 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 26 Apr 2022 22:06:24 +0500 Subject: [PATCH 227/348] safety check to CCPubKey --- src/script/cc.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/script/cc.cpp b/src/script/cc.cpp index 18023086c2d..d259abc2350 100644 --- a/src/script/cc.cpp +++ b/src/script/cc.cpp @@ -112,6 +112,8 @@ CScript CCPubKey(const CC *cond, CC_SUBVER ccSubVersion) unsigned char buf[MAX_FULFILLMENT_SIZE]; size_t len; + if (!cond) return CScript(); + if (ccSubVersion >= CC_MIXED_MODE_SUBVER_0) { buf[0] = (uint8_t)CC_MIXED_MODE_PREFIX + ccSubVersion; CC *condCopy = cc_copy(cond); From bdb75024e4dc40717eaa68b7545d4b9e311945e5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 27 Apr 2022 16:29:31 +0500 Subject: [PATCH 228/348] assets py tests fixed for new rpc tokenv2transferMofN, refactored --- src/tui/tui_assets_orders.py | 304 +++++++++++++++++++---------------- 1 file changed, 162 insertions(+), 142 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index d61b9c1d28a..f6521015f56 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -14,13 +14,38 @@ header = "komodo assets cc tokenask/bid v2 test\n" tui_config_name = './tui_assets_orders.ini' +def wait_until_confirmed(rpc, txid) : + for i in range(60) : + try : + txdecoded = rpc.getrawtransaction(txid, 1) + # print('get.confirmations', txdecoded.get('confirmations'), type(txdecoded.get('confirmations'))) + if not txdecoded.get('confirmations') is None : + print('confirmations', int(txdecoded.get('confirmations'))) + if int(txdecoded.get('confirmations')) > 0 : + return + except : + print('getrawtransaction exception') + pass + time.sleep(10) + print('still waiting for confirmation...') + +def get_my_address(rpc) : + gr = rpc.listaddressgroupings() + total = 0 + for l1 in gr : + for l2 in l1 : + for addr in l2 : + return addr + return "" + def get_result_error(r): if isinstance(r, dict) : if r.get('result') == "error" : return r.get('error') return '' -def check_tx(r): +# check if result is valid tx +def check_tx_result(r): if isinstance(r, str) : # print("r is str, true") return True @@ -46,7 +71,7 @@ def check_txid(txid) : return True return False -def run_tokens_create(): +def run_tokens_create(rpc1, rpc2, rpc3): # set your own two node params # DIMXY20 @@ -55,9 +80,9 @@ def run_tokens_create(): # rpc3 = rpclib.rpc_connect("user972794450", "passe7eb16f5c015a53463cc5f27a004854cb76f4ec5c9aece177f01d8b3d13119e445", 16723) # DIMXY29 - rpc1 = rpclib.rpc_connect("user977812407", "pass45a4a6ce9ffafbebd2a478d3858d55c8a4bded74632bb488c8c93164d048237516", 14723) - rpc2 = rpclib.rpc_connect("user4228621419", "pass4e51de899bd15c12569d762ded036e5aecd5aeb7be40788a339e72e1fea7359d7e", 15723) - rpc3 = rpclib.rpc_connect("user3877003389", "passea3e5a6c7a8a88f5447cc39bc8720cf783bbcef43345b16be9aadc0a1b381006eb", 16723) + # rpc1 = rpclib.rpc_connect("user977812407", "pass45a4a6ce9ffafbebd2a478d3858d55c8a4bded74632bb488c8c93164d048237516", 14723) + # rpc2 = rpclib.rpc_connect("user4228621419", "pass4e51de899bd15c12569d762ded036e5aecd5aeb7be40788a339e72e1fea7359d7e", 15723) + # rpc3 = rpclib.rpc_connect("user3877003389", "passea3e5a6c7a8a88f5447cc39bc8720cf783bbcef43345b16be9aadc0a1b381006eb", 16723) ## for v in ["", "v2"] : @@ -65,54 +90,62 @@ def run_tokens_create(): for v in ["v2"] : print("creating fungible token 1...") result = call_rpc(rpc1, "token"+v+"create", "T1", str(0.000001)) # 100 - assert(check_tx(result)) + assert(check_tx_result(result)) tokenid1 = rpc1.sendrawtransaction(result['hex']) print("created token:", tokenid1) - + # wait_until_confirmed(rpc1, tokenid1) + print("creating fungible token 2...") result = call_rpc(rpc1, "token"+v+"create", "T2", str(0.1)) - assert(check_tx(result)) + assert(check_tx_result(result)) tokenid2 = rpc1.sendrawtransaction(result['hex']) print("created token:", tokenid2) + # wait_until_confirmed(rpc1, tokenid2) print("creating tokel NFT 1 with empty data...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-00-1", str(0.00000001), "nft tokel empty", '{}') - assert(check_tx(result)) + assert(check_tx_result(result)) nft00id1 = rpc1.sendrawtransaction(result['hex']) print("created token:", nft00id1) + # wait_until_confirmed(rpc1, nft00id1) print("creating tokel NFT 2 with arbitrary data...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-00-2", str(0.00000001), "nft tokel arbitrary", '{"arbitrary":"010203"}') - assert(check_tx(result)) + assert(check_tx_result(result)) nft00id2 = rpc1.sendrawtransaction(result['hex']) print("created token:", nft00id2) + # wait_until_confirmed(rpc1, nft00id2) # tokel nft data F7 evalcode print("creating tokel NFT with royalty 0...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-1", str(0.00000001), "nft tokel royalty=0", '{"royalty":0}') - assert(check_tx(result)) + assert(check_tx_result(result)) nftf7id1 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id1) + # wait_until_confirmed(rpc1, nftf7id1) print("creating tokel NFT with royalty 99...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-2", str(0.00000001), "nft tokel royalty=99", '{"royalty":99}') - assert(check_tx(result)) + assert(check_tx_result(result)) nftf7id2 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id2) + # wait_until_confirmed(rpc1, nftf7id2) print("creating tokel NFT with royalty 1 (to test dust)...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-3", str(0.00000001), "nft tokel royalty=1", '{"royalty":1}') - assert(check_tx(result)) + assert(check_tx_result(result)) nftf7id3 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id3) + # wait_until_confirmed(rpc1, nftf7id3) print("creating tokel NFT with royalty 500 (to test dust)...") result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-4", str(0.00000001), "nft tokel royalty=500", '{"royalty":500}') - assert(check_tx(result)) + assert(check_tx_result(result)) nftf7id4 = rpc1.sendrawtransaction(result['hex']) print("created token:", nftf7id4) - print("tokens for tests created okay!") + # wait_until_confirmed(rpc1, nftf7id4) + print("tokens for tests created okay!") # test tokenlist: check_tokenlist(rpc1, v, [tokenid1, tokenid2, nft00id1, nft00id2, nftf7id1, nftf7id2, nftf7id3, nftf7id4]) # test tokenallbalances: @@ -121,6 +154,8 @@ def run_tokens_create(): # first try transfer tokens to a pk and back, then run assets tests print("starting transfer tests for tokenid version=" + v + "...") run_transfers(rpc1, rpc2, v, tokenid1, tokenid2, 10) + + ''' print("starting transfer tests for nft00id version=" + v + "...") run_transfers(rpc1, rpc2, v, nft00id1, nft00id2, 1) print("starting transfer tests for nftf7id version=" + v + "...") @@ -145,6 +180,7 @@ def run_tokens_create(): print("starting assets order expiration tests for tokenid1 version=" + v + "...") run_assets_expired_orders(rpc1, rpc2, v, tokenid1, 10, 8, 0.0001, False) print("assets tests finished okay!") + ''' if v == "v2" : # MofN supported for tokens cc v2 only print("running MofN tests for tokens v2:") @@ -156,6 +192,8 @@ def run_tokens_create(): run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) print("token MofN transfer tests finished okay!") + + print("all token/assets tests finished okay!") time.sleep(3) exit @@ -172,7 +210,7 @@ def call_token_rpc_create_tx(rpc, rpcname, stop_error, *args) : print("calling " + rpcname) result = rpcfunc(*args) print(rpcname + " create tx result:", result, " arg=", args[0]) - if check_tx(result): + if check_tx_result(result): break if stop_error and get_result_error(result) == stop_error : print(rpcname + " retrying stopped because of expected stop error received: " + stop_error) @@ -180,7 +218,7 @@ def call_token_rpc_create_tx(rpc, rpcname, stop_error, *args) : if i < retries-1: print("retrying " + rpcname + '...') time.sleep(delay) - assert(check_tx(result)) + assert(check_tx_result(result)) print(rpcname + " tx created") return result @@ -188,11 +226,11 @@ def call_token_rpc_send_tx(rpc, rpcname, stop_error, *args) : for i in range(3) : result = call_token_rpc_create_tx(rpc, rpcname, stop_error, *args) - if check_tx(result) : + if check_tx_result(result) : try : txid = rpc.sendrawtransaction(result['hex']) print("sendrawtransaction result: ", txid) - assert(check_tx(txid)) + assert(check_tx_result(txid)) print(rpcname + " tx sent") return txid except RpcException as e : @@ -213,7 +251,7 @@ def call_rpc_retry(rpc, rpcname, stop_error, *args) : print("calling " + rpcname) result = rpcfunc(*args) # print(rpcname + " result:", result) - if check_tx(result): + if check_tx_result(result): break if stop_error and get_result_error(result) == stop_error : print(rpcname + " retrying stopped because of expected stop error received: " + stop_error) @@ -221,7 +259,7 @@ def call_rpc_retry(rpc, rpcname, stop_error, *args) : if i < retries-1: print("retrying " + rpcname + '...') time.sleep(delay) - assert(check_tx(result)) + assert(check_tx_result(result)) # print(rpcname + " finished okay") return result @@ -283,8 +321,8 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): param["destpubkeys"] = [ pubkey1, pubkey2 ] param["M"] = 1 param["amount"] = amount - print("creating tokenv2transfer tokenid amount tx to 1of2 tx...", json.dumps(param)) - tx1of2 = call_token_rpc_create_tx(rpc1, "tokenv2transfer", '', json.dumps(param)) + print("creating tokenv2transferMofN tokenid amount tx to 1of2 tx...", json.dumps(param)) + tx1of2 = call_token_rpc_create_tx(rpc1, "tokenv2transferMofN", '', json.dumps(param)) txid = rpc1.sendrawtransaction(tx1of2['hex']) print("sendrawtransaction result: ", txid) assert(check_txid(txid)) @@ -301,22 +339,22 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): if amount > 1 : # if not nft first send half to pk2 (to test lib cc fulfilment ordering) # try firs1 to pk2 param["destpubkeys"] = [ pubkey2 ] - print("creating tokenv2transfer tokenid1 tx spending 1of2 back to pk2...", json.dumps(param)) - txid = call_token_rpc_send_tx(rpc2, "tokenv2transfer", '', json.dumps(param)) + print("creating tokenv2transferMofN tokenid1 tx spending 1of2 back to pk2...", json.dumps(param)) + txid = call_token_rpc_send_tx(rpc2, "tokenv2transferMofN", '', json.dumps(param)) assert(check_txid(txid)) else : # if nft send 1 back to pk1 for the next test param["destpubkeys"] = [ pubkey1 ] - print("creating tokenv2transfer tokenid tx spending 1of2 back to pk1...", json.dumps(param)) - txid = call_token_rpc_send_tx(rpc1, "tokenv2transfer", '', json.dumps(param)) + print("creating tokenv2transferMofN tokenid tx spending 1of2 back to pk1...", json.dumps(param)) + txid = call_token_rpc_send_tx(rpc1, "tokenv2transferMofN", '', json.dumps(param)) assert(check_txid(txid)) if amount > 1 : # if not nft send half amount back to pk1 # wait to prevent adding same inputs while tx is not propagated to this node mempool time.sleep(3) param["destpubkeys"] = [ pubkey1 ] - print("creating tokenv2transfer tokenid tx spending 1of2 back to pk1...",json.dumps(param)) - txid = call_token_rpc_send_tx(rpc1, "tokenv2transfer", '', json.dumps(param)) + print("creating tokenv2transferMofN tokenid tx spending 1of2 back to pk1...",json.dumps(param)) + txid = call_token_rpc_send_tx(rpc1, "tokenv2transferMofN", '', json.dumps(param)) assert(check_txid(txid)) time.sleep(1) # pause to allow tx in mempool to propagate to prevent double spending in mempool @@ -327,8 +365,8 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): param["destpubkeys"] = [ pubkey1, pubkey2 ] param["M"] = 2 param["amount"] = amount - print("creating tokenv2transfer tokenid amount tx to 2of2 ...", json.dumps(param)) - tx2of2 = call_token_rpc_create_tx(rpc1, "tokenv2transfer", '', json.dumps(param)) + print("creating tokenv2transferMofN tokenid amount tx to 2of2 ...", json.dumps(param)) + tx2of2 = call_token_rpc_create_tx(rpc1, "tokenv2transferMofN", '', json.dumps(param)) txid = rpc1.sendrawtransaction(tx2of2['hex']) print("sendrawtransaction result: ", txid) assert(check_txid(txid)) @@ -343,8 +381,8 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): param["destpubkeys"] = [ pubkey1 ] param["M"] = 1 param["amount"] = amount - print("creating tokenv2transfer tokenid tx spending 2of2 back to pk1...", json.dumps(param)) - partialtx = call_token_rpc(rpc1, "tokenv2transfer", '', json.dumps(param)) + print("creating tokenv2transferMofN tokenid tx spending 2of2 back to pk1...", json.dumps(param)) + partialtx = call_token_rpc(rpc1, "tokenv2transferMofN", '', json.dumps(param)) assert partialtx['hex'], 'partial tx not created' assert partialtx['PartiallySigned'], 'partially signed object' @@ -372,8 +410,8 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): param["destpubkeys"] = [ pubkey1, pubkey2, pubkey3 ] param["M"] = 2 param["amount"] = amount - print("creating tokenv2transfer tokenid amount tx to 2of3 tx...", json.dumps(param)) - tx2of3 = call_token_rpc_create_tx(rpc1, "tokenv2transfer", '', json.dumps(param)) + print("creating tokenv2transferMofN tokenid amount tx to 2of3 tx...", json.dumps(param)) + tx2of3 = call_token_rpc_create_tx(rpc1, "tokenv2transferMofN", '', json.dumps(param)) txid = rpc1.sendrawtransaction(tx2of3['hex']) print("sendrawtransaction result: ", txid) assert(check_txid(txid)) @@ -388,8 +426,8 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): param["M"] = 1 param["amount"] = amountback param["destpubkeys"] = [ pubkey1 ] - print("creating tokenv2transfer tokenid tx spending 2of3 back to pk1...", json.dumps(param)) - partialtx = call_token_rpc(rpc1, "tokenv2transfer", '', json.dumps(param)) + print("creating tokenv2transferMofN tokenid tx spending 2of3 back to pk1...", json.dumps(param)) + partialtx = call_token_rpc(rpc1, "tokenv2transferMofN", '', json.dumps(param)) assert partialtx['hex'], 'partial tx not created' assert partialtx['PartiallySigned'], 'partially signed object' @@ -419,8 +457,8 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): param["destpubkeys"] = [ pubkey1, pubkey2, pubkey3 ] param["M"] = 3 param["amount"] = amount - print("creating tokenv2transfer tokenid amount tx to 3of3 ...", json.dumps(param)) - tx3of3 = call_token_rpc_create_tx(rpc1, "tokenv2transfer", '', json.dumps(param)) + print("creating tokenv2transferMofN tokenid amount tx to 3of3 ...", json.dumps(param)) + tx3of3 = call_token_rpc_create_tx(rpc1, "tokenv2transferMofN", '', json.dumps(param)) txid = rpc1.sendrawtransaction(tx3of3['hex']) print("sendrawtransaction result: ", txid) assert(check_txid(txid)) @@ -435,8 +473,8 @@ def run_MofN_transfers(rpc1, rpc2, rpc3, tokenid, amount): param["destpubkeys"] = [ pubkey1 ] param["M"] = 1 param["amount"] = amount - print("creating tokenv2transfer tokenid tx spending 3of3 back to pk1...", json.dumps(param)) - partialtx1 = call_token_rpc(rpc1, "tokenv2transfer", '', json.dumps(param)) + print("creating tokenv2transferMofN tokenid tx spending 3of3 back to pk1...", json.dumps(param)) + partialtx1 = call_token_rpc(rpc1, "tokenv2transferMofN", '', json.dumps(param)) assert partialtx1['hex'], 'partial tx not created' assert partialtx1['PartiallySigned'], 'partially signed object' @@ -495,7 +533,7 @@ def run_assets_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, isnft): # get initial balance result = call_rpc(rpc1, "token"+v+"balance", tokenid) - assert(check_tx(result)) + assert(check_tx_result(result)) initial_balance = int(result["balance"]) print("initial balance for tokenid " + tokenid + " = " + str(initial_balance)) @@ -589,7 +627,7 @@ def run_assets_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, isnft): for i in range(retries): print("calling " + "token"+v+"balance") finresult = call_rpc(rpc1, "token"+v+"balance", tokenid) - assert(check_tx(result)) + assert(check_tx_result(result)) if int(finresult["balance"]) == initial_balance : break if i < retries-1: @@ -598,6 +636,17 @@ def run_assets_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, isnft): assert(int(finresult["balance"]) == initial_balance) +def wait_for_height(rpc, ht) : + # wait for expiration height + while True : + time.sleep(30) + getinfo = rpc.getinfo() + h1 = getinfo["blocks"] + if h1 >= ht : + break + print ('waiting for expiration height...') + myaddr = get_my_address(rpc) + rpc.sendtoaddress(myaddr, 0.1) # this is for on demand chains to advance a chain # test expiration height in orders def run_assets_expired_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, isnft): @@ -614,7 +663,7 @@ def run_assets_expired_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, i print("trying to cancel not yet expired order with other pk: token"+v+"cancelask...") result = call_token_rpc_create_tx(rpc2, "token"+v+"cancelask", 'ask is empty', tokenid, askid1) - assert(check_tx(result)) + assert(check_tx_result(result)) try : cancelid = rpc2.sendrawtransaction(result['hex']) assert(get_result_error(cancelid)) # should return error for not yet expired order @@ -623,17 +672,11 @@ def run_assets_expired_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, i pass # exception is a normal execution # wait for expiration height - while True : - time.sleep(30) - getinfo = rpc1.getinfo() - h1 = getinfo["blocks"] - if h1 >= h0 + hoff : - break - print ('waiting for expiration height...') + wait_for_height(rpc1, h0 + hoff) print("trying to fill expired order token"+v+"fillask tx #1...") result = call_token_rpc_create_tx(rpc2, "token"+v+"fillask", '', tokenid, askid1, str(askunits)) - assert(check_tx(result)) + assert(check_tx_result(result)) try : fillaskid1 = rpc2.sendrawtransaction(result['hex']) print("fillaskid1", fillaskid1) @@ -656,7 +699,7 @@ def run_assets_expired_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, i print("trying to cancel not yet expired order with other pk: token"+v+"cancelbid...") result = call_token_rpc_create_tx(rpc1, "token"+v+"cancelbid", 'bid is empty', tokenid, bidid1) - assert(check_tx(result)) + assert(check_tx_result(result)) try : cancelid = rpc1.sendrawtransaction(result['hex']) assert(get_result_error(cancelid)) # should return error for not yet expired order @@ -665,17 +708,11 @@ def run_assets_expired_orders(rpc1, rpc2, v, tokenid, total, units, unitprice, i pass # should be exception # wait for expiration height - while True : - time.sleep(30) - getinfo = rpc1.getinfo() - h1 = getinfo["blocks"] - if h1 >= h0 + hoff : - break - print ('waiting for expiration height...') + wait_for_height(rpc1, h0 + hoff) print("trying to fill expired order token"+v+"fillbid tx #1...") result = call_token_rpc_create_tx(rpc1, "token"+v+"fillbid", '', tokenid, bidid1, str(bidunits)) - assert(check_tx(result)) + assert(check_tx_result(result)) try : fillbidid1 = rpc1.sendrawtransaction(result['hex']) assert(get_result_error(fillbidid1)) # should return error for yet expired order @@ -725,90 +762,73 @@ def check_tokenallbalances(rpc, v, checkbalances) : assert len(results) == len(checkbalances), "not all tokenids have correct amounts in " + rpcname + " results" print('check_tokenallbalances okay!') -''' -menuItems = [ - {"run token create/transfers and assets orders": run_tokens_create}, - {"Exit": exit} -] - -def readConfig(path) : - - tui_config = configparser.ConfigParser() - tui_config.read(tui_config_name) - node_ini_path = tui_config['DEFAULT'][path] - assert node_ini_path, "cannot read " + path + " property from tui config" - - chain_config = configparser.ConfigParser() - chain_config.read(node_ini_path) - uname = chain_config['DEFAULT']['rpcuser'] - passw = chain_config['DEFAULT']['rpcpassword'] - port = chain_config['DEFAULT']['rpcport'] - - assert uname and passw and port, node_ini_path + ' has empty params rpcuser or rpcpassword or rpcport' - r = {'rpcuser' : uname, 'rpcpassword' : passw, 'rpcport': port } - return r - - -def makeTuiConfig() : - - tui_config = configparser.ConfigParser() - tui_config.read(tui_config_name) - old_path1 = old_path2 = old_path3 = '' - if tui_config.read(tui_config_name) : - old_path1 = tui_config['path1'] - old_path2 = tui_config['path2'] - old_path3 = tui_config['path3'] - - ask_path1 = "" - if old_path1 : - ask_path1 = "(" + old_path1 + ")" - path1 = input("node1 path " + ask_path1 + ":" ) - - ask_path2 = "" - if old_path2 : - ask_path2 = "(" + old_path2 + ")" - path2 = input("node2 path " + ask_path2 + ":" ) - - ask_path3 = "" - if old_path3 : - ask_path3 = "(" + old_path3 + ")" - path3 = input("node3 path " + ask_path3 + ":" ) - - if path1 or path2 or path3 : - assert path1 != path2 and path1 != path3 and path2 != path3, 'paths should be different' - if path1 : - tui_config['path1'] = path1 - if path2 : - tui_config['path2'] = path2 - if path3 : - tui_config['path3'] = path3 - with open(tui_config_name, 'w') as configfile: # save tui config - tui_config.write(configfile) - -def main(): - while True: - os.system('clear') - print(tuilib.colorize(header, 'pink')) - print(tuilib.colorize('CLI version 0.2\n', 'green')) - for item in menuItems: - print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0]) - choice = input(">> ") - try: - if int(choice) < 0: - raise ValueError - # Call the matching function - if list(menuItems[int(choice)].keys())[0] == "Exit": - list(menuItems[int(choice)].values())[0]() - else: - list(menuItems[int(choice)].values())[0]() - except (ValueError, IndexError): - pass -''' +def get_kmd_rpc(config) : + rpc = None + with open(config) as file: + lines = file.readlines() + + rpcport = 7771 + cookiename = '__cookie__' + cookie = '' + for l in lines : + t = l.split(':') + if len(t) == 2 : + if t[0] == cookiename : + cookie = t[1] + + rpc = rpclib.rpc_connect(cookiename, cookie, int(rpcport)) + return rpc + + +def get_as_chain_rpc(config) : + rpc = None + with open(config) as file: + lines = file.readlines() + rpcuser = '' + rpcpassword = '' + rpcport = 0 + for l in lines : + t = l.split('=') + # print('t=', t) + if len(t) == 2 : + if t[0] == 'rpcuser' : + rpcuser = t[1].strip() + elif t[0] == 'rpcpassword' : + rpcpassword = t[1].strip() + elif t[0] == 'rpcport' : + rpcport = int(t[1]) + + print('rpcuser', rpcuser, 'rpcpassword', rpcpassword, 'rpcport', rpcport) + rpc = rpclib.rpc_connect(rpcuser, rpcpassword, int(rpcport)) + return rpc + +def get_chain_rpc(config) : + + rpc = None + # print('config[-4:]', config[-4:]) + if config[-4:] == 'conf' : + rpc = get_as_chain_rpc(config) + elif config[-6:] == 'cookie' : + rpc = get_kmd_rpc(config) + else : + assert False, 'could not find connection params' + + rpc.getinfo() # try connect + print('rpc connected') + return rpc if __name__ == "__main__": - print("starting assets orders test\n plz first start a chain of three nodes and enter paths for your node config files)") + print("starting assets orders test") + print("plz first start a chain of three nodes and enter rpc params in the code") + print("ensure you have at least 10 utxos in the first node wallet for batch test txns creation") + + rpc1 = get_chain_rpc('/Users/dimxy/Library/Application Support/Komodo/DIMXY31/DIMXY31.conf') + rpc2 = get_chain_rpc('/Users/dimxy/repo/tokel/src/DIMXY31/nodes/1/DIMXY31.conf') + rpc3 = get_chain_rpc('/Users/dimxy/repo/tokel/src/DIMXY31/nodes/2/DIMXY31.conf') + + # time.sleep(2) # makeTuiConfig() # main() - run_tokens_create() + run_tokens_create(rpc1, rpc2, rpc3) From fb172badc64aa8f875916521946a619a263644fe Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 27 Apr 2022 20:39:24 +0500 Subject: [PATCH 229/348] fixed cc test (no-signature conds enabled); disabled incompatible bet tests --- src/test-komodo/test_cryptoconditions.cpp | 2 +- src/test-komodo/test_eval_bet.cpp | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/test-komodo/test_cryptoconditions.cpp b/src/test-komodo/test_cryptoconditions.cpp index f56ab66a071..22170844559 100644 --- a/src/test-komodo/test_cryptoconditions.cpp +++ b/src/test-komodo/test_cryptoconditions.cpp @@ -79,7 +79,7 @@ TEST_F(CCTest, testMayAcceptCryptoCondition) { "type": "eval-sha-256", "code": "" } ] })!!"); - ASSERT_FALSE(CCPubKey(cond).MayAcceptCryptoCondition()); + ASSERT_TRUE(CCPubKey(cond).MayAcceptCryptoCondition()); // used to be ASSERT_FALSE, now enabled for generic evals } diff --git a/src/test-komodo/test_eval_bet.cpp b/src/test-komodo/test_eval_bet.cpp index 1f6ba6e38ca..a9c6fffebc6 100644 --- a/src/test-komodo/test_eval_bet.cpp +++ b/src/test-komodo/test_eval_bet.cpp @@ -15,6 +15,7 @@ extern Eval* EVAL_TEST; +extern int32_t KOMODO_CONNECTING; namespace TestBet { @@ -311,9 +312,10 @@ TEST_F(TestBet, testSignDisputeCond) EXPECT_EQ(1, cc_isFulfilled(disputeCond)); } - -TEST_F(TestBet, testDispute) +// these tests do not work in the existing ProcessCC implementation (it does not allow a eval param in the cond->code) +TEST_F(TestBet, DISABLED_testDispute) { + KOMODO_CONNECTING = 1; EvalMock eval = ebet.SetEvalMock(12); // Only one key needed to dispute @@ -332,8 +334,7 @@ TEST_F(TestBet, testDispute) EXPECT_EQ("wrong-payout", eval.state.GetRejectReason()); } - -TEST_F(TestBet, testDisputeInvalidOutput) +TEST_F(TestBet, DISABLED_testDisputeInvalidOutput) { EvalMock eval = ebet.SetEvalMock(11); @@ -356,7 +357,7 @@ TEST_F(TestBet, testDisputeInvalidOutput) } -TEST_F(TestBet, testDisputeEarly) +TEST_F(TestBet, DISABLED_testDisputeEarly) { EvalMock eval = ebet.SetEvalMock(11); @@ -370,7 +371,7 @@ TEST_F(TestBet, testDisputeEarly) } -TEST_F(TestBet, testDisputeInvalidParams) +TEST_F(TestBet, DISABLED_testDisputeInvalidParams) { EvalMock eval = ebet.SetEvalMock(12); @@ -399,7 +400,7 @@ TEST_F(TestBet, testDisputeInvalidParams) } -TEST_F(TestBet, testDisputeInvalidEvidence) +TEST_F(TestBet, DISABLED_testDisputeInvalidEvidence) { EvalMock eval = ebet.SetEvalMock(12); From d4805f440f4431c6e89d01875b1253680b7269f0 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 27 Apr 2022 20:40:00 +0500 Subject: [PATCH 230/348] fixed GetScriptForDestination for CLTV --- src/script/standard.cpp | 4 ++-- src/test-komodo/test_script_standard_tests.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 6f9b6544ca3..fa09c676b5c 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -553,9 +553,9 @@ class CScriptVisitor : public boost::static_visitor bool operator()(const CCLTVID &dest) const { script->clear(); if (dest.which() == TX_PUBKEY) - *script << dest.GetUnlockTime() << OP_CHECKLOCKTIMEVERIFY << OP_DROP << ToByteVector(dest.GetPubKey()) << OP_CHECKSIG; + *script << CScriptNum::serialize(dest.GetUnlockTime()) << OP_CHECKLOCKTIMEVERIFY << OP_DROP << ToByteVector(dest.GetPubKey()) << OP_CHECKSIG; else - *script << dest.GetUnlockTime() << OP_CHECKLOCKTIMEVERIFY << OP_DROP << OP_DUP << OP_HASH160 << ToByteVector(dest.GetKeyID()) << OP_EQUALVERIFY << OP_CHECKSIG; + *script << CScriptNum::serialize(dest.GetUnlockTime()) << OP_CHECKLOCKTIMEVERIFY << OP_DROP << OP_DUP << OP_HASH160 << ToByteVector(dest.GetKeyID()) << OP_EQUALVERIFY << OP_CHECKSIG; return true; } }; diff --git a/src/test-komodo/test_script_standard_tests.cpp b/src/test-komodo/test_script_standard_tests.cpp index 53447f7f32e..53e56caea89 100644 --- a/src/test-komodo/test_script_standard_tests.cpp +++ b/src/test-komodo/test_script_standard_tests.cpp @@ -342,6 +342,19 @@ namespace TestScriptStandartTests { OP_3 << OP_CHECKMULTISIG; result = GetScriptForMultisig(2, std::vector(pubkeys, pubkeys + 3)); ASSERT_TRUE(result == expected); + + + // CCLTVID + int64_t utm = 1651073436; + expected.clear(); + expected << CScriptNum::serialize(utm) << OP_CHECKLOCKTIMEVERIFY << OP_DROP << ToByteVector(pubkeys[0]) << OP_CHECKSIG; + result = GetScriptForDestination(CCLTVID(pubkeys[0], utm)); + ASSERT_TRUE(result == expected); + + expected.clear(); + expected << CScriptNum::serialize(utm) << OP_CHECKLOCKTIMEVERIFY << OP_DROP << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + result = GetScriptForDestination(CCLTVID(pubkeys[0].GetID(), utm)); + ASSERT_TRUE(result == expected); } TEST(TestScriptStandartTests, script_standard_IsMine) { From 9495004bfcda858a28241a11d6d7fc54297cff49 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 27 Apr 2022 21:07:31 +0500 Subject: [PATCH 231/348] cltv destination test refactored --- src/test-komodo/test_script_standard_tests.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test-komodo/test_script_standard_tests.cpp b/src/test-komodo/test_script_standard_tests.cpp index 53e56caea89..75918c3312d 100644 --- a/src/test-komodo/test_script_standard_tests.cpp +++ b/src/test-komodo/test_script_standard_tests.cpp @@ -342,7 +342,19 @@ namespace TestScriptStandartTests { OP_3 << OP_CHECKMULTISIG; result = GetScriptForMultisig(2, std::vector(pubkeys, pubkeys + 3)); ASSERT_TRUE(result == expected); + } + + // timelocked script in tokel repo + TEST(TestScriptStandartTests, script_standard_GetScriptFor_CLTV) { + CKey keys[1]; + CPubKey pubkeys[1]; + for (int i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) { + keys[i].MakeNewKey(true); + pubkeys[i] = keys[i].GetPubKey(); + } + + CScript expected, result; // CCLTVID int64_t utm = 1651073436; From a491e5d824f5965f18e669923e77eed092ab1b56 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 28 Apr 2022 01:16:26 +0500 Subject: [PATCH 232/348] CCupgrades.h name fixed --- src/cc/import.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 2c45f3aba6b..4fd06f073d2 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -23,7 +23,7 @@ #include "cc/CCinclude.h" #include "cc/CCtokens.h" #include "cc/CCImportGateway.h" -#include "cc/CCUpgrades.h" +#include "cc/CCupgrades.h" #include "key_io.h" From 38102896ec76eaaa36f7f031e1f743913f115078 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 28 Apr 2022 02:34:40 +0500 Subject: [PATCH 233/348] rearrange src to enable komodo-tx build --- src/Makefile.am | 2 +- src/cc/CCtokens.cpp | 47 +++++++++++++++++++++++++++++++++++++++++ src/cc/CCtokenutils.cpp | 47 ----------------------------------------- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index e24d5ac0679..eaf19d755be 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -364,7 +364,6 @@ libbitcoin_server_a_SOURCES = \ txdb.cpp \ txmempool.cpp \ validationinterface.cpp \ - cc/CCupgrades.cpp \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) @@ -509,6 +508,7 @@ libbitcoin_common_a_SOURCES = \ transaction_builder.cpp \ cc/CCtokenutils.cpp \ cc/CCutilbits.cpp \ + cc/CCupgrades.cpp \ gmp_i64.c \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 68372952d2c..2bffa0020aa 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -851,3 +851,50 @@ UniValue TokenV2List(const UniValue ¶ms) return(result); } + +// get token indexkey for pubkey for old tokens: +std::vector GetTokenV1IndexKeys(const CPubKey &pk) +{ + std::vector tokenindexkeys; + char tokenindexkeyPK[KOMODO_ADDRESS_BUFSIZE]; + struct CCcontract_info *cp, C; + cp = CCinit(&C, EVAL_TOKENS); + + GetTokensCCaddress(cp, tokenindexkeyPK, pk, false); + tokenindexkeys.push_back(tokenindexkeyPK); + + return tokenindexkeys; +} + +// get conds from pubkey: +std::vector GetTokenV2Conds(const CPubKey &pk) +{ + std::vector tokenconds; + char normaladdr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(normaladdr, CScript() << vuint8_t(pk.begin(), pk.end()) << OP_CHECKSIG); + std::vector dests{ CTxDestination(pk), DecodeDestination(normaladdr) }; + +// for (CC_SUBVER ccSubVersion = CC_MIXED_MODE_SUBVER_0; i < dests.size() && ccSubVersion <= CC_MIXED_MODE_SUBVER_MAX; ccSubVersion = (CC_SUBVER)(ccSubVersion + 1), i ++) { + for (int i = 0; i < dests.size(); i ++) { + CCwrapper tokenCond( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { dests[i] }) ); + //if (!CCtoAnon(tokenCond.get())) { std::cerr << __func__ << " CCtoAnon failed" << std::endl; continue; } // now in CCPubKey() + if (tokenCond == nullptr) continue; + tokenconds.push_back(tokenCond); + } + return tokenconds; +} + +// get all token indexkeys for pubkey for tokens mixed mode: +std::vector GetTokenV2IndexKeys(const CPubKey &pk) +{ + std::vector tokenindexkeys; + + std::vector tokenconds = GetTokenV2Conds(pk); + for (auto const &cond : tokenconds) { + char tokenindexkey[KOMODO_ADDRESS_BUFSIZE]; + CC_SUBVER ccSubVersion = (cc_typeMask(cond.get()) & (1 << CC_Secp256k1hash)) ? CC_MIXED_MODE_SECHASH_SUBVER_1 : CC_MIXED_MODE_SUBVER_0; + Getscriptaddress(tokenindexkey, CCPubKey(cond.get(), ccSubVersion)); + tokenindexkeys.push_back(tokenindexkey); + } + return tokenindexkeys; +} \ No newline at end of file diff --git a/src/cc/CCtokenutils.cpp b/src/cc/CCtokenutils.cpp index a1273841723..f7e205b53ef 100644 --- a/src/cc/CCtokenutils.cpp +++ b/src/cc/CCtokenutils.cpp @@ -529,50 +529,3 @@ uint8_t DecodeTokenOpretVersion(const CScript &scriptPubKey) } return version; } - -// get token indexkey for pubkey for old tokens: -std::vector GetTokenV1IndexKeys(const CPubKey &pk) -{ - std::vector tokenindexkeys; - char tokenindexkeyPK[KOMODO_ADDRESS_BUFSIZE]; - struct CCcontract_info *cp, C; - cp = CCinit(&C, EVAL_TOKENS); - - GetTokensCCaddress(cp, tokenindexkeyPK, pk, false); - tokenindexkeys.push_back(tokenindexkeyPK); - - return tokenindexkeys; -} - -// get conds from pubkey: -std::vector GetTokenV2Conds(const CPubKey &pk) -{ - std::vector tokenconds; - char normaladdr[KOMODO_ADDRESS_BUFSIZE]; - Getscriptaddress(normaladdr, CScript() << vuint8_t(pk.begin(), pk.end()) << OP_CHECKSIG); - std::vector dests{ CTxDestination(pk), DecodeDestination(normaladdr) }; - -// for (CC_SUBVER ccSubVersion = CC_MIXED_MODE_SUBVER_0; i < dests.size() && ccSubVersion <= CC_MIXED_MODE_SUBVER_MAX; ccSubVersion = (CC_SUBVER)(ccSubVersion + 1), i ++) { - for (int i = 0; i < dests.size(); i ++) { - CCwrapper tokenCond( MakeTokensv2CCcondMofNDest(EVAL_TOKENSV2, 0, 1, { dests[i] }) ); - //if (!CCtoAnon(tokenCond.get())) { std::cerr << __func__ << " CCtoAnon failed" << std::endl; continue; } // now in CCPubKey() - if (tokenCond == nullptr) continue; - tokenconds.push_back(tokenCond); - } - return tokenconds; -} - -// get all token indexkeys for pubkey for tokens mixed mode: -std::vector GetTokenV2IndexKeys(const CPubKey &pk) -{ - std::vector tokenindexkeys; - - std::vector tokenconds = GetTokenV2Conds(pk); - for (auto const &cond : tokenconds) { - char tokenindexkey[KOMODO_ADDRESS_BUFSIZE]; - CC_SUBVER ccSubVersion = (cc_typeMask(cond.get()) & (1 << CC_Secp256k1hash)) ? CC_MIXED_MODE_SECHASH_SUBVER_1 : CC_MIXED_MODE_SUBVER_0; - Getscriptaddress(tokenindexkey, CCPubKey(cond.get(), ccSubVersion)); - tokenindexkeys.push_back(tokenindexkey); - } - return tokenindexkeys; -} \ No newline at end of file From 0e25606a35ea0e9e6ad33ed388a33f236b82c4a6 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 28 Apr 2022 02:41:32 +0500 Subject: [PATCH 234/348] move importcoin.cpp to server lib --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index eaf19d755be..751c5a4e34c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -296,6 +296,7 @@ libbitcoin_server_a_SOURCES = \ cc/eval.cpp \ cc/import.cpp \ cc/importgateway.cpp \ + importcoin.cpp \ cc/CCassetsUtils.cpp \ cc/CCcustom.cpp \ cc/CCtx.cpp \ @@ -486,7 +487,6 @@ libbitcoin_common_a_SOURCES = \ crypto/verus_hash.h \ crypto/verus_hash.cpp \ hash.cpp \ - importcoin.cpp \ key.cpp \ key_io.cpp \ keystore.cpp \ From d311ffca83aa3b7ec90fddc993809c9cd8fd4f46 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 28 Apr 2022 02:53:38 +0500 Subject: [PATCH 235/348] more src rearrange to enable tools build --- src/Makefile.am | 2 +- src/cc/CCtokens.cpp | 11 ----------- src/cc/CCutilbits.cpp | 28 ++++++++++++++++++++++++++++ src/cc/CCutils.cpp | 16 +--------------- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 751c5a4e34c..eaf19d755be 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -296,7 +296,6 @@ libbitcoin_server_a_SOURCES = \ cc/eval.cpp \ cc/import.cpp \ cc/importgateway.cpp \ - importcoin.cpp \ cc/CCassetsUtils.cpp \ cc/CCcustom.cpp \ cc/CCtx.cpp \ @@ -487,6 +486,7 @@ libbitcoin_common_a_SOURCES = \ crypto/verus_hash.h \ crypto/verus_hash.cpp \ hash.cpp \ + importcoin.cpp \ key.cpp \ key_io.cpp \ keystore.cpp \ diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 2bffa0020aa..79d9c5b8774 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -29,17 +29,6 @@ thread_local uint32_t tokenValIndentSize = 0; // for debug logging // helper funcs: -// extract and compare addresses -bool IsEqualDestinations(const CScript &spk1, const CScript &spk2) -{ - char addr1[KOMODO_ADDRESS_BUFSIZE]; - char addr2[KOMODO_ADDRESS_BUFSIZE]; - if (Getscriptaddress(addr1, spk1) && Getscriptaddress(addr2, spk2)) - return strcmp(addr1, addr2) == 0; - else - return false; -} - // remove token->unspendablePk (it is only for marker usage) static void FilterOutTokensUnspendablePk(const std::vector &sourcePubkeys, std::vector &destPubkeys) { struct CCcontract_info *cpTokens, tokensC; diff --git a/src/cc/CCutilbits.cpp b/src/cc/CCutilbits.cpp index 240093fdd7b..67277bd365f 100644 --- a/src/cc/CCutilbits.cpp +++ b/src/cc/CCutilbits.cpp @@ -20,6 +20,34 @@ #include "CCinclude.h" #include "komodo_structs.h" +// get address for a scriptPubKey +bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey) +{ + CTxDestination address; txnouttype whichType; + destaddr[0] = 0; + if ( scriptPubKey.begin() != 0 ) + { + if ( ExtractDestination(scriptPubKey,address) != 0 ) + { + strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str()); + return(true); + } + } + //fprintf(stderr,"ExtractDestination failed\n"); + return(false); +} + +// extract and compare addresses +bool IsEqualDestinations(const CScript &spk1, const CScript &spk2) +{ + char addr1[KOMODO_ADDRESS_BUFSIZE]; + char addr2[KOMODO_ADDRESS_BUFSIZE]; + if (Getscriptaddress(addr1, spk1) && Getscriptaddress(addr2, spk2)) + return strcmp(addr1, addr2) == 0; + else + return false; +} + int32_t unstringbits(char *buf,uint64_t bits) { int32_t i; diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 89f6583b56e..ab8355eb708 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -239,21 +239,7 @@ void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, u strcpy(cp->tokens1of2addr, tokenaddr); } -bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey) -{ - CTxDestination address; txnouttype whichType; - destaddr[0] = 0; - if ( scriptPubKey.begin() != 0 ) - { - if ( ExtractDestination(scriptPubKey,address) != 0 ) - { - strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str()); - return(true); - } - } - //fprintf(stderr,"ExtractDestination failed\n"); - return(false); -} +// NOTE: bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey) moved to CCutilsbits.cpp to enable build komodo-tx tool bool GetCustomscriptaddress(char *destaddr,const CScript &scriptPubKey,uint8_t taddr,uint8_t prefix, uint8_t prefix2) { From f87e3c23d593849a7ade52e4ade6824001e2ca5c Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 18 Jan 2022 18:14:48 +0500 Subject: [PATCH 236/348] check if json from str is valid --- src/rpc/tokensrpc.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 93e9e7dc905..9f7c6565f06 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -466,8 +466,10 @@ UniValue tokencreatetokel(const UniValue& params, bool fHelp, const CPubKey& rem if (params[3].getType() == UniValue::VOBJ) jsonParams = params[3].get_array(); - else if (params[3].getType() == UniValue::VSTR) // json in quoted string '{...}' - jsonParams.read(params[3].get_str().c_str()); + else if (params[3].getType() == UniValue::VSTR) { // json in quoted string '{...}' + if (!jsonParams.read(params[3].get_str().c_str())) + return MakeResultError("parameter 4 must be a valid json object\n"); + } if (jsonParams.getType() != UniValue::VOBJ) throw runtime_error("parameter 4 must be a json object\n"); @@ -499,8 +501,10 @@ UniValue tokenv2createtokel(const UniValue& params, bool fHelp, const CPubKey& r if (params[3].getType() == UniValue::VOBJ) jsonParams = params[3].get_array(); - else if (params[3].getType() == UniValue::VSTR) // json in quoted string '{...}' - jsonParams.read(params[3].get_str().c_str()); + else if (params[3].getType() == UniValue::VSTR) { // json in quoted string '{...}' + if (!jsonParams.read(params[3].get_str().c_str())) + return MakeResultError("parameter 4 must be a valid json object\n"); + } if (jsonParams.getType() != UniValue::VOBJ) return MakeResultError("parameter 4 must be a json object\n"); From 2f6aff4b5598937b8c7ee96ff0dbdb94fe4d0833 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 31 Jan 2022 14:26:02 +0500 Subject: [PATCH 237/348] added chain for py asset test --- src/tui/tui_assets_orders.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index f6521015f56..0838ecd273f 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -80,10 +80,9 @@ def run_tokens_create(rpc1, rpc2, rpc3): # rpc3 = rpclib.rpc_connect("user972794450", "passe7eb16f5c015a53463cc5f27a004854cb76f4ec5c9aece177f01d8b3d13119e445", 16723) # DIMXY29 - # rpc1 = rpclib.rpc_connect("user977812407", "pass45a4a6ce9ffafbebd2a478d3858d55c8a4bded74632bb488c8c93164d048237516", 14723) - # rpc2 = rpclib.rpc_connect("user4228621419", "pass4e51de899bd15c12569d762ded036e5aecd5aeb7be40788a339e72e1fea7359d7e", 15723) - # rpc3 = rpclib.rpc_connect("user3877003389", "passea3e5a6c7a8a88f5447cc39bc8720cf783bbcef43345b16be9aadc0a1b381006eb", 16723) - + #rpc1 = rpclib.rpc_connect("user977812407", "pass45a4a6ce9ffafbebd2a478d3858d55c8a4bded74632bb488c8c93164d048237516", 14723) + #rpc2 = rpclib.rpc_connect("user4228621419", "pass4e51de899bd15c12569d762ded036e5aecd5aeb7be40788a339e72e1fea7359d7e", 15723) + #rpc3 = rpclib.rpc_connect("user3877003389", "passea3e5a6c7a8a88f5447cc39bc8720cf783bbcef43345b16be9aadc0a1b381006eb", 16723) ## for v in ["", "v2"] : ## for v in [""] : From d327c46aa17c3af19cb1373835455e0d24d0d0d9 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 31 Jan 2022 15:24:32 +0500 Subject: [PATCH 238/348] fixed getting req type in rate limiter --- src/komodo_nSPV_defs.h | 9 ++++++--- src/komodo_nSPV_fullnode.h | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 241cb8570c2..bd14bde5ddb 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -56,15 +56,18 @@ #define NSPV_MEMPOOLRESP 0x11 #define NSPV_CCMODULEUTXOS 0x12 #define NSPV_CCMODULEUTXOSRESP 0x13 +#define NSPV_REMOTERPC 0x14 +#define NSPV_REMOTERPCRESP 0x15 +#define NSPV_ERRORRESP 0xff +#define NSPV_MAX_REQ NSPV_REMOTERPC + #define NSPV_MEMPOOL_ALL 0 #define NSPV_MEMPOOL_ADDRESS 1 #define NSPV_MEMPOOL_ISSPENT 2 #define NSPV_MEMPOOL_INMEMPOOL 3 #define NSPV_MEMPOOL_CCEVALCODE 4 #define NSPV_CC_TXIDS 16 -#define NSPV_REMOTERPC 0x14 -#define NSPV_REMOTERPCRESP 0x15 -#define NSPV_ERRORRESP 0xff + #define NSPV_ERROR_INVALID_REQUEST_TYPE (-10) #define NSPV_ERROR_INVALID_REQUEST_DATA (-11) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 72485feeddb..4755a48049a 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -912,7 +912,7 @@ int32_t NSPV_getntzsproofresp(struct NSPV_ntzsproofresp* ntzproofp, uint256 next ntzproofp->nextntz = NSPV_getrawtx(tx, nextHashBlock, &ntzproofp->nexttxlen, ntzproofp->nexttxid); ntzproofp->nexttxidht = komodo_blockheight(nextHashBlock); if (NSPV_notarizationextract(DONTVALIDATESIG, &ntzproofp->common.nextht, &bhash1, &desttxid1, &momdepth, tx) < 0) { - LogPrintf("%s error: cant decode notarization opreturn ptr->common.nextht.%d bhash1 %s\n", __func__, ntzproofp->common.nextht, bhash1.ToString()); + LogPrintf("%s error: cant decode notarization opreturn nexttxid %s ptr->common.nextht.%d bhash1 %s\n", __func__, ntzproofp->nexttxid.GetHex(), ntzproofp->common.nextht, bhash1.ToString()); return (-5); } else if (komodo_blockheight(bhash1) != ntzproofp->common.nextht) { LogPrintf("%s error: bhash1 ht.%d not equal to nextht.%d\n", __func__, komodo_blockheight(bhash1), ntzproofp->common.nextht); @@ -991,7 +991,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re int32_t requestDataLen = request.size() - nspvHeaderSize; // rate limit no more NSPV_MAXREQSPERSEC request/sec of same type from same node: - int32_t idata = requestData[0] >> 1; + int32_t idata = requestType >> 1; if (idata >= sizeof(pfrom->nspvdata) / sizeof(pfrom->nspvdata[0])) idata = (int32_t)(sizeof(pfrom->nspvdata) / sizeof(pfrom->nspvdata[0])) - 1; if (pfrom->nspvdata[idata].prevtime > timestamp) { From 644e9aace91fd0d5b414fcfc2fa503df6febeef8 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 31 Jan 2022 15:25:07 +0500 Subject: [PATCH 239/348] help sendtoaddress fixed --- src/wallet/rpcwallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 94ff3319d92..95d356f83ac 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -524,7 +524,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) if (fHelp || params.size() < 2 || params.size() > 6) throw runtime_error( - "sendtoaddress \"" + strprintf("%s",komodo_chainname()) + "_address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount unlocktime )\n" + "sendtoaddress \"" + strprintf("%s", komodo_chainname()) + "_address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n" "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n" + HelpRequiringPassphrase() + "\nArguments:\n" @@ -544,7 +544,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1") + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"donation\" \"seans outpost\"") + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"\" \"\" true") -// test cltv: + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"donation\" \"seans outpost\" false \"\" 1634663625") + // test cltv: + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"donation\" \"seans outpost\" false \"\" 1634663625") + HelpExampleRpc("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.1, \"donation\", \"seans outpost\"") ); From aca3648426787c9535ea46f6a05a3ec38da7590a Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 1 Feb 2022 12:33:57 +0500 Subject: [PATCH 240/348] added websockets support (no tls) --- configure.ac | 18 ++++++++++++++++ depends/packages/openssl.mk | 6 +++--- depends/packages/packages.mk | 4 ++-- src/Makefile.am | 23 +++++++++++++++++++-- src/addrman.cpp | 32 +++++++++++++++++++++++++++++ src/addrman.h | 40 ++++++++++++++++++++++++++++++++++++ src/init.cpp | 14 +++++++++++++ src/main.cpp | 13 +++++++++++- src/net.cpp | 19 ++++++++++++++--- src/protocol.h | 2 ++ src/rpc/register.h | 8 +++++++- zcutil/build-mac.sh | 12 +++++++++-- zcutil/build-win.sh | 11 +++++++++- zcutil/build.sh | 13 ++++++++++-- 14 files changed, 198 insertions(+), 17 deletions(-) diff --git a/configure.ac b/configure.ac index 977bcc45c91..1d22cf5b9cd 100644 --- a/configure.ac +++ b/configure.ac @@ -195,6 +195,13 @@ AC_ARG_ENABLE([werror], [enable_werror=$enableval], [enable_werror=no]) +# Enable websockets listener +AC_ARG_ENABLE([websockets], + [AS_HELP_STRING([--enable-websockets], + [enable websockets (default is no)])], + [enable_websockets=$enableval], + [enable_websockets=no]) + AC_LANG_PUSH([C++]) AX_CHECK_COMPILE_FLAG([-Werror],[CXXFLAG_WERROR="-Werror"],[CXXFLAG_WERROR=""]) @@ -613,6 +620,15 @@ else AC_DEFINE(ENABLE_PROTON, 0, [Define to 1 to enable Proton functions]) fi +dnl enable websockets +AC_MSG_CHECKING([if websockets should be enabled]) +if test x$enable_websockets != xno; then + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED([ENABLE_WEBSOCKETS],[1],[Define to 1 to enable websockets listener]) +else + AC_MSG_RESULT(no) +fi + if test x$build_bitcoin_utils$build_bitcoind$use_tests = xnonono; then use_boost=no else @@ -906,6 +922,7 @@ AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes]) AM_CONDITIONAL([EXPERIMENTAL_ASM],[test x$experimental_asm = xyes]) AM_CONDITIONAL([ASAN],[test x$use_asan = xyes]) AM_CONDITIONAL([TSAN],[test x$use_tsan = xyes]) +AM_CONDITIONAL([ENABLE_WEBSOCKETS],[test x$enable_websockets = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) @@ -1037,6 +1054,7 @@ echo " with zmq = $use_zmq" echo " with test = $use_tests" echo " debug enabled = $enable_debug" echo " werror = $enable_werror" +echo " with websockets = $enable_websockets" echo echo " target os = $TARGET_OS" echo " build os = $BUILD_OS" diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk index 296a553894f..351735010d1 100644 --- a/depends/packages/openssl.mk +++ b/depends/packages/openssl.mk @@ -1,8 +1,8 @@ package=openssl -$(package)_version=1.1.1f +$(package)_version=1.1.1k $(package)_download_path=https://www.openssl.org/source $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=186c6bfe6ecfba7a5b48c47f8a1673d0f3b0e5ba2e25602dd23b629975da3f35 +$(package)_sha256_hash=892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5 define $(package)_set_vars $(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" @@ -62,7 +62,7 @@ $(package)_config_opts+=no-srtp $(package)_config_opts+=no-ssl3 $(package)_config_opts+=no-ssl3-method $(package)_config_opts+=no-ssl-trace -$(package)_config_opts+=no-stdio +# $(package)_config_opts+=no-stdio $(package)_config_opts+=no-tls1 $(package)_config_opts+=no-tls1-method $(package)_config_opts+=no-ts diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 1c1a506689f..88369698bce 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -47,8 +47,8 @@ native_packages := native_ccache wallet_packages=bdb ifeq ($(host_os),linux) - packages := boost openssl libevent zeromq $(zcash_packages) googletest libcurl #googlemock + packages := boost openssl libevent zeromq $(zcash_packages) googletest libcurl websocketspp #googlemock else - packages := boost openssl libevent zeromq $(zcash_packages) libcurl googletest #googlemock + packages := boost openssl libevent zeromq $(zcash_packages) libcurl googletest websocketspp #googlemock endif diff --git a/src/Makefile.am b/src/Makefile.am index eaf19d755be..12253ecfa7b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -120,6 +120,9 @@ endif lib_LTLIBRARIES = $(LIBZCASH_CONSENSUS) +LIBSSLSTATIC = $(abs_builddir)/../depends/$(host)/lib/libssl.a +LIBCRYPTOSTATIC = $(abs_builddir)/../depends/$(host)/lib/libcrypto.a + bin_PROGRAMS = noinst_PROGRAMS = TESTS = @@ -275,6 +278,9 @@ BITCOIN_CORE_H = \ zmq/zmqnotificationinterface.h \ zmq/zmqpublishnotifier.h +if ENABLE_WEBSOCKETS + BITCOIN_CORE_H += komodo_websockets.h +endif obj/build.h: FORCE @$(MKDIR_P) $(builddir)/obj @@ -367,6 +373,10 @@ libbitcoin_server_a_SOURCES = \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) +if ENABLE_WEBSOCKETS + libbitcoin_server_a_SOURCES += komodo_websockets.cpp +endif + if ENABLE_ZMQ libbitcoin_zmq_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(ZMQ_CFLAGS) libbitcoin_zmq_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -588,8 +598,6 @@ endif komodod_LDADD += \ $(BOOST_LIBS) \ $(BDB_LIBS) \ - $(SSL_LIBS) \ - $(CRYPTO_LIBS) \ $(EVENT_PTHREADS_LIBS) \ $(EVENT_LIBS) \ $(ZMQ_LIBS) \ @@ -601,6 +609,17 @@ komodod_LDADD += \ komodod_LDADD += $(LIBDYNCUSTOMCONSENSUS) $(LIBSECP256K1) +if ENABLE_WEBSOCKETS +# link statically openssl +komodod_LDADD += \ + $(LIBSSLSTATIC) \ + $(LIBCRYPTOSTATIC) +else +komodod_LDADD += \ + $(SSL_LIBS) \ + $(CRYPTO_LIBS) +endif + if ENABLE_PROTON komodod_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) endif diff --git a/src/addrman.cpp b/src/addrman.cpp index 10c011028f2..2fe50f7eedf 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -513,6 +513,38 @@ void CAddrMan::GetAddr_(std::vector& vAddr) } } +#ifdef ENABLE_WEBSOCKETS +// get no more than N addresses for clients (do not use 23% limit assuming there are no many websockets listeners in the net) +void CAddrMan::GetAddrAtMost_(std::vector& vAddr) +{ + unsigned int nNodes = vRandom.size(); + if (nNodes > 1000) // actually MAX_ADDR_TO_SEND + nNodes = 1000; + + // gather a list of random nodes, skipping those of low quality + for (unsigned int n = 0; n < vRandom.size(); n++) { + if (vAddr.size() >= nNodes) + break; + + int nRndPos = RandomInt(vRandom.size() - n) + n; + SwapRandom(n, nRndPos); + assert(mapInfo.count(vRandom[n]) == 1); + + const CAddrInfo& ai = mapInfo[vRandom[n]]; + if (!ai.IsTerrible()) + vAddr.push_back(ai); + } +} + +// get all addrinfo for printing +void CAddrMan::GetAddrInfoAll_(std::vector& vAddrInfo) +{ + for (auto const i : mapInfo) { + vAddrInfo.push_back(i.second); + } +} +#endif + void CAddrMan::Connected_(const CService& addr, int64_t nTime) { CAddrInfo* pinfo = Find(addr); diff --git a/src/addrman.h b/src/addrman.h index 1385ac8090f..e8925c7cd5f 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -266,6 +266,12 @@ friend class CAddrManTest; //! Select several addresses at once. void GetAddr_(std::vector &vAddr); +#ifdef ENABLE_WEBSOCKETS + //! Actual function to select several at most N addresses at once. + void GetAddrAtMost_(std::vector &vAddr); + void GetAddrInfoAll_(std::vector &vAddrInfo); +#endif + //! Mark an entry as currently-connected-to. void Connected_(const CService &addr, int64_t nTime); @@ -639,6 +645,40 @@ friend class CAddrManTest; return vAddr; } +#ifdef ENABLE_WEBSOCKETS + //! Return at most N addresses, selected at random. + std::vector GetAddrAtMost() + { + Check(); + std::vector vAddr; + { + LOCK(cs); + GetAddrAtMost_(vAddr); + } + Check(); + return vAddr; + } + + //! Return all addrinfo. + std::vector GetAddrInfoAll() + { + Check(); + std::vector vAddrInfo; + { + LOCK(cs); + GetAddrInfoAll_(vAddrInfo); + } + Check(); + return vAddrInfo; + } + + // for debugging: access to addrinfo private member + CNetAddr GetSource(CAddrInfo addrInfo) + { + return addrInfo.source; + } +#endif + //! Mark an entry as currently-connected-to. void Connected(const CService &addr, int64_t nTime = GetTime()) { diff --git a/src/init.cpp b/src/init.cpp index b2c796224e1..da1fa68c461 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -91,6 +91,10 @@ #include "librustzcash.h" +#ifdef ENABLE_WEBSOCKETS +#include "komodo_websockets.h" +#endif + using namespace std; #include "komodo_defs.h" @@ -223,6 +227,9 @@ void Shutdown() mempool.AddTransactionsUpdated(1); StopHTTPRPC(); +#ifdef ENABLE_WEBSOCKETS + StopWebSockets(); +#endif StopREST(); StopRPC(); StopHTTPServer(); @@ -902,6 +909,10 @@ bool AppInitServers(boost::thread_group& threadGroup) return false; if (!StartHTTPRPC()) return false; +#ifdef ENABLE_WEBSOCKETS + if (!StartWebSockets(threadGroup)) + return false; +#endif if (GetBoolArg("-rest", false) && !StartREST()) return false; if (!StartHTTPServer()) @@ -2082,6 +2093,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 11: finished SetRPCWarmupFinished(); +#ifdef ENABLE_WEBSOCKETS + SetWebSocketsWarmupFinished(); +#endif uiInterface.InitMessage(_("Done loading")); #ifdef ENABLE_WALLET diff --git a/src/main.cpp b/src/main.cpp index dae4617f671..afd2273b5c6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -66,6 +66,10 @@ #include #include +#ifdef ENABLE_WEBSOCKETS +#include "komodo_websockets.h" +#endif + using namespace std; #if defined(NDEBUG) @@ -8592,7 +8596,14 @@ bool ProcessMessages(CNode* pfrom) bool fRet = false; try { - fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime); + +#ifdef ENABLE_WEBSOCKETS + if (pfrom->hSocket != INVALID_SOCKET || !(fRet = ProcessWsMessage(pfrom, strCommand, vRecv, msg.nTime))) { +#endif + fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime); +#ifdef ENABLE_WEBSOCKETS + } +#endif boost::this_thread::interruption_point(); } catch (const std::ios_base::failure& e) diff --git a/src/net.cpp b/src/net.cpp index a291c5df04f..cbe97c98be8 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1439,6 +1439,13 @@ void ThreadOpenConnections() if (!addr.IsValid() || setConnected.count(addr.GetGroup(addrman.m_asmap)) || IsLocal(addr)) break; +#ifdef ENABLE_WEBSOCKETS + // do not connect to client nodes (looks like this should be added for non-websocket version too): + if ((addr.nServices & NODE_NETWORK) == 0) { + continue; + } +#endif + // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman, // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates // already-connected network ranges, ...) before trying new addrman addresses. @@ -2262,9 +2269,15 @@ void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend) ssSend.GetAndClear(*it); nSendSize += (*it).size(); - // If write queue empty, attempt "optimistic write" - if (it == vSendMsg.begin()) - SocketSendData(this); +#ifdef ENABLE_WEBSOCKETS + if (this->hSocket != INVALID_SOCKET) { +#endif + // If write queue empty, attempt "optimistic write" + if (it == vSendMsg.begin()) + SocketSendData(this); +#ifdef ENABLE_WEBSOCKETS + } +#endif LEAVE_CRITICAL_SECTION(cs_vSend); } diff --git a/src/protocol.h b/src/protocol.h index b7ad483ace2..239fb79a746 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -102,6 +102,8 @@ enum { // collisions and other cases where nodes may be advertising a service they // do not actually support. Other service bits should be allocated via the // BIP process. + + NODE_WEBSOCKETS = (1 << 31) // nspv listening on websockets }; /** A CService with information about it as peer */ diff --git a/src/rpc/register.h b/src/rpc/register.h index 829143591a5..aebb427327e 100644 --- a/src/rpc/register.h +++ b/src/rpc/register.h @@ -38,7 +38,10 @@ void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC); void RegisterTokensRPCCommands(CRPCTable &tableRPC); // cc utils rpcs: void RegisterCCUtilsRPCCommands(CRPCTable &tableRPC); - +#ifdef ENABLE_WEBSOCKETS +// websockets helper rpcs +void RegisterWebSocketsRPCCommands(CRPCTable &tableRPC); +#endif static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC) { @@ -49,6 +52,9 @@ static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC) RegisterRawTransactionRPCCommands(tableRPC); RegisterTokensRPCCommands(tableRPC); RegisterCCUtilsRPCCommands(tableRPC); +#ifdef ENABLE_WEBSOCKETS + RegisterWebSocketsRPCCommands(tableRPC); +#endif } #endif diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index 825b49d8eb3..d19d8d6a54f 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -23,7 +23,7 @@ Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov ] [ --enable-debug ] [ MAKEARGS... ] +$0 [ --enable-lcov ] [ --enable-debug ] [ --enable-websockets ] [ MAKEARGS... ] Build Komodo and most of its transitive dependencies from source. MAKEARGS are applied to both dependencies and Komodo itself. If --enable-lcov is passed, Komodo is configured to add coverage @@ -54,6 +54,14 @@ then shift fi +# If --enable-websockets is the next argument, enable websockets support for nspv clients: +WEBSOCKETS_ARG='' +if [ "x${1:-}" = 'x--enable-websockets' ] +then +WEBSOCKETS_ARG='--enable-websockets=yes' +shift +fi + TRIPLET=`./depends/config.guess` PREFIX="$(pwd)/depends/$TRIPLET" @@ -62,7 +70,7 @@ make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ -./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" "$DEBUGGING_ARG" \ +./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$CONFIGURE_FLAGS" "$WEBSOCKETS_ARG" "$DEBUGGING_ARG" \ --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index 297fb9d7b20..b625b26f534 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -10,6 +10,15 @@ UTIL_DIR="$(dirname "$(readlink -f "$0")")" BASE_DIR="$(dirname "$(readlink -f "$UTIL_DIR")")" PREFIX="$BASE_DIR/depends/$HOST" + +# If --enable-websockets is the next argument, enable websockets support for nspv clients: +WEBSOCKETS_ARG='' +if [ "x${1:-}" = 'x--enable-websockets' ] +then +WEBSOCKETS_ARG='--enable-websockets=yes' +shift +fi + # make dependences cd depends/ && make HOST=$HOST V=1 NO_QT=1 cd ../ @@ -19,7 +28,7 @@ make HOST=$HOST NO_QT=1 "$@" cd $BASE_DIR ./autogen.sh -CONFIG_SITE=$BASE_DIR/depends/$HOST/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix=$PREFIX --host=$HOST --enable-static --disable-shared \ +CONFIG_SITE=$BASE_DIR/depends/$HOST/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix=$PREFIX --host=$HOST --enable-static --disable-shared "$WEBSOCKETS_ARG" \ --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' diff --git a/zcutil/build.sh b/zcutil/build.sh index 5b0399ef654..2c590f9ea72 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -44,7 +44,7 @@ then Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [ --enable-debug ] [ MAKEARGS... ] +$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [ --enable-debug ] [--enable-websockets] [ MAKEARGS... ] Build Komodo and most of its transitive dependencies from source. MAKEARGS are applied to both dependencies and Komodo itself. If --enable-lcov is passed, Komodo is configured to add coverage @@ -55,6 +55,7 @@ $0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] If --enable-proton is passed, Komodo is configured to build the Apache Qpid Proton library required for AMQP support. This library is not built by default. It must be passed after the test/mining arguments, if present. + If --enable-websockets is passed, Komodo is configured to build with webspckets support for nspv protocol EOF exit 0 fi @@ -108,6 +109,14 @@ else VERBOSITY="--disable-silent-rules" fi +# If --enable-websockets is the next argument, enable websockets support for nspv clients: +WEBSOCKETS_ARG='' +if [ "x${1:-}" = 'x--enable-websockets' ] +then +WEBSOCKETS_ARG='--enable-websockets=yes' +shift +fi + eval "$MAKE" --version as --version ld -v @@ -115,7 +124,7 @@ ld -v HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh -CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$DEBUGGING_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' \ +CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$DEBUGGING_ARG" "$CONFIGURE_FLAGS" "$WEBSOCKETS_ARG" CXXFLAGS='-g' \ --with-custom-bin=yes CUSTOM_BIN_NAME=tokel CUSTOM_BRAND_NAME=Tokel \ CUSTOM_SERVER_ARGS="'-ac_name=TOKEL -ac_supply=100000000 -ac_eras=2 -ac_cbmaturity=1 -ac_reward=100000000,4250000000 -ac_end=80640,0 -ac_decay=0,77700000 -ac_halving=0,525600 -ac_cc=555 -ac_ccenable=236,245,246,247 -ac_adaptivepow=6 -addnode=135.125.204.169 -addnode=192.99.71.125 -nspv_msg=1'" \ CUSTOM_CLIENT_ARGS='-ac_name=TOKEL' From dc888d8af6164c1c349e7445d83488675e41f103 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 2 Feb 2022 20:13:19 +0500 Subject: [PATCH 241/348] websockets src and lib added --- depends/packages/websocketspp.mk | 11 + src/komodo_websockets.cpp | 1673 ++++++++++++++++++++++++++++++ src/komodo_websockets.h | 71 ++ 3 files changed, 1755 insertions(+) create mode 100644 depends/packages/websocketspp.mk create mode 100644 src/komodo_websockets.cpp create mode 100644 src/komodo_websockets.h diff --git a/depends/packages/websocketspp.mk b/depends/packages/websocketspp.mk new file mode 100644 index 00000000000..0e1bfa03c14 --- /dev/null +++ b/depends/packages/websocketspp.mk @@ -0,0 +1,11 @@ +package=websocketpp +$(package)_version=0.8.2 +$(package)_download_path=https://github.com/zaphoyd/websocketpp/archive +$(package)_file_name=$(package)-$($(package)_version).tar.gz +$(package)_sha256_hash=6ce889d85ecdc2d8fa07408d6787e7352510750daa66b5ad44aacb47bea76755 +$(package)_download_file=$($(package)_version).tar.gz + +define $(package)_stage_cmds + mkdir $($(package)_staging_dir)$(host_prefix)/include && \ + cp -a ./websocketpp $($(package)_staging_dir)$(host_prefix)/include +endef diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp new file mode 100644 index 00000000000..1f368c5df50 --- /dev/null +++ b/src/komodo_websockets.cpp @@ -0,0 +1,1673 @@ +// Copyright (c) 2020 The SuperNet developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +// websockets support for komodod +// based on websocketspp library +// introduces new commands getwsaddr/wsaddr to get list of websockets listener +// to build ws listener table a object of CAddrMan is used, wsaddrman +// generally the same protocol is used like for the original p2p addrman: +// + + +//#include "httpserver.h" +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "timedata.h" +#include "main.h" +#include "consensus/validation.h" +#include "util.h" +#include "net.h" +#include "addrman.h" +#include "sync.h" +#include "utilstrencodings.h" +#include "univalue.h" +#include "rpc/server.h" + +//#include + +#ifndef ENABLE_WEBSOCKETS +#error "ENABLE_WEBSOCKETS not defined" +#endif + +#include "komodo_websockets.h" + +static CAddrMan wsaddrman; + +static bool bWebSocketsStarted = false; +static bool fWebSocketsInWarmup = true; +static bool fWebSocketsStopping = false; + +static CCriticalSection cs_wsWarmup; + +static CSemaphore *semWsOutbound = NULL; +static boost::condition_variable wsMessageHandlerCondition; + + +static std::set setservAddNodeWsAddresses; +static CCriticalSection cs_setservAddNodeWsAddresses; + +static std::vector vAddedWsNodes; +static CCriticalSection cs_vAddedWsNodes; + +typedef websocketpp::lib::shared_ptr ws_thread_ptr; +static std::vector vWsThreads; + +static boost::thread_group wsThreadGroup; + +unsigned short GetWebSocketListenPort() +{ + return (unsigned short)(GetArg("-wsport", 8192)); +} + +CAddress GetLocalWebSocketAddress(const CNetAddr *paddrPeer) +{ + CAddress ret(CService("0.0.0.0", GetWebSocketListenPort()), 0); + // TODO: decide if we need websocket listeners bound to specific local address (not 0.0.0.0) + CService addr; + if (GetLocal(addr, paddrPeer)) + { + ret = CAddress(addr); + } + ret.nServices = NODE_NETWORK | NODE_WEBSOCKETS; + ret.nTime = GetTime(); + return ret; +} + +// advertizes websockets listen address +void AdvertizeLocalWebSockets(CNode *pnode) +{ + if (/*fListen && <-- TODO: add this flag*/ pnode->fSuccessfullyConnected) + { + CAddress addrLocal = GetLocalWebSocketAddress(&pnode->addr); + // If discovery is enabled, sometimes give our peer the address it + // tells us that it sees us as in case it has a better idea of our + // address than we do. + if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() || + GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0)) + { + addrLocal.SetIP(pnode->addrLocal); + } + if (addrLocal.IsRoutable()) + { + LogPrintf("AdvertizeLocalWebSockets: advertizing local websocket address %s for peer %d\n", addrLocal.ToString(), pnode->id); + pnode->PushAddress(addrLocal); + } + } +} + +class CWsNode; + +// base wrapper class both for server and outbound endpoints +class CWsEndpointWrapper { +public: + CWsEndpointWrapper() {} + virtual void send(websocketpp::connection_hdl hdl, void const * payload, size_t len, + websocketpp::frame::opcode::value op, websocketpp::lib::error_code & ec) = 0; + + virtual void close(websocketpp::connection_hdl hdl, websocketpp::close::status::value) = 0; + virtual void sendWsData(CWsNode *pNode) = 0; +}; + +typedef std::shared_ptr ws_endpoint_ptr; +static ws_endpoint_ptr spWebSocketServer; + +class CWsNode : public CNode { +public: + CWsNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false) + : CNode(hSocketIn, addrIn, addrNameIn, fInboundIn) + { + closeErrorOnSend = 0; + closeErrorOnReceive = 0; + nLastRebroadcast = 0; + } + + websocketpp::connection_hdl m_hdl; + ws_endpoint_ptr m_spWsEndpoint; + websocketpp::close::status::value closeErrorOnSend; + websocketpp::close::status::value closeErrorOnReceive; + int64_t nLastRebroadcast; // for rebroacasting local address + + void PushWsVersion() + { + int nBestHeight = GetNodeSignals().GetHeight().get_value_or(0); + + int64_t nTime = (fInbound ? GetTime() : GetTime()); + CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0))); + CAddress addrMe = GetLocalWebSocketAddress(&addr); + GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); + if (fLogIPs) + LogPrint("websockets", "send websocket version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id); + else + LogPrint("websockets", "send websocket version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id); + PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, + nLocalHostNonce, strSubVersion, nBestHeight, true); + } + + ~CWsNode() { + wsaddrman.Connected(addr); + } +}; + +typedef std::shared_ptr CWsNodePtr; +static std::vector vWsNodes; // websocket own node list +static CCriticalSection cs_vWsNodes; + +static std::set vWsNodesDisconnected; // websocket disconnected nodes +static CCriticalSection cs_vWsNodesDisconnected; + +class CWebSocketOutbound; +static std::vector vOutboundEndpoints; // wait until enpoint opens +static CCriticalSection cs_vOutboundEndpoints; + +static CWsNodePtr FindWsNode(const CNetAddr& ip) +{ + LOCK(cs_vWsNodes); + for(auto const & pnode : vWsNodes) + if ((CNetAddr)pnode->addr == ip) + return (pnode); + return NULL; +} + +static CWsNodePtr FindWsNode(const CSubNet& subNet) +{ + LOCK(cs_vWsNodes); + for(auto const & pnode : vWsNodes) + if (subNet.Match((CNetAddr)pnode->addr)) + return (pnode); + return NULL; +} + +static CWsNodePtr FindWsNode(const std::string& addrName) +{ + LOCK(cs_vWsNodes); + for(auto const & pnode : vWsNodes) + if (pnode->addrName == addrName) + return (pnode); + return NULL; +} + +static CWsNodePtr FindWsNode(const CService& addr) +{ + LOCK(cs_vWsNodes); + for(auto const & pnode : vWsNodes) + if ((CService)pnode->addr == addr) + return (pnode); + return NULL; +} + + +static void RemoveWsNode(CWsNodePtr pNode) +{ + AssertLockHeld(cs_vWsNodes); + vWsNodes.erase(std::remove(vWsNodes.begin(), vWsNodes.end(), pNode), vWsNodes.end()); + LOCK(cs_vWsNodesDisconnected); + vWsNodesDisconnected.insert(pNode); +} + +// returns true if message was recognized +bool ProcessWsMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, int64_t nTimeReceived) +{ + + if (strCommand == "version") + { + // Each connection can only send one version message + if (pfrom->nVersion != 0) + { + pfrom->PushMessage("reject", strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")); + Misbehaving(pfrom->GetId(), 1); + return false; + } + + int64_t nTime; + CAddress addrMe; + CAddress addrFrom; + uint64_t nNonce = 1; + int nVersion; // use temporary for version, don't set version number until validated as connected + int minVersion = MIN_PEER_PROTO_VERSION; + + //if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 ) + // minVersion = STAKEDMIN_PEER_PROTO_VERSION; + vRecv >> nVersion >> pfrom->nServices >> nTime >> addrMe; + if (nVersion == 10300) + nVersion = 300; + if (nVersion < minVersion) + { + // disconnect from peers older than this proto version + LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion); + pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, + strprintf("Version must be %d or greater", minVersion)); + pfrom->fDisconnect = true; + return false; + } + + // not relevant to websockets: + // Reject incoming connections from nodes that don't know about the current epoch + /*const Consensus::Params& params = Params().GetConsensus(); + auto currentEpoch = CurrentEpoch(GetHeight(), params); + if (nVersion < params.vUpgrades[currentEpoch].nProtocolVersion) + { + LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, nVersion); + pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, + strprintf("Version must be %d or greater", + params.vUpgrades[currentEpoch].nProtocolVersion)); + pfrom->fDisconnect = true; + return false; + }*/ + + if (!vRecv.empty()) + vRecv >> addrFrom >> nNonce; + if (!vRecv.empty()) { + vRecv >> LIMITED_STRING(pfrom->strSubVer, MAX_SUBVERSION_LENGTH); + pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer); + } + if (!vRecv.empty()) + vRecv >> pfrom->nStartingHeight; + + // not relevant to websockets: + /* if (!vRecv.empty()) + vRecv >> pfrom->fRelayTxes; // set to true after we get the first filter* message + else + pfrom->fRelayTxes = true;*/ + + // Disconnect if we connected to ourself + if (nNonce == nLocalHostNonce && nNonce > 1) + { + LogPrintf("websockets connected to self at %s, disconnecting\n", pfrom->addr.ToString()); + pfrom->fDisconnect = true; + return true; + } + + pfrom->nVersion = nVersion; + + pfrom->addrLocal = addrMe; + if (pfrom->fInbound && addrMe.IsRoutable()) + { + // SeenLocal(addrMe); // TODO: better not to influence the main p2p net + } + + // Be shy and don't send version until we hear + if (pfrom->fInbound) + static_cast(pfrom)->PushWsVersion(); + + pfrom->fClient = !(pfrom->nServices & NODE_NETWORK); + + // not relevant to websockets + // Potentially mark this peer as a preferred download peer. + //UpdatePreferredDownload(pfrom, State(pfrom->GetId())); + + // Change version + pfrom->PushMessage("verack"); + pfrom->ssSend.SetVersion(std::min(pfrom->nVersion, PROTOCOL_VERSION)); + + if (!pfrom->fInbound) + { + + // Advertise our ws address + // but only if this node connected to remote (outbound) nodes + // note that because of that a listening node does not advertise its local address on "version" cmd + // also the outbound node will get back its local white address only on the next addr message + // the outbound node will get the next "wsaddr" on "getwsaddr" response + // (note that the first "getaddr" for the first outbound will return none as no any advertised local addr yet on the listening node) + // plus "wsaddr" cmd is sent in SendMessages will also have a empty address list to send + // Note, that "addrMe" from a remote node from "version" is not added to AddrLocal + if (!IsInitialBlockDownload()) // TODO: isWebsocketStarted + { + // get best real local websocket listening address (known outside) and advertize it + CAddress addr = GetLocalWebSocketAddress(&pfrom->addr); + if (addr.IsRoutable()) + { + LogPrintf("%s: advertizing local websocket address %s for peer %d (from local)\n", __func__, addr.ToString(), pfrom->GetId()); + pfrom->PushAddress(addr); + } else if (IsPeerAddrLocalGood(pfrom)) { + addr.SetIP(pfrom->addrLocal); + LogPrintf("%s: advertizing local websocket address %s for peer %d (from node)\n", __func__, addr.ToString(), pfrom->GetId()); + pfrom->PushAddress(addr); + } + } + else + { + LogPrint("websockets", "note: websockets local address advertising skipped: IsInitialBlockDownload()=%d\n", IsInitialBlockDownload()); + } + + // Get recent websocket addresses + if (pfrom->fOneShot || pfrom->nVersion >= WSADDR_VERSION || wsaddrman.size() < 1000) + { + LogPrint("websockets", "pushing getwsaddr request for peer=%d\n", pfrom->GetId()); + pfrom->PushMessage("getwsaddr"); + } + wsaddrman.Good(pfrom->addr); + } + else + { + std::cerr << __func__ << " version from inbound pfrom->addr=" << pfrom->addr.ToStringIPPort() << " (CNetAddr)pfrom->addr=" << ((CNetAddr)pfrom->addr).ToString() << " (CNetAddr)addrFrom=" << ((CNetAddr)addrFrom).ToString() << std::endl; + if (((CNetAddr)pfrom->addr) == (CNetAddr)addrFrom) + { + LogPrint("websockets", " storing in wsaddrman inbound pfrom->addr=%s\n", pfrom->addr.ToStringIPPort()); + wsaddrman.Add(addrFrom, addrFrom); + wsaddrman.Good(addrFrom); + } + // can't add here remote wsaddr for the node as we dont know the websocket port (as it is not contained in the version message and we have not extended it) + } + + LogPrint("websockets", "websockets version received: from addr=%s peer=%d\n", pfrom->addr.ToStringIPPort(), pfrom->id); + pfrom->fSuccessfullyConnected = true; + return true; + } + + // websocket nodes propagation + else if (strCommand == "wsaddr") + { + std::vector vAddr; + vRecv >> vAddr; + + LogPrint("websockets", "cmd \"wsaddr\" received, vWsaddr.size=%d from peer=%d\n", vAddr.size(), pfrom->id); + + // Don't want wsaddr from older versions + if (pfrom->nVersion < WSADDR_VERSION) { + LogPrintf("version too old for wsaddr %d peer %d", pfrom->nVersion, pfrom->GetId()); + return true; + } + + if (wsaddrman.size() > 1000) { + LogPrintf("websockets addrman full, don't accept wsaddr from peer %d", pfrom->GetId()); + return true; + } + + if (vAddr.size() > 1000) { + LogPrintf("websockets node misbehaving, message wsaddr size() = %u peer %d", vAddr.size(), pfrom->GetId()); + Misbehaving(pfrom->GetId(), 20); + return true; + } + + // Store the new addresses + std::vector vAddrOk; + int64_t nNow = GetTime(); + int64_t nSince = nNow - 10 * 60; + BOOST_FOREACH(CAddress& addr, vAddr) + { + boost::this_thread::interruption_point(); + + if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60) + addr.nTime = nNow - 5 * 24 * 60 * 60; + pfrom->AddAddressKnown(addr); + bool fReachable = IsReachable(addr); + if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable()) + { + // Relay to a limited number of other nodes + { + LOCK(cs_vWsNodes); + // Use deterministic randomness to send to the same ws nodes for 24 hours + // at a time so the wsaddrKnowns of the chosen nodes prevent repeats + static uint256 hashSalt; + if (hashSalt.IsNull()) + hashSalt = GetRandHash(); + uint64_t hashAddr = addr.GetHash(); + uint256 hashRand = ArithToUint256(UintToArith256(hashSalt) ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/(24*60*60))); + hashRand = Hash(BEGIN(hashRand), END(hashRand)); + std::multimap mapMix; + for(auto const & pnode : vWsNodes) + { + if (pnode->nVersion >= WSADDR_VERSION && (pnode->nServices & NODE_WEBSOCKETS) != 0) // should be relayed to any node supporting "wsaddr" + { + unsigned int nPointer; + memcpy(&nPointer, &pnode, sizeof(nPointer)); + uint256 hashKey = ArithToUint256(UintToArith256(hashRand) ^ nPointer); + hashKey = Hash(BEGIN(hashKey), END(hashKey)); + mapMix.insert(std::make_pair(hashKey, pnode)); + } + } + int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s) + for (std::multimap::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) { + LogPrint("websockets"," relaying ws address=%s to peer=%d\n", addr.ToStringIPPort(), ((*mi).second)->GetId()); + ((*mi).second)->PushAddress(addr); + } + } + } + // Do not store addresses outside our network + if (fReachable) { + vAddrOk.push_back(addr); + LogPrint("websockets", "cmd \"wsaddr\": adding to wsaddrman addr=%s from peer=%d\n", addr.ToString(), pfrom->id); + } + else + LogPrint("websockets", "cmd \"wsaddr\": not reachable addr=%s from peer=%d\n", addr.ToString(), pfrom->id); + } + wsaddrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60); + + if (vAddr.size() < 1000) + pfrom->fGetAddr = false; + return true; + } + + else if ((strCommand == "getwsaddr") && (pfrom->fInbound)) // allow to getwsaddr for clients and newly connected nodes to initialize their addrman + { + // comment to allow multiply requests for nspv clients: + // ----- + // Only send one getaddr response per connection to reduce resource waste + // and discourage addr stamping of INV announcements. + //if (pfrom->fSentAddr) { + // LogPrint("net", "Ignoring repeated \"getwsaddr\". peer=%d\n", pfrom->id); + // return true; + //} + //pfrom->fSentAddr = true; + //pfrom->sentAddrTime = GetTime(); + // ------ + + pfrom->vAddrToSend.clear(); + std::vector vWsaddr = wsaddrman.GetAddrAtMost(); + LogPrint("websockets", "received getwsaddr cmd, found vAddr.size=%s from peer=%d\n", vWsaddr.size(), pfrom->GetId()); + BOOST_FOREACH(const CAddress &addr, vWsaddr) { + LogPrint("websockets", "in response to getwsaddr pushing wsaddr=%s\n", addr.ToString()); + pfrom->PushAddress(addr); + } + return true; + } + + return false; +} + +// create periodical messages +bool SendWsMessages(CWsNode *pto, bool fTrickle) +{ + + if (pto->nVersion == 0) + return true; + + // Address refresh broadcast + static int64_t nLastRebroadcast; + //MilliSleep(1000); + int64_t nCurrentTime = GetTime(); + if (nCurrentTime - nLastRebroadcast > 60) // check every 60 sec + { + // for the node clear known addresses each 24h and advertize local ws listener address + LOCK(cs_vWsNodes); + for(auto const pnode : vWsNodes) + { + if (nCurrentTime - pnode->nLastRebroadcast > 24 * 60 * 60) { // rebroadcast to each node each 24h + pnode->addrKnown.reset(); + AdvertizeLocalWebSockets(pnode.get()); + pnode->nLastRebroadcast = nCurrentTime; + } + } + nLastRebroadcast = nCurrentTime; + } + + if (fTrickle) + { + // if there are addresses to send for this node send them + std::vector vAddr; + vAddr.reserve(pto->vAddrToSend.size()); + for(const CAddress& addr : pto->vAddrToSend) + { + if (!pto->addrKnown.contains(addr.GetKey())) + { + pto->AddAddressKnown(addr); + vAddr.push_back(addr); + LogPrint("websockets", "sending message with ws address=%s to peer=%d\n", addr.ToStringIPPort(), pto->GetId()); + // receiver rejects addr messages larger than 1000 + if (vAddr.size() >= 1000) + { + pto->PushMessage("wsaddr", vAddr); + LogPrint("websockets", "sent %d websocket addresses to peer %d\n", vAddr.size(), pto->id); + vAddr.clear(); + } + } + } + pto->vAddrToSend.clear(); + if (!vAddr.empty()) { + pto->PushMessage("wsaddr", vAddr); + LogPrint("websockets", "sent %d websocket addresses to peer %d\n", vAddr.size(), pto->id); + } + } + + return true; +} + + +// requires LOCK(cs_vSend) +void WebSocketSendData(CWsEndpointWrapper *pEndPoint, websocketpp::connection_hdl hdl, CWsNode *pnode) +{ + std::deque::iterator it = pnode->vSendMsg.begin(); + pnode->closeErrorOnSend = 0; + + while (it != pnode->vSendMsg.end()) { + const CSerializeData &data = *it; + assert(data.size() > pnode->nSendOffset); + websocketpp::lib::error_code ec; + int nBytes = data.size() - pnode->nSendOffset; + pEndPoint->send(hdl, &data[pnode->nSendOffset], nBytes, websocketpp::frame::opcode::binary, ec); // should not throw ws exception as ec is passed + + if (!ec) { + pnode->nLastSend = GetTime(); // needed to prevent inactivity disconnect + pnode->nSendBytes += nBytes; + pnode->nSendOffset += nBytes; + pnode->RecordBytesSent(nBytes); + if (pnode->nSendOffset == data.size()) { + pnode->nSendOffset = 0; + pnode->nSendSize -= data.size(); + it++; + } else { + // could not send full message; stop sending more + break; + } + } else { // error + // int nErr = WSAGetLastError(); + // if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) // no similar errs in websocketpp... + { + LogPrint("websockets", "websocket send error %d %s\n", ec.value(), ec.category().name()); + pnode->closeErrorOnSend = websocketpp::close::status::try_again_later; + pnode->fDisconnect; + } + // couldn't send anything at all + break; + } + } + + if (it == pnode->vSendMsg.end()) { + assert(pnode->nSendOffset == 0); + assert(pnode->nSendSize == 0); + } + pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it); +} + +void HandleWebSocketMessage(CWsEndpointWrapper *pEndPoint, CWsNode *pNode, websocketpp::connection_hdl hdl, wsserver::message_ptr msg) +{ + pNode->closeErrorOnReceive = 0; + + LOCK(pNode->cs_vRecvMsg); + if (pNode->ReceiveMsgBytes(msg->get_payload().c_str(), msg->get_payload().size())) { + pNode->nLastRecv = GetTime(); // needed to prevent inactivity disconnect + pNode->nRecvBytes += msg->get_payload().size(); + pNode->RecordBytesRecv(msg->get_payload().size()); + if (ProcessMessages(pNode)) { + LOCK(pNode->cs_vSend); + WebSocketSendData(pEndPoint, hdl, pNode); + } + } + else { + LogPrint("websockets", "error websocket message processing, disconnecting peer %d\n", pNode->id); + pNode->closeErrorOnReceive = websocketpp::close::status::unsupported_data; + pNode->fDisconnect = true; + } +} + + +class CWebSocketServer : public CWsEndpointWrapper { +public: + bool init() { + + LogPrintf("Starting websockets listener\n"); + + try { + + // Set logging settings + m_endpoint.set_error_channels(websocketpp::log::elevel::rerror); // & ~websocketpp::log::elevel::devel); + m_endpoint.set_access_channels(websocketpp::log::alevel::none); + + // Initialize Asio + m_endpoint.init_asio(); + m_endpoint.set_reuse_addr(true); // this would prevent komodod restart failure on the socket in use + // bcz the ws socket might be in CLOSE_WAIT state for a long time komodod has finished (especially if local app has not close the socket), + // however this is not recommended as allows for other apps to use this socket as shared (security issue) + // looks like still a websocketpp issue with socket shutdown + // Set the default message handler to the echo handler + m_endpoint.set_message_handler(std::bind( + &CWebSocketServer::on_message, this, + std::placeholders::_1, std::placeholders::_2 + )); + + m_endpoint.set_tls_init_handler(bind(&CWebSocketServer::on_tls_init, this, MOZILLA_MODERN, _1)); // add tls init + m_endpoint.set_open_handler(bind(&CWebSocketServer::on_open, this, _1)); + m_endpoint.set_close_handler(bind(&CWebSocketServer::on_close, this, _1)); + m_endpoint.set_validate_handler(bind(&CWebSocketServer::on_validate, this, _1)); + m_endpoint.set_fail_handler(bind(&CWebSocketServer::on_fail, this, _1)); + + } + catch (websocketpp::exception const & e) { + LogPrintf("websockets init failed: %s (for possible a reason check openssl lib 1.1.1 is installed)\n", e.what()); + return false; + } + return true; + } + + bool run() + { + try { + // Listen on port 9002 + m_endpoint.listen(8192); + + // Queues a connection accept operation + m_endpoint.start_accept(); + + // Start the Asio io_service run loop + //m_endpoint.run(); + for (int i = 0; i < 4; i ++) + vWsThreads.push_back(websocketpp::lib::make_shared(&wsserver::run, &m_endpoint)); + } + catch (websocketpp::exception const & e) { + LogPrintf("websockets listener run failed: %s \n", e.what()); + return false; + } + return true; + } + + void on_message(websocketpp::connection_hdl hdl, wsserver::message_ptr msg) { + boost::this_thread::interruption_point(); + // write a new message + //std::cerr << __func__ << " payload=" << HexStr(msg->get_payload()) << std::endl; + //m_endpoint.send(hdl, msg->get_payload(), msg->get_opcode()); + CAddress clientAddr = GetClientAddressFromHdl(hdl); + LOCK(cs_vWsNodes); + CWsNodePtr pNode = FindWsNode(clientAddr); + //CWsNode *pNode = m_connections[hdl]; + if (!pNode) { + return; + } + if (pNode->fDisconnect) { + return; + } + + //std::cerr << __func__ << " pnode found=" << clientAddr.ToStringIPPort() << " id=" << pNode->id << std::endl; + + HandleWebSocketMessage(this, pNode.get(), hdl, msg); + } + + void stop() + { + LogPrintf("Stopping websocket listener...\n"); + websocketpp::lib::error_code ec; + m_endpoint.stop_listening(ec); + + //LogPrintf("closing websocket connections...\n"); + std::vector vWsNodesCopy; + { + LOCK(cs_vWsNodes); + vWsNodesCopy = vWsNodes; + } + + for(const auto & pnode : vWsNodesCopy) + { + if (pnode->fInbound) + { + //wsserver::connection_ptr conn_ptr = m_endpoint.get_con_from_hdl(conn.first); + try { + pnode->m_spWsEndpoint->close(pnode->m_hdl, websocketpp::close::status::going_away); + } catch (websocketpp::exception const & e) { // might be already close from remote site or on a error + std::cout << __func__ << " websocketpp::exception: " << e.what() << " (could be okay)" << std::endl; + } + } + } + + LogPrintf("Waiting for websocket threads to stop... \n(Note that a possible following 'asio async_shutdown error' message is an expected behaviour)\n"); + // expalined here https://github.com/zaphoyd/websocketpp/issues/556 + // see also a possible workaround https://github.com/zaphoyd/websocketpp/issues/545 + // and http://docs.websocketpp.org/faq.html + /*for (size_t i = 0; i < vWsThreads.size(); i++) { + vWsThreads[i]->interrupt(); + }*/ + for (size_t i = 0; i < vWsThreads.size(); i++) { + vWsThreads[i]->join(); + } + //m_endpoint.close(); + //LOCK(cs_vWsNodes); + //for (auto const &pNode : vWsNodes) + // RemoveWsNode(pNode); + std::cerr << __func__ << " waiting for listener endpoint stopped state..." << std::endl; + while(!m_endpoint.stopped()) + MilliSleep(250); + + LogPrintf("Websocket listener stopped\n"); + } + + virtual void send(websocketpp::connection_hdl hdl, void const * payload, size_t len, websocketpp::frame::opcode::value op, websocketpp::lib::error_code & ec) { + m_endpoint.send(hdl, payload, len, op, ec); + } + +private: + bool on_validate(websocketpp::connection_hdl hdl) + { + return !fWebSocketsInWarmup; + } + + std::string get_password() { + return "test"; + } + + context_ptr on_tls_init(tls_mode mode, websocketpp::connection_hdl hdl) { + namespace asio = websocketpp::lib::asio; + + std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl; + std::cout << "using TLS mode: " << (mode == MOZILLA_MODERN ? "Mozilla Modern" : "Mozilla Intermediate") << std::endl; + + context_ptr ctx = websocketpp::lib::make_shared(asio::ssl::context::sslv23); + + try { + if (mode == MOZILLA_MODERN) { + // Modern disables TLSv1 + ctx->set_options(asio::ssl::context::default_workarounds | + asio::ssl::context::no_sslv2 | + asio::ssl::context::no_sslv3 | + asio::ssl::context::no_tlsv1 | + asio::ssl::context::single_dh_use); + } else { + ctx->set_options(asio::ssl::context::default_workarounds | + asio::ssl::context::no_sslv2 | + asio::ssl::context::no_sslv3 | + asio::ssl::context::single_dh_use); + } + ctx->set_password_callback(bind(&CWebSocketServer::get_password, this)); + + // self signed test certificate generated with: + // openssl req -newkey rsa:2048 -nodes -subj '/CN=komodo.test' -keyout key.pem -x509 -days 365 -out certificate.crt + // cat certificate.crt key.pem > server.pem + ctx->use_certificate_chain_file("server.pem"); + ctx->use_private_key_file("server.pem", asio::ssl::context::pem); + + // Example method of generating this file: + // `openssl dhparam -out dh.pem 2048` + // Mozilla Intermediate suggests 1024 as the minimum size to use + // Mozilla Modern suggests 2048 as the minimum size to use. + ctx->use_tmp_dh_file("dh.pem"); + + std::string ciphers; + + if (mode == MOZILLA_MODERN) { + ciphers = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK"; + } else { + ciphers = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"; + } + + if (SSL_CTX_set_cipher_list(ctx->native_handle() , ciphers.c_str()) != 1) { + std::cout << "Error setting cipher list" << std::endl; + } + } catch (std::exception& e) { + std::cout << "Exception: " << e.what() << std::endl; + } + return ctx; + } + + void on_fail(websocketpp::connection_hdl hdl) { + wsserver::connection_ptr con = m_endpoint.get_con_from_hdl(hdl); + + //std::cout << "Websocket server error for remote peer " << GetClientAddressFromHdl(hdl).ToStringIPPort() << ": " << con->get_ec() << " - " << con->get_ec().message() << std::endl; + /*std::cout << con->get_state() << std::endl; + std::cout << con->get_local_close_code() << std::endl; + std::cout << con->get_local_close_reason() << std::endl; + std::cout << con->get_remote_close_code() << std::endl; + std::cout << con->get_remote_close_reason() << std::endl; + std::cout << con->get_ec() << " - " << con->get_ec().message() << std::endl;*/ + CAddress clientAddr = GetClientAddressFromHdl(hdl); + LOCK(cs_vWsNodes); + CWsNodePtr pNode = FindWsNode(clientAddr); + if (!pNode) { + return; + } + + LogPrint("websockets", "error on inbound connection from ws peer %d\n", pNode->GetId()); + pNode->fDisconnect = true; + // RemoveWsNode(pNode); // TODO: make remove the same way like in CWebSocketOutbound, maybe better if nodes are removed in the common loop in net.cpp + // NOTE: do not modify the pNode might be deleted in RemoveWsNode + } + + void on_open(websocketpp::connection_hdl hdl) + { + CAddress addr = GetClientAddressFromHdl(hdl); + + CWsNodePtr pNode( new CWsNode(INVALID_SOCKET, addr, "", true) ); // not used hSocket for websockets + pNode->m_spWsEndpoint = spWebSocketServer; + pNode->m_hdl = hdl; + { + LOCK(cs_vWsNodes); + vWsNodes.push_back(pNode); + } + } + + void on_close(websocketpp::connection_hdl hdl) + { + CAddress clientAddr = GetClientAddressFromHdl(hdl); + LOCK(cs_vWsNodes); + CWsNodePtr pNode = FindWsNode(clientAddr); + if (!pNode) { + return; + } + + LogPrint("websockets", "closing inbound connection from ws peer %d\n", pNode->GetId()); + + pNode->fDisconnect = true; + RemoveWsNode(pNode); + } + + virtual void close(websocketpp::connection_hdl hdl, websocketpp::close::status::value status) + { + LogPrint("websockets", "closing connection %s\n", GetClientAddressFromHdl(hdl).ToStringIPPort().c_str()); + m_endpoint.close(hdl, status, ""); + } + + virtual void sendWsData(CWsNode *pNode) + { + LOCK(pNode->cs_vSend); + WebSocketSendData(this, pNode->m_hdl, pNode); + } + + CAddress GetClientAddressFromHdl(websocketpp::connection_hdl hdl) + { + wsserver::connection_ptr conn_ptr = m_endpoint.get_con_from_hdl(hdl); + std::string sAddr = conn_ptr->get_remote_endpoint(); + CService svc(sAddr); + return CAddress(svc); + } +private: + wsserver m_endpoint; +}; + +// object to try peer websocket nodes +class CWebSocketOutbound : public CWsEndpointWrapper { +public: + + CWebSocketOutbound () { + m_endpoint.set_error_channels(websocketpp::log::elevel::rerror); + m_endpoint.set_access_channels(websocketpp::log::alevel::none); + + // Initialize ASIO + m_endpoint.init_asio(); + + // Register our handlers + m_endpoint.set_socket_init_handler(bind(&CWebSocketOutbound::on_socket_init,this,::_1)); + //m_endpoint.set_http_init_handler(bind(&CWebSocketOutbound::on_socket_init,this,::_1)); + //m_endpoint.set_tls_init_handler(bind(&CWebSocketOutbound::on_socket_init,this,::_1)); + + m_endpoint.set_message_handler(bind(&CWebSocketOutbound::on_message,this,::_1,::_2)); + m_endpoint.set_open_handler(bind(&CWebSocketOutbound::on_open,this,::_1)); + m_endpoint.set_close_handler(bind(&CWebSocketOutbound::on_close,this,::_1)); + m_endpoint.set_fail_handler(bind(&CWebSocketOutbound::on_fail,this,::_1)); + + m_bFailed = false; + } + + ~CWebSocketOutbound() { + // do not delete m_pNode, it is deleted in NetCleanUp + } + + bool start(CAddress addrConnect, std::string uri) + { + if (fWebSocketsInWarmup) + return false; + + websocketpp::lib::error_code ec; + + m_addrConnect = addrConnect; + if (!uri.empty()) + m_uri = uri; + else + m_uri = "ws://" + addrConnect.ToStringIPPort(); + + wsclient::connection_ptr con = m_endpoint.get_connection(m_uri, ec); + + if (ec) { + m_endpoint.get_alog().write(websocketpp::log::alevel::app, ec.message()); + return false; + } + + + m_endpoint.connect(con); + return true; + } + + void run() + { + LOCK(cs); + m_thread = websocketpp::lib::make_shared(&wsclient::run, &m_endpoint); + } + + void on_socket_init(websocketpp::connection_hdl hdl) { + } + + void on_fail(websocketpp::connection_hdl hdl) { + //wsclient::connection_ptr conn_ptr = m_endpoint.get_con_from_hdl(hdl); + m_bFailed = true; + if (m_pNode) { + LOCK(cs_vWsNodes); + LogPrint("websockets", "error on outbound connection to websocket peer %d\n", m_pNode->GetId()); + + m_pNode->fDisconnect = true; // mark for disconnection + RemoveWsNode(m_pNode); + } + else { + LogPrint("websockets", "could not connect to remote websocket peer %s\n", m_uri.c_str()); + } + } + + void on_open(websocketpp::connection_hdl hdl) { + + // Add node + { + LOCK2(cs, cs_vOutboundEndpoints); + m_pNode.reset( new CWsNode(INVALID_SOCKET, m_addrConnect, (!m_uri.empty() ? m_uri : ""), false) ); + m_pNode->m_spWsEndpoint = *(std::find_if(vOutboundEndpoints.begin(), vOutboundEndpoints.end(), [&](const ws_endpoint_ptr& sp){ return sp.get() == static_cast(this); })); + } + + m_pNode->m_hdl = hdl; + m_pNode->nTimeConnected = GetTime(); + m_pNode->fNetworkNode = true; + + { + LOCK(cs_vWsNodes); + vWsNodes.push_back(m_pNode); + } + + m_pNode->PushWsVersion(); + { + LOCK(m_pNode->cs_vSend); + WebSocketSendData(this, hdl, m_pNode.get()); + } + } + void on_message(websocketpp::connection_hdl hdl, wsclient::message_ptr msg) { + HandleWebSocketMessage(this, m_pNode.get(), hdl, msg); + } + void on_close(websocketpp::connection_hdl) { + if ((bool)m_pNode) { + LOCK(cs_vWsNodes); + LogPrint("websockets", "closing outbound connection to ws peer %d\n", m_pNode->GetId()); + + m_pNode->fDisconnect = true; + RemoveWsNode(m_pNode); + } + } + + virtual void close(websocketpp::connection_hdl hdl, websocketpp::close::status::value status) + { + if (m_endpoint.get_con_from_hdl(hdl) != nullptr) { + m_endpoint.close(hdl, status, std::string()); + } + } + + virtual void send(websocketpp::connection_hdl hdl, void const * payload, size_t len, websocketpp::frame::opcode::value op, websocketpp::lib::error_code & ec) { + m_endpoint.send(hdl, payload, len, op, ec); + } + + virtual void sendWsData(CWsNode*) + { + if (m_pNode) { + LOCK(m_pNode->cs_vSend); + WebSocketSendData(this, m_pNode->m_hdl, m_pNode.get()); + } + } + +private: + wsclient m_endpoint; + std::string m_uri; + CAddress m_addrConnect; + +public: + CWsNodePtr m_pNode; + ws_thread_ptr m_thread; + bool m_bFailed; + CCriticalSection cs; +}; + +CWebSocketOutbound* ConnectWsNode(CAddress addrConnect, const char *pszDest) +{ + if (pszDest == NULL) { + if (IsLocal(addrConnect)) + return NULL; + + // Look for an existing connection + CWsNodePtr pnode = FindWsNode((CService)addrConnect); + if ((bool)pnode) + { + return NULL; + } + } + + /// debug print + LogPrint("websockets", "trying websockets connection %s lastseen=%.1fhrs\n", + pszDest ? pszDest : addrConnect.ToString(), + pszDest ? 0.0 : (double)(GetTime() - addrConnect.nTime)/3600.0); + + // Connect + bool proxyConnectionFailed = false; + + CWebSocketOutbound *pwsOutbound = new CWebSocketOutbound(); + bool bStarted; + try { + bStarted = pwsOutbound->start(addrConnect, pszDest ? pszDest : ""); + } + catch (websocketpp::exception const & e) { + LogPrint("websockets", "could not start connection to websockets peer %s %s\n", addrConnect.ToStringIPPort().c_str(), pszDest ? pszDest : ""); + delete pwsOutbound; + return NULL; + } + if (bStarted) { + wsaddrman.Attempt(addrConnect); + } else if (!proxyConnectionFailed) { + // If connecting to the node failed, and failure is not caused by a problem connecting to + // the proxy, mark this as an attempt. + wsaddrman.Attempt(addrConnect); + } + + return pwsOutbound; +} + +// if successful, this moves the passed grant to the constructed node +bool OpenWebSocketNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound /*, const char *pszDest, bool fOneShot*/) +{ + // + // Initiate outbound network connection + // + boost::this_thread::interruption_point(); + //if (!pszDest) { + if (IsLocal(addrConnect) || + FindWsNode((CNetAddr)addrConnect) || CWsNode::IsBanned(addrConnect) || + FindWsNode(addrConnect.ToStringIPPort())) + return false; + //} else if (FindWsNode(std::string(pszDest))) + // return false; + + CWebSocketOutbound * pOutbound = ConnectWsNode(addrConnect, NULL /*pszDest*/); // Note: pOutbound ptr is stored in pNode (which itself is stored in vWsNodes) and handled from there + boost::this_thread::interruption_point(); + + if (!pOutbound) + return false; + + // Start the ASIO io_service run loop + pOutbound->run(); + + { + LOCK(cs_vOutboundEndpoints); + vOutboundEndpoints.push_back(ws_endpoint_ptr(pOutbound)); + } + //if (fOneShot) + // pnode->fOneShot = true; // one shot not implemented + + return true; +} + +// select a node and create messages to send +void ThreadWebSocketMessageHandler() +{ + boost::mutex condition_mutex; + boost::unique_lock lock(condition_mutex); + + SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); + while (true) + { + boost::this_thread::interruption_point(); + + std::vector vWsNodesCopy; + { + LOCK(cs_vWsNodes); + vWsNodesCopy = vWsNodes; + } + + CWsNodePtr pnodeTrickle = NULL; + if (!vWsNodesCopy.empty()) + pnodeTrickle = vWsNodesCopy[GetRand(vWsNodesCopy.size())]; + + bool fSleep = true; + + for(auto const & pnode : vWsNodesCopy) + { + if (pnode->fDisconnect) + continue; + + // Send messages + { + TRY_LOCK(pnode->cs_vSend, lockSend); + if (lockSend) { + bool fTrickle = pnode == pnodeTrickle || pnode->fWhitelisted; + SendWsMessages(pnode.get(), fTrickle); + if (fTrickle) { + WebSocketSendData(pnode->m_spWsEndpoint.get(), pnode->m_hdl, pnode.get()); + if (pnode->closeErrorOnSend || pnode->closeErrorOnReceive) { + try { + pnode->m_spWsEndpoint->close(pnode->m_hdl, (pnode->closeErrorOnSend ? pnode->closeErrorOnSend : pnode->closeErrorOnReceive)); + } catch (websocketpp::exception const & e) { // might be already closed from remote site or on a error + std::cout << __func__ << " close websocketpp::exception: " << e.what() << " (could be okay)" << std::endl; + } + } + } + } + } + + boost::this_thread::interruption_point(); + } + + if (fSleep) + wsMessageHandlerCondition.timed_wait(lock, boost::posix_time::microsec_clock::universal_time() + boost::posix_time::milliseconds(100)); + } +} + +// join for disconnected outbound threads to stop +static void ThreadWebSocketWaitForDisconnectedThreads() +{ + boost::mutex condition_mutex; + boost::unique_lock lock(condition_mutex); + + SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); + while (true) + { + boost::this_thread::interruption_point(); + + // remove failed outbound endpoints + std::vector vOutboundEndpointsCopy; + { + LOCK(cs_vOutboundEndpoints); + vOutboundEndpointsCopy = vOutboundEndpoints; + } + for (auto &spOutbound : vOutboundEndpointsCopy) + { + CWebSocketOutbound *pOutbound = static_cast(spOutbound.get()); + bool bJoin = false; + bool bRemove = false; + { + LOCK(pOutbound->cs); + bJoin = (bool)pOutbound->m_bFailed && !pOutbound->m_pNode && (bool)pOutbound->m_thread || (bool)pOutbound->m_thread && fWebSocketsStopping; // join outbound threads that never connected + // stop tracking either failed outbounds with no node created or + bRemove = (bool)pOutbound->m_pNode || pOutbound->m_bFailed || fWebSocketsStopping; + } + if (bRemove) + { + { + LOCK(pOutbound->cs); + if (bJoin && (bool)pOutbound->m_thread && pOutbound->m_thread->joinable()) { + pOutbound->m_thread->join(); + } + } + { + LOCK(cs_vOutboundEndpoints); + auto it = std::remove(vOutboundEndpoints.begin(), vOutboundEndpoints.end(), spOutbound); + vOutboundEndpoints.erase(it, vOutboundEndpoints.end()); + } + } + } + + std::vector vWsNodesCopy; + { + LOCK(cs_vWsNodes); + vWsNodesCopy = vWsNodes; + } + for(auto const & pnode : vWsNodesCopy) + { + // + // Inactivity checking + // + int64_t nTime = GetTime(); + if (nTime - pnode->nTimeConnected > 60) + { + if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) + { + LogPrint("websockets", "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id); + pnode->fDisconnect = true; + } + else if (nTime - pnode->nLastSend > WEBSOCKETS_TIMEOUT_INTERVAL) + { + LogPrintf("websocket sending timeout: %is\n", nTime - pnode->nLastSend); + pnode->fDisconnect = true; + } + else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? WEBSOCKETS_TIMEOUT_INTERVAL : 90*60)) + { + LogPrintf("websocket receive timeout: %is\n", nTime - pnode->nLastRecv); + pnode->fDisconnect = true; + } + else if (pnode->nPingNonceSent && pnode->nPingUsecStart + WEBSOCKETS_TIMEOUT_INTERVAL * 1000000 < GetTimeMicros()) + { + LogPrintf("websocket ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart)); + pnode->fDisconnect = true; + } + + if (pnode->fDisconnect) + { + try { + pnode->m_spWsEndpoint->close(pnode->m_hdl, websocketpp::close::status::no_status); + } catch (websocketpp::exception const & e) { // might be already close from remote site or on a error + std::cout << __func__ << " close websocketpp::exception: " << e.what() << " (could be okay)" << std::endl; + LOCK(cs_vWsNodes); + RemoveWsNode(pnode); + } + } + } + } + + // make a copy in order to not to block while waiting for thread join + std::set vWsNodesDisconnectedCopy; + { + LOCK(cs_vWsNodesDisconnected); + vWsNodesDisconnectedCopy = vWsNodesDisconnected; + vWsNodesDisconnected.clear(); + + } + + // join and delete + for(auto itnode = vWsNodesDisconnectedCopy.begin() ; itnode != vWsNodesDisconnectedCopy.end(); ) + { + if (!(*itnode)->fInbound) + { + ws_thread_ptr outboundThreadPtr = static_cast((*itnode)->m_spWsEndpoint.get())->m_thread; + if ((bool)outboundThreadPtr && outboundThreadPtr->joinable()) + outboundThreadPtr->join(); // wait for outbound thread to stop + + } + auto itnext = vWsNodesDisconnectedCopy.erase(itnode); + itnode = itnext; + + } + + MilliSleep(1000); + } +} + +static int GetOutboundNodes() +{ + LOCK(cs_vWsNodes); + int nOutbounds = 0; + for (const auto &pNode : vWsNodes) + if (!pNode->fInbound) + nOutbounds ++; + return nOutbounds; +} + +void ThreadOpenWebSocketConnections() +{ + // Connect to specific addresses + /*if (mapArgs.count("-wsconnect") && mapMultiArgs["-wsconnect"].size() > 0) + { + for (int64_t nLoop = 0;; nLoop++) + { + ProcessOneShot(); + BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-wsconnect"]) + { + CAddress addr; + OpenNetworkConnection(addr, NULL, strAddr.c_str()); + for (int i = 0; i < 10 && i < nLoop; i++) + { + MilliSleep(500); + } + } + MilliSleep(500); + } + }*/ + + // Initiate network connections + int64_t nStart = GetTime(); + while (true) + { + //ProcessOneShot(); + + MilliSleep(2000); + + CSemaphoreGrant grant; + boost::this_thread::interruption_point(); + + if (fWebSocketsStopping) + continue; + + // Add seed nodes if DNS seeds are all down (an infrastructure attack?). + // if (addrman.size() == 0 && (GetTime() - nStart > 60)) { + /*if (GetTime() - nStart > 60) { + static bool done = false; + if (!done) { + // skip DNS seeds for staked chains. + if ( is_STAKED(ASSETCHAINS_SYMBOL) == 0 && KOMODO_DEX_P2P == 0 ) { + //LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n"); + LogPrintf("Adding fixed seed nodes.\n"); + addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1")); + } + done = true; + } + }*/ + + + // + // Choose an address to connect to based on most recently seen + // + CAddress addrConnect; + + // Only connect out to one peer per network group (/16 for IPv4). + // Do this here so we don't have to critsect vWsNodes inside mapAddresses critsect. + int nOutbound = 0; + std::set > setConnected; + { + LOCK(cs_vWsNodes); + for (auto const & pnode : vWsNodes) { + if (!pnode->fInbound) { + setConnected.insert(pnode->addr.GetGroup(wsaddrman.m_asmap)); + nOutbound++; + } + } + } + + if (GetOutboundNodes() >= 8) + continue; + + int64_t nANow = GetTime(); + + int nTries = 0; + while (true) + { + CAddrInfo addr = wsaddrman.Select(); + + // if we selected an invalid address, restart + if (!addr.IsValid() || setConnected.count(addr.GetGroup(wsaddrman.m_asmap)) || IsLocal(addr)) + break; + +#ifdef ENABLE_WEBSOCKETS + // do not connect to client nodes (looks like this should be added for non-websocket version too): + if ((addr.nServices & NODE_NETWORK) == 0) + continue; +#endif + + // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman, + // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates + // already-connected network ranges, ...) before trying new addrman addresses. + nTries++; + if (nTries > 100) + break; + + if (IsLimited(addr)) + continue; + + // only consider very recently tried nodes after 30 failed attempts + if (nANow - addr.nLastTry < 600 && nTries < 30) + continue; + + // no default port for websockets. TODO: set up a websockets default port + // do not allow non-default ports, unless after 50 invalid addresses selected already + //if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50) + // continue; + + addrConnect = addr; + break; + } + + if (addrConnect.IsValid()) { + OpenWebSocketNetworkConnection(addrConnect, &grant); + } + } +} + +static void ThreadOpenAddedWebSocketConnections() +{ + { + LOCK(cs_vAddedWsNodes); + vAddedWsNodes = mapMultiArgs["-addwsnode"]; + } + + /*if (HaveNameProxy()) { + // don't use proxy for websocket listeners + }*/ + + for (unsigned int i = 0; true; i++) + { + boost::this_thread::interruption_point(); + + std::list lAddresses(0); + { + LOCK(cs_vAddedNodes); + for(const std::string& strAddNode : vAddedWsNodes) + lAddresses.push_back(strAddNode); + } + + std::list > lservAddressesToAdd(0); + for(const std::string& strAddNode : lAddresses) { + std::vector vservNode(0); + if(Lookup(strAddNode.c_str(), vservNode, GetWebSocketListenPort(), fNameLookup, 0)) + { + lservAddressesToAdd.push_back(vservNode); + { + LOCK(cs_setservAddNodeWsAddresses); + BOOST_FOREACH(const CService& serv, vservNode) + setservAddNodeWsAddresses.insert(serv); // seems not used + } + } + } + // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry + // (keeping in mind that addnode entries can have many IPs if fNameLookup) + { + LOCK(cs_vWsNodes); + for(auto const & pnode : vWsNodes) + { + for (std::list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++) + { + BOOST_FOREACH(const CService& addrNode, *(it)) + if (pnode->addr == addrNode) + { + it = lservAddressesToAdd.erase(it); + if ( it != lservAddressesToAdd.begin() ) + it--; + break; + } + if (it == lservAddressesToAdd.end()) + break; + } + } + } + if (!fWebSocketsStopping) + { + for(std::vector& vserv : lservAddressesToAdd) + { + if (GetOutboundNodes() >= 8) + break; + CSemaphoreGrant grant; + OpenWebSocketNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant); + MilliSleep(500); + } + } + MilliSleep(120000); // Retry every 2 minutes + } +} + + +// start stop + +bool StartWebSockets(boost::thread_group& threadGroup) +{ + spWebSocketServer.reset(new CWebSocketServer); + + if (!static_cast(spWebSocketServer.get())->init()) + return false; + if (!static_cast(spWebSocketServer.get())->run()) + return false; + + //if (semWsOutbound == NULL) + // semWsOutbound = new CSemaphore(8); // allow 8 peer connections + + // Initiate outbound connections + wsThreadGroup.create_thread(boost::bind(&TraceThread, "wsopencon", &ThreadOpenWebSocketConnections)); + + // Initiate outbound 'addwsnode' connections + wsThreadGroup.create_thread(boost::bind(&TraceThread, "wsopenaddedcon", &ThreadOpenAddedWebSocketConnections)); + + // periodical send messages thread + wsThreadGroup.create_thread(boost::bind(&TraceThread, "wsmsghand", &ThreadWebSocketMessageHandler)); + + // wait for disconnected oupud threads + wsThreadGroup.create_thread(boost::bind(&TraceThread, "wsdiscon", &ThreadWebSocketWaitForDisconnectedThreads)); + + bWebSocketsStarted = true; + return true; +} + +void SetWebSocketsWarmupFinished() +{ + LOCK(cs_wsWarmup); + assert(fWebSocketsInWarmup); + fWebSocketsInWarmup = false; +} + + +void StopWebSockets() +{ + if (!bWebSocketsStarted) + return; + + if (!spWebSocketServer) + return; + + fWebSocketsStopping = true; + static_cast(spWebSocketServer.get())->stop(); + + LogPrintf("Closing outbound websocket connections...\n"); + { + std::vector vWsNodesCopy; + { + LOCK(cs_vWsNodes); + vWsNodesCopy = vWsNodes; + } + for(const auto &pnode : vWsNodesCopy) + { + if (!pnode->fInbound) { // inbounds are close when the ws listener stops + try { + pnode->m_spWsEndpoint->close(pnode->m_hdl, websocketpp::close::status::going_away); + } catch (websocketpp::exception const & e) { // might be already close from remote site or on a error + std::cout << __func__ << " close websocketpp::exception: " << e.what() << " (could be okay)" << std::endl; + } + } + } + } + + LogPrintf("Waiting for websockets outbound threads to stop...\n"); + // joined in "wsdiscon" thread: + while(vWsNodesDisconnected.size() > 0 || GetOutboundNodes() > 0 || vOutboundEndpoints.size() > 0) { + //std::cerr << __func__ << " vWsNodesDisconnected.size()=" << vWsNodesDisconnected.size() << " GetOutboundNodes()=" << GetOutboundNodes() << " vOutboundEndpoints.size()=" << vOutboundEndpoints.size() << std::endl; + MilliSleep(500); + } + + LogPrintf("Waiting for websockets work threads to stop...\n"); + + wsThreadGroup.interrupt_all(); + wsThreadGroup.join_all(); + + LogPrintf("All websockets threads stopped\n"); + +} + +// debug rpc impl +UniValue GetWsPeers() +{ + UniValue result(UniValue::VARR); + std::vector vstats; + + { + LOCK(cs_vWsNodes); + vstats.reserve(vWsNodes.size()); + for(const auto & pnode : vWsNodes) { + CNodeStats stats; + pnode->copyStats(stats, wsaddrman.m_asmap); + vstats.push_back(stats); + } + } + + for (auto const &stats : vstats) { + UniValue peer(UniValue::VOBJ); + + peer.push_back(Pair("id", stats.nodeid)); + peer.push_back(Pair("addr", stats.addrName)); + if (!(stats.addrLocal.empty())) + peer.push_back(Pair("addrlocal", stats.addrLocal)); + peer.push_back(Pair("services", strprintf("%016x", stats.nServices))); + peer.push_back(Pair("version", stats.nVersion)); + // Use the sanitized form of subver here, to avoid tricksy remote peers from + // corrupting or modifying the JSON output by putting special characters in + // their ver message. + peer.push_back(Pair("subver", stats.cleanSubVer)); + peer.push_back(Pair("inbound", stats.fInbound)); + + result.push_back(peer); + } + return result; +} + +// temp rpc to dump addrman table. TODO: remove this code +UniValue printaddrman(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() != 0) + { + std::string msg = "printaddrman\n" + "\nReturns an array of addresses\n"; + throw std::runtime_error(msg); + } + std::vector addrInfos = addrman.GetAddrInfoAll(); + UniValue result (UniValue::VOBJ); + UniValue array (UniValue::VARR); + int64_t nNow = GetTime(); + for(auto const & a : addrInfos) { + UniValue e(UniValue::VOBJ); + + e.pushKV("address", a.ToString()); + std::ostringstream strhex; + strhex << std::hex << a.nServices; + e.pushKV("services", strhex.str()); + e.pushKV("source", addrman.GetSource(a).ToString()); + e.pushKV("IsTerrible", a.IsTerrible()); + e.pushKV("SinceLastTry", nNow - a.nLastTry); + e.pushKV("SinceLastSeen", nNow - a.nTime); + array.push_back(e); + } + result.pushKV("addresses", array); + + return result; +} + +// temp rpc to dump addrman table. TODO: remove this code +UniValue printwsaddrman(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() != 0) + { + std::string msg = "printwsaddrman\n" + "\nReturns an array of addresses\n"; + throw std::runtime_error(msg); + } + + std::vector addrInfos = wsaddrman.GetAddrInfoAll(); + UniValue result (UniValue::VOBJ); + UniValue array (UniValue::VARR); + int64_t nNow = GetTime(); + for(auto const & a : addrInfos) { + UniValue e(UniValue::VOBJ); + + e.pushKV("wsaddress", a.ToString()); + std::ostringstream strhex; + strhex << std::hex << a.nServices; + e.pushKV("services", strhex.str()); + e.pushKV("source", wsaddrman.GetSource(a).ToString()); + e.pushKV("IsTerrible", a.IsTerrible()); + e.pushKV("SinceLastTry", nNow - a.nLastTry); + e.pushKV("SinceLastSeen", nNow - a.nTime); + array.push_back(e); + } + result.pushKV("wsaddresses", array); + + return result; +} + +UniValue getwspeers(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + UniValue result = GetWsPeers(); + return result; +} + + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "hidden", "printaddrman", &printaddrman, true }, + { "hidden", "printwsaddrman", &printwsaddrman, true }, + { "hidden", "getwspeers", &getwspeers, true }, +}; + +void RegisterWebSocketsRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} \ No newline at end of file diff --git a/src/komodo_websockets.h b/src/komodo_websockets.h new file mode 100644 index 00000000000..dfcbae1db90 --- /dev/null +++ b/src/komodo_websockets.h @@ -0,0 +1,71 @@ + +// Copyright (c) 2020 The SuperNet developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef __KOMODO_WEBSOCKETS_H__ +#define __KOMODO_WEBSOCKETS_H__ + +#include + +// The ASIO_STANDALONE define is necessary to use the standalone version of Asio. +// Remove if you are using Boost Asio. +// #define ASIO_STANDALONE +//#include +#include +#include +#include +#include +#include +#include +//#include + +//using websocketpp::lib::bind; + +static const int WSADDR_VERSION = 170008; +#define WEBSOCKETS_TIMEOUT_INTERVAL 120 + + +//struct wsserver_mt_config : public websocketpp::config::asio { // no tls +struct wsserver_mt_config : public websocketpp::config::asio_tls { // tls + + // pull default settings from our core config + static bool const enable_multithreading = true; + + struct transport_config : public websocketpp::config::core::transport_config { + static bool const enable_multithreading = true; + }; + + /// permessage_compress extension + //struct permessage_deflate_config {}; + + //typedef websocketpp::extensions::permessage_deflate::enabled + // permessage_deflate_type; +}; + +//typedef websocketpp::server wsserver; // no tls +typedef websocketpp::server wsserver; // tls + +//transport::asio::tls_socket::endpoint + +typedef websocketpp::client wsclient; + + +typedef websocketpp::lib::shared_ptr context_ptr; + +// See https://wiki.mozilla.org/Security/Server_Side_TLS for more details about +// the TLS modes. The code below demonstrates how to implement both the modern +enum tls_mode { + MOZILLA_INTERMEDIATE = 1, + MOZILLA_MODERN = 2 +}; + +bool StartWebSockets(boost::thread_group& threadGroup); +void SetWebSocketsWarmupFinished(); +void StopWebSockets(); + +int GetnScore(const CService& addr); //net.cpp + +bool ProcessWsMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, int64_t nTimeReceived); + +#endif \ No newline at end of file From 1350e9ef3b2257dde3556ba63d186e39cc235581 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 2 Feb 2022 21:18:26 +0500 Subject: [PATCH 242/348] added faucet demo nspv support --- src/cc/CCfaucet.h | 2 ++ src/komodo_nSPV_fullnode.h | 1 + src/rpc/ccutilsrpc.cpp | 51 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/cc/CCfaucet.h b/src/cc/CCfaucet.h index af3237ab1b5..7155168380e 100644 --- a/src/cc/CCfaucet.h +++ b/src/cc/CCfaucet.h @@ -29,4 +29,6 @@ UniValue FaucetFund(const CPubKey& mypk,uint64_t txfee,int64_t funds); UniValue FaucetGet(const CPubKey& mypk,uint64_t txfee); UniValue FaucetInfo(); +int64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs); + #endif diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 4755a48049a..12abe6076c1 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -56,6 +56,7 @@ static std::map nspv_remote_commands = { { "tokenv2orders", true }, { "mytokenv2orders", true }, { "tokenv2transfer", false }, { "tokenv2create", false }, { "tokenv2address", true }, // nspv helpers { "createtxwithnormalinputs", true }, { "tokenv2addccinputs", true }, { "tokenv2infotokel", true }, { "gettransactionsmany", true }, + { "faucetaddccinputs", true }, }; diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index 8f8e3890f13..fd3d481dfbb 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -28,6 +28,8 @@ #include "sync_ext.h" #include "../main.h" #include "../cc/CCinclude.h" +#include "../cc/CCfaucet.h" + using namespace std; @@ -278,6 +280,53 @@ UniValue searchforpubkey(const UniValue& params, bool fHelp, const CPubKey& remo throw std::runtime_error("pubkey not found"); } +UniValue faucetaddccinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + if (fHelp || params.size() != 1) + { + string msg = "faucetaddccinputs amount\n" + "\nReturns a new tx with added normal inputs and previous txns. Note that the caller must add the change output\n" + "\nArguments:\n" + //"address which utxos are added from\n" + "amount (in satoshi) which will be added as normal inputs (equal or more)\n" + "Result: json object with created tx and added vin txns\n\n"; + throw runtime_error(msg); + } + /*std::string address = params[0].get_str(); + if (!CBitcoinAddress(address.c_str()).IsValid()) + throw runtime_error("address invalid");*/ + CAmount amount = atoll(params[0].get_str().c_str()); + if (amount <= 0) + throw runtime_error("amount invalid"); + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + std::vector vintxns; + struct CCcontract_info *cp, C; + cp = CCinit(&C, EVAL_FAUCET); + CPubKey faucetpk = GetUnspendable(cp,0); + + CAmount added = AddFaucetInputs(cp, mtx, faucetpk, amount, CC_MAXVINS); + if (added < amount) + throw runtime_error("could not find normal inputs"); + + for (auto const & vin : mtx.vin) { + CTransaction tx; + uint256 hashBlock; + if (myGetTransaction(vin.prevout.hash, tx, hashBlock)) + vintxns.push_back(tx); + } + + + UniValue result (UniValue::VOBJ); + UniValue array (UniValue::VARR); + + result.pushKV("txhex", HexStr(E_MARSHAL(ss << mtx))); + for (auto const &vtx : vintxns) + array.push_back(HexStr(E_MARSHAL(ss << vtx))); + result.pushKV("previousTxns", array); + return result; +} + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------- ------------------------ ----------------------- ---------- @@ -287,6 +336,8 @@ static const CRPCCommand commands[] = { "ccutils", "searchforpubkey", &searchforpubkey, true }, { "nspv", "createtxwithnormalinputs", &createtxwithnormalinputs, true }, { "nspv", "gettransactionsmany", &gettransactionsmany, true }, + { "nspv", "faucetaddccinputs", &faucetaddccinputs, true }, + }; void RegisterCCUtilsRPCCommands(CRPCTable &tableRPC) From 4291935870e7ef7aef156d739c1438b04af11615 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 28 Apr 2022 01:14:38 +0500 Subject: [PATCH 243/348] fixed -wsport use --- src/komodo_websockets.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index 1f368c5df50..1c3c0fb59ea 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -644,8 +644,8 @@ class CWebSocketServer : public CWsEndpointWrapper { bool run() { try { - // Listen on port 9002 - m_endpoint.listen(8192); + // Listen on -wsport + m_endpoint.listen(GetWebSocketListenPort()); // Queues a connection accept operation m_endpoint.start_accept(); From 1143b671af3fac9dcbaa38b34b05d1080f8dea01 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 28 Apr 2022 17:35:11 +0500 Subject: [PATCH 244/348] logging cc script --- src/script/script.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/script/script.cpp b/src/script/script.cpp index 465872b8bf2..cc6609b6fe3 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -360,14 +360,20 @@ static bool IsCCOpcodeValid(opcodetype opcode, const vector &data { if (data.size() > 0) { - if (opcode > OP_0 && opcode < OP_PUSHDATA1) // pre mixed mode (cc_conditionBinary always < 76 bytes) or small mixed mode + if (opcode > OP_0 && opcode < OP_PUSHDATA1) { // pre mixed mode (cc_conditionBinary always < 76 bytes) or small mixed mode + std::cerr << __func__ << " valid0" << std::endl; return true; - else if (data[0] == CC_MIXED_MODE_PREFIX /*&& opcode > OP_0 && opcode <= OP_PUSHDATA1*/) // for mixed mode subver 'M'+0 enable longer data upto 255 b + } + else if (data[0] == CC_MIXED_MODE_PREFIX /*&& opcode > OP_0 && opcode <= OP_PUSHDATA1*/) { // for mixed mode subver 'M'+0 enable longer data upto 255 b + std::cerr << __func__ << " valid1" << std::endl; return true; + } else if (data[0] == CC_MIXED_MODE_PREFIX+1 /*&& opcode > OP_0 && opcode <= OP_PUSHDATA2*/) { // for mixed mode subver >= 'M'+1 enable even longer data upto 65K b + std::cerr << __func__ << " valid2" << std::endl; return true; } } + std::cerr << __func__ << " invalid" << std::endl; return false; } @@ -480,11 +486,15 @@ bool CScript::MayAcceptCryptoCondition() const if (!IsCCOpcodeValid(opcode, data)) return false; CC *cond = cc_readConditionBinaryMaybeMixed(data.data(), data.size()); - if (!cond) return false; + if (!cond) { + std::cerr << __func__ << " cond is null" << std::endl; + return false; + } CC_SUBVER ccSubVersion = CC_MixedModeSubVersion((*this)[0]); bool out = IsSupportedCryptoCondition(cond, ccSubVersion); cc_free(cond); + std::cerr << __func__ << " out=" << out << std::endl; return out; } From dbb32f6260310bff8018df21f8296420e55bfeaf Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 28 Apr 2022 22:08:43 +0500 Subject: [PATCH 245/348] fixed cc subversion getting in main.cpp --- src/main.cpp | 5 +++-- src/script/script.cpp | 26 +++++--------------------- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index afd2273b5c6..f0fc31a760a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3014,10 +3014,11 @@ bool ContextualCheckOutputs( { for (unsigned int i = 0; i < tx.vout.size(); i++) { - int subversion; - if (tx.vout[i].scriptPubKey.IsPayToCCV2(subversion) ) + + if (tx.vout[i].scriptPubKey.IsPayToCCV2() ) { // check if secp256hash and eval param in action: + int subversion = CC_MixedModeSubVersion(tx.vout[i].scriptPubKey[0]); if (subversion >= CC_MIXED_MODE_SECHASH_SUBVER_1 && !CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) { return state.DoS(100,false, REJECT_INVALID, std::string("cc v2 subversion 1 or more not yet enabled")); diff --git a/src/script/script.cpp b/src/script/script.cpp index cc6609b6fe3..6d7dcfe947a 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -360,20 +360,13 @@ static bool IsCCOpcodeValid(opcodetype opcode, const vector &data { if (data.size() > 0) { - if (opcode > OP_0 && opcode < OP_PUSHDATA1) { // pre mixed mode (cc_conditionBinary always < 76 bytes) or small mixed mode - std::cerr << __func__ << " valid0" << std::endl; + if (opcode > OP_0 && opcode < OP_PUSHDATA1) // pre mixed mode (cc_conditionBinary always < 76 bytes) or small mixed mode return true; - } - else if (data[0] == CC_MIXED_MODE_PREFIX /*&& opcode > OP_0 && opcode <= OP_PUSHDATA1*/) { // for mixed mode subver 'M'+0 enable longer data upto 255 b - std::cerr << __func__ << " valid1" << std::endl; + else if (data[0] == CC_MIXED_MODE_PREFIX /*&& opcode > OP_0 && opcode <= OP_PUSHDATA1*/) // for mixed mode subver 'M'+0 enable longer data upto 255 b return true; - } - else if (data[0] == CC_MIXED_MODE_PREFIX+1 /*&& opcode > OP_0 && opcode <= OP_PUSHDATA2*/) { // for mixed mode subver >= 'M'+1 enable even longer data upto 65K b - std::cerr << __func__ << " valid2" << std::endl; + else if (data[0] == CC_MIXED_MODE_PREFIX+1 /*&& opcode > OP_0 && opcode <= OP_PUSHDATA2*/) // for mixed mode subver >= 'M'+1 enable even longer data upto 65K b return true; - } } - std::cerr << __func__ << " invalid" << std::endl; return false; } @@ -423,7 +416,7 @@ bool CScript::IsPayToCryptoCondition() const return IsPayToCryptoCondition(NULL); } -bool CScript::IsPayToCCV2(int &subversion) const +bool CScript::IsPayToCCV2() const { const_iterator pc = begin(); std::vector data; @@ -436,11 +429,6 @@ bool CScript::IsPayToCCV2(int &subversion) const } return (false); } -bool CScript::IsPayToCCV2() const -{ - int subversion; - return IsPayToCCV2(subversion); -} const std::vector CScript::GetCCV2SPK() const { @@ -486,15 +474,11 @@ bool CScript::MayAcceptCryptoCondition() const if (!IsCCOpcodeValid(opcode, data)) return false; CC *cond = cc_readConditionBinaryMaybeMixed(data.data(), data.size()); - if (!cond) { - std::cerr << __func__ << " cond is null" << std::endl; - return false; - } + if (!cond) return false; CC_SUBVER ccSubVersion = CC_MixedModeSubVersion((*this)[0]); bool out = IsSupportedCryptoCondition(cond, ccSubVersion); cc_free(cond); - std::cerr << __func__ << " out=" << out << std::endl; return out; } From a7e8a1b286a2830ded23fed6c44527fc430b16ef Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 29 Apr 2022 13:04:44 +0500 Subject: [PATCH 246/348] help cond fixed --- src/rpc/ccutilsrpc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index fd3d481dfbb..35f6bbd58c0 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -208,7 +208,7 @@ UniValue getindexkeyforcc(const UniValue& params, bool fHelp, const CPubKey& rem "Sample:\n" "getindexkeyforcc \'{ \"type\": \"threshold-sha-256\", \"threshold\": 2, \"subfulfillments\":" "[{\"type\":\"eval-sha-256\",\"code\":\"9A\"}, {\"type\":\"threshold-sha-256\", \"threshold\":1," - "subfulfillments\":[{ \"type\": \"secp256k1-sha-256\", \"publicKey\": \"03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12\" }] }] }\' true\n\n" + "\"subfulfillments\":[{ \"type\": \"secp256k1-sha-256\", \"publicKey\": \"03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12\" }] }] }\' true\n\n" ; throw std::runtime_error(msg); } From 616c3e04fd8094b602b04e99fc1bcf742d67fae3 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 2 May 2022 12:06:24 +0500 Subject: [PATCH 247/348] fixed royalty dust calc for assets cc --- src/cc/CCassets.h | 2 ++ src/cc/CCassetsUtils.cpp | 18 ++++++++++++++++++ src/cc/assets.cpp | 37 +++++++++++++++++++++++++++---------- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index 198b5be97c1..637aef5a496 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -47,6 +47,8 @@ bool SetAskFillamounts(CAmount unit_price, CAmount fill_assetoshis, CAmount orig bool SetSwapFillamounts(CAmount unit_price, CAmount &paid, CAmount orig_nValue, CAmount &received, CAmount totalprice); // not implemented CAmount AssetsGetTxCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx); CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, const CTransaction &tx); +bool AssetsFillAskIsDust(int32_t royaltyFract, CAmount nOutputValue, int32_t nHeight, bool &isRoyaltyDust); + const char ccassets_log[] = "ccassets"; diff --git a/src/cc/CCassetsUtils.cpp b/src/cc/CCassetsUtils.cpp index 38037932849..2e52ada9bb5 100644 --- a/src/cc/CCassetsUtils.cpp +++ b/src/cc/CCassetsUtils.cpp @@ -15,6 +15,9 @@ #include "CCassets.h" #include "CCtokens.h" +#include "cc/CCupgrades.h" +#include "CCTokelData.h" + #include vscript_t EncodeAssetOpRetV1(uint8_t assetFuncId, CAmount unit_price, vscript_t origpubkey, int32_t expiryHeight) @@ -497,4 +500,19 @@ CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, con } } return inputs; +} + +// check if either royalty or paid_value is dust in fill ask +// nOutputValue is the total amount of paid_value + royalty +bool AssetsFillAskIsDust(int32_t royaltyFract, CAmount nOutputValue, int32_t nHeight, bool &isRoyaltyDust) +{ + // nOutputValue is sum of paid_value + royalty_value + // check whether any of them is assets' dust (calc min of royalty and paid_value, compare with assets' dust): + if (nOutputValue / (int64_t)TKLROYALTY_DIVISOR * std::min(royaltyFract, (int32_t)TKLROYALTY_DIVISOR - royaltyFract) <= ASSETS_NORMAL_DUST) { + // decide who should receive nOutputValue if one of values is dust + isRoyaltyDust = royaltyFract < (int64_t)TKLROYALTY_DIVISOR / 2 ? true : false; + //std::cerr << __func__ << " new calc, nOutputValue=" << nOutputValue << " test dust=" << nOutputValue / (int64_t)TKLROYALTY_DIVISOR * std::min(royaltyFract, (int32_t)TKLROYALTY_DIVISOR - royaltyFract) << " isRoyaltyDust=" << isRoyaltyDust << std::endl; + return true; + } + return false; } \ No newline at end of file diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 00dc8c22973..0fa98c0b6b1 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -544,13 +544,30 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (royaltyFract < 0LL || royaltyFract >= TKLROYALTY_DIVISOR) return eval->Invalid("invalid royalty value"); - int32_t r = royaltyFract > 0 ? 1 : 0; - // check if royalty not dust - if (royaltyFract > 0 && tx.vout[2].nValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) // if value paid to seller less than when the royalty is minimum - r = 0; - //if (royaltyValue <= ASSETS_NORMAL_DUST) - // royaltyValue = 0LL; // reset if dust - CAmount paid_value = r > 0 ? tx.vout[2].nValue + tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner + int32_t hasRoyaltyVout = royaltyFract > 0 ? 1 : 0; + bool isRoyaltyDust = true; // if no royalty then to order creator + + // check if royalty or paid_value is not dust + if (royaltyFract > 0) + { + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1) == false) { + // old bad calc: only if royalty<=50% works bcz of loss of significance bcz of division by royaltyFract first. + // also wrong assumption that paid_value is subtracted by the royalty (in fact it is sum of both if the royalty is dust) + // suppose the nValue is such that the royalty_value is assets' dust: + if (tx.vout[2].nValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) { // if value paid to seller less than when the royalty is minimum + isRoyaltyDust = true; // always to order creator + hasRoyaltyVout = 0; // no royalty vout + //std::cerr << __func__ << " old calc, tx.vout[2].nValue=" << tx.vout[2].nValue << " test dust=" << ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST << std::endl; + } + } + else { + // fixed dust calc: + if (AssetsFillAskIsDust(royaltyFract, vin_tokens * vin_unit_price, eval->GetCurrentHeight(), isRoyaltyDust)) + hasRoyaltyVout = 0; // no dedicated royalty vout, total goes to tx.vout[2].nValue + } + } + + CAmount paid_value = hasRoyaltyVout > 0 ? tx.vout[2].nValue + tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner if (!ValidateAskRemainder(unit_price, tx.vout[0].nValue, vin_tokens, tx.vout[1].nValue, paid_value)) return eval->Invalid("mismatched vout0 remainder for fillask"); else if (!AssetsValidateTokenId_Activated(eval, cp, tx, 0, assetid)) @@ -559,9 +576,9 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("vout1 should be cc for fillask"); else if (!AssetsValidateTokenId_Activated(eval, cp, tx, 1, assetid)) return eval->Invalid("invalid tokenid in vout1 for fillask"); - else if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, origNormalAddr, 0LL, 0)) // coins to originator normal addr + else if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, (hasRoyaltyVout > 0 || isRoyaltyDust ? origNormalAddr : ownerNormalAddr), 0LL, 0)) // coins to order originator normal addr (if royalty dust then to token creator) return eval->Invalid("vout2 should be cc for fillask"); - if (r > 0) { + if (hasRoyaltyVout > 0) { if ((tx.vout[2].nValue + tx.vout[3].nValue) / TKLROYALTY_DIVISOR * royaltyFract != tx.vout[3].nValue) // validate royalty value return eval->Invalid("vout3 invalid royalty amount for fillask"); if (!A::ConstrainVout(tx.vout[3], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest @@ -570,7 +587,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (!A::ConstrainVout(tx.vout[0], CCVOUT, tokensDualEvalUnspendableCCaddr, 0LL, A::EvalCode())) // tokens remainder on global addr return eval->Invalid("invalid vout0 should pay to tokens/assets global address for fillask"); if (tx.vout[0].nValue > 0) { - int32_t markerVout = r > 0 ? 4 : 3; + int32_t markerVout = hasRoyaltyVout > 0 ? 4 : 3; // marker should exist if remainder not empty if (tx.vout.size() <= markerVout || A::ConstrainVout(tx.vout[markerVout], CCVOUT, markerCCaddress, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false) // marker to originator asset cc addr return eval->Invalid("invalid marker vout for original pubkey"); From b90533f60600b9dbc3deecbad8d2943b6dbfed59 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 2 May 2022 12:07:10 +0500 Subject: [PATCH 248/348] indent space in build-mac --- zcutil/build-mac.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index d19d8d6a54f..499c143fe4f 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -58,8 +58,8 @@ fi WEBSOCKETS_ARG='' if [ "x${1:-}" = 'x--enable-websockets' ] then -WEBSOCKETS_ARG='--enable-websockets=yes' -shift + WEBSOCKETS_ARG='--enable-websockets=yes' + shift fi TRIPLET=`./depends/config.guess` From 820e4de966c5a32810327465a49b5d45ec9614ec Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 2 May 2022 12:07:55 +0500 Subject: [PATCH 249/348] validation tests fixed for assets cc royalty --- src/test-komodo-cc/test-assets.cpp | 155 +++++++++++++++++++++++------ 1 file changed, 122 insertions(+), 33 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 181cb57a5e2..1603108339e 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -165,7 +165,6 @@ bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vin // in functions like cp->ismyvin() or TotalPubkeyNormalAmount() bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_t *myprivkey, CAmount txfee, CScript opret) { - std::cerr << __func__ << " enterred" << std::endl; auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); CAmount totaloutputs = 0LL; for (int i = 0; i < mtx.vout.size(); i ++) @@ -646,11 +645,13 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " cant get tokendata" << std::endl; return CTransaction(); } + bool bGetTokelDataAsInt64 = false; if (vextraData.size() > 0) { - GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); + bGetTokelDataAsInt64 = GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); if (royaltyFract > TKLROYALTY_DIVISOR-1) royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } + //std::cerr << __func__ << " vextraData.size()=" << vextraData.size() << " bGetTokelDataAsInt64=" << bGetTokelDataAsInt64 << std::endl; vuint8_t ownerpubkey = std::get<0>(tokenData); vuint8_t origpubkey; @@ -662,8 +663,27 @@ class TestAssetsCC : public ::testing::Test { CAmount paid_nValue = paid_unit_price * fill_units; CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / TKLROYALTY_DIVISOR * royaltyFract : 0; - if (royaltyFract > 0 && paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) // if value paid to seller less than when the royalty is minimum - royaltyValue = 0LL; + + bool isRoyaltyDust = true; + if (royaltyFract > 0) { + + if (CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1) == false) { + // corrected old calculation to allow tx creation and pass to fillask validation code + // (note division on TKLROYALTY_DIVISOR first): + if(paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / (int64_t)TKLROYALTY_DIVISOR * royaltyFract - ASSETS_NORMAL_DUST) { // if value paid to seller less than when the royalty is minimum + royaltyValue = 0; + //std::cerr << __func__ << " old calc corrected, paid_nValue - royaltyValue=" << paid_nValue - royaltyValue << " test dust=" << ASSETS_NORMAL_DUST / (int64_t)TKLROYALTY_DIVISOR * royaltyFract - ASSETS_NORMAL_DUST << std::endl; + } + } + else { + // correct calculation: + if (AssetsFillAskIsDust(royaltyFract, paid_nValue, eval.GetCurrentHeight(), isRoyaltyDust)) + royaltyValue = 0; // all amount (with dust) to go to one pk (depending on which is not dust) + } + } + + + //std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << std::endl; if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { std::cerr << __func__ << " cant add normal inputs" << std::endl; @@ -675,8 +695,10 @@ class TestAssetsCC : public ::testing::Test { mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), orig_assetoshis - fill_units, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, mypk)); - mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, mypk)); + + vuint8_t destpk = (royaltyValue > 0 || isRoyaltyDust) ? origpubkey : ownerpubkey; // if paid_value is dust send all amount to token owner + mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << destpk << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr if (royaltyValue > 0) // note it makes the vout even if roaltyValue is 0 mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner @@ -702,7 +724,9 @@ class TestAssetsCC : public ::testing::Test { data.pushKV("ownerpubkey", HexStr(ownerpubkey)); data.pushKV("origpubkey", HexStr(origpubkey)); data.pushKV("unit_price", unit_price); - + data.pushKV("royaltyFract", royaltyFract); + data.pushKV("royaltyValue", royaltyValue); + data.pushKV("isRoyaltyDust", isRoyaltyDust); return mtx; } @@ -865,6 +889,8 @@ class TestAssetsCC : public ::testing::Test { data.pushKV("origpubkey", HexStr(origpubkey)); data.pushKV("unit_price", unit_price); data.pushKV("expiryHeight", expiryHeight); + data.pushKV("royaltyFract", royaltyFract); + data.pushKV("royaltyValue", royaltyValue); return mtx; } @@ -1644,7 +1670,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_royalty) { eval.SetCurrentHeight(111); //set height - for(int r = 0; r < 1000; r += 100) + for(int r = 100; r < 1000; r += 100) { UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx UniValue tokeldata(UniValue::VOBJ); @@ -1654,27 +1680,31 @@ TEST_F(TestAssetsCC, tokenv2fillbid_royalty) cpAssets = CCinit(&assetsC, AssetsV2::EvalCode()); tokeldata.pushKV("royalty", r); - // use static mtx as it is added to static eval - static CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); + CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); uint256 mytokenid = mytxtokencreate.GetHash(); eval.AddTx(mytxtokencreate); - static CTransaction mytxbid = MakeTokenV2BidTx(cpAssets, pk2, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); + CTransaction mytxbid = MakeTokenV2BidTx(cpAssets, pk2, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); eval.AddTx(mytxbid); - CMutableTransaction mytxfill = MakeTokenV2FillBidTx(cpTokens, pk1, mytokenid, mytxbid.GetHash(), 1, 0, data); - ASSERT_FALSE(CTransaction(mytxfill).IsNull()); + CMutableTransaction mytxfillbid = MakeTokenV2FillBidTx(cpTokens, pk1, mytokenid, mytxbid.GetHash(), 1, 0, data); + ASSERT_FALSE(CTransaction(mytxfillbid).IsNull()); + ASSERT_TRUE(data["royaltyFract"].get_int64() == r); // test: valid tokenv2fillbid - EXPECT_TRUE(TestRunCCEval(mytxfill)); + EXPECT_TRUE(TestRunCCEval(mytxfillbid)); } } -TEST_F(TestAssetsCC, tokenv2fillask_royalty) +// test old incorrect validation rule that failed royalties > 50% +TEST_F(TestAssetsCC, tokenv2fillask_royalty_non_fixed) { - eval.SetCurrentHeight(111); //set height + eval.SetCurrentHeight(CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT - 1); + strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); - for(int r = 0; r < 1000; r += 100) + ASSERT_FALSE(CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)); + for(int r = 100; r < 1000; r += 100) { UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx UniValue tokeldata(UniValue::VOBJ); @@ -1684,18 +1714,79 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty) cpAssets = CCinit(&assetsC, AssetsV2::EvalCode()); tokeldata.pushKV("royalty", r); - static CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); + CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); uint256 mytokenid = mytxtokencreate.GetHash(); eval.AddTx(mytxtokencreate); - static CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); + CAmount price = 211110000; + CAmount asktokens = 1; + CAmount filltokens = 1; + + // CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); + CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, asktokens, price, CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT + 222); eval.AddTx(mytxask); - CMutableTransaction mytxfill = MakeTokenV2FillAskTx(cpAssets, pk2, mytokenid, mytxask.GetHash(), 1, 0, data); - ASSERT_FALSE(CTransaction(mytxfill).IsNull()); + CMutableTransaction mytxfillask = MakeTokenV2FillAskTx(cpAssets, pk2, mytokenid, mytxask.GetHash(), filltokens, 0, data); + ASSERT_FALSE(CTransaction(mytxfillask).IsNull()); + ASSERT_TRUE(data["royaltyFract"].get_int64() == r); + ASSERT_TRUE(data["royaltyValue"].get_int64() > 0); // must not be dust for this test - // test: valid tokenv2fillbid - EXPECT_TRUE(TestRunCCEval(mytxfill)); + if (r <= 500) + EXPECT_TRUE(TestRunCCEval(mytxfillask)); // valid fillask if royalty <= 50% + else + EXPECT_FALSE(TestRunCCEval(mytxfillask)); + } +} + +// test fill ask updated validation rule +TEST_F(TestAssetsCC, tokenv2fillask_royalty_fixed) +{ + eval.SetCurrentHeight(CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT); + strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); + + ASSERT_TRUE(CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)); // fix in action + for(int r = 100; r < 1000; r += 100) + { + UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx + UniValue tokeldata(UniValue::VOBJ); + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + struct CCcontract_info *cpAssets, assetsC; + cpAssets = CCinit(&assetsC, AssetsV2::EvalCode()); + + tokeldata.pushKV("royalty", r); + CTransaction mytxtokencreate = MakeTokenV2CreateTx(pk1, 1, tokeldata); + uint256 mytokenid = mytxtokencreate.GetHash(); + eval.AddTx(mytxtokencreate); + CAmount price = 4999; + CAmount asktokens = 1; + CAmount filltokens = 1; + // CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); + CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, asktokens, price, CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT + 222); + eval.AddTx(mytxask); + + CMutableTransaction mytxfillask = MakeTokenV2FillAskTx(cpAssets, pk2, mytokenid, mytxask.GetHash(), filltokens, 0, data); + ASSERT_FALSE(CTransaction(mytxfillask).IsNull()); + ASSERT_TRUE(data["royaltyFract"].get_int64() == r); + + if (r == 100 || r == 900) EXPECT_TRUE(data["royaltyValue"].get_int64() == 0); // for these royalties t should be dust + + // test: valid tokenv2fillask + //std::cerr << __func__ << " good rule, is dust calc=" << (filltokens * price / (int64_t)TKLROYALTY_DIVISOR * std::min(r, (int32_t)TKLROYALTY_DIVISOR - r)) << " royaltyValue=" << data["royaltyValue"].get_int64() << std::endl; + if (filltokens * price / (int64_t)TKLROYALTY_DIVISOR * std::min(r, (int32_t)TKLROYALTY_DIVISOR - r) <= ASSETS_NORMAL_DUST) { + // have dust + EXPECT_TRUE(data["royaltyValue"].get_int64() == 0); + EXPECT_TRUE(TestRunCCEval(mytxfillask)); + EXPECT_TRUE(mytxfillask.vout[2].nValue == filltokens * price); + EXPECT_TRUE(r < TKLROYALTY_DIVISOR/2 ? data["isRoyaltyDust"].get_bool() : !data["isRoyaltyDust"].get_bool()); // is dust royalty or paid_value + } + else { + // no dust + EXPECT_TRUE(data["royaltyValue"].get_int64() > 0); + EXPECT_TRUE(TestRunCCEval(mytxfillask)); + EXPECT_TRUE(mytxfillask.vout[2].nValue + mytxfillask.vout[3].nValue == filltokens * price); + } } } @@ -1824,13 +1915,11 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - // use static mtx as it is added to static eval - static CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txaskexp).IsNull()); eval.AddTx(txaskexp); EXPECT_TRUE(TestRunCCEval(txaskexp)); - UniValue data(UniValue::VOBJ); uint256 asktxid = txaskexp.GetHash(); @@ -1848,7 +1937,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - static CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txaskexp).IsNull()); eval.AddTx(txaskexp); EXPECT_TRUE(TestRunCCEval(txaskexp)); @@ -1871,7 +1960,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); // use static mtx as it is added to static eval - static CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txaskexp).IsNull()); eval.AddTx(txaskexp); EXPECT_TRUE(TestRunCCEval(txaskexp)); @@ -1899,7 +1988,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_expired) struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - static CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txaskexp).IsNull()); eval.AddTx(txaskexp); EXPECT_TRUE(TestRunCCEval(txaskexp)); @@ -2011,7 +2100,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid_expired) cpAssets0 = CCinit(&C0, AssetsV2::EvalCode()); // use static mtx as it is added to static eval - static CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txbidexp).IsNull()); eval.AddTx(txbidexp); EXPECT_TRUE(TestRunCCEval(txbidexp)); @@ -2034,7 +2123,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid_expired) struct CCcontract_info *cpAssets0, C0; cpAssets0 = CCinit(&C0, AssetsV2::EvalCode()); - static CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txbidexp).IsNull()); eval.AddTx(txbidexp); EXPECT_TRUE(TestRunCCEval(txbidexp)); @@ -2057,7 +2146,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid_expired) cpAssets0 = CCinit(&C0, AssetsV2::EvalCode()); // use static mtx as it is added to static eval - static CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 + CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txbidexp).IsNull()); eval.AddTx(txbidexp); EXPECT_TRUE(TestRunCCEval(txbidexp)); @@ -2085,7 +2174,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_expired) struct CCcontract_info *cpAssets, assetsC; cpAssets = CCinit(&assetsC, AssetsV2::EvalCode()); - static CTransaction txbidexp = MakeTokenV2BidTx(cpAssets, pk1, tokenid2, 2, 10000, 222); // set expiry height 222 + CTransaction txbidexp = MakeTokenV2BidTx(cpAssets, pk1, tokenid2, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txbidexp).IsNull()); eval.AddTx(txbidexp); EXPECT_TRUE(TestRunCCEval(txbidexp)); From b355bd12ac808edc545d4905eb69a745aab3b9bd Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 6 May 2022 19:42:00 +0500 Subject: [PATCH 250/348] added kmd tokel version to configure, show fixed ver in getpeerinfo getinfo --- configure.ac | 15 ++++++++++-- src/alert.cpp | 4 +++- src/cc/CCupgrades.cpp | 53 ++++++++++++++++++++++++++++++++++--------- src/cc/CCupgrades.h | 24 ++++++++++++++++---- src/clientversion.cpp | 18 ++++++--------- src/clientversion.h | 8 +++---- src/init.cpp | 9 +++++--- src/komodo_version.h | 31 +++++++++++++++++++++++++ src/main.cpp | 19 +++++++++++++--- src/rpc/misc.cpp | 7 ++++-- src/rpc/net.cpp | 3 ++- src/version.h | 2 +- 12 files changed, 149 insertions(+), 44 deletions(-) create mode 100644 src/komodo_version.h diff --git a/configure.ac b/configure.ac index 1d22cf5b9cd..08372eb4a14 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,6 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) +dnl zcash version define(_CLIENT_VERSION_MAJOR, 3) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 0) @@ -7,13 +8,23 @@ define(_CLIENT_VERSION_BUILD, 0) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) -define(_COPYRIGHT_YEAR, 2018) -AC_INIT([Verus-CLI],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://github.com/VerusCoin/VerusCoin/issues],[verus-cli]) +define(_COPYRIGHT_YEAR, 2022) +AC_INIT([tokel-CLI],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://github.com/TokelPlatform/komodo/issues],[tokel-cli]) AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([build-aux/m4]) +dnl komodo codebase version +define(_KOMODO_VERSION, 60000) + +dnl tokel codebase version +define(_TOKEL_VERSION, 30100) + +AC_DEFINE(KOMODO_VERSION, _KOMODO_VERSION, [Komodo Version]) +AC_DEFINE(TOKEL_VERSION, _TOKEL_VERSION, [Tokel Version]) + + BITCOIN_DAEMON_NAME=komodod BITCOIN_CLI_NAME=komodo-cli BITCOIN_TX_NAME=komodo-tx diff --git a/src/alert.cpp b/src/alert.cpp index e76f6a41108..d6686bb629b 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -27,6 +27,8 @@ #include "ui_interface.h" #include "util.h" +#include "komodo_version.h" + #include #include #include @@ -137,7 +139,7 @@ bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const bool CAlert::AppliesToMe() const { - return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector())); + return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, { TOKEL_CLIENT_NAME })); } bool CAlert::RelayTo(CNode* pnode) const diff --git a/src/cc/CCupgrades.cpp b/src/cc/CCupgrades.cpp index 0037c20404b..8f90edaeca3 100644 --- a/src/cc/CCupgrades.cpp +++ b/src/cc/CCupgrades.cpp @@ -14,31 +14,48 @@ ******************************************************************************/ #include +#include #include "CCupgrades.h" namespace CCUpgrades { class CUpgradesContainer { private: - void addUpgradeActive(const std::string &chainName, UPGRADE_ID upgradeId, int32_t nHeight) + + + void init(const std::string &chainName, int nProtocolVersion) + { + assert(mChainUpgrades.find(chainName) == mChainUpgrades.end()); // mChainUpgrades[chainName] must be empty + mChainUpgrades[chainName].setActivationHeight(CCASSETS_INITIAL_CHAIN, 0, UPGRADE_ACTIVE, nProtocolVersion); + } + + void addUpgradeActive(const std::string &chainName, UPGRADE_ID upgradeId, int32_t nHeight, int nProtocolVersion) { - mChainUpgrades[chainName].setActivationHeight(upgradeId, nHeight, UPGRADE_ACTIVE); + assert(mChainUpgrades.find(chainName) != mChainUpgrades.end()); // mChainUpgrades[chainName] must be initialised + mChainUpgrades[chainName].setActivationHeight(upgradeId, nHeight, UPGRADE_ACTIVE, nProtocolVersion); } public: CUpgradesContainer() { // default upgrades: always enable all fixes - defaultUpgrades.IsAllEnabled = true; + init("TOKEL", CCOLDDEFAULT_PROTOCOL_VERSION); + init("TKLTEST", CCOLDDEFAULT_PROTOCOL_VERSION); + init("DIMXY24", CCOLDDEFAULT_PROTOCOL_VERSION); + init("DIMXY28", CCOLDDEFAULT_PROTOCOL_VERSION); + init("TKLTEST2", CCOLDDEFAULT_PROTOCOL_VERSION); + init("DIMXY32", CCOLDDEFAULT_PROTOCOL_VERSION); // CCASSETS_OPDROP_VALIDATE_FIX activation - addUpgradeActive("TOKEL", CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); - addUpgradeActive("TKLTEST", CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT); + addUpgradeActive("TOKEL", CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TOKEL_HEIGHT, CCOLDDEFAULT_PROTOCOL_VERSION); + addUpgradeActive("TKLTEST", CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT, CCOLDDEFAULT_PROTOCOL_VERSION); // CCMIXEDMODE_SUBVER_1 activation - addUpgradeActive("TOKEL", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT); - addUpgradeActive("TKLTEST", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT); - addUpgradeActive("DIMXY24", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT); - addUpgradeActive("TKLTEST2", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT); + addUpgradeActive("TOKEL", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("TKLTEST", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("DIMXY24", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("DIMXY28", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("DIMXY32", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("TKLTEST2", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); // add more chains here... // ... @@ -69,8 +86,8 @@ namespace CCUpgrades { bool IsUpgradeActive(int32_t nHeight, const ChainUpgrades &chainUpgrades, UPGRADE_ID id) { - if (chainUpgrades.IsAllEnabled) - return true; + if (chainUpgrades.mUpgrades.size() == 0) + return chainUpgrades.defaultUpgrade.status == UPGRADE_ACTIVE; else { std::map::const_iterator it = chainUpgrades.mUpgrades.find(id); if (it != chainUpgrades.mUpgrades.end()) @@ -78,5 +95,19 @@ namespace CCUpgrades { return false; } } + + UpgradeInfo GetCurrentUpgradeInfo(int32_t nHeight, const ChainUpgrades &chainUpgrades) + { + if (chainUpgrades.mUpgrades.size() == 0) + return chainUpgrades.defaultUpgrade; + else { + UpgradeInfo current = chainUpgrades.mUpgrades.find(CCASSETS_INITIAL_CHAIN)->second; // set as initial chain info + for (auto const & it : chainUpgrades.mUpgrades) { + if (nHeight >= it.second.nActivationHeight) + current = it.second; // find latest active upgrade + } + return current; + } + } }; // namespace CCUpgrades diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index 1685352bbe4..d3c524ae67b 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -21,6 +21,8 @@ #include #include +#include "version.h" + namespace CCUpgrades { // asset chain activation heights @@ -30,36 +32,48 @@ namespace CCUpgrades { const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT = 100000000; // TBD const int32_t CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT = 100000000; // TBD const int32_t CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT = 100000000; // TBD + const int32_t CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT = 100000000; // TBD + const int32_t CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT = 100000000; // TBD const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 57544; // 25 apr 2022 4:10p.m + // latest protocol version: + const int CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION = 170010; + // pre-upgrade protocol version: + const int CCOLDDEFAULT_PROTOCOL_VERSION = 170009; + const int CCNEWCHAIN_PROTOCOL_VERSION = CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION; enum UPGRADE_STATUS { UPGRADE_ACTIVE = 1, }; enum UPGRADE_ID { + CCASSETS_INITIAL_CHAIN = 0x00, CCASSETS_OPDROP_VALIDATE_FIX = 0x01, - CCMIXEDMODE_SUBVER_1 = 0x02, // new cc secp256k1 cond type and eval param + CCMIXEDMODE_SUBVER_1 = 0x02, // new cc secp256k1 cond type and eval param, assets cc royalty fixes }; struct UpgradeInfo { int32_t nActivationHeight; UPGRADE_STATUS status; + int nProtocolVersion; // used for disconnecting old nodes }; class ChainUpgrades { public: - ChainUpgrades() : IsAllEnabled(false) { } - void setActivationHeight(UPGRADE_ID upgId, int32_t nHeight, UPGRADE_STATUS upgStatus) { - mUpgrades[upgId] = { nHeight, upgStatus }; + ChainUpgrades() : defaultUpgrade({0, UPGRADE_ACTIVE, CCNEWCHAIN_PROTOCOL_VERSION}) { } + void setActivationHeight(UPGRADE_ID upgId, int32_t nHeight, UPGRADE_STATUS upgStatus, int nProtocolVersion) { + mUpgrades[upgId] = { nHeight, upgStatus, nProtocolVersion }; } + public: std::map mUpgrades; - bool IsAllEnabled; + const UpgradeInfo defaultUpgrade; }; void SelectUpgrades(const std::string &chainName); const ChainUpgrades &GetUpgrades(); bool IsUpgradeActive(int32_t nHeight, const ChainUpgrades &chainUpgrades, UPGRADE_ID upgId); + UpgradeInfo GetCurrentUpgradeInfo(int32_t nHeight, const ChainUpgrades &chainUpgrades); + }; // namespace CCUpgrades #endif // #ifndef CC_UPGRADES_H diff --git a/src/clientversion.cpp b/src/clientversion.cpp index 084bbd5ceed..36bffea8cce 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2022 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -35,7 +35,8 @@ * for both bitcoind and bitcoin-core, to make it harder for attackers to * target servers or GUI users specifically. */ -const std::string CLIENT_NAME = GetArg("-clientname", "MagicBean"); + +const std::string CLIENT_NAME = GetArg("-clientname", "komodod"); /** * Client version number @@ -117,16 +118,10 @@ const std::string CLIENT_NAME = GetArg("-clientname", "MagicBean"); const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX); const std::string CLIENT_DATE(BUILD_DATE); -std::string FormatVersion(int nVersion) +std::string FormatVersion(int nVersion, const std::string &stage) { - if (nVersion % 100 < 25) - return strprintf("%d.%d.%d-beta%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, (nVersion % 100)+1); - if (nVersion % 100 < 50) - return strprintf("%d.%d.%d-rc%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, (nVersion % 100)-24); - else if (nVersion % 100 == 50) - return strprintf("%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100); - else - return strprintf("%d.%d.%d-%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, (nVersion % 100)-50); + // use own rules to determine the development stage + return strprintf("%d.%d.%d%s", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, stage); } std::string FormatFullVersion() @@ -136,6 +131,7 @@ std::string FormatFullVersion() /** * Format the subversion field according to BIP 14 spec (https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki) + * added derived repo extension's version */ std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments) { diff --git a/src/clientversion.h b/src/clientversion.h index eced952e12f..f05f31d3507 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2022 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -30,8 +30,8 @@ */ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it -#define CLIENT_VERSION_MAJOR 3 -#define CLIENT_VERSION_MINOR 0 +#define CLIENT_VERSION_MAJOR 0 +#define CLIENT_VERSION_MINOR 6 #define CLIENT_VERSION_REVISION 1 #define CLIENT_VERSION_BUILD 0 @@ -78,7 +78,7 @@ extern const std::string CLIENT_BUILD; extern const std::string CLIENT_DATE; -std::string FormatVersion(int nVersion); +std::string FormatVersion(int nVersion, const std::string &stage = std::string()); std::string FormatFullVersion(); std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments); diff --git a/src/init.cpp b/src/init.cpp index da1fa68c461..453804bc179 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -36,6 +36,7 @@ #include "httprpc.h" #include "key.h" #include "notarisationdb.h" +#include "komodo_version.h" #ifdef ENABLE_MINING #include "key_io.h" @@ -1007,7 +1008,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fLogIPs = GetBoolArg("-logips", false); LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("Zcash version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); + LogPrintf("Zcash version %s\n", FormatFullVersion()); // when specifying an explicit binding address, you want to listen on it // even when -connect or -proxy is specified @@ -1381,7 +1382,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (GetBoolArg("-shrinkdebugfile", !fDebug)) ShrinkDebugFile(); LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("Komodo version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); + LogPrintf("Komodo version %s\n", FormatVersion(KOMODO_VERSION)); + LogPrintf("Tokel version %s (%s)\n", FormatVersion(TOKEL_VERSION), CLIENT_DATE); if (fPrintToDebugLog) OpenDebugLog(); @@ -1473,7 +1475,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(strprintf("User Agent comment (%s) contains unsafe characters.", cmt)); uacomments.push_back(SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)); } - strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments); + uacomments.insert(uacomments.begin(), TOKEL_CLIENT_NAME); + strSubVersion = FormatSubVersion(CLIENT_NAME, KOMODO_VERSION, uacomments); if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) { return InitError(strprintf("Total length of network version string %i exceeds maximum of %i characters. Reduce the number and/or size of uacomments.", strSubVersion.size(), MAX_SUBVERSION_LENGTH)); diff --git a/src/komodo_version.h b/src/komodo_version.h new file mode 100644 index 00000000000..c84b4645362 --- /dev/null +++ b/src/komodo_version.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * Copyright © 2022 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. * + * * + ******************************************************************************/ + +#ifndef KOMODO_VERSION_H +#define KOMODO_VERSION_H + +#include +#include "clientversion.h" +#include "config/bitcoin-config.h" + +// version = major * 1000000 + minor * 10000 + rev * 100 + build +//const int KOMODO_VERSION = 60000; +//const int TOKEL_VERSION = 30100; + +const std::string KOMODO_CLIENT_NAME = std::string("komodod:") + FormatVersion(KOMODO_VERSION); +const std::string TOKEL_CLIENT_NAME = std::string("tokeld:") + FormatVersion(TOKEL_VERSION); + + +#endif // #ifndef KOMODO_VERSION_H diff --git a/src/main.cpp b/src/main.cpp index f0fc31a760a..79afa34f748 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7530,7 +7530,7 @@ void static ProcessGetData(CNode* pfrom) bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived) { - int32_t nProtocolVersion; + //int32_t nProtocolVersion; const CChainParams& chainparams = Params(); LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); //if ( KOMODO_NSPV_SUPERLITE ) @@ -7588,6 +7588,17 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return false; } + // check min cc version + if (nVersion < GetCurrentUpgradeInfo(GetHeight(), CCUpgrades::GetUpgrades()).nProtocolVersion) + { + LogPrintf("peer=%d using obsolete version %i, needed %d; disconnecting by ccupgrades\n", pfrom->id, nVersion, GetCurrentUpgradeInfo(GetHeight(), CCUpgrades::GetUpgrades()).nProtocolVersion); + pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, + strprintf("Version must be %d or greater", + GetCurrentUpgradeInfo(GetHeight(), CCUpgrades::GetUpgrades()).nProtocolVersion)); + pfrom->fDisconnect = true; + return false; + } + if (!vRecv.empty()) vRecv >> addrFrom >> nNonce; if (!vRecv.empty()) { @@ -7891,6 +7902,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // the getaddr message mitigates the attack. else if ((strCommand == "getaddr") && (pfrom->fInbound)) { + std::cerr << __func__ << " in getaddr, node=" << pfrom->id << std::endl; // Only send one GetAddr response per connection to reduce resource waste // and discourage addr stamping of INV announcements. if (pfrom->fSentAddr) { @@ -7902,7 +7914,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->vAddrToSend.clear(); vector vAddr = addrman.GetAddr(); BOOST_FOREACH(const CAddress &addr, vAddr) - pfrom->PushAddress(addr); + pfrom->PushAddress(addr); + std::cerr << __func__ << " on getaddr pushed addresses=" << vAddr.size() << " node=" << pfrom->id << std::endl; } // temporary optional nspv message processing else if ((nLocalServices & NODE_NSPV) && @@ -8599,7 +8612,7 @@ bool ProcessMessages(CNode* pfrom) { #ifdef ENABLE_WEBSOCKETS - if (pfrom->hSocket != INVALID_SOCKET || !(fRet = ProcessWsMessage(pfrom, strCommand, vRecv, msg.nTime))) { + if (pfrom->hSocket != INVALID_SOCKET || !(fRet = ws::ProcessWsMessage(pfrom, strCommand, vRecv, msg.nTime))) { #endif fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime); #ifdef ENABLE_WEBSOCKETS diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 1e4ebb058a1..d5e9f06d6a1 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -35,6 +35,7 @@ #include "wallet/wallet.h" #include "wallet/walletdb.h" #endif +#include "komodo_version.h" #include @@ -60,8 +61,9 @@ using namespace std; * Or alternatively, create a specific query method for the information. **/ -#define KOMODO_VERSION "0.6.1" +// #define KOMODO_VERSION "0.6.1" // see komodo_version.h #define VERUS_VERSION "0.4.0g" +// see also TOKEL_VERSION in komodo_version.h int32_t getera(int timestamp) { @@ -211,7 +213,8 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) UniValue obj(UniValue::VOBJ); obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("protocolversion", PROTOCOL_VERSION)); - obj.push_back(Pair("KMDversion", KOMODO_VERSION)); + obj.push_back(Pair("KMDversion", FormatVersion(KOMODO_VERSION))); + obj.push_back(Pair("TokelVersion", FormatVersion(TOKEL_VERSION))); obj.push_back(Pair("synced", KOMODO_INSYNC!=0)); //obj.push_back(Pair("VRSCversion", VERUS_VERSION)); obj.push_back(Pair("notarized", notarized_height)); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 68a5c915063..70463f4a232 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -28,6 +28,7 @@ #include "util.h" #include "version.h" #include "deprecation.h" +#include "komodo_version.h" #include @@ -426,7 +427,7 @@ UniValue getdeprecationinfo(const UniValue& params, bool fHelp, const CPubKey& m UniValue obj(UniValue::VOBJ); obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("subversion", - FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()))); + FormatSubVersion(CLIENT_NAME, KOMODO_VERSION, { FormatVersion(TOKEL_VERSION) }))); obj.push_back(Pair("deprecationheight", DEPRECATION_HEIGHT)); return obj; diff --git a/src/version.h b/src/version.h index 81624e423b3..e698a919a8f 100644 --- a/src/version.h +++ b/src/version.h @@ -24,7 +24,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 170009; +static const int PROTOCOL_VERSION = 170009 + 1; // Tokel HF June 2022 //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; From 49bbc8eb9a6f67cb18e646cd214ec3726d1e3c4b Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 6 May 2022 19:42:39 +0500 Subject: [PATCH 251/348] build.sh help fixed --- zcutil/build-mac.sh | 19 ++++++++++--------- zcutil/build.sh | 6 ++++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index 499c143fe4f..458e16caf50 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -23,11 +23,12 @@ Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov ] [ --enable-debug ] [ --enable-websockets ] [ MAKEARGS... ] +$0 [ --enable-lcov ] [ --enable-websockets ] [ --enable-debug ] [ MAKEARGS... ] Build Komodo and most of its transitive dependencies from source. MAKEARGS are applied to both dependencies and Komodo itself. If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. + If --enable-websockets is passed then websockets support is added for nSPV protocol If --enable-debug is passed, Komodo is built with debugging information. It must be passed after the previous arguments, if present. EOF @@ -44,6 +45,14 @@ then shift fi +# If --enable-websockets is the next argument, enable websockets support for nspv clients: +WEBSOCKETS_ARG='' +if [ "x${1:-}" = 'x--enable-websockets' ] +then + WEBSOCKETS_ARG='--enable-websockets=yes' + shift +fi + # If --enable-debug is the next argument, enable debugging DEBUGGING_ARG='' if [ "x${1:-}" = 'x--enable-debug' ] @@ -54,14 +63,6 @@ then shift fi -# If --enable-websockets is the next argument, enable websockets support for nspv clients: -WEBSOCKETS_ARG='' -if [ "x${1:-}" = 'x--enable-websockets' ] -then - WEBSOCKETS_ARG='--enable-websockets=yes' - shift -fi - TRIPLET=`./depends/config.guess` PREFIX="$(pwd)/depends/$TRIPLET" diff --git a/zcutil/build.sh b/zcutil/build.sh index 2c590f9ea72..8ec5c3255cb 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -44,7 +44,7 @@ then Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [ --enable-debug ] [--enable-websockets] [ MAKEARGS... ] +$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [--enable-websockets] [ --enable-debug ] [ MAKEARGS... ] Build Komodo and most of its transitive dependencies from source. MAKEARGS are applied to both dependencies and Komodo itself. If --enable-lcov is passed, Komodo is configured to add coverage @@ -55,7 +55,9 @@ $0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] If --enable-proton is passed, Komodo is configured to build the Apache Qpid Proton library required for AMQP support. This library is not built by default. It must be passed after the test/mining arguments, if present. - If --enable-websockets is passed, Komodo is configured to build with webspckets support for nspv protocol + If --enable-websockets is passed, Komodo is configured to build with websockets support for nspv protocol + If --enable-debug is passed, Komodo is built with debugging information. It + must be passed after the previous arguments, if present. EOF exit 0 fi From 125e334b44b9a53fe6a9bc9da766d7d422480022 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 6 May 2022 19:43:07 +0500 Subject: [PATCH 252/348] added jmj fixes for debug build --- src/Makefile.am | 84 ++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 12253ecfa7b..caadee77728 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,5 @@ DIST_SUBDIRS = secp256k1 univalue SUBDIRS = cryptoconditions - AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) AM_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) AM_CPPFLAGS = $(HARDENED_CPPFLAGS) @@ -16,7 +15,7 @@ LIBMEMENV += $(builddir)/leveldb/libmemenv.a $(LIBLEVELDB): $(LIBMEMENV) $(LIBLEVELDB) $(LIBMEMENV): - @echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \ + $(AM_V_at)$(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \ CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \ OPT="$(AM_CXXFLAGS) $(PIE_FLAGS) $(CXXFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -D__STDC_LIMIT_MACROS" endif @@ -32,16 +31,8 @@ BITCOIN_INCLUDES += -I$(srcdir)/snark BITCOIN_INCLUDES += -I$(srcdir)/snark/libsnark BITCOIN_INCLUDES += -I$(srcdir)/univalue/include -if TARGET_WINDOWS -LIBBITCOIN_SERVER=libbitcoin_server.a -lcurl -endif -if TARGET_DARWIN -LIBBITCOIN_SERVER=libbitcoin_server.a -lcurl -endif -if TARGET_LINUX -LIBBITCOIN_SERVER=libbitcoin_server.a -lcurl -endif - +LIBBITCOIN_SERVER=libbitcoin_server.a +LIBBITCOIN_WALLET=libbitcoin_wallet.a LIBBITCOIN_COMMON=libbitcoin_common.a LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a @@ -52,6 +43,7 @@ LIBSECP256K1=secp256k1/libsecp256k1.la LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.a LIBSNARK=snark/libsnark.a LIBUNIVALUE=univalue/libunivalue.la +LIBCC=libcc.a LIBZCASH=libzcash.a if ENABLE_ZMQ @@ -63,17 +55,10 @@ endif if BUILD_BITCOIN_LIBS LIBZCASH_CONSENSUS=libzcashconsensus.la endif -if ENABLE_WALLET -LIBBITCOIN_WALLET=libbitcoin_wallet.a -endif - -LIBDYNCUSTOMCONSENSUS = cc/libcc.a - -$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " LIBSNARK_CXXFLAGS = $(AM_CXXFLAGS) $(PIC_FLAGS) -DBINARY_OUTPUT -DNO_PT_COMPRESSION=1 -fstack-protector-all LIBSNARK_CONFIG_FLAGS = CURVE=ALT_BN128 NO_PROCPS=1 NO_DOCS=1 STATIC=1 NO_SUPERCOP=1 FEATUREFLAGS=-DMONTGOMERY_OUTPUT NO_COPY_DEPINST=1 NO_COMPILE_LIBGTEST=1 +LIBSNARK_OPTFLAGS = $(CPPFLAGS) -march=x86-64 if HAVE_OPENMP LIBSNARK_CONFIG_FLAGS += MULTICORE=1 endif @@ -81,20 +66,24 @@ if TARGET_DARWIN LIBSNARK_CONFIG_FLAGS += PLATFORM=darwin endif +$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="$(LIBSNARK_OPTFLAGS) " + $(LIBSNARK): $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" + $(AM_V_at)CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" libsnark-tests: $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" + $(AM_V_at)CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" $(LIBUNIVALUE): $(wildcard univalue/lib/*) - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" -$(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptoconditions/include/*) - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " - -$(LIBDYNCUSTOMCONSENSUS): $(wildcard *.h) $(wildcard cc/*.h) $(wildcard cryptoconditions/include/*) - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) -f Makefile_custom HOST=$(host) +# libcjson build +LIBCJSON=libcjson.a +libcjson_a_SOURCES = cJSON.c \ + komodo_cJSON.c komodo_cutils.cpp +libcjson_a_CPPFLAGS=-fPIC +EXTRA_LIBRARIES += $(LIBCJSON) # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: @@ -118,7 +107,7 @@ if ENABLE_PROTON EXTRA_LIBRARIES += $(LIBBITCOIN_PROTON) endif -lib_LTLIBRARIES = $(LIBZCASH_CONSENSUS) +lib_LTLIBRARIES = $(LIBZCASH_CONSENSUS) $(LIBCC) LIBSSLSTATIC = $(abs_builddir)/../depends/$(host)/lib/libssl.a LIBCRYPTOSTATIC = $(abs_builddir)/../depends/$(host)/lib/libcrypto.a @@ -291,6 +280,7 @@ libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: komodod libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +libbitcoin_server_a_CPPFLAGS += -fPIC libbitcoin_server_a_SOURCES = \ sendalert.cpp \ addrman.cpp \ @@ -307,6 +297,8 @@ libbitcoin_server_a_SOURCES = \ cc/CCtx.cpp \ cc/CCutils.cpp \ cc/CCvalidation.cpp \ + cc/CCtokens.h \ + cc/CCtokens_impl.h \ cc/CCtokens.cpp \ cc/assets.cpp \ cc/faucet.cpp \ @@ -325,6 +317,7 @@ libbitcoin_server_a_SOURCES = \ cc/betprotocol.cpp \ cc/pricesfeed.cpp \ cc/priceslibs/cjsonpointer.cpp \ + cc/CCTokelData.h \ cc/CCTokelData.cpp \ chain.cpp \ checkpoints.cpp \ @@ -422,6 +415,11 @@ libbitcoin_wallet_a_SOURCES = \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) +# a shared library for cryptoconditions +libcc_a_SOURCES = cc/cclib.cpp +libcc_a_CXXFLAGS = -DBUILD_CUSTOMCC -I../secp256k1/include -I../depends/$(shell echo `../depends/config.guess`/include) -I./univalue/include -I./cryptoconditions/include -I./cryptoconditions/src -I./cryptoconditions/src/asn -I. -I./cc +libcc_a_LDFLAGS = -version-info 0:0:0 + # crypto primitives library crypto_libbitcoin_crypto_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_CONFIG_INCLUDES) crypto_libbitcoin_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -518,7 +516,9 @@ libbitcoin_common_a_SOURCES = \ transaction_builder.cpp \ cc/CCtokenutils.cpp \ cc/CCutilbits.cpp \ + cc/CCupgrades.h \ cc/CCupgrades.cpp \ + komodo_version.h \ gmp_i64.c \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) @@ -605,9 +605,9 @@ komodod_LDADD += \ $(LIBBITCOIN_CRYPTO) \ $(LIBVERUS_CRYPTO) \ $(LIBVERUS_PORTABLE_CRYPTO) \ - $(LIBZCASH_LIBS) - -komodod_LDADD += $(LIBDYNCUSTOMCONSENSUS) $(LIBSECP256K1) + $(LIBZCASH_LIBS) \ + $(LIBCC) \ + -lcurl if ENABLE_WEBSOCKETS # link statically openssl @@ -707,7 +707,6 @@ komodo_tx_LDADD = \ $(LIBCRYPTOCONDITIONS) komodo_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) -# # zcash protocol primitives # libzcash_a_SOURCES = \ @@ -727,12 +726,11 @@ libzcash_a_SOURCES = \ zcash/circuit/prfs.tcc \ zcash/circuit/utils.tcc -libzcash_a_CPPFLAGS = -DMULTICORE -fopenmp -fPIC -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS $(HARDENED_CPPFLAGS) $(HARDENED_CXXFLAGS) $(HARDENED_LDFLAGS) -pipe $(SAN_LDFLAGS) -O1 -g -Wstack-protector $(SAN_CXXFLAGS) -fstack-protector-all -fPIE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES) - -#libzcash_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -#libzcash_a_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -#libzcash_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMONTGOMERY_OUTPUT - +libzcash_a_CPPFLAGS = -DMULTICORE -fopenmp -fPIC -DBINARY_OUTPUT -DCURVE_ALT_BN128 \ + -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS $(HARDENED_CPPFLAGS) \ + $(HARDENED_CXXFLAGS) $(HARDENED_LDFLAGS) -pipe $(SAN_LDFLAGS) \ + -Wstack-protector $(SAN_CXXFLAGS) -fstack-protector-all -fPIE -fvisibility=hidden \ + -DSTATIC $(BITCOIN_INCLUDES) libzcash_a_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing libzcash_a_LDFLAGS = $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) libzcash_a_CPPFLAGS += -DMONTGOMERY_OUTPUT @@ -785,7 +783,13 @@ clean-local: -rm -f config.h -rm -f cc/customcc.so cc/customcc.dll cc/customcc.dylib # clean now unused file -rm -f libcc.so libcc.dll libcc.dylib # clean now unused file - -$(MAKE) -C cc -f Makefile_custom clean + -$(RM) *.a + -$(RM) crypto/*.a + -$(RM) cryptoconditions/.libs/*.a + +clean-all: clean-local + -$(MAKE) -C snark clean-all + -$(MAKE) -C univalue clean-all .rc.o: @test -f $(WINDRES) From 71c0c156db11ed4ea32a1f059e5efe8057de0096 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 6 May 2022 20:33:40 +0500 Subject: [PATCH 253/348] added disconnection of old version websocket peers --- src/init.cpp | 6 +++--- src/komodo_websockets.cpp | 44 ++++++++++++++++++++++++++++++++------- src/komodo_websockets.h | 27 ++++++++++++++---------- 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 453804bc179..bc0845f7ebd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -229,7 +229,7 @@ void Shutdown() StopHTTPRPC(); #ifdef ENABLE_WEBSOCKETS - StopWebSockets(); + ws::StopWebSockets(); #endif StopREST(); StopRPC(); @@ -911,7 +911,7 @@ bool AppInitServers(boost::thread_group& threadGroup) if (!StartHTTPRPC()) return false; #ifdef ENABLE_WEBSOCKETS - if (!StartWebSockets(threadGroup)) + if (!ws::StartWebSockets(threadGroup)) return false; #endif if (GetBoolArg("-rest", false) && !StartREST()) @@ -2097,7 +2097,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) SetRPCWarmupFinished(); #ifdef ENABLE_WEBSOCKETS - SetWebSocketsWarmupFinished(); + ws::SetWebSocketsWarmupFinished(); #endif uiInterface.InitMessage(_("Done loading")); diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index 1c3c0fb59ea..3703ca9849a 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -35,6 +35,9 @@ #include "univalue.h" #include "rpc/server.h" +#include "cc/CCupgrades.h" + + //#include #ifndef ENABLE_WEBSOCKETS @@ -43,6 +46,9 @@ #include "komodo_websockets.h" +namespace ws +{ + static CAddrMan wsaddrman; static bool bWebSocketsStarted = false; @@ -71,6 +77,16 @@ unsigned short GetWebSocketListenPort() return (unsigned short)(GetArg("-wsport", 8192)); } +int GetHeight() +{ + LOCK(cs_main); + CBlockIndex* pindex; + if ((pindex = chainActive.LastTip()) != 0) + return pindex->GetHeight(); + else + return 0; +} + CAddress GetLocalWebSocketAddress(const CNetAddr *paddrPeer) { CAddress ret(CService("0.0.0.0", GetWebSocketListenPort()), 0); @@ -227,7 +243,7 @@ bool ProcessWsMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, { pfrom->PushMessage("reject", strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")); Misbehaving(pfrom->GetId(), 1); - return false; + return true; } int64_t nTime; @@ -245,26 +261,37 @@ bool ProcessWsMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, if (nVersion < minVersion) { // disconnect from peers older than this proto version - LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion); + LogPrintf("wspeer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion); pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", minVersion)); pfrom->fDisconnect = true; - return false; + return true; } - // not relevant to websockets: + // zcash upgrades are not relevant to websockets: // Reject incoming connections from nodes that don't know about the current epoch /*const Consensus::Params& params = Params().GetConsensus(); auto currentEpoch = CurrentEpoch(GetHeight(), params); if (nVersion < params.vUpgrades[currentEpoch].nProtocolVersion) { - LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, nVersion); + LogPrintf("wspeer=%d using obsolete version %i; disconnecting\n", pfrom->id, nVersion); pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", params.vUpgrades[currentEpoch].nProtocolVersion)); pfrom->fDisconnect = true; return false; }*/ + + // check min cc version + if (nVersion < GetCurrentUpgradeInfo(GetHeight(), CCUpgrades::GetUpgrades()).nProtocolVersion) + { + LogPrint("websockets", "wspeer=%d using obsolete version %i; disconnecting by ccupgrades\n", pfrom->id, nVersion); + pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, + strprintf("Version must be %d or greater", + GetCurrentUpgradeInfo(GetHeight(), CCUpgrades::GetUpgrades()).nProtocolVersion)); + pfrom->fDisconnect = true; + return true; + } if (!vRecv.empty()) vRecv >> addrFrom >> nNonce; @@ -1657,13 +1684,14 @@ UniValue getwspeers(const UniValue& params, bool fHelp, const CPubKey& remotepk) return result; } +}; // namespace ws static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- - { "hidden", "printaddrman", &printaddrman, true }, - { "hidden", "printwsaddrman", &printwsaddrman, true }, - { "hidden", "getwspeers", &getwspeers, true }, + { "hidden", "printaddrman", &ws::printaddrman, true }, + { "hidden", "printwsaddrman", &ws::printwsaddrman, true }, + { "hidden", "getwspeers", &ws::getwspeers, true }, }; void RegisterWebSocketsRPCCommands(CRPCTable &tableRPC) diff --git a/src/komodo_websockets.h b/src/komodo_websockets.h index dfcbae1db90..e494e8c988c 100644 --- a/src/komodo_websockets.h +++ b/src/komodo_websockets.h @@ -22,12 +22,15 @@ //using websocketpp::lib::bind; +namespace ws +{ + static const int WSADDR_VERSION = 170008; #define WEBSOCKETS_TIMEOUT_INTERVAL 120 -//struct wsserver_mt_config : public websocketpp::config::asio { // no tls -struct wsserver_mt_config : public websocketpp::config::asio_tls { // tls +// struct wsserver_mt_config : public websocketpp::config::asio { // no tls +struct wsserver_mt_config : public websocketpp::config::asio_tls { // tls // pull default settings from our core config static bool const enable_multithreading = true; @@ -35,18 +38,18 @@ struct wsserver_mt_config : public websocketpp::config::asio_tls { // tls struct transport_config : public websocketpp::config::core::transport_config { static bool const enable_multithreading = true; }; - + /// permessage_compress extension - //struct permessage_deflate_config {}; + // struct permessage_deflate_config {}; - //typedef websocketpp::extensions::permessage_deflate::enabled - // permessage_deflate_type; + // typedef websocketpp::extensions::permessage_deflate::enabled + // permessage_deflate_type; }; -//typedef websocketpp::server wsserver; // no tls -typedef websocketpp::server wsserver; // tls +// typedef websocketpp::server wsserver; // no tls +typedef websocketpp::server wsserver; // tls -//transport::asio::tls_socket::endpoint +// transport::asio::tls_socket::endpoint typedef websocketpp::client wsclient; @@ -64,8 +67,10 @@ bool StartWebSockets(boost::thread_group& threadGroup); void SetWebSocketsWarmupFinished(); void StopWebSockets(); -int GetnScore(const CService& addr); //net.cpp - bool ProcessWsMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, int64_t nTimeReceived); +}; // namespace ws + +int GetnScore(const CService& addr); // from net.cpp + #endif \ No newline at end of file From 5d0abd282f4e42535688daf95280b9ca21b7e899 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 6 May 2022 20:34:53 +0500 Subject: [PATCH 254/348] in FinalizeCCV2Tx probe R-address token cond added --- src/cc/CCtx.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index f4a91682e09..397cbb2c07c 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -437,8 +437,7 @@ UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info int64_t utxovalues[CC_MAXVINS], change, totaloutputs = 0, totalinputs = 0; char destaddr[KOMODO_ADDRESS_BUFSIZE], myccaddr[KOMODO_ADDRESS_BUFSIZE], - globaladdr[KOMODO_ADDRESS_BUFSIZE], - mynftaddr[KOMODO_ADDRESS_BUFSIZE] = { '\0' }; + globaladdr[KOMODO_ADDRESS_BUFSIZE]; uint8_t myprivkey[32] = {'\0'}; //CC *cond = NULL, *probecond = NULL; UniValue sigData(UniValue::VARR), result(UniValue::VOBJ), partialConds(UniValue::VARR); @@ -447,7 +446,12 @@ UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info globalpk = GetUnspendable(cp, 0); _GetCCaddress(myccaddr, cp->evalcode, mypk, true); _GetCCaddress(globaladdr, cp->evalcode, globalpk, true); - GetTokensCCaddress(cp, mynftaddr, mypk, true); // get token or nft probe + + // mynftaddr[KOMODO_ADDRESS_BUFSIZE] = { '\0' }; + // GetTokensCCaddress(cp, mynftaddr, mypk, true); // get token or nft probe + std::vector tokenconds = GetTokenV2Conds(mypk); + std::vector tokenaddrs = GetTokenV2IndexKeys(mypk); + std::vector::iterator tokenit; n = mtx.vout.size(); for (int i = 0; i < n; i++) { @@ -531,9 +535,11 @@ UniValue FinalizeCCV2Tx(bool remote, uint32_t changeFlag, struct CCcontract_info } else if (strcmp(destaddr, myccaddr) == 0) { privkey = myprivkey; cond.reset(MakeCCcond1(cp->evalcode, mypk)); - } else if (strcmp(destaddr, mynftaddr) == 0) { + //} else if (strcmp(destaddr, mynftaddr) == 0) { + } else if ((tokenit = std::find(tokenaddrs.begin(), tokenaddrs.end(), std::string(destaddr))) != tokenaddrs.end()) { privkey = myprivkey; - cond.reset(MakeTokensv2CCcond1(cp->evalcode, mypk)); + //cond.reset(MakeTokensv2CCcond1(cp->evalcode, mypk)); + cond = tokenconds[ std::distance(tokenaddrs.begin(), tokenit) ]; } else { const uint8_t nullpriv[32] = {'\0'}; const uint8_t dontsign[32] = { 0xff }; From 8cc119f146fb0d7f49df1bab62e89ee3f227f673 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 6 May 2022 20:36:12 +0500 Subject: [PATCH 255/348] fixed assets cc royalty dust calculation (HF activated) --- src/cc/CCassets.h | 2 +- src/cc/CCassetsCore_impl.h | 4 +- src/cc/CCassetsUtils.cpp | 2 +- src/cc/CCassetstx_impl.h | 134 +++++++++++++++++++++++-------------- src/cc/assets.cpp | 99 +++++++++++++++++++-------- 5 files changed, 156 insertions(+), 85 deletions(-) diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index 637aef5a496..cd58bbd3564 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -47,7 +47,7 @@ bool SetAskFillamounts(CAmount unit_price, CAmount fill_assetoshis, CAmount orig bool SetSwapFillamounts(CAmount unit_price, CAmount &paid, CAmount orig_nValue, CAmount &received, CAmount totalprice); // not implemented CAmount AssetsGetTxCCInputs(Eval *eval, struct CCcontract_info *cp, const char *addr, const CTransaction &tx); CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, const CTransaction &tx); -bool AssetsFillAskIsDust(int32_t royaltyFract, CAmount nOutputValue, int32_t nHeight, bool &isRoyaltyDust); +bool AssetsFillOrderIsDust(int32_t royaltyFract, CAmount nOutputValue, bool &isRoyaltyDust); const char ccassets_log[] = "ccassets"; diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index 108f77eefcd..f952bb7204b 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -304,9 +304,9 @@ bool AssetsValidateTokenId(Eval *eval, struct CCcontract_info *cp, const CTransa template bool AssetsValidateTokenId_Activated(Eval *eval, struct CCcontract_info *cpTokens, const CTransaction &tx, int32_t v, uint256 assetid) { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCASSETS_OPDROP_VALIDATE_FIX)) + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCASSETS_OPDROP_VALIDATE_FIX)) return AssetsValidateTokenId(eval, cpTokens, tx, v, assetid); - else + else return true; } diff --git a/src/cc/CCassetsUtils.cpp b/src/cc/CCassetsUtils.cpp index 2e52ada9bb5..7364062f2a2 100644 --- a/src/cc/CCassetsUtils.cpp +++ b/src/cc/CCassetsUtils.cpp @@ -504,7 +504,7 @@ CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, con // check if either royalty or paid_value is dust in fill ask // nOutputValue is the total amount of paid_value + royalty -bool AssetsFillAskIsDust(int32_t royaltyFract, CAmount nOutputValue, int32_t nHeight, bool &isRoyaltyDust) +bool AssetsFillOrderIsDust(int32_t royaltyFract, CAmount nOutputValue, bool &isRoyaltyDust) { // nOutputValue is sum of paid_value + royalty_value // check whether any of them is assets' dust (calc min of royalty and paid_value, compare with assets' dust): diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index b832d37a1df..f9e607b3eeb 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2022 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -56,7 +56,7 @@ UniValue AssetOrders(uint256 refassetid, const CPubKey &mypk, const UniValue &pa { uint256 hashBlock, assetid; CAmount unit_price; - vscript_t origpubkey; + vscript_t vorigpubkey; CTransaction ordertx; uint8_t funcid, evalCode; char origaddr[KOMODO_ADDRESS_BUFSIZE], origtokenaddr[KOMODO_ADDRESS_BUFSIZE]; @@ -68,7 +68,7 @@ UniValue AssetOrders(uint256 refassetid, const CPubKey &mypk, const UniValue &pa return; } - if (ordertx.vout.size() > 1 && (funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, unit_price, origpubkey, expiryHeight)) != 0) + if (ordertx.vout.size() > 1 && (funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, unit_price, vorigpubkey, expiryHeight)) != 0) { LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " checking ordertx.vout.size()=" << ordertx.vout.size() << " funcid=" << (char)(funcid ? funcid : ' ') << " assetid=" << assetid.GetHex() << std::endl); @@ -94,7 +94,7 @@ UniValue AssetOrders(uint256 refassetid, const CPubKey &mypk, const UniValue &pa LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " could not load order txid=" << ordertxid.GetHex() << std::endl); return; } - if ((funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, unit_price, origpubkey, expiryHeight)) == 0) { + if ((funcid = A::DecodeAssetTokenOpRet(ordertx.vout.back().scriptPubKey, evalCode, assetid, unit_price, vorigpubkey, expiryHeight)) == 0) { LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " could not decode order txid=" << ordertxid.GetHex() << std::endl); return; } @@ -120,11 +120,11 @@ UniValue AssetOrders(uint256 refassetid, const CPubKey &mypk, const UniValue &pa } else return; - if (origpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) + if (vorigpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { - GetCCaddress(cp, origaddr, pubkey2pk(origpubkey), A::IsMixed()); + GetCCaddress(cp, origaddr, pubkey2pk(vorigpubkey), A::IsMixed()); item.push_back(Pair("origaddress", origaddr)); - GetTokensCCaddress(cpTokens, origtokenaddr, pubkey2pk(origpubkey), A::IsMixed()); + GetTokensCCaddress(cpTokens, origtokenaddr, pubkey2pk(vorigpubkey), A::IsMixed()); item.push_back(Pair("origtokenaddress", origtokenaddr)); } if (assetid != zeroid) @@ -265,7 +265,7 @@ UniValue CreateBuyOffer(const CPubKey &mypk, CAmount txfee, CAmount bidamount, u struct CCcontract_info *cpAssets, C; uint256 hashBlock; CTransaction vintx; - std::vector origpubkey; + std::vector vorigpubkey; std::string name,description; CAmount inputs; std::vector oprets; @@ -285,7 +285,7 @@ UniValue CreateBuyOffer(const CPubKey &mypk, CAmount txfee, CAmount bidamount, u CCerror = "could not find assetid\n"; return(""); } - if (vintx.vout.size() == 0 || T::DecodeTokenCreateOpRet(vintx.vout.back().scriptPubKey, origpubkey, name, description, oprets) == 0) { + if (vintx.vout.size() == 0 || T::DecodeTokenCreateOpRet(vintx.vout.back().scriptPubKey, vorigpubkey, name, description, oprets) == 0) { CCerror = "assetid isn't token creation txid\n"; return(""); } @@ -481,7 +481,7 @@ UniValue CancelBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uin { uint8_t dummyEvalCode; uint256 dummyAssetid; CAmount dummyPrice; - vscript_t origpubkey; + vscript_t vorigpubkey; int32_t expiryHeight; uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk; @@ -495,7 +495,7 @@ UniValue CancelBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uin } mtx.vin.push_back(CTxIn(bidtxid, ASSETS_GLOBALADDR_VOUT, CScript())); // coins in Assets - uint8_t funcid = A::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, origpubkey, expiryHeight); + uint8_t funcid = A::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, vorigpubkey, expiryHeight); if (funcid == 'b' && vintx.vout.size() > 1) mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' else if (funcid == 'B' && vintx.vout.size() > 3) @@ -506,19 +506,19 @@ UniValue CancelBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uin } if (bidamount > ASSETS_NORMAL_DUST) - mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); + mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(vorigpubkey)) << OP_CHECKSIG)); else { // send dust back to global addr mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bidamount, unspendableAssetsPk)); - LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "dust detected bidamount=" << bidamount << std::endl); + LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "remainder dust detected left on global bidamount=" << bidamount << std::endl); } // probe to spend marker: - if (mypk == pubkey2pk(origpubkey)) { - CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + if (mypk == pubkey2pk(vorigpubkey)) { + CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk } else { - CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk (for expired orders) } @@ -563,7 +563,7 @@ UniValue CancelSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 uint8_t dummyEvalCode; uint256 dummyAssetid; CAmount dummyPrice; - vscript_t origpubkey; + vscript_t vorigpubkey; int32_t expiryHeight; askamount = vintx.vout[ASSETS_GLOBALADDR_VOUT].nValue; @@ -573,7 +573,7 @@ UniValue CancelSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 } mtx.vin.push_back(CTxIn(asktxid, ASSETS_GLOBALADDR_VOUT, CScript())); - uint8_t funcid = A::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, origpubkey, expiryHeight); + uint8_t funcid = A::DecodeAssetTokenOpRet(vintx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, vorigpubkey, expiryHeight); if (funcid == 's' && vintx.vout.size() > 1) mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // spend marker if funcid='s' else if (funcid == 'S' && vintx.vout.size() > 3) @@ -582,7 +582,7 @@ UniValue CancelSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 CCerror = "invalid ask tx or not enough vouts"; return ""; } - mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), askamount, pubkey2pk(origpubkey))); // one-eval token vout + mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), askamount, pubkey2pk(vorigpubkey))); // one-eval token vout // mtx.vout.push_back(CTxOut(ASSETS_MARKER_AMOUNT, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // we dont need marker for cancelled orders // init assets 'unspendable' privkey and pubkey @@ -594,11 +594,11 @@ UniValue CancelSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // probe to spend marker - if (mypk == pubkey2pk(origpubkey)) { - CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + if (mypk == pubkey2pk(vorigpubkey)) { + CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk } else { - CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCwrapper wrCond(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk (for expired orders) } @@ -624,9 +624,9 @@ UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint2 CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction vintx; uint256 hashBlock; - std::vector origpubkey; + std::vector vorigpubkey; const int32_t bidvout = ASSETS_GLOBALADDR_VOUT; - CAmount orig_units, unit_price, bid_amount, paid_amount, remaining_units, inputs; + CAmount orig_units, unit_price, bid_amount, paid_amount, remaining_units, tokenInputs; struct CCcontract_info *cpTokens, tokensC; struct CCcontract_info *cpAssets, assetsC; @@ -645,7 +645,7 @@ UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint2 if (royaltyFract > TKLROYALTY_DIVISOR-1) royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } - vuint8_t ownerpubkey = std::get<0>(tokenData); + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); if (txfee == 0) txfee = 10000; @@ -656,13 +656,14 @@ UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint2 int32_t spendingvin, h; LOCK(cs_main); + int32_t nextHeight = komodo_nextheight(); if ((CCgetspenttxid(spendingtxid, spendingvin, h, bidtxid, bidvout) != 0 || !IsTxidInActiveChain(spendingtxid)) && myGetTransaction(bidtxid, vintx, hashBlock) != 0 && vintx.vout.size() > bidvout) { uint256 assetidOpret; int32_t expiryHeight; bid_amount = vintx.vout[bidvout].nValue; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, vintx); // get orig pk, orig units + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, vintx); // get orig pk, orig units if (funcid != 'b' && funcid != 'B') { CCerror = "not an bid order"; return ""; @@ -676,9 +677,9 @@ UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint2 paid_unit_price = unit_price; mtx.vin.push_back(CTxIn(bidtxid, bidvout, CScript())); // Coins on Assets unspendable - if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, fill_units, 0x1000, false)) > 0) + if ((tokenInputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, fill_units, 0x1000, false)) > 0) { - if (inputs < fill_units) { + if (tokenInputs < fill_units) { CCerror = strprintf("insufficient tokens to fill buy offer"); return (""); } @@ -689,9 +690,19 @@ UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint2 } CAmount royaltyValue = royaltyFract > 0 ? paid_amount / TKLROYALTY_DIVISOR * royaltyFract : 0; // check for dust: - if (royaltyValue <= ASSETS_NORMAL_DUST) - royaltyValue = 0; - CAmount tokensChange = inputs - fill_units; + //if (royaltyValue <= ASSETS_NORMAL_DUST) + // royaltyValue = 0; + bool hasDust = false; + bool isRoyaltyDust = true; + if (royaltyFract > 0) { + // correct calculation: + if (AssetsFillOrderIsDust(royaltyFract, paid_amount, isRoyaltyDust)) { + royaltyValue = 0; // all amount (with dust) to go to one pk (depending on which is not dust) + hasDust = true; + } + } + + CAmount tokensChange = tokenInputs - fill_units; uint8_t unspendableAssetsPrivkey[32]; cpAssets = CCinit(&assetsC, A::EvalCode()); @@ -699,19 +710,26 @@ UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint2 if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { // bidder has coins for more tokens or only dust is sent back to global address mtx.vout.push_back(T::MakeCC1vout(A::EvalCode(), bid_amount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder or the dust is sent back to cc global addr - if (bid_amount - paid_amount <= ASSETS_NORMAL_DUST) - LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "dust detected (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl); + if (bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { + LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "remainder dust detected, left on global addr (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl); + std::cerr << __func__ << " bid_amount - paid_amount <= ASSETS_NORMAL_DUST, left on globalpk, bid_amount - paid_amount=" << bid_amount - paid_amount << std::endl; + } } - else - mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator - mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to mypk normal + else { + mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << vorigpubkey << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator + std::cerr << __func__ << " no more amount for tokens, sending to vorigpubkey bid_amount - paid_amount=" << bid_amount - paid_amount << std::endl; + } + mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << (royaltyFract > 0 && hasDust && !isRoyaltyDust ? vtokenCreatorPubkey : vuint8_t(mypk.begin(), mypk.end())) << OP_CHECKSIG)); // vout1 coins to mypk normal (if value to my pk is dust then send to the token owner) + std::cerr << __func__ << " to owner or mypk, paid_amount - royaltyValue=" << paid_amount - royaltyValue << " toTokenCreator exp=" << (royaltyFract > 0 && hasDust && !isRoyaltyDust) << std::endl; + if (royaltyValue > 0) { // note it makes vout even if roaltyValue is 0 - mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG)); // vout2 trade royalty to token owner + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << vtokenCreatorPubkey << OP_CHECKSIG)); // vout2 trade royalty to token owner + std::cerr << __func__ << " royaltyValue > 0, adding it to vtokenCreatorPubkey royaltyValue=" << royaltyValue << std::endl; LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_amount - royaltyValue=" << paid_amount - royaltyValue << std::endl); } - mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator + mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), fill_units, pubkey2pk(vorigpubkey))); // vout2(3) single-eval tokens sent to the originator if (orig_units - fill_units > 0) // order is not finished yet - mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey, unspendableAssetsPk)); // vout3(4 if royalty) marker to origpubkey + mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, vorigpubkey, unspendableAssetsPk)); // vout3(4 if royalty) marker to vorigpubkey if (tokensChange != 0LL) mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), tokensChange, mypk)); // change in single-eval tokens @@ -723,12 +741,12 @@ UniValue FillBuyOffer(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint2 CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey // probe to spend marker - CCwrapper wrCond3(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCwrapper wrCond3(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond3, nullptr); // spend with mypk UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpTokens, mtx, mypk, txfee, - T::EncodeTokenOpRet(assetid, { pubkey2pk(origpubkey) }, - { A::EncodeAssetOpRet('B', unit_price, origpubkey, expiryHeight) })); + T::EncodeTokenOpRet(assetid, { pubkey2pk(vorigpubkey) }, + { A::EncodeAssetOpRet('B', unit_price, vorigpubkey, expiryHeight) })); if (!ResultHasTx(sigData)) return MakeResultError("Could not finalize tx"); return sigData; @@ -754,7 +772,7 @@ UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 a CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction vintx; uint256 hashBlock; - std::vector origpubkey; + std::vector vorigpubkey; const int32_t askvout = ASSETS_GLOBALADDR_VOUT; CAmount unit_price, orig_assetoshis, paid_nValue; struct CCcontract_info *cpAssets, assetsC; @@ -774,7 +792,7 @@ UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 a if (royaltyFract > TKLROYALTY_DIVISOR-1) royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } - vuint8_t ownerpubkey = std::get<0>(tokenData); + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); cpAssets = CCinit(&assetsC, A::EvalCode()); @@ -786,10 +804,11 @@ UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 a LOCK(cs_main); if ((CCgetspenttxid(spendingtxid, spendingvin, h, asktxid, askvout) != 0 || !IsTxidInActiveChain(spendingtxid)) && myGetTransaction(asktxid, vintx, hashBlock) && vintx.vout.size() > askvout) { + int32_t nextHeight = komodo_nextheight(); uint256 assetidOpret; int32_t expiryHeight; orig_assetoshis = vintx.vout[askvout].nValue; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, vintx); // get orig pk, orig value + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, vintx); // get orig pk, orig value if (funcid != 's' && funcid != 'S') { CCerror = "not an ask order"; return ""; @@ -811,8 +830,19 @@ UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 a //if (royaltyValue <= ASSETS_NORMAL_DUST) // royaltyValue = 0; // more accurate check matching to AssetValidate's check - if (royaltyFract > 0 && paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) // if value paid to seller less than when the royalty is minimum - royaltyValue = 0LL; + + // bad calc + //if (royaltyFract > 0 && paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) // if value paid to seller less than when the royalty is minimum + // royaltyValue = 0LL; + bool hasDust = false; + bool isRoyaltyDust = true; + if (royaltyFract > 0) { + // correct calculation: + if (AssetsFillOrderIsDust(royaltyFract, paid_nValue, isRoyaltyDust)) { + royaltyValue = 0; // all amount (with dust) to go to one pk (depending on which is not dust) + hasDust = true; + } + } // Use only one AddNormalinputs() in each rpc call to allow payment if user has only single utxo with normal funds CAmount inputs = AddNormalinputs(mtx, mypk, txfee + ASSETS_MARKER_AMOUNT + paid_nValue, 0x10000, IsRemoteRPCCall()); @@ -841,14 +871,14 @@ UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 a //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: mtx.vout.push_back(T::MakeTokensCC1vout(T::EvalCode(), fillunits, mypk)); - mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr + mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << (royaltyFract > 0 && hasDust && !isRoyaltyDust ? vtokenCreatorPubkey : vorigpubkey) << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr if (royaltyValue > 0) { // note it makes the vout even if roaltyValue is 0 - mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << vtokenCreatorPubkey << OP_CHECKSIG)); // vout.3 royalty to token owner LOGSTREAMFN(ccassets_log, CCLOG_DEBUG1, stream << "royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_nValue - royaltyValue=" << paid_nValue - royaltyValue << std::endl); } if (orig_assetoshis - fillunits > 0) // we dont need the marker if order is filled - mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, origpubkey, GetUnspendable(cpAssets, NULL))); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) + mtx.vout.push_back(T::MakeCC1of2vout(A::EvalCode(), ASSETS_MARKER_AMOUNT, vorigpubkey, GetUnspendable(cpAssets, NULL))); //vout.3(4 if royalty) marker to vorigpubkey (for my tokenorders?) // init assets 'unspendable' privkey and pubkey uint8_t unspendableAssetsPrivkey[32]; @@ -858,12 +888,12 @@ UniValue FillSell(const CPubKey &mypk, CAmount txfee, uint256 assetid, uint256 a CCAddVintxCond(cpAssets, wrCond1, unspendableAssetsPrivkey); // probe to spend marker - CCwrapper wrCond2(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCwrapper wrCond2(::MakeCCcond1of2(A::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond2, nullptr); // spend with mypk UniValue sigData = T::FinalizeCCTx(IsRemoteRPCCall(), FINALIZECCTX_NO_CHANGE_WHEN_DUST, cpAssets, mtx, mypk, txfee, T::EncodeTokenOpRet(assetid, { mypk }, - { A::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) } )); + { A::EncodeAssetOpRet('S', unit_price, vorigpubkey, expiryHeight) } )); if (!ResultHasTx(sigData)) return MakeResultError("Could not finalize tx"); return sigData; diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 0fa98c0b6b1..61c18f92742 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -171,7 +171,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const vuint8_t vorigpubkey, vin_origpubkey, vextraData; TokenDataTuple tokenData; uint8_t funcid, evalCodeInOpret; - char destaddr[KOMODO_ADDRESS_BUFSIZE], origNormalAddr[KOMODO_ADDRESS_BUFSIZE], ownerNormalAddr[KOMODO_ADDRESS_BUFSIZE]; + char destaddr[KOMODO_ADDRESS_BUFSIZE], origNormalAddr[KOMODO_ADDRESS_BUFSIZE], tokenCreatorNormalAddr[KOMODO_ADDRESS_BUFSIZE]; char origTokensCCaddr[KOMODO_ADDRESS_BUFSIZE], origCCaddrDummy[KOMODO_ADDRESS_BUFSIZE]; char tokensDualEvalUnspendableCCaddr[KOMODO_ADDRESS_BUFSIZE], origAssetsCCaddr[KOMODO_ADDRESS_BUFSIZE], globalAssetsCCaddr[KOMODO_ADDRESS_BUFSIZE]; char markerCCaddress[KOMODO_ADDRESS_BUFSIZE]; @@ -206,8 +206,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } - vuint8_t ownerpubkey = std::get<0>(tokenData); - Getscriptaddress(ownerNormalAddr, CScript() << ownerpubkey << OP_CHECKSIG); + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); + Getscriptaddress(tokenCreatorNormalAddr, CScript() << vtokenCreatorPubkey << OP_CHECKSIG); // find dual-eval tokens global addr where tokens are locked: GetTokensCCaddress(cpAssets, tokensDualEvalUnspendableCCaddr, GetUnspendable(cpAssets, NULL), A::IsMixed()); @@ -353,16 +353,38 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (royaltyFract < 0LL || royaltyFract >= TKLROYALTY_DIVISOR) return eval->Invalid("invalid royalty value"); - CAmount royaltyValue = royaltyFract > 0 ? vin_coins / TKLROYALTY_DIVISOR * royaltyFract : 0; - if (royaltyValue <= ASSETS_NORMAL_DUST) - royaltyValue = 0LL; // reset if dust - int32_t r = royaltyValue > 0LL ? 1 : 0; - /*int32_t r = 0; - if (royaltyFract > 0 && tx.vout[1].nValue > ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) // if vout1 > min - r = 1; - if (royaltyFract > 0) - std::cerr << __func__ << " r=" << r << " tx.vout[1].nValue=" << tx.vout[1].nValue << " min-vout1=" << (ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) << std::endl;*/ - //std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << std::endl; + // moved under CCUpgrades condition: + // CAmount royaltyValue = royaltyFract > 0 ? vin_coins / TKLROYALTY_DIVISOR * royaltyFract : 0; + //if (royaltyValue <= ASSETS_NORMAL_DUST) + // royaltyValue = 0LL; // reset if dust + + int32_t r = royaltyFract > 0LL ? 1 : 0; + bool isRoyaltyDust = true; // if no royalty then to order creator + + // check if royalty or paid_value is not dust + if (royaltyFract > 0) + { + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1) == false) { + // old bad calc: + // incorrect use of vin_coins to calculate royalty (this is true only for nfts) + CAmount royaltyValue = royaltyFract > 0 ? vin_coins / TKLROYALTY_DIVISOR * royaltyFract : 0; + std::cerr << __func__ << " fillbid=" << royaltyValue << " dust=" << ASSETS_NORMAL_DUST << std::endl; + if (royaltyValue <= ASSETS_NORMAL_DUST) { + isRoyaltyDust = true; // always to order creator + r = 0; // no royalty vout + } + } + else { + // upgrade June 2022 HF + int32_t tokenVout = 1; + // find first cc vout (token to buyer): + for(; tokenVout < tx.vout.size() && !tx.vout[tokenVout].scriptPubKey.IsPayToCryptoCondition(); tokenVout ++) {} + if (tokenVout == tx.vout.size()) return eval->Invalid("could not find token vout for fillbid"); + // fixed dust calc: + if (AssetsFillOrderIsDust(royaltyFract, tx.vout[tokenVout].nValue * vin_unit_price, isRoyaltyDust)) + r = 0; // no dedicated royalty vout, total goes to tx.vout[2].nValue + } + } CAmount assetoshis = tx.vout[0].nValue + tx.vout[1].nValue + (r ? tx.vout[2].nValue : 0LL); if( vin_coins != assetoshis ) // coins -> global cc address (remainder) + normal self address @@ -376,9 +398,9 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const ccvouts ++; } else - { // if remaining_units == 0 (empty bid) then the remainder should go to the originator normal address, if it is not dust + { // if remaining_units == 0 (empty bid) then the remainder should go to the order originator normal address, if it is not dust if (!A::ConstrainVout(tx.vout[0], NORMALVOUT, origNormalAddr, 0LL, 0)) // remainder less than token price should return to originator normal addr - return eval->Invalid("vout0 should be originator normal address with remainder for fillbid"); + return eval->Invalid("vout0 should be order originator normal address with remainder for fillbid"); } vin_tokens = AssetsGetTxTokenInputs(eval, cpTokens, tx); @@ -405,7 +427,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("vout" + std::to_string(myTokenVout) + " should have tokens to originator cc addr for fillbid"); ccvouts ++; } - if (!A::ConstrainVout(tx.vout[myNormalVout], NORMALVOUT, NULL, 0LL, 0)) // amount paid for tokens goes to normal addr (we can't check 'self' address) + if (!A::ConstrainVout(tx.vout[myNormalVout], NORMALVOUT, NULL, 0LL, 0)) // amount paid for tokens goes to normal addr (could be any address selected by token seller) return eval->Invalid("vout " + std::to_string(myNormalVout) + " should be normal for fillbid"); if (tx.vout[0].nValue / unit_price > 0) { // bid coins remainder sufficient for more tokens - marker should exist @@ -418,13 +440,23 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const CAmount received_value = r ? tx.vout[1].nValue + tx.vout[2].nValue : tx.vout[1].nValue; // vout1 paid value to seller, vout2 royalty to owner CAmount paid_units = tx.vout[2+r].nValue; if (!ValidateBidRemainder(unit_price, tx.vout[0].nValue, vin_coins, received_value, paid_units)) // check real price and coins spending from global addr - return eval->Invalid("vout" + std::to_string(2+r) + " mismatched remainder for fillbid"); + return eval->Invalid("vout" + std::to_string(0) + " mismatched remainder for fillbid"); if (r) { if ((tx.vout[1].nValue + tx.vout[2].nValue) / TKLROYALTY_DIVISOR * royaltyFract != tx.vout[2].nValue) // validate royalty value return eval->Invalid("vout2 invalid royalty amount for fillask"); - if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest + if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, tokenCreatorNormalAddr, 0LL, 0)) // validate owner royalty dest return eval->Invalid("vout2 invalid royalty detination for fillask"); } + else { + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + { + // validate that the paid value to go to the token owner if amount to seller is dust + if (royaltyFract > 0 && r == 0 && !isRoyaltyDust) { // there is royalty dust and royalty is not dust --> send to token owner + if (!A::ConstrainVout(tx.vout[myNormalVout], NORMALVOUT, tokenCreatorNormalAddr, 0LL, 0)) // amount paid for tokens goes to normal addr (we can't check 'self' address) + return eval->Invalid("vout " + std::to_string(myNormalVout) + " should go to token owner for fillbid (dust reason)"); + } + } + } if (eval->GetCurrentHeight() >= vin_expiryHeight) return eval->Invalid("order is expired"); } @@ -544,9 +576,8 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const if (royaltyFract < 0LL || royaltyFract >= TKLROYALTY_DIVISOR) return eval->Invalid("invalid royalty value"); - int32_t hasRoyaltyVout = royaltyFract > 0 ? 1 : 0; + int32_t r = royaltyFract > 0 ? 1 : 0; bool isRoyaltyDust = true; // if no royalty then to order creator - // check if royalty or paid_value is not dust if (royaltyFract > 0) { @@ -554,20 +585,22 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // old bad calc: only if royalty<=50% works bcz of loss of significance bcz of division by royaltyFract first. // also wrong assumption that paid_value is subtracted by the royalty (in fact it is sum of both if the royalty is dust) // suppose the nValue is such that the royalty_value is assets' dust: + std::cerr << __func__ << " fillask tx.vout[2].nValue=" << tx.vout[2].nValue << " dust=" << ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST << std::endl; if (tx.vout[2].nValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) { // if value paid to seller less than when the royalty is minimum isRoyaltyDust = true; // always to order creator - hasRoyaltyVout = 0; // no royalty vout + r = 0; // no royalty vout bcz of dust //std::cerr << __func__ << " old calc, tx.vout[2].nValue=" << tx.vout[2].nValue << " test dust=" << ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST << std::endl; } } else { // fixed dust calc: - if (AssetsFillAskIsDust(royaltyFract, vin_tokens * vin_unit_price, eval->GetCurrentHeight(), isRoyaltyDust)) - hasRoyaltyVout = 0; // no dedicated royalty vout, total goes to tx.vout[2].nValue + if (AssetsFillOrderIsDust(royaltyFract, vin_tokens * vin_unit_price, isRoyaltyDust)) { + r = 0; // no dedicated royalty vout bcz of dust, total goes to tx.vout[2].nValue + } } } - CAmount paid_value = hasRoyaltyVout > 0 ? tx.vout[2].nValue + tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner + CAmount paid_value = r > 0 ? tx.vout[2].nValue + tx.vout[3].nValue : tx.vout[2].nValue; // vout2 paid value to seller, vout3 royalty to owner if (!ValidateAskRemainder(unit_price, tx.vout[0].nValue, vin_tokens, tx.vout[1].nValue, paid_value)) return eval->Invalid("mismatched vout0 remainder for fillask"); else if (!AssetsValidateTokenId_Activated(eval, cp, tx, 0, assetid)) @@ -576,18 +609,26 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("vout1 should be cc for fillask"); else if (!AssetsValidateTokenId_Activated(eval, cp, tx, 1, assetid)) return eval->Invalid("invalid tokenid in vout1 for fillask"); - else if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, (hasRoyaltyVout > 0 || isRoyaltyDust ? origNormalAddr : ownerNormalAddr), 0LL, 0)) // coins to order originator normal addr (if royalty dust then to token creator) - return eval->Invalid("vout2 should be cc for fillask"); - if (hasRoyaltyVout > 0) { + else { + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1) == false) { + if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, origNormalAddr, 0LL, 0)) // coins to originator normal addr + return eval->Invalid("vout2 should be cc for fillask"); + } + else { + if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, (royaltyFract > 0 && r == 0 && !isRoyaltyDust ? tokenCreatorNormalAddr : origNormalAddr), 0LL, 0)) // coins to order originator normal addr (if royalty dust then to token creator) + return eval->Invalid(std::string("vout2 should be normal to ") + (royaltyFract > 0 && r == 0 && !isRoyaltyDust ? std::string("token creator") : std::string("order creator")) + " for fillask"); + } + } + if (r > 0) { if ((tx.vout[2].nValue + tx.vout[3].nValue) / TKLROYALTY_DIVISOR * royaltyFract != tx.vout[3].nValue) // validate royalty value return eval->Invalid("vout3 invalid royalty amount for fillask"); - if (!A::ConstrainVout(tx.vout[3], NORMALVOUT, ownerNormalAddr, 0LL, 0)) // validate owner royalty dest + if (!A::ConstrainVout(tx.vout[3], NORMALVOUT, tokenCreatorNormalAddr, 0LL, 0)) // validate owner royalty dest return eval->Invalid("vout3 invalid royalty destination for fillask"); } if (!A::ConstrainVout(tx.vout[0], CCVOUT, tokensDualEvalUnspendableCCaddr, 0LL, A::EvalCode())) // tokens remainder on global addr return eval->Invalid("invalid vout0 should pay to tokens/assets global address for fillask"); if (tx.vout[0].nValue > 0) { - int32_t markerVout = hasRoyaltyVout > 0 ? 4 : 3; + int32_t markerVout = r > 0 ? 4 : 3; // marker should exist if remainder not empty if (tx.vout.size() <= markerVout || A::ConstrainVout(tx.vout[markerVout], CCVOUT, markerCCaddress, ASSETS_MARKER_AMOUNT, A::EvalCode()) == false) // marker to originator asset cc addr return eval->Invalid("invalid marker vout for original pubkey"); From 6f51cf992268cf7137cdf23e47c25266efe62dd5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 6 May 2022 20:38:37 +0500 Subject: [PATCH 256/348] debug logs removed assets --- src/cc/assets.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 61c18f92742..f39ab4b54d8 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -368,7 +368,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // old bad calc: // incorrect use of vin_coins to calculate royalty (this is true only for nfts) CAmount royaltyValue = royaltyFract > 0 ? vin_coins / TKLROYALTY_DIVISOR * royaltyFract : 0; - std::cerr << __func__ << " fillbid=" << royaltyValue << " dust=" << ASSETS_NORMAL_DUST << std::endl; + // std::cerr << __func__ << " fillbid=" << royaltyValue << " dust=" << ASSETS_NORMAL_DUST << std::endl; if (royaltyValue <= ASSETS_NORMAL_DUST) { isRoyaltyDust = true; // always to order creator r = 0; // no royalty vout @@ -585,7 +585,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // old bad calc: only if royalty<=50% works bcz of loss of significance bcz of division by royaltyFract first. // also wrong assumption that paid_value is subtracted by the royalty (in fact it is sum of both if the royalty is dust) // suppose the nValue is such that the royalty_value is assets' dust: - std::cerr << __func__ << " fillask tx.vout[2].nValue=" << tx.vout[2].nValue << " dust=" << ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST << std::endl; + // std::cerr << __func__ << " fillask tx.vout[2].nValue=" << tx.vout[2].nValue << " dust=" << ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST << std::endl; if (tx.vout[2].nValue <= ASSETS_NORMAL_DUST / royaltyFract * TKLROYALTY_DIVISOR - ASSETS_NORMAL_DUST) { // if value paid to seller less than when the royalty is minimum isRoyaltyDust = true; // always to order creator r = 0; // no royalty vout bcz of dust From aa199ce431a4b752fb8449c7208f52bbd2884fb6 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 6 May 2022 20:39:18 +0500 Subject: [PATCH 257/348] assets consensus tests added for royalty dust fixes --- src/test-komodo-cc/test-assets.cpp | 581 ++++++++++++++++------------- 1 file changed, 320 insertions(+), 261 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 1603108339e..693fc6c8e35 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -76,7 +76,7 @@ class EvalMock : public Eval static EvalMock eval; static uint256 tokenid1, tokenid2, tokenid3, tokenid4, tokenidUnused; -static uint256 askid1, askid2, bidid1; +static uint256 askid1, askid2, bidid1, bidid2, bidid3; // RJXkCF7mn2DRpUZ77XBNTKCe55M2rJbTcu static CPubKey pk1 = CPubKey(ParseHex("035d3b0f2e98cf0fba19f80880ec7c08d770c6cf04aa5639bc57130d5ac54874db")); @@ -415,7 +415,6 @@ class TestAssetsCC : public ::testing::Test { return false; } //std::cerr << __func__ << " cc_verify okay for vin.hash=" << vin.prevout.hash.GetHex() << std::endl; - break; } } for(const auto &vout : tx.vout) { @@ -425,7 +424,7 @@ class TestAssetsCC : public ::testing::Test { bool bCheck = checker.CheckCryptoConditionSpk(vout.scriptPubKey.GetCCV2SPK(), &error); if (!bCheck) { - std::cerr << __func__ << " CheckCryptoCondition error=" << ScriptErrorString(error) << " eval=" << eval.state.GetRejectReason() << std::endl; + std::cerr << __func__ << " CheckCryptoConditionSpk error=" << ScriptErrorString(error) << " eval=" << eval.state.GetRejectReason() << std::endl; return false; } //std::cerr << __func__ << " cc_verify okay for vout.nValue=" << vout.nValue << std::endl; @@ -436,60 +435,71 @@ class TestAssetsCC : public ::testing::Test { static void CreateMockTransactions() { - CTransaction txnormal1, txnormal2, txnormal3, txnormal4, txnormalg, txask1, txask2, txbid1, txbid2, - txtokencreate1, txtokencreate2, txtokencreate3, txtokencreate4, txtokencreateUnused; - txnormal1 = MakeNormalTx(pk1, 20000); + CTransaction txnormal1 = MakeNormalTx(pk1, 20000); eval.AddTx(txnormal1); - txnormal2 = MakeNormalTx(pk1, 20000); + CTransaction txnormal2 = MakeNormalTx(pk1, 20000); eval.AddTx(txnormal2); - txnormal3 = MakeNormalTx(pk2, 20000); + CTransaction txnormal3 = MakeNormalTx(pk2, 20000); eval.AddTx(txnormal3); - txnormal4 = MakeNormalTx(pk2, 20000); + CTransaction txnormal4 = MakeNormalTx(pk2, 20000); eval.AddTx(txnormal4); + CTransaction txnormal5 = MakeNormalTx(pk2, 20000); + eval.AddTx(txnormal5); + struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! - txnormalg = MakeNormalTx(GetUnspendable(cpTokens, NULL), 20000); + CTransaction txnormalg = MakeNormalTx(GetUnspendable(cpTokens, NULL), 20000); eval.AddTx(txnormalg); - txtokencreate1 = MakeTokenV2CreateTx(pk1, 10); + CTransaction txtokencreate1 = MakeTokenV2CreateTx(pk1, 10); eval.AddTx(txtokencreate1); tokenid1 = txtokencreate1.GetHash(); - txtokencreate2 = MakeTokenV2CreateTx(pk2, 10); + CTransaction txtokencreate2 = MakeTokenV2CreateTx(pk2, 10); eval.AddTx(txtokencreate2); tokenid2 = txtokencreate2.GetHash(); - txtokencreate3 = MakeTokenV2CreateTx(pk2, 10); + CTransaction txtokencreate3 = MakeTokenV2CreateTx(pk2, 10); eval.AddTx(txtokencreate3); tokenid3 = txtokencreate3.GetHash(); - txtokencreate4 = MakeTokenV2CreateTx(pk1, 10); + CTransaction txtokencreate4 = MakeTokenV2CreateTx(pk1, 10); eval.AddTx(txtokencreate4); tokenid4 = txtokencreate4.GetHash(); - txtokencreateUnused = MakeTokenV2CreateTx(pk1, 10); + CTransaction txtokencreateUnused = MakeTokenV2CreateTx(pk1, 10); eval.AddTx(txtokencreateUnused); tokenidUnused = txtokencreateUnused.GetHash(); - txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); + CTransaction txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); eval.AddTx(txask1); askid1 = txask1.GetHash(); - txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); + CTransaction txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); eval.AddTx(txask2); askid2 = txask2.GetHash(); - txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 222); + CTransaction txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 222); eval.AddTx(txbid1); bidid1 = txbid1.GetHash(); - //txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2, 222); // test dust + + CTransaction txbid2 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+2, 222, ASSETS_NORMAL_DUST+1); + eval.AddTx(txbid2); + bidid2 = txbid2.GetHash(); + + CTransaction txbid3 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 222, ASSETS_NORMAL_DUST-1); + eval.AddTx(txbid3); + bidid3 = txbid3.GetHash(); + + + //CTransaction txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2, 222); // test dust } static CTransaction MakeNormalTx(CPubKey mypk, CAmount val) @@ -586,7 +596,7 @@ class TestAssetsCC : public ::testing::Test { return mtx; } - static CMutableTransaction MakeTokenV2BidTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, CAmount numtokens, CAmount unit_price, int32_t expiryHeight) + static CMutableTransaction MakeTokenV2BidTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, CAmount numtokens, CAmount unit_price, int32_t expiryHeight, CAmount extraCoins = 0LL) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); //struct CCcontract_info *cpAssets, C; @@ -598,12 +608,12 @@ class TestAssetsCC : public ::testing::Test { //cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! //CAmount unit_price = bidamount / numtokens; - if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { + if (TestAddNormalInputs(mtx, mypk, txfee + bidamount + extraCoins) == 0LL) { std::cerr << __func__ << " cant add normal inputs" << std::endl; return CTransaction(); } CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, nullptr); - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, unspendableAssetsPubkey)); + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount + extraCoins, unspendableAssetsPubkey)); mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); // marker for my orders // sign vins: @@ -652,11 +662,11 @@ class TestAssetsCC : public ::testing::Test { royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } //std::cerr << __func__ << " vextraData.size()=" << vextraData.size() << " bGetTokelDataAsInt64=" << bGetTokelDataAsInt64 << std::endl; - vuint8_t ownerpubkey = std::get<0>(tokenData); + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); - vuint8_t origpubkey; + vuint8_t vorigpubkey; int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, asktx); // get orig pk, orig value + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, asktx); // get orig pk, orig value if (paid_unit_price <= 0LL) paid_unit_price = unit_price; @@ -664,6 +674,7 @@ class TestAssetsCC : public ::testing::Test { CAmount paid_nValue = paid_unit_price * fill_units; CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / TKLROYALTY_DIVISOR * royaltyFract : 0; + bool hasDust = false; bool isRoyaltyDust = true; if (royaltyFract > 0) { @@ -672,13 +683,17 @@ class TestAssetsCC : public ::testing::Test { // (note division on TKLROYALTY_DIVISOR first): if(paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / (int64_t)TKLROYALTY_DIVISOR * royaltyFract - ASSETS_NORMAL_DUST) { // if value paid to seller less than when the royalty is minimum royaltyValue = 0; + hasDust = true; + isRoyaltyDust = true; //old code assumes dust always royalty //std::cerr << __func__ << " old calc corrected, paid_nValue - royaltyValue=" << paid_nValue - royaltyValue << " test dust=" << ASSETS_NORMAL_DUST / (int64_t)TKLROYALTY_DIVISOR * royaltyFract - ASSETS_NORMAL_DUST << std::endl; } } else { // correct calculation: - if (AssetsFillAskIsDust(royaltyFract, paid_nValue, eval.GetCurrentHeight(), isRoyaltyDust)) + if (AssetsFillOrderIsDust(royaltyFract, paid_nValue, isRoyaltyDust)) { royaltyValue = 0; // all amount (with dust) to go to one pk (depending on which is not dust) + hasDust = true; + } } } @@ -697,13 +712,13 @@ class TestAssetsCC : public ::testing::Test { //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, mypk)); - vuint8_t destpk = (royaltyValue > 0 || isRoyaltyDust) ? origpubkey : ownerpubkey; // if paid_value is dust send all amount to token owner + vuint8_t destpk = (royaltyFract > 0 && hasDust && !isRoyaltyDust) ? vtokenCreatorPubkey : vorigpubkey; // if paid_value is dust send all amount to token owner mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << destpk << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr if (royaltyValue > 0) // note it makes the vout even if roaltyValue is 0 - mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout.3 royalty to token owner + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << vtokenCreatorPubkey << OP_CHECKSIG)); // vout.3 royalty to token owner if (orig_assetoshis - fill_units > 0) // we dont need the marker if order is filled - mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(origpubkey), GetUnspendable(cpAssets, NULL))); //vout.3(4 if royalty) marker to origpubkey (for my tokenorders?) + mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(vorigpubkey), GetUnspendable(cpAssets, NULL))); //vout.3(4 if royalty) marker to vorigpubkey (for my tokenorders?) uint8_t unspendableAssetsPrivkey[32]; CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); @@ -712,21 +727,21 @@ class TestAssetsCC : public ::testing::Test { CCAddVintxCond(cpAssets, wrCond1, unspendableAssetsPrivkey); // probe to spend marker - CCwrapper wrCond2(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(ownerpubkey), unspendableAssetsPk)); + CCwrapper wrCond2(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vtokenCreatorPubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond2, nullptr); // spend with mypk if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, TokensV2::EncodeTokenOpRet(tokenid, { mypk }, - { AssetsV2::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) } ))) { + { AssetsV2::EncodeAssetOpRet('S', unit_price, vorigpubkey, expiryHeight) } ))) { std::cerr << __func__ << " cant finalize tx" << std::endl; return CTransaction(); } - data.pushKV("ownerpubkey", HexStr(ownerpubkey)); - data.pushKV("origpubkey", HexStr(origpubkey)); + data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); + data.pushKV("vorigpubkey", HexStr(vorigpubkey)); data.pushKV("unit_price", unit_price); data.pushKV("royaltyFract", royaltyFract); data.pushKV("royaltyValue", royaltyValue); - data.pushKV("isRoyaltyDust", isRoyaltyDust); + data.pushKV("isRoyaltyDust", isRoyaltyDust); return mtx; } @@ -783,7 +798,6 @@ class TestAssetsCC : public ::testing::Test { CTransaction bidtx; uint256 hashBlock; - std::cerr << __func__ << " call to GetTxUnconfirmedOpt " << bidtxid.GetHex() << std::endl; if (!GetTxUnconfirmedOpt(&eval, bidtxid, bidtx, hashBlock)) { std::cerr << __func__ << " could not load bidtx" << std::endl; return CTransaction(); @@ -801,15 +815,15 @@ class TestAssetsCC : public ::testing::Test { if (royaltyFract > TKLROYALTY_DIVISOR-1) royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit } - vuint8_t ownerpubkey = std::get<0>(tokenData); + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); //std::cerr << __func__ << " bidtx=" << bidtx.GetHash().GetHex() << " " << HexStr(E_MARSHAL(ss << bidtx)) << " vouts=" << bidtx.vout.size() << std::endl; CAmount bid_amount = bidtx.vout[bidvout].nValue; - vuint8_t origpubkey; + vuint8_t vorigpubkey; int32_t expiryHeight; CAmount unit_price; - if (GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, bidtx) == 0) { // get orig pk, orig value + if (GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, bidtx) == 0) { // get orig pk, orig value std::cerr << __func__ << " cant get order data" << std::endl; return CTransaction(); } @@ -840,9 +854,19 @@ class TestAssetsCC : public ::testing::Test { } CAmount royaltyValue = royaltyFract > 0 ? paid_amount / TKLROYALTY_DIVISOR * royaltyFract : 0; - if (royaltyValue <= ASSETS_NORMAL_DUST) - royaltyValue = 0LL; - std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << std::endl; + //if (royaltyValue <= ASSETS_NORMAL_DUST) + // royaltyValue = 0LL; + bool hasDust = false; + bool isRoyaltyDust = true; + if (royaltyFract > 0) { + // correct calculation: + if (AssetsFillOrderIsDust(royaltyFract, paid_amount, isRoyaltyDust)) { + royaltyValue = 0; // all amount (with dust) to go to one pk (depending on which is not dust) + hasDust = true; + } + } + + std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_amount=" << paid_amount << std::endl; CAmount tokensChange = tokenInputs - fill_units; uint8_t unspendableAssetsPrivkey[32]; @@ -851,18 +875,18 @@ class TestAssetsCC : public ::testing::Test { if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { // bidder has coins for more tokens or only dust is sent back to global address mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bid_amount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder or the dust is sent back to cc global addr if (orig_units - fill_units == 0) - std::cerr << __func__ << " dust detected (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; + std::cerr << __func__ << " remainder dust detected, left on global addr (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; } else - mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << origpubkey << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator - mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << vuint8_t(mypk.begin(), mypk.end()) << OP_CHECKSIG)); // vout1 coins to mypk normal + mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << vorigpubkey << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator + mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << (royaltyFract > 0 && hasDust && !isRoyaltyDust ? vtokenCreatorPubkey : vuint8_t(mypk.begin(), mypk.end())) << OP_CHECKSIG)); // vout1 coins to mypk normal if (royaltyValue > 0) // note it makes vout even if roaltyValue is 0 - mtx.vout.push_back(CTxOut(royaltyValue, CScript() << ownerpubkey << OP_CHECKSIG)); // vout2 trade royalty to token owner - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, pubkey2pk(origpubkey))); // vout2(3) single-eval tokens sent to the originator + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << vtokenCreatorPubkey << OP_CHECKSIG)); // vout2 trade royalty to token owner + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, pubkey2pk(vorigpubkey))); // vout2(3) single-eval tokens sent to the originator //specially change to make valid tx if bidder takes tokens for lower price //if (orig_units - fill_units > 0) // order is not finished yet if (mtx.vout[0].scriptPubKey.IsPayToCryptoCondition() && mtx.vout[0].nValue / unit_price > 0) - mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(origpubkey), unspendableAssetsPk)); // vout3(4 if royalty) marker to origpubkey + mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(vorigpubkey), unspendableAssetsPk)); // vout3(4 if royalty) marker to vorigpubkey if (tokensChange != 0LL) mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), tokensChange, mypk)); // change in single-eval tokens @@ -876,21 +900,22 @@ class TestAssetsCC : public ::testing::Test { CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey // probe to spend marker - CCwrapper wrCond3(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(ownerpubkey), unspendableAssetsPk)); + CCwrapper wrCond3(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vtokenCreatorPubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond3, nullptr); // spend with mypk if (!TestFinalizeTx(mtx, cpTokens, testKeys[mypk], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', unit_price, origpubkey, expiryHeight) }))) { + TokensV2::EncodeTokenOpRet(tokenid, { pubkey2pk(vorigpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', unit_price, vorigpubkey, expiryHeight) }))) { std::cerr << __func__ << " could not finalize tx" << std::endl; return CTransaction(); } - data.pushKV("ownerpubkey", HexStr(ownerpubkey)); - data.pushKV("origpubkey", HexStr(origpubkey)); + data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); + data.pushKV("vorigpubkey", HexStr(vorigpubkey)); data.pushKV("unit_price", unit_price); data.pushKV("expiryHeight", expiryHeight); data.pushKV("royaltyFract", royaltyFract); data.pushKV("royaltyValue", royaltyValue); + data.pushKV("isRoyaltyDust", isRoyaltyDust); return mtx; } @@ -914,7 +939,7 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " could not load token data" << std::endl; return CTransaction(); } - vuint8_t ownerpubkey = std::get<0>(tokenData); + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { std::cerr << __func__ << " could not add normal inputs" << std::endl; @@ -925,9 +950,9 @@ class TestAssetsCC : public ::testing::Test { uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; - vuint8_t origpubkey; + vuint8_t vorigpubkey; int32_t expiryHeight; - uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(asktx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, origpubkey, expiryHeight); + uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(asktx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, vorigpubkey, expiryHeight); if (funcid == 's' && asktx.vout.size() > 1) mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // spend marker if funcid='s' else if (funcid == 'S' && asktx.vout.size() > 3) @@ -937,7 +962,7 @@ class TestAssetsCC : public ::testing::Test { return CTransaction(); } - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), askamount, origpubkey)); // one-eval token vout + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), askamount, vorigpubkey)); // one-eval token vout // init assets 'unspendable' privkey and pubkey uint8_t unspendableAssetsPrivkey[32]; @@ -947,26 +972,26 @@ class TestAssetsCC : public ::testing::Test { CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // probe to spend marker - //std::cerr << __func__ << " mypk=" << HexStr(mypk) << " origpubkey=" << HexStr(pubkey2pk(origpubkey)) << std::endl; - if (mypk == pubkey2pk(origpubkey)) { - CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + //std::cerr << __func__ << " mypk=" << HexStr(mypk) << " vorigpubkey=" << HexStr(pubkey2pk(vorigpubkey)) << std::endl; + if (mypk == pubkey2pk(vorigpubkey)) { + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk //std::cerr << __func__ << " use mypk" << std::endl; } else { - CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk //std::cerr << __func__ << " use unspendableAssetsPrivkey=" << HexStr(unspendableAssetsPrivkey, unspendableAssetsPrivkey+32) << std::endl; } if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { origpubkey }, + TokensV2::EncodeTokenOpRet(tokenid, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(), 0) } ))) { std::cerr << __func__ << " could not finalize tx" << std::endl; return CTransaction(); } - data.pushKV("ownerpubkey", HexStr(ownerpubkey)); - data.pushKV("origpubkey", HexStr(origpubkey)); + data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); + data.pushKV("vorigpubkey", HexStr(vorigpubkey)); data.pushKV("askamount", askamount); return mtx; @@ -991,7 +1016,7 @@ class TestAssetsCC : public ::testing::Test { std::cerr << __func__ << " could not load token data" << std::endl; return CTransaction(); } - vuint8_t ownerpubkey = std::get<0>(tokenData); + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { std::cerr << __func__ << " could not add normal inputs" << std::endl; @@ -1002,9 +1027,9 @@ class TestAssetsCC : public ::testing::Test { uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; - vuint8_t origpubkey; + vuint8_t vorigpubkey; int32_t expiryHeight; - uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(bidtx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, origpubkey, expiryHeight); + uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(bidtx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, vorigpubkey, expiryHeight); if (funcid == 'b' && bidtx.vout.size() > 1) mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' else if (funcid == 'B' && bidtx.vout.size() > 3) @@ -1014,11 +1039,11 @@ class TestAssetsCC : public ::testing::Test { return CTransaction(); } if (bidamount > ASSETS_NORMAL_DUST) - mtx.vout.push_back(CTxOut(bidamount, CScript() << ParseHex(HexStr(origpubkey)) << OP_CHECKSIG)); + mtx.vout.push_back(CTxOut(bidamount, CScript() << vorigpubkey << OP_CHECKSIG)); else { // send dust back to global addr mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, GetUnspendable(cpAssets, NULL))); - std::cerr << __func__ << " dust detected bidamount=" << bidamount << std::endl; + std::cerr << __func__ << " remainder dust detected, left on global addr, bidamount=" << bidamount << std::endl; } // init assets 'unspendable' privkey and pubkey @@ -1026,23 +1051,23 @@ class TestAssetsCC : public ::testing::Test { CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); // probe to spend marker - if (mypk == pubkey2pk(origpubkey)) { - CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + if (mypk == pubkey2pk(vorigpubkey)) { + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk } else { - CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(origpubkey), unspendableAssetsPk)); + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk } // sign, add change, add opreturn if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { origpubkey }, + TokensV2::EncodeTokenOpRet(tokenid, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(), 0) } ))) { std::cerr << __func__ << " could not finalise tx" << std::endl; return CTransaction(); } - data.pushKV("ownerpubkey", HexStr(ownerpubkey)); - data.pushKV("origpubkey", HexStr(origpubkey)); + data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); + data.pushKV("vorigpubkey", HexStr(vorigpubkey)); data.pushKV("bidamount", bidamount); return mtx; } @@ -1079,11 +1104,11 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) CMutableTransaction mtx = MakeTokenV2AskTx(cpTokens, mypk, mytokenid, numtokens, 501, 222); // price more than dust ASSERT_FALSE(CTransaction(mtx).IsNull()); - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, mtx); + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, mtx); // test: valid tokenv2ask EXPECT_TRUE(TestRunCCEval(mtx)); @@ -1094,7 +1119,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + { AssetsV2::EncodeAssetOpRet('s', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); } { @@ -1103,7 +1128,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pkunused }, // bad pk instead of global - { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); EXPECT_TRUE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { @@ -1121,7 +1146,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) // mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); } { @@ -1131,7 +1156,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { @@ -1143,7 +1168,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) mtx1.vout.pop_back(); // remove old opreturn ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { @@ -1155,7 +1180,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) mtx1.vout.pop_back(); // remove old opreturn ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { @@ -1166,7 +1191,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) mtx1.vout.pop_back(); // remove old opreturn ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { @@ -1194,7 +1219,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) mtx.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(tokenid2, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop.." << " GetRejectReason=" << eval.state.GetRejectReason() << std::endl; EXPECT_TRUE(!TestRunCCEval(mtx) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // fail: can't ask for different tokenid } @@ -1256,26 +1281,26 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, bidid1, txbid1, hashBlock)); ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, askid2, txask2, hashBlock)); - //vuint8_t ownerpubkey = ParseHex(data["ownerpubkey"].getValStr()); + //vuint8_t vtokenCreatorPubkey = ParseHex(data["vtokenCreatorPubkey"].getValStr()); CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, askid1, 2, 0, data); // test: spend invalid tokenid { CMutableTransaction mtx1(mtx); mtx1.vin.back() = CTxIn(askid1, ASSETS_GLOBALADDR_VOUT, CScript()); // spend order tx - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; CTransaction txask1; uint256 hashBlock; ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, askid1, txask1, hashBlock)); - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txask1); ASSERT_TRUE(funcid != 0); mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(tokenidUnused, { pk2 }, - { AssetsV2::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) } ))); + { AssetsV2::EncodeAssetOpRet('S', unit_price, vorigpubkey, expiryHeight) } ))); EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail } @@ -1284,16 +1309,16 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) CMutableTransaction mtx1(mtx); CAmount txfee = 10000; - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txbid1); mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], txfee, - TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', unit_price, origpubkey, expiryHeight) }))); // 'S' -> 'B' + TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(vorigpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', unit_price, vorigpubkey, expiryHeight) }))); // 'S' -> 'B' EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid } @@ -1301,46 +1326,46 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) { CMutableTransaction mtx2(mtx); mtx2.vin.push_back( CTxIn(askid2, ASSETS_GLOBALADDR_VOUT, CScript()) ); // spend yet another order tx - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask2); + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txask2); ASSERT_TRUE(funcid != 0); mtx2.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx2, cpAssets, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, - { AssetsV2::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) } ))); + { AssetsV2::EncodeAssetOpRet('S', unit_price, vorigpubkey, expiryHeight) } ))); EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail } { // test: change unit_price in opret CMutableTransaction mtx2(mtx); - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; CTransaction txask1; uint256 hashBlock; ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, askid1, txask1, hashBlock)); - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); // get orig pk, orig value + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txask1); // get orig pk, orig value ASSERT_TRUE(funcid != 0); mtx2.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx2, cpAssets, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, - { AssetsV2::EncodeAssetOpRet('S', unit_price+1, origpubkey, expiryHeight) } ))); + { AssetsV2::EncodeAssetOpRet('S', unit_price+1, vorigpubkey, expiryHeight) } ))); EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail } { // test: changed origpk in assets opreturn CMutableTransaction mtx1(mtx); - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); // get orig pk, orig value + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txask1); // get orig pk, orig value mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(tokenid1, { pk2 }, @@ -1348,11 +1373,11 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) EXPECT_FALSE(TestRunCCEval(mtx1)); } { - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txask1); CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, askid1, 2, unit_price-1, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); @@ -1361,11 +1386,11 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) EXPECT_FALSE(TestRunCCEval(mtx)); // must fail } { - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txask1); CMutableTransaction mtx = MakeTokenV2FillAskTx(cpAssets, pk2, tokenid1, askid1, 2, unit_price+1, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); @@ -1383,14 +1408,14 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) //strcpy(ASSETCHAINS_SYMBOL, "MYCHAIN_8173645"); CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; CTransaction txask1; uint256 hashBlock; ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, askid1, txask1, hashBlock)); - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txask1); + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txask1); CMutableTransaction mtx2 = MakeTokenV2FillAskTx(cpAssets, pk2, assetidOpret, askid1, fillUnits, unit_price, data); @@ -1421,7 +1446,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) ASSERT_TRUE(TestFinalizeTx(mtx2, cpAssets, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, - { AssetsV2::EncodeAssetOpRet('S', unit_price, vuint8_t(origpubkey.begin(), origpubkey.end()), expiryHeight) }))); + { AssetsV2::EncodeAssetOpRet('S', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); std::cerr << __func__ << " test: tokenfillask with different tokenid in opdrop, fillUnuts=" << fillUnits << std::endl; EXPECT_FALSE(assetidOpret == tokenid3); @@ -1521,156 +1546,169 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) UniValue data(UniValue::VOBJ); struct CCcontract_info *cpTokens, C; cpTokens = CCinit(&C, TokensV2::EvalCode()); - eval.SetCurrentHeight(111); //set height - - CTransaction txbid1; - uint256 hashBlock; - ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, bidid1, txbid1, hashBlock)); - - CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, bidid1, 2, 0, data); - ASSERT_FALSE(CTransaction(mtx).IsNull()); - // test: valid tokenv2fillbid - EXPECT_TRUE(TestRunCCEval(mtx)); + std::vector bidids = { bidid1, bidid2, bidid3 }; // bids with no extra coins and with some + int i = 0; + for (auto const & bidid : bidids) { - // test: fill with another tokenid - CMutableTransaction mtx1(mtx); + eval.SetCurrentHeight(111); - CAmount txfee = 10000; - vuint8_t ownerpubkey = ParseHex(data["ownerpubkey"].getValStr()); - vuint8_t origpubkey = ParseHex(data["origpubkey"].getValStr()); - CAmount unit_price = data["unit_price"].get_int64(); - int32_t expiryHeight = data["expiryHeight"].get_int(); + CTransaction txbid; + uint256 hashBlock; + ASSERT_TRUE(GetTxUnconfirmedOpt(&eval, bidid, txbid, hashBlock)); - mtx1.vin[1] = CTxIn(tokenid3, 1, CScript()); // spend other tokenid3 - mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx - ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, - TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', unit_price, origpubkey, expiryHeight) }))); + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, bidid, 2, 0, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: can't fill with another tokenid3 - } - { - // test: use opposite funcid - CMutableTransaction mtx1(mtx); + // test: valid tokenv2fillbid + EXPECT_TRUE(TestRunCCEval(mtx)); + { + // test: fill with another tokenid + CMutableTransaction mtx1(mtx); - CAmount txfee = 10000; - vuint8_t origpubkey; - CAmount unit_price; - uint256 assetidOpret; - int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value + CAmount txfee = 10000; + vuint8_t vtokenCreatorPubkey = ParseHex(data["vtokenCreatorPubkey"].getValStr()); + vuint8_t vorigpubkey = ParseHex(data["vorigpubkey"].getValStr()); + CAmount unit_price = data["unit_price"].get_int64(); + int32_t expiryHeight = data["expiryHeight"].get_int(); - mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx - ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, - TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('S', unit_price, origpubkey, expiryHeight) }))); // 'B' -> 'S' + mtx1.vin[1] = CTxIn(tokenid3, 1, CScript()); // spend other tokenid3 + mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(vorigpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', unit_price, vorigpubkey, expiryHeight) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid - } - { - // test: changed origpk in opreturn - CMutableTransaction mtx1(mtx); - vuint8_t origpubkey; - CAmount unit_price; - uint256 assetidOpret; - int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value - mtx1.vout.pop_back(); - ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], 10000, - TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, - { AssetsV2::EncodeAssetOpRet('B', unit_price, vuint8_t(pkunused.begin(), pkunused.end()), expiryHeight) }))); // not matched origpk (should be pk1) - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail changed origpk - } - { - vuint8_t origpubkey; - CAmount unit_price; - uint256 assetidOpret; - int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: can't fill with another tokenid3 + } + { + // test: use opposite funcid + CMutableTransaction mtx1(mtx); - CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, bidid1, 1, unit_price, data); - mtx.vout[1].nValue += 1; // imitate lower price - ASSERT_FALSE(CTransaction(mtx).IsNull()); + CAmount txfee = 10000; + vuint8_t vorigpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txbid); // get orig pk, orig value - // test: invalid tokenv2fillbid with lower price but invalid cc inputs != cc outputs - EXPECT_FALSE(TestRunCCEval(mtx)); // must fail - } - { - vuint8_t origpubkey; - CAmount unit_price; - uint256 assetidOpret; - int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value + mtx1.vout.pop_back(); // remove opret to replace it in TestFinalizeTx + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(vorigpubkey) }, + { AssetsV2::EncodeAssetOpRet('S', unit_price, vorigpubkey, expiryHeight) }))); // 'B' -> 'S' - CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, bidid1, 1, unit_price-1, data); - ASSERT_FALSE(CTransaction(mtx).IsNull()); + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid + } + { + // test: changed origpk in opreturn + CMutableTransaction mtx1(mtx); + vuint8_t vorigpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txbid); // get orig pk, orig value + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, + { AssetsV2::EncodeAssetOpRet('B', unit_price, vuint8_t(pkunused.begin(), pkunused.end()), expiryHeight) }))); // not matched origpk (should be pk1) + EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail changed origpk + } + { + vuint8_t vorigpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txbid); // get orig pk, orig value - // test: valid tokenv2fillbid with lower sell price than requested - EXPECT_TRUE(TestRunCCEval(mtx)); - } - { - vuint8_t origpubkey; - CAmount unit_price; - uint256 assetidOpret; - int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, bidid, 1, unit_price, data); + mtx.vout[1].nValue += 1; // imitate lower price + ASSERT_FALSE(CTransaction(mtx).IsNull()); - CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, txbid1.GetHash(), 1, unit_price+1, data); - ASSERT_FALSE(CTransaction(mtx).IsNull()); + // test: invalid tokenv2fillbid with lower price but invalid cc inputs != cc outputs + EXPECT_FALSE(TestRunCCEval(mtx)); // must fail + } + { + vuint8_t vorigpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txbid); // get orig pk, orig value - // test: invalid tokenv2fillbid with bigger sell price than requested - EXPECT_FALSE(TestRunCCEval(mtx)); // must fail - } - { - // test: fillbid with different tokenid in opdrop - //eval.SetCurrentHeight(111); - eval.SetCurrentHeight(CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); - strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); - CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, bidid, 1, unit_price-1, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); - vuint8_t origpubkey; - CAmount unit_price; - uint256 assetidOpret; - int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, txbid1); // get orig pk, orig value + // test: valid tokenv2fillbid with lower sell price than requested + EXPECT_TRUE(TestRunCCEval(mtx)); + } + { + vuint8_t vorigpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txbid); // get orig pk, orig value - CMutableTransaction mtx2 = MakeTokenV2FillBidTx(cpTokens, pk2, assetidOpret, txbid1.GetHash(), 2, 0, data); + CMutableTransaction mtx = MakeTokenV2FillBidTx(cpTokens, pk2, tokenid2, txbid.GetHash(), 1, unit_price+1, data); + ASSERT_FALSE(CTransaction(mtx).IsNull()); - CAmount txfee = 10000; - mtx2.vin[1] = CTxIn(tokenid3, 1, CScript()); // spend other tokenid3 - { - CScript opret = TokensV2::EncodeTokenOpRet(tokenid3, { origpubkey }, {}); //send to tokenid3 when assetidOpret = tokenid2 - vscript_t vopret; - GetOpReturnData(opret, vopret); - std::vector vData { vopret }; - mtx2.vout[2] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[2].nValue, origpubkey, &vData); + // test: invalid tokenv2fillbid with bigger sell price than requested + EXPECT_FALSE(TestRunCCEval(mtx)); // must fail } { - CScript opretCh = TokensV2::EncodeTokenOpRet(tokenid3, { pk2 }, {}); //send to tokenid3 when assetidOpret = tokenid2 - vscript_t vopretCh; - GetOpReturnData(opretCh, vopretCh); - std::vector vDataCh { vopretCh }; - mtx2.vout[3] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[3].nValue, pk2, &vDataCh); // change - } + // test: fillbid with different tokenid in opdrop + //eval.SetCurrentHeight(111); + eval.SetCurrentHeight(CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); + strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); - mtx2.vout.pop_back(); // remove opret to replace it in TestFinalizeTx - ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk2], txfee, - TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(origpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', unit_price, origpubkey, expiryHeight) }))); + vuint8_t vorigpubkey; + CAmount unit_price; + uint256 assetidOpret; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, txbid); // get orig pk, orig value + + CMutableTransaction mtx2 = MakeTokenV2FillBidTx(cpTokens, pk2, assetidOpret, txbid.GetHash(), 2, 0, data); + + CAmount txfee = 10000; + mtx2.vin[1] = CTxIn(tokenid3, 1, CScript()); // spend other tokenid3 + { + CScript opret = TokensV2::EncodeTokenOpRet(tokenid3, { vorigpubkey }, {}); //send to tokenid3 when assetidOpret = tokenid2 + vscript_t vopret; + GetOpReturnData(opret, vopret); + std::vector vData { vopret }; + mtx2.vout[2] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[2].nValue, vorigpubkey, &vData); + } + { + CScript opretCh = TokensV2::EncodeTokenOpRet(tokenid3, { pk2 }, {}); //send to tokenid3 when assetidOpret = tokenid2 + vscript_t vopretCh; + GetOpReturnData(opretCh, vopretCh); + std::vector vDataCh { vopretCh }; + mtx2.vout[3] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx2.vout[3].nValue, pk2, &vDataCh); // change + } + + mtx2.vout.pop_back(); // remove opret to replace it in TestFinalizeTx + ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk2], txfee, + TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(vorigpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', unit_price, vorigpubkey, expiryHeight) }))); - std::cerr << __func__ << " test: tokenfillbid with different tokenid in opdrop" << std::endl; - EXPECT_FALSE(assetidOpret == tokenid3); - //EXPECT_TRUE(TestRunCCEval(mtx2)); - EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid3 in opdrop + std::cerr << __func__ << " test: tokenfillbid with different tokenid in opdrop, tokenid3=" << tokenid3.GetHex() << " assetidOpret=" << assetidOpret.GetHex() << std::endl; + std::cerr << __func__ << " i=" << i++ << std::endl; + EXPECT_FALSE(assetidOpret == tokenid3); + //EXPECT_TRUE(TestRunCCEval(mtx2)); + bool b = false; + EXPECT_TRUE(!(b=TestRunCCEval(mtx2)) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid3 in opdrop + std::cerr <<__func__ << " b=" << b << " eval.state.GetRejectReason()=" << eval.state.GetRejectReason() << " mtx2=" << HexStr(E_MARSHAL(ss << mtx2)) << std::endl; + } } } -TEST_F(TestAssetsCC, tokenv2fillbid_royalty) +// NOTE: no test for tokenv2fillbid_royalty_non_fixed + +TEST_F(TestAssetsCC, tokenv2fillbid_royalty_fixed) { eval.SetCurrentHeight(111); //set height - for(int r = 100; r < 1000; r += 100) + std::vector royalties = { 1, 200, 500, 800, 999 }; + //for(int r = 100; r < 1000; r += 100) + for (auto const r : royalties) { UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx UniValue tokeldata(UniValue::VOBJ); @@ -1684,12 +1722,33 @@ TEST_F(TestAssetsCC, tokenv2fillbid_royalty) uint256 mytokenid = mytxtokencreate.GetHash(); eval.AddTx(mytxtokencreate); - CTransaction mytxbid = MakeTokenV2BidTx(cpAssets, pk2, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); + CAmount price = 4999; + CAmount asktokens = 1; + CAmount filltokens = 1; + + //CTransaction mytxbid = MakeTokenV2BidTx(cpAssets, pk2, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); + CTransaction mytxbid = MakeTokenV2BidTx(cpAssets, pk2, mytokenid, asktokens, price, 222); eval.AddTx(mytxbid); - CMutableTransaction mytxfillbid = MakeTokenV2FillBidTx(cpTokens, pk1, mytokenid, mytxbid.GetHash(), 1, 0, data); + CMutableTransaction mytxfillbid = MakeTokenV2FillBidTx(cpTokens, pk1, mytokenid, mytxbid.GetHash(), filltokens, 0, data); ASSERT_FALSE(CTransaction(mytxfillbid).IsNull()); - ASSERT_TRUE(data["royaltyFract"].get_int64() == r); + ASSERT_TRUE(data["royaltyFract"].get_int64() == r); + if (filltokens * price / (int64_t)TKLROYALTY_DIVISOR * std::min(r, (int32_t)TKLROYALTY_DIVISOR - r) <= ASSETS_NORMAL_DUST) { + // have dust + EXPECT_TRUE(data["royaltyValue"].get_int64() == 0); + EXPECT_TRUE(TestRunCCEval(mytxfillbid)); + EXPECT_TRUE(mytxfillbid.vout[1].nValue == filltokens * price); + EXPECT_TRUE(r < TKLROYALTY_DIVISOR/2 ? data["isRoyaltyDust"].get_bool() : !data["isRoyaltyDust"].get_bool()); // is dust royalty or paid_value + // if royalty is not dust then the value should go either to tokenowner + if (r >= TKLROYALTY_DIVISOR/2) + EXPECT_TRUE(IsEqualDestinations(mytxfillbid.vout[1].scriptPubKey, CScript() << vuint8_t(pk1.begin(), pk1.end()) << OP_CHECKSIG)); + } + else { + // no dust + EXPECT_TRUE(data["royaltyValue"].get_int64() > 0); + EXPECT_TRUE(TestRunCCEval(mytxfillbid)); + EXPECT_TRUE(mytxfillbid.vout[1].nValue + mytxfillbid.vout[2].nValue == filltokens * price); + } // test: valid tokenv2fillbid EXPECT_TRUE(TestRunCCEval(mytxfillbid)); @@ -1748,7 +1807,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty_fixed) ASSERT_TRUE(CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)); // fix in action for(int r = 100; r < 1000; r += 100) { - UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx + UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FilAskTx UniValue tokeldata(UniValue::VOBJ); struct CCcontract_info *cpTokens, tokensC; cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); @@ -1770,7 +1829,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty_fixed) ASSERT_FALSE(CTransaction(mytxfillask).IsNull()); ASSERT_TRUE(data["royaltyFract"].get_int64() == r); - if (r == 100 || r == 900) EXPECT_TRUE(data["royaltyValue"].get_int64() == 0); // for these royalties t should be dust + //if (r == 100 || r == 900) EXPECT_TRUE(data["royaltyValue"].get_int64() == 0); // for these royalties t should be dust // test: valid tokenv2fillask //std::cerr << __func__ << " good rule, is dust calc=" << (filltokens * price / (int64_t)TKLROYALTY_DIVISOR * std::min(r, (int32_t)TKLROYALTY_DIVISOR - r)) << " royaltyValue=" << data["royaltyValue"].get_int64() << std::endl; @@ -1810,15 +1869,15 @@ TEST_F(TestAssetsCC, tokenv2cancelask) UniValue data(UniValue::VOBJ); uint256 asktxid = vintx.GetHash(); - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, vintx); + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, vintx); struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); - CMutableTransaction mtx = MakeTokenV2CancelAskTx(cpAssets, pubkey2pk(origpubkey), tokenid1, asktxid, data); + CMutableTransaction mtx = MakeTokenV2CancelAskTx(cpAssets, pubkey2pk(vorigpubkey), tokenid1, asktxid, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); CAmount askamount = data["askamount"].get_int64(); @@ -1829,7 +1888,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask) // test: invalid pk2 in assets opreturn CMutableTransaction mtx2(mtx); mtx2.vout.pop_back(); - mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { origpubkey }, + mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(pk2.begin(), pk2.end()), 0) } ))); EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret not checked } @@ -1838,7 +1897,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask) CMutableTransaction mtx3(mtx); mtx3.vout.pop_back(); mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { pkunused }, - { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); + { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked for token v2, it is only for a hint } { @@ -1851,16 +1910,16 @@ TEST_F(TestAssetsCC, tokenv2cancelask) // test: invalid tokenid in token opret CMutableTransaction mtx5(mtx); mtx5.vout.pop_back(); - mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { origpubkey }, - { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); + mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { vorigpubkey }, + { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); EXPECT_FALSE(TestRunCCEval(mtx5)); // must fail: cant send to another tokenid } { // test: invalid funcid in token opret CMutableTransaction mtx6(mtx); mtx6.vout.pop_back(); - mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { origpubkey }, - { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); + mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { vorigpubkey }, + { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); EXPECT_FALSE(TestRunCCEval(mtx6)); // must fail } { @@ -1871,33 +1930,33 @@ TEST_F(TestAssetsCC, tokenv2cancelask) CMutableTransaction mtx7(mtx); CAmount txfee = 10000; - CAmount otherAmount = TestAddTokenInputs(mtx7, origpubkey, tokenid4, mtx7.vout[0].nValue); //add different tokenid + CAmount otherAmount = TestAddTokenInputs(mtx7, vorigpubkey, tokenid4, mtx7.vout[0].nValue); //add different tokenid ASSERT_TRUE(otherAmount > 0); mtx7.vout.insert(mtx7.vout.begin() + mtx7.vout.size() - 1, mtx7.vout[0]); // copy vout with tokens with assetidOpret back - CScript opret = TokensV2::EncodeTokenOpRet(tokenid4, { origpubkey }, {}); // put tokenid4 in opdrop while assetid differs + CScript opret = TokensV2::EncodeTokenOpRet(tokenid4, { vorigpubkey }, {}); // put tokenid4 in opdrop while assetid differs vscript_t vopret; GetOpReturnData(opret, vopret); std::vector vData { vopret }; - mtx7.vout[0] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx7.vout[0].nValue, origpubkey, &vData); // replace remainder with tokenid4 + mtx7.vout[0] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx7.vout[0].nValue, vorigpubkey, &vData); // replace remainder with tokenid4 std::cerr << __func__ << " tokenid4=" << tokenid4.GetHex() << " assetidOpret=" << assetidOpret.GetHex() << " otherAmount=" << otherAmount << " mtx7.vin.size()=" << mtx7.vin.size() << std::endl; if (otherAmount > mtx7.vout[0].nValue) { // if tokenid4 change exists - CScript opret = TokensV2::EncodeTokenOpRet(tokenid4, { origpubkey }, {}); + CScript opret = TokensV2::EncodeTokenOpRet(tokenid4, { vorigpubkey }, {}); vscript_t vopret; GetOpReturnData(opret, vopret); std::vector vData { vopret }; mtx7.vout.insert(mtx7.vout.begin() + mtx7.vout.size() - 1, - TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), otherAmount - mtx7.vout[0].nValue, origpubkey, &vData)); // add tokenid4 change + TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), otherAmount - mtx7.vout[0].nValue, vorigpubkey, &vData)); // add tokenid4 change } - CCwrapper wrCond1(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), origpubkey)); // spend my tokenid4 + CCwrapper wrCond1(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), vorigpubkey)); // spend my tokenid4 CCAddVintxCond(cpAssets, wrCond1, NULL); // NULL indicates to use myprivkey mtx7.vout.pop_back(); //remove opret - ASSERT_TRUE(TestFinalizeTx(mtx7, cpAssets, testKeys[origpubkey], 10000, - TokensV2::EncodeTokenOpRet(assetidOpret, { origpubkey }, + ASSERT_TRUE(TestFinalizeTx(mtx7, cpAssets, testKeys[vorigpubkey], 10000, + TokensV2::EncodeTokenOpRet(assetidOpret, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(), 0) }))); std::cerr << __func__ << " test: tokencancelask with different tokenid in opdrop" << std::endl; @@ -2028,15 +2087,15 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) UniValue data(UniValue::VOBJ); uint256 bidtxid = vintx.GetHash(); - vuint8_t origpubkey; + vuint8_t vorigpubkey; CAmount unit_price; uint256 assetidOpret; int32_t expiryHeight; - uint8_t funcid = GetOrderParams(origpubkey, unit_price, assetidOpret, expiryHeight, vintx); + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, vintx); struct CCcontract_info *cpAssets, C; cpAssets = CCinit(&C, AssetsV2::EvalCode()); - CMutableTransaction mtx = MakeTokenV2CancelBidTx(cpAssets, pubkey2pk(origpubkey), tokenid2, bidtxid, data); + CMutableTransaction mtx = MakeTokenV2CancelBidTx(cpAssets, pubkey2pk(vorigpubkey), tokenid2, bidtxid, data); ASSERT_FALSE(CTransaction(mtx).IsNull()); CAmount bidamount = data["bidamount"].get_int64(); @@ -2047,7 +2106,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) // test: invalid pk in assets opreturn CMutableTransaction mtx2(mtx); mtx2.vout.pop_back(); - mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { origpubkey }, + mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(pk1.begin(), pk1.end()), 0) } ))); EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret is not checked } @@ -2056,7 +2115,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) CMutableTransaction mtx3(mtx); mtx3.vout.pop_back(); mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pkunused }, - { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); + { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked } { @@ -2069,8 +2128,8 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) // test: invalid tokenid in token opret CMutableTransaction mtx5(mtx); mtx5.vout.pop_back(); - mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { origpubkey }, - { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); + mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { vorigpubkey }, + { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); EXPECT_FALSE(TestRunCCEval(mtx5)); } { @@ -2078,13 +2137,13 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) CMutableTransaction mtx6(mtx); mtx6.vout.pop_back(); mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pk2 }, - { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(origpubkey.begin(), origpubkey.end()), 0) } ))); + { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); EXPECT_FALSE(TestRunCCEval(mtx6)); } { // test: send dust to normals - bad test params here //CMutableTransaction mtx7(mtx); - //mtx7.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(ownerpubkey)) << OP_CHECKSIG); + //mtx7.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(vtokenCreatorPubkey)) << OP_CHECKSIG); //EXPECT_FALSE(TestRunCCEval(mtx7)); // must fail: dust should stay on cc global output } } From b871bc229c544b43d57106a6322a374a86732345 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 6 May 2022 20:39:48 +0500 Subject: [PATCH 258/348] more assets py tests added for big royalties --- src/tui/tui_assets_orders.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 0838ecd273f..2e67b3bbafc 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -123,28 +123,37 @@ def run_tokens_create(rpc1, rpc2, rpc3): print("created token:", nftf7id1) # wait_until_confirmed(rpc1, nftf7id1) - print("creating tokel NFT with royalty 99...") - result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-2", str(0.00000001), "nft tokel royalty=99", '{"royalty":99}') + print("creating tokel NFT with royalty 999 on rpc3...") + result = call_rpc(rpc3, "token"+v+"createtokel", "NFT-F7-2", str(0.00000001), "nft tokel royalty=999", '{"royalty":999}') assert(check_tx_result(result)) - nftf7id2 = rpc1.sendrawtransaction(result['hex']) + nftf7id2 = rpc3.sendrawtransaction(result['hex']) print("created token:", nftf7id2) # wait_until_confirmed(rpc1, nftf7id2) - print("creating tokel NFT with royalty 1 (to test dust)...") - result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-3", str(0.00000001), "nft tokel royalty=1", '{"royalty":1}') + print("creating tokel NFT with royalty 1 on rpc3 (to test dust)...") + result = call_rpc(rpc3, "token"+v+"createtokel", "NFT-F7-3", str(0.00000001), "nft tokel royalty=1", '{"royalty":1}') assert(check_tx_result(result)) - nftf7id3 = rpc1.sendrawtransaction(result['hex']) + nftf7id3 = rpc3.sendrawtransaction(result['hex']) print("created token:", nftf7id3) # wait_until_confirmed(rpc1, nftf7id3) print("creating tokel NFT with royalty 500 (to test dust)...") - result = call_rpc(rpc1, "token"+v+"createtokel", "NFT-F7-4", str(0.00000001), "nft tokel royalty=500", '{"royalty":500}') + result = call_rpc(rpc3, "token"+v+"createtokel", "NFT-F7-4", str(0.00000001), "nft tokel royalty=500", '{"royalty":500}') assert(check_tx_result(result)) - nftf7id4 = rpc1.sendrawtransaction(result['hex']) + nftf7id4 = rpc3.sendrawtransaction(result['hex']) print("created token:", nftf7id4) # wait_until_confirmed(rpc1, nftf7id4) print("tokens for tests created okay!") + + # transfer tokens from rpc3 to rpc1 (to make a different pubkey than tokencreator) + pubkey1 = rpc1.getinfo()['pubkey'] + call_token_rpc_send_tx(rpc3, "token"+v+"transfer", '', nftf7id2, pubkey1, str(1)) + call_token_rpc_send_tx(rpc3, "token"+v+"transfer", '', nftf7id3, pubkey1, str(1)) + call_token_rpc_send_tx(rpc3, "token"+v+"transfer", '', nftf7id4, pubkey1, str(1)) + + + ''' # test tokenlist: check_tokenlist(rpc1, v, [tokenid1, tokenid2, nft00id1, nft00id2, nftf7id1, nftf7id2, nftf7id3, nftf7id4]) # test tokenallbalances: @@ -154,13 +163,14 @@ def run_tokens_create(rpc1, rpc2, rpc3): print("starting transfer tests for tokenid version=" + v + "...") run_transfers(rpc1, rpc2, v, tokenid1, tokenid2, 10) - ''' + print("starting transfer tests for nft00id version=" + v + "...") run_transfers(rpc1, rpc2, v, nft00id1, nft00id2, 1) print("starting transfer tests for nftf7id version=" + v + "...") run_transfers(rpc1, rpc2, v, nftf7id1, nftf7id2, 1) print("token transfers tests finished okay!") time.sleep(3) + ''' # assets cc tests: print("starting assets tests for tokenid1 version=" + v + "...") @@ -175,12 +185,11 @@ def run_tokens_create(rpc1, rpc2, rpc3): run_assets_orders(rpc1, rpc2, v, nftf7id3, 1, 1, 0.0001, True) print("starting assets tests for nftf7id4 with unit price creating dust royalty and checking that round correct, version=" + v + "...") run_assets_orders(rpc1, rpc2, v, nftf7id4, 1, 1, 0.0000_1001, True) - print("starting assets order expiration tests for tokenid1 version=" + v + "...") run_assets_expired_orders(rpc1, rpc2, v, tokenid1, 10, 8, 0.0001, False) print("assets tests finished okay!") + ''' - if v == "v2" : # MofN supported for tokens cc v2 only print("running MofN tests for tokens v2:") print("starting MofN tests for tokenid1...") @@ -190,7 +199,7 @@ def run_tokens_create(rpc1, rpc2, rpc3): print("starting MofN tests for nftf7id1...") run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) print("token MofN transfer tests finished okay!") - + ''' print("all token/assets tests finished okay!") @@ -819,7 +828,7 @@ def get_chain_rpc(config) : if __name__ == "__main__": print("starting assets orders test") print("plz first start a chain of three nodes and enter rpc params in the code") - print("ensure you have at least 10 utxos in the first node wallet for batch test txns creation") + print("ensure you have at least 10 utxos in the nodes' wallets for batch transaction creation") rpc1 = get_chain_rpc('/Users/dimxy/Library/Application Support/Komodo/DIMXY31/DIMXY31.conf') rpc2 = get_chain_rpc('/Users/dimxy/repo/tokel/src/DIMXY31/nodes/1/DIMXY31.conf') From 3c960b14db3220bc8553f9bf4e445409cbebf64f Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 6 May 2022 22:58:16 +0500 Subject: [PATCH 259/348] fixes to enable debug build --- src/Makefile.am | 19 ++++++++++++++++--- src/cryptoconditions/Makefile.am | 4 ++-- src/wallet-utility.cpp | 6 ++++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index caadee77728..b96faa2554e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -642,7 +642,7 @@ endif if ENABLE_WALLET wallet_utility_SOURCES = wallet-utility.cpp wallet_utility_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -wallet_utility_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +wallet_utility_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) $(CXXFLAGS) wallet_utility_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) endif @@ -731,7 +731,7 @@ libzcash_a_CPPFLAGS = -DMULTICORE -fopenmp -fPIC -DBINARY_OUTPUT -DCURVE_ALT_BN1 $(HARDENED_CXXFLAGS) $(HARDENED_LDFLAGS) -pipe $(SAN_LDFLAGS) \ -Wstack-protector $(SAN_CXXFLAGS) -fstack-protector-all -fPIE -fvisibility=hidden \ -DSTATIC $(BITCOIN_INCLUDES) -libzcash_a_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing +libzcash_a_CXXFLAGS = $(CXXFLAGS) $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing libzcash_a_LDFLAGS = $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) libzcash_a_CPPFLAGS += -DMONTGOMERY_OUTPUT @@ -874,10 +874,23 @@ customd_LDADD += \ $(LIBBITCOIN_CRYPTO) \ $(LIBVERUS_CRYPTO) \ $(LIBVERUS_PORTABLE_CRYPTO) \ - $(LIBZCASH_LIBS) + $(LIBZCASH_LIBS) \ + $(LIBCC) \ + -lcurl customd_LDADD += $(LIBDYNCUSTOMCONSENSUS) $(LIBSECP256K1) +if ENABLE_WEBSOCKETS +# link statically openssl +customd_LDADD += \ + $(LIBSSLSTATIC) \ + $(LIBCRYPTOSTATIC) +else +customd_LDADD += \ + $(SSL_LIBS) \ + $(CRYPTO_LIBS) +endif + if ENABLE_PROTON customd_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) endif diff --git a/src/cryptoconditions/Makefile.am b/src/cryptoconditions/Makefile.am index 7db566e035c..5565ffa27bb 100644 --- a/src/cryptoconditions/Makefile.am +++ b/src/cryptoconditions/Makefile.am @@ -2,7 +2,7 @@ noinst_LIBRARIES=libcryptoconditions_core.a SUBDIRS = src/include/secp256k1 # optimisation off to allow better gdb/lldb -CFLAGS = -g -O0 +# CFLAGS = -g -O0 # use to debug: # CPPFLAGS = -DEMIT_ASN_DEBUG=1 @@ -14,7 +14,7 @@ include_HEADERS = include/cryptoconditions.h src/internal.h LIBSECP256K1=src/include/secp256k1/libsecp256k1.la $(LIBSECP256K1): $(wildcard src/secp256k1/*) - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) -march:x86-64 -g -O0 + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) -march:x86-64 -g libcryptoconditions_core_a_SOURCES = \ src/cryptoconditions.c \ diff --git a/src/wallet-utility.cpp b/src/wallet-utility.cpp index 0b664ecb35a..4972ccd35bb 100644 --- a/src/wallet-utility.cpp +++ b/src/wallet-utility.cpp @@ -9,7 +9,9 @@ #include #include "komodo_defs.h" -char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +#include "komodo_globals.h" + +/*char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; int64_t MAX_MONEY = 200000000 * 100000000LL; uint64_t ASSETCHAINS_SUPPLY; uint16_t BITCOIND_RPCPORT = 7771; @@ -26,7 +28,7 @@ int32_t ASSETCHAINS_OVERWINTER = 227520; int32_t ASSETCHAINS_SAPLING = 227520; int32_t KOMODO_TESTNODE = 0; -unsigned int MAX_BLOCK_SIGOPS = 20000; +unsigned int MAX_BLOCK_SIGOPS = 20000;*/ void show_help() { From 9b091d99e5e049d833a2e7976ceeec70439fd77c Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 9 May 2022 15:45:49 +0500 Subject: [PATCH 260/348] CCUpgrade const names refactored --- src/cc/CCassetsCore_impl.h | 2 +- src/cc/CCtokens_impl.h | 4 ++-- src/cc/CCupgrades.cpp | 24 ++++++++++++------------ src/cc/CCupgrades.h | 6 +++--- src/cc/assets.cpp | 8 ++++---- src/cc/import.cpp | 2 +- src/importcoin.cpp | 2 +- src/main.cpp | 2 +- src/rpc/tokensrpc.cpp | 4 ++-- src/test-komodo-cc/test-assets.cpp | 6 +++--- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index f952bb7204b..6c5efc1d559 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -304,7 +304,7 @@ bool AssetsValidateTokenId(Eval *eval, struct CCcontract_info *cp, const CTransa template bool AssetsValidateTokenId_Activated(Eval *eval, struct CCcontract_info *cpTokens, const CTransaction &tx, int32_t v, uint256 assetid) { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCASSETS_OPDROP_VALIDATE_FIX)) + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_ASSETS_OPDROP_VALIDATE_FIX)) return AssetsValidateTokenId(eval, cpTokens, tx, v, assetid); else return true; diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 5bb44025307..c8489e6d03c 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -451,7 +451,7 @@ std::string TokenTransferDest(CAmount txfee, uint256 tokenid, uint8_t M, const s //vuint8_t vextraData = std::get<4>(tokenData); std::vector tokenindexkeys = V::GetTokenIndexKeys(mypk); - UniValue sigData = TokenTransferExtDest(CPubKey(), txfee, tokenid, tokenindexkeys, {}, M, destinations, total, true); + UniValue sigData = TokenTransferExtDest(CPubKey(), txfee, tokenid, tokenindexkeys, {}, M, destinations, total, false); return ResultGetTx(sigData); } @@ -939,7 +939,7 @@ static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 } vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey diff --git a/src/cc/CCupgrades.cpp b/src/cc/CCupgrades.cpp index 8f90edaeca3..df3ebf9751c 100644 --- a/src/cc/CCupgrades.cpp +++ b/src/cc/CCupgrades.cpp @@ -26,7 +26,7 @@ namespace CCUpgrades { void init(const std::string &chainName, int nProtocolVersion) { assert(mChainUpgrades.find(chainName) == mChainUpgrades.end()); // mChainUpgrades[chainName] must be empty - mChainUpgrades[chainName].setActivationHeight(CCASSETS_INITIAL_CHAIN, 0, UPGRADE_ACTIVE, nProtocolVersion); + mChainUpgrades[chainName].setActivationHeight(CCUPGID_ASSETS_INITIAL_CHAIN, 0, UPGRADE_ACTIVE, nProtocolVersion); } void addUpgradeActive(const std::string &chainName, UPGRADE_ID upgradeId, int32_t nHeight, int nProtocolVersion) @@ -45,17 +45,17 @@ namespace CCUpgrades { init("TKLTEST2", CCOLDDEFAULT_PROTOCOL_VERSION); init("DIMXY32", CCOLDDEFAULT_PROTOCOL_VERSION); - // CCASSETS_OPDROP_VALIDATE_FIX activation - addUpgradeActive("TOKEL", CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TOKEL_HEIGHT, CCOLDDEFAULT_PROTOCOL_VERSION); - addUpgradeActive("TKLTEST", CCASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT, CCOLDDEFAULT_PROTOCOL_VERSION); + // CCUPGID_ASSETS_OPDROP_VALIDATE_FIX activation + addUpgradeActive("TOKEL", CCUPGID_ASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TOKEL_HEIGHT, CCOLDDEFAULT_PROTOCOL_VERSION); + addUpgradeActive("TKLTEST", CCUPGID_ASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT, CCOLDDEFAULT_PROTOCOL_VERSION); - // CCMIXEDMODE_SUBVER_1 activation - addUpgradeActive("TOKEL", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); - addUpgradeActive("TKLTEST", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); - addUpgradeActive("DIMXY24", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); - addUpgradeActive("DIMXY28", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); - addUpgradeActive("DIMXY32", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); - addUpgradeActive("TKLTEST2", CCMIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + // CCUPGID_MIXEDMODE_SUBVER_1 activation + addUpgradeActive("TOKEL", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("TKLTEST", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("DIMXY24", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("DIMXY28", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("DIMXY32", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("TKLTEST2", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); // add more chains here... // ... @@ -101,7 +101,7 @@ namespace CCUpgrades { if (chainUpgrades.mUpgrades.size() == 0) return chainUpgrades.defaultUpgrade; else { - UpgradeInfo current = chainUpgrades.mUpgrades.find(CCASSETS_INITIAL_CHAIN)->second; // set as initial chain info + UpgradeInfo current = chainUpgrades.mUpgrades.find(CCUPGID_ASSETS_INITIAL_CHAIN)->second; // set as initial chain info for (auto const & it : chainUpgrades.mUpgrades) { if (nHeight >= it.second.nActivationHeight) current = it.second; // find latest active upgrade diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index d3c524ae67b..0ec36ae25ae 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -46,9 +46,9 @@ namespace CCUpgrades { }; enum UPGRADE_ID { - CCASSETS_INITIAL_CHAIN = 0x00, - CCASSETS_OPDROP_VALIDATE_FIX = 0x01, - CCMIXEDMODE_SUBVER_1 = 0x02, // new cc secp256k1 cond type and eval param, assets cc royalty fixes + CCUPGID_ASSETS_INITIAL_CHAIN = 0x00, + CCUPGID_ASSETS_OPDROP_VALIDATE_FIX = 0x01, + CCUPGID_MIXEDMODE_SUBVER_1 = 0x02, // new cc secp256k1 cond type and eval param, assets cc royalty fixes }; struct UpgradeInfo { diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index f39ab4b54d8..6930bda129b 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -364,7 +364,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // check if royalty or paid_value is not dust if (royaltyFract > 0) { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1) == false) { + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { // old bad calc: // incorrect use of vin_coins to calculate royalty (this is true only for nfts) CAmount royaltyValue = royaltyFract > 0 ? vin_coins / TKLROYALTY_DIVISOR * royaltyFract : 0; @@ -448,7 +448,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("vout2 invalid royalty detination for fillask"); } else { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) { // validate that the paid value to go to the token owner if amount to seller is dust if (royaltyFract > 0 && r == 0 && !isRoyaltyDust) { // there is royalty dust and royalty is not dust --> send to token owner @@ -581,7 +581,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // check if royalty or paid_value is not dust if (royaltyFract > 0) { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1) == false) { + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { // old bad calc: only if royalty<=50% works bcz of loss of significance bcz of division by royaltyFract first. // also wrong assumption that paid_value is subtracted by the royalty (in fact it is sum of both if the royalty is dust) // suppose the nValue is such that the royalty_value is assets' dust: @@ -610,7 +610,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const else if (!AssetsValidateTokenId_Activated(eval, cp, tx, 1, assetid)) return eval->Invalid("invalid tokenid in vout1 for fillask"); else { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1) == false) { + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, origNormalAddr, 0LL, 0)) // coins to originator normal addr return eval->Invalid("vout2 should be cc for fillask"); } diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 4fd06f073d2..4919a7084e5 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -550,7 +550,7 @@ bool CheckMigration(Eval *eval, const CTransaction &importTx, const CTransaction std::vector vDeadPubkeys; vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey // calc outputs for burn tx diff --git a/src/importcoin.cpp b/src/importcoin.cpp index 7a41f11bd01..1af9ac5f4f4 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -347,7 +347,7 @@ CAmount GetCoinImportValue(const CTransaction &tx, int32_t nHeight) std::vector vDeadPubkeys; vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); - if (CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + if (CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey // calc outputs for burn tx diff --git a/src/main.cpp b/src/main.cpp index 79afa34f748..3ded0af23f6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3019,7 +3019,7 @@ bool ContextualCheckOutputs( { // check if secp256hash and eval param in action: int subversion = CC_MixedModeSubVersion(tx.vout[i].scriptPubKey[0]); - if (subversion >= CC_MIXED_MODE_SECHASH_SUBVER_1 && !CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + if (subversion >= CC_MIXED_MODE_SECHASH_SUBVER_1 && !CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) { return state.DoS(100,false, REJECT_INVALID, std::string("cc v2 subversion 1 or more not yet enabled")); } diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 9f7c6565f06..52ab51d5b96 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -553,13 +553,13 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b dest = CPubKey(vpubkey); else dest = DecodeDestination(params[1].get_str()); - if (dest.which() == TX_PUBKEYHASH && !CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + if (dest.which() == TX_PUBKEYHASH && !CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) return MakeResultError("destination as address not active yet"); if (dest.which() != TX_PUBKEYHASH && dest.which() != TX_PUBKEY) return MakeResultError("invalid destination pubkey or address"); // after subver_1 upgrade only addresses always will be used as destination, pubkeys are converted to addresses - if (dest.which() == TX_PUBKEY && CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)) + if (dest.which() == TX_PUBKEY && CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) dests.push_back(boost::get(dest).GetID()); else dests.push_back(dest); // address or pubkey diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index 693fc6c8e35..caf7fba8221 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -678,7 +678,7 @@ class TestAssetsCC : public ::testing::Test { bool isRoyaltyDust = true; if (royaltyFract > 0) { - if (CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1) == false) { + if (CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { // corrected old calculation to allow tx creation and pass to fillask validation code // (note division on TKLROYALTY_DIVISOR first): if(paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / (int64_t)TKLROYALTY_DIVISOR * royaltyFract - ASSETS_NORMAL_DUST) { // if value paid to seller less than when the royalty is minimum @@ -1762,7 +1762,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty_non_fixed) strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); - ASSERT_FALSE(CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)); + ASSERT_FALSE(CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)); for(int r = 100; r < 1000; r += 100) { UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx @@ -1804,7 +1804,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty_fixed) strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); - ASSERT_TRUE(CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCMIXEDMODE_SUBVER_1)); // fix in action + ASSERT_TRUE(CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)); // fix in action for(int r = 100; r < 1000; r += 100) { UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FilAskTx From 960dbae17039da3319ba04f857f041aa568ce7e9 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 9 May 2022 15:46:27 +0500 Subject: [PATCH 261/348] disabled eval param for future --- .../include/cryptoconditions.h | 2 +- src/cryptoconditions/src/eval.c | 44 ++++++++++++------- src/script/cc.cpp | 22 ++++++---- 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/cryptoconditions/include/cryptoconditions.h b/src/cryptoconditions/include/cryptoconditions.h index 5c88470a2f4..33320dbc567 100644 --- a/src/cryptoconditions/include/cryptoconditions.h +++ b/src/cryptoconditions/include/cryptoconditions.h @@ -65,7 +65,7 @@ typedef struct CC { struct { uint8_t *prefix; size_t prefixLength; struct CC *subcondition; size_t maxMessageLength; }; // eval - struct { uint8_t *code; size_t codeLength; uint8_t *param; size_t paramLength; int includeParamInFP; }; + struct { uint8_t *code; size_t codeLength; /*uint8_t *param; size_t paramLength; int includeParamInFP;*/ }; // enable param when new generic evals added // anon struct { uint8_t fingerprint[32]; uint32_t subtypes; unsigned long cost; struct CCType *conditionType; }; diff --git a/src/cryptoconditions/src/eval.c b/src/cryptoconditions/src/eval.c index 2cede6db862..80a1633ee69 100644 --- a/src/cryptoconditions/src/eval.c +++ b/src/cryptoconditions/src/eval.c @@ -28,15 +28,17 @@ struct CCType CC_EvalType; static void evalFingerprint(const CC *cond, uint8_t *out) { - if (!cond->includeParamInFP) - sha256(cond->code, cond->codeLength, out); - else { - uint8_t *msg = malloc(cond->codeLength + cond->paramLength); - memcpy(msg, cond->code, cond->codeLength); - memcpy(msg + cond->codeLength, cond->param, cond->paramLength); - sha256(msg, cond->codeLength+cond->paramLength, out); - free(msg); - } + /* TODO: enable for generic evals + if (!cond->includeParamInFP) */ + sha256(cond->code, cond->codeLength, out); + /* TODO: enable for generic evals + else { + uint8_t *msg = malloc(cond->codeLength + cond->paramLength); + memcpy(msg, cond->code, cond->codeLength); + memcpy(msg + cond->codeLength, cond->param, cond->paramLength); + sha256(msg, cond->codeLength+cond->paramLength, out); + free(msg); + } */ } @@ -52,6 +54,8 @@ static CC *evalFromJSON(const cJSON *params, char *err) { if (!jsonGetBase64(params, "code", err, &code, &codeLength) && !jsonGetHex(params, "codehex", err, &code, &codeLength) ) { return NULL; } + + /* TODO: enable for generic evals unsigned char *param = NULL; size_t param_len = 0; @@ -62,20 +66,21 @@ static CC *evalFromJSON(const cJSON *params, char *err) { int includeParamInFP = 0; cJSON *objfp = cJSON_GetObjectItem(params, "includeParamInFP"); - if (objfp) includeParamInFP = !!objfp->valueint; + if (objfp) includeParamInFP = !!objfp->valueint; */ CC *cond = cc_new(CC_Eval); cond->code = code; cond->codeLength = codeLength; + /* TODO: enable for generic evals cond->param = param; - cond->paramLength = param_len; + cond->paramLength = param_len; */ /* debug: if (cond->param) { unsigned char *hex = cc_hex_encode(cond->param, cond->paramLength); printf("%s cond->param=%s\n", __func__, hex); free(hex); }*/ - cond->includeParamInFP = includeParamInFP; + // cond->includeParamInFP = includeParamInFP; int dontFulfill = 0; cJSON *objdf = cJSON_GetObjectItem(params, "dontFulfill"); @@ -96,6 +101,7 @@ static void evalToJSON(const CC *cond, cJSON *code) { cJSON_AddItemToObject(code, "codehex", cJSON_CreateString(codehex)); free(codehex); + /* TODO: enable for generic evals if (cond->param) { unsigned char *hex = cc_hex_encode(cond->param, cond->paramLength); cJSON_AddItemToObject(code, "param", cJSON_CreateString(hex)); @@ -103,7 +109,7 @@ static void evalToJSON(const CC *cond, cJSON *code) { } if (cond->includeParamInFP) { cJSON_AddItemToObject(code, "includeParamInFP", cJSON_CreateNumber(cond->includeParamInFP)); - } + } */ } @@ -117,6 +123,7 @@ static CC *evalFromFulfillment(const Fulfillment_t *ffill) { cond->code = calloc(1,octets.size); memcpy(cond->code, octets.buf, octets.size); + /* TODO: enable for generic evals cond->param = NULL; cond->paramLength = 0; @@ -128,7 +135,7 @@ static CC *evalFromFulfillment(const Fulfillment_t *ffill) { //free(hex); cond->param = calloc(1, paramOctets.size); memcpy(cond->param, paramOctets.buf, paramOctets.size); - } + } */ return cond; } @@ -139,13 +146,14 @@ static Fulfillment_t *evalToFulfillment(const CC *cond) { ffill->present = Fulfillment_PR_evalSha256; EvalFulfillment_t *eval = &ffill->choice.evalSha256; OCTET_STRING_fromBuf(&eval->code, cond->code, cond->codeLength); + /* TODO: enable for generic evals if (cond->param) { eval->param = (OCTET_STRING_t*)calloc(1, sizeof(OCTET_STRING_t)); OCTET_STRING_fromBuf(eval->param, cond->param, cond->paramLength); //unsigned char *hex = cc_hex_encode(cond->param, cond->paramLength); //printf("%s cond->param=%s\n", __func__, hex); //free(hex); - } + } */ return ffill; } @@ -157,8 +165,9 @@ int evalIsFulfilled(const CC *cond) { static void evalFree(CC *cond) { free(cond->code); + /* TODO enable for generic evals if (cond->param) - free(cond->param); + free(cond->param); */ } @@ -205,12 +214,13 @@ static CC* evalCopy(const CC* cond) memcpy(condCopy->code, cond->code, cond->codeLength); condCopy->codeLength=cond->codeLength; + /* TODO enable for generic evals condCopy->param = NULL; condCopy->paramLength=cond->paramLength; if (cond->paramLength) { condCopy->param = calloc(cond->paramLength, sizeof(uint8_t)); memcpy(condCopy->param, cond->param, cond->paramLength); - } + }*/ condCopy->dontFulfill = cond->dontFulfill; return (condCopy); } diff --git a/src/script/cc.cpp b/src/script/cc.cpp index d259abc2350..954200e7925 100644 --- a/src/script/cc.cpp +++ b/src/script/cc.cpp @@ -34,12 +34,16 @@ bool IsSupportedCryptoCondition(const CC *cond, CC_SUBVER ccSubVersion) int CCSigningNodesVersioned = CCSigningNodes; if (ccSubVersion >= CC_MIXED_MODE_SECHASH_SUBVER_1) CCSigningNodesVersioned = 0; // allow non signed conds - // TODO: allow non signed conds for ver >= 1 in June 2022? - // if (ccSubVersion < CC_MIXED_MODE_SECHASH_SUBVER_1 && !(mask & CCSigningNodes)) return false; - - // TODO: check for eval params enabled if ccSubVersion >= CC_MIXED_MODE_SECHASH_SUBVER_1 - // ... - + // TODO: allow non signed conds generic evals + // if (ccSubVersion < CC_GENERIC_EVALS_SUBVER && !(mask & CCSigningNodes)) return false; + + // TODO: when generic evals are enabled + // check that eval params enabled if ccSubVersion >= CC_GENERIC_EVALS_SUBVER: + /*VerifyEval eval = [](CC* cond, void* evalcode) { + return cond->param ? 0 : 1; + }; + bool hasEvalParam = !cc_verifyEval(cond, eval, nullptr); + if (hasEvalParam && ccSubVersion < CC_GENERIC_EVALS_SUBVER) return false; */ return true; } @@ -47,10 +51,12 @@ bool IsSupportedCryptoCondition(const CC *cond, CC_SUBVER ccSubVersion) bool IsSignedCryptoCondition(const CC *cond, CC_SUBVER ccSubVersion) { if (!cc_isFulfilled(cond)) return false; - //if (ccSubVersion >= CC_MIXED_MODE_SECHASH_SUBVER_1) return true; // TODO enable unsigned conds in this June 2022 or not? + + // TODO enable not signed conds when generic evals enabled + // if (ccSubVersion >= CC_GENERIC_EVALS_SUBVER) return true; int CCSigningNodesVersioned = CCSigningNodes; - if (ccSubVersion >= CC_MIXED_MODE_SECHASH_SUBVER_1) CCSigningNodesVersioned |= (1 << CC_Secp256k1hash); // allow new secp hash cond + if (ccSubVersion >= CC_MIXED_MODE_SECHASH_SUBVER_1) CCSigningNodesVersioned |= (1 << CC_Secp256k1hash); // allow new secp256k1hash cond if (1 << cc_typeId(cond) & CCSigningNodesVersioned) return true; if (cc_typeId(cond) == CC_Threshold) for (int i=0; isize; i++) From 82be938c5830db73140c1c5f049635e6d9551c32 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 9 May 2022 15:46:50 +0500 Subject: [PATCH 262/348] non-tls in websockets --- src/komodo_websockets.cpp | 10 +++++++--- src/komodo_websockets.h | 14 +++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index 3703ca9849a..ffa650b945d 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -654,7 +654,8 @@ class CWebSocketServer : public CWsEndpointWrapper { std::placeholders::_1, std::placeholders::_2 )); - m_endpoint.set_tls_init_handler(bind(&CWebSocketServer::on_tls_init, this, MOZILLA_MODERN, _1)); // add tls init + // enable for tls: + // m_endpoint.set_tls_init_handler(bind(&CWebSocketServer::on_tls_init, this, MOZILLA_MODERN, _1)); // add tls init m_endpoint.set_open_handler(bind(&CWebSocketServer::on_open, this, _1)); m_endpoint.set_close_handler(bind(&CWebSocketServer::on_close, this, _1)); m_endpoint.set_validate_handler(bind(&CWebSocketServer::on_validate, this, _1)); @@ -771,6 +772,7 @@ class CWebSocketServer : public CWsEndpointWrapper { return "test"; } + /* enable for tls context_ptr on_tls_init(tls_mode mode, websocketpp::connection_hdl hdl) { namespace asio = websocketpp::lib::asio; @@ -822,7 +824,7 @@ class CWebSocketServer : public CWsEndpointWrapper { std::cout << "Exception: " << e.what() << std::endl; } return ctx; - } + } */ void on_fail(websocketpp::connection_hdl hdl) { wsserver::connection_ptr con = m_endpoint.get_con_from_hdl(hdl); @@ -911,6 +913,8 @@ class CWebSocketOutbound : public CWsEndpointWrapper { // Register our handlers m_endpoint.set_socket_init_handler(bind(&CWebSocketOutbound::on_socket_init,this,::_1)); + + // enable for tls version: //m_endpoint.set_http_init_handler(bind(&CWebSocketOutbound::on_socket_init,this,::_1)); //m_endpoint.set_tls_init_handler(bind(&CWebSocketOutbound::on_socket_init,this,::_1)); @@ -937,7 +941,7 @@ class CWebSocketOutbound : public CWsEndpointWrapper { if (!uri.empty()) m_uri = uri; else - m_uri = "ws://" + addrConnect.ToStringIPPort(); + m_uri = "ws://" + addrConnect.ToStringIPPort(); // use wss for tls version wsclient::connection_ptr con = m_endpoint.get_connection(m_uri, ec); diff --git a/src/komodo_websockets.h b/src/komodo_websockets.h index e494e8c988c..f2256e730f8 100644 --- a/src/komodo_websockets.h +++ b/src/komodo_websockets.h @@ -29,8 +29,8 @@ static const int WSADDR_VERSION = 170008; #define WEBSOCKETS_TIMEOUT_INTERVAL 120 -// struct wsserver_mt_config : public websocketpp::config::asio { // no tls -struct wsserver_mt_config : public websocketpp::config::asio_tls { // tls +struct wsserver_mt_config : public websocketpp::config::asio { // no tls +// struct wsserver_mt_config : public websocketpp::config::asio_tls { // tls // pull default settings from our core config static bool const enable_multithreading = true; @@ -46,22 +46,22 @@ struct wsserver_mt_config : public websocketpp::config::asio_tls { // tls // permessage_deflate_type; }; -// typedef websocketpp::server wsserver; // no tls -typedef websocketpp::server wsserver; // tls +typedef websocketpp::server wsserver; // no tls +// typedef websocketpp::server wsserver; // tls // transport::asio::tls_socket::endpoint typedef websocketpp::client wsclient; -typedef websocketpp::lib::shared_ptr context_ptr; +// typedef websocketpp::lib::shared_ptr context_ptr; // See https://wiki.mozilla.org/Security/Server_Side_TLS for more details about // the TLS modes. The code below demonstrates how to implement both the modern -enum tls_mode { +/* enum tls_mode { MOZILLA_INTERMEDIATE = 1, MOZILLA_MODERN = 2 -}; +}; */ bool StartWebSockets(boost::thread_group& threadGroup); void SetWebSocketsWarmupFinished(); From bcbe7b4b338b5912babdb2d56e54ed307edd2b65 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 9 May 2022 18:12:00 +0500 Subject: [PATCH 263/348] set ws listen port for local addr --- src/komodo_websockets.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index ffa650b945d..99662feae6c 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -94,6 +94,7 @@ CAddress GetLocalWebSocketAddress(const CNetAddr *paddrPeer) CService addr; if (GetLocal(addr, paddrPeer)) { + addr.SetPort(GetWebSocketListenPort()); ret = CAddress(addr); } ret.nServices = NODE_NETWORK | NODE_WEBSOCKETS; From 5e1b951304a606fd06ae01e064e09ee8665a0f8d Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 9 May 2022 18:22:56 +0500 Subject: [PATCH 264/348] change NODE_ enum type to uint64_t to enable 31bit const --- src/protocol.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/protocol.h b/src/protocol.h index 239fb79a746..c38017c58c7 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -81,19 +81,19 @@ class CMessageHeader }; /** nServices flags */ -enum { +enum : uint64_t { // NODE_NETWORK means that the node is capable of serving the block chain. It is currently // set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want // network services but don't provide them. - NODE_NETWORK = (1 << 0), + NODE_NETWORK = (1UL << 0), // NODE_BLOOM means the node is capable and willing to handle bloom-filtered connections. // Zcash nodes used to support this by default, without advertising this bit, // but no longer do as of protocol version 170004 (= NO_BLOOM_VERSION) - NODE_BLOOM = (1 << 2), + NODE_BLOOM = (1UL << 2), - NODE_NSPV = (1 << 30), - NODE_ADDRINDEX = (1 << 29), - NODE_SPENTINDEX = (1 << 28), + NODE_NSPV = (1UL << 30), + NODE_ADDRINDEX = (1UL << 29), + NODE_SPENTINDEX = (1UL << 28), // Bits 24-31 are reserved for temporary experiments. Just pick a bit that // isn't getting used, or one not being used much, and notify the @@ -103,7 +103,7 @@ enum { // do not actually support. Other service bits should be allocated via the // BIP process. - NODE_WEBSOCKETS = (1 << 31) // nspv listening on websockets + NODE_WEBSOCKETS = (1UL << 31) // nspv listening on websockets }; /** A CService with information about it as peer */ From 1956c0d0c034b4da9fb6870c39ec67c6ba4b181b Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 9 May 2022 18:23:23 +0500 Subject: [PATCH 265/348] add NODE_NSPV flag to websockets --- src/komodo_websockets.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index 99662feae6c..2d5d56179e3 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -98,6 +98,8 @@ CAddress GetLocalWebSocketAddress(const CNetAddr *paddrPeer) ret = CAddress(addr); } ret.nServices = NODE_NETWORK | NODE_WEBSOCKETS; + if (GetBoolArg("-nspv_msg", DEFAULT_NSPV_PROCESSING)) + ret.nServices |= NODE_NSPV; ret.nTime = GetTime(); return ret; } From e937bf61a31d4cf158893caae06e7b943d727ee3 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 9 May 2022 21:41:30 +0500 Subject: [PATCH 266/348] added NODE_ flag for tls websockets --- src/protocol.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/protocol.h b/src/protocol.h index c38017c58c7..b730cb73cf6 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -103,7 +103,8 @@ enum : uint64_t { // do not actually support. Other service bits should be allocated via the // BIP process. - NODE_WEBSOCKETS = (1UL << 31) // nspv listening on websockets + NODE_WEBSOCKETS = (1UL << 31), // nspv listening on websockets + NODE_WEBSOCKETS_TLS = (1UL << 32) // websockets tls }; /** A CService with information about it as peer */ From 991fbd1aae91f488811a0a4f63ce33af6262f8fd Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 9 May 2022 22:19:57 +0500 Subject: [PATCH 267/348] simple rate limit for wsaddr --- src/komodo_websockets.cpp | 17 ++++++----------- src/net.cpp | 1 + src/net.h | 1 + 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index 2d5d56179e3..d43bf5f3598 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -482,17 +482,12 @@ bool ProcessWsMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, else if ((strCommand == "getwsaddr") && (pfrom->fInbound)) // allow to getwsaddr for clients and newly connected nodes to initialize their addrman { - // comment to allow multiply requests for nspv clients: - // ----- - // Only send one getaddr response per connection to reduce resource waste - // and discourage addr stamping of INV announcements. - //if (pfrom->fSentAddr) { - // LogPrint("net", "Ignoring repeated \"getwsaddr\". peer=%d\n", pfrom->id); - // return true; - //} - //pfrom->fSentAddr = true; - //pfrom->sentAddrTime = GetTime(); - // ------ + // rate limit for wsaddr requests + if (GetTime() - pfrom->nLastWsAddrTime < 60) { + LogPrint("net", "Ignoring repeated \"getwsaddr\". peer=%d\n", pfrom->id); + return true; + } + pfrom->nLastWsAddrTime = GetTime(); pfrom->vAddrToSend.clear(); std::vector vWsaddr = wsaddrman.GetAddrAtMost(); diff --git a/src/net.cpp b/src/net.cpp index cbe97c98be8..fdd345d5a06 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2154,6 +2154,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa fPingQueued = false; nMinPingUsecTime = std::numeric_limits::max(); memset(nspvdata, '\0', sizeof(nspvdata)); + nLastWsAddrTime = 0LL; { LOCK(cs_nLastNodeId); diff --git a/src/net.h b/src/net.h index 64f55b8aa6b..86fbc5c5f83 100644 --- a/src/net.h +++ b/src/net.h @@ -345,6 +345,7 @@ class CNode CRollingBloomFilter addrKnown; bool fGetAddr; std::set setKnown; + int64_t nLastWsAddrTime; // inventory based relay mruset setInventoryKnown; From 6b3c3d9b41db83474106775aaf956b3fb2c812ed Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 10 May 2022 00:24:39 +0500 Subject: [PATCH 268/348] websockets logging improved --- src/komodo_websockets.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index d43bf5f3598..bdf434635af 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -482,9 +482,9 @@ bool ProcessWsMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, else if ((strCommand == "getwsaddr") && (pfrom->fInbound)) // allow to getwsaddr for clients and newly connected nodes to initialize their addrman { - // rate limit for wsaddr requests + // rate limit for getwsaddr requests if (GetTime() - pfrom->nLastWsAddrTime < 60) { - LogPrint("net", "Ignoring repeated \"getwsaddr\". peer=%d\n", pfrom->id); + LogPrint("websockets", "Ignoring repeated \"getwsaddr\". peer=%d\n", pfrom->id); return true; } pfrom->nLastWsAddrTime = GetTime(); @@ -730,7 +730,7 @@ class CWebSocketServer : public CWsEndpointWrapper { try { pnode->m_spWsEndpoint->close(pnode->m_hdl, websocketpp::close::status::going_away); } catch (websocketpp::exception const & e) { // might be already close from remote site or on a error - std::cout << __func__ << " websocketpp::exception: " << e.what() << " (could be okay)" << std::endl; + LogPrint("websockets", "%s stop listener websocketpp::exception: %s (this could be okay)\n", __func__, e.what()); } } } @@ -869,7 +869,7 @@ class CWebSocketServer : public CWsEndpointWrapper { return; } - LogPrint("websockets", "closing inbound connection from ws peer %d\n", pNode->GetId()); + LogPrint("websockets", "closed inbound connection from ws peer %d\n", pNode->GetId()); pNode->fDisconnect = true; RemoveWsNode(pNode); @@ -877,7 +877,7 @@ class CWebSocketServer : public CWsEndpointWrapper { virtual void close(websocketpp::connection_hdl hdl, websocketpp::close::status::value status) { - LogPrint("websockets", "closing connection %s\n", GetClientAddressFromHdl(hdl).ToStringIPPort().c_str()); + LogPrint("websockets", "closing connection %s called for wsserver\n", GetClientAddressFromHdl(hdl).ToStringIPPort().c_str()); m_endpoint.close(hdl, status, ""); } @@ -1007,7 +1007,7 @@ class CWebSocketOutbound : public CWsEndpointWrapper { void on_close(websocketpp::connection_hdl) { if ((bool)m_pNode) { LOCK(cs_vWsNodes); - LogPrint("websockets", "closing outbound connection to ws peer %d\n", m_pNode->GetId()); + LogPrint("websockets", "closed outbound connection to ws peer %d\n", m_pNode->GetId()); m_pNode->fDisconnect = true; RemoveWsNode(m_pNode); @@ -1017,6 +1017,7 @@ class CWebSocketOutbound : public CWsEndpointWrapper { virtual void close(websocketpp::connection_hdl hdl, websocketpp::close::status::value status) { if (m_endpoint.get_con_from_hdl(hdl) != nullptr) { + LogPrint("websockets", "closing outbound connection to %s called\n", m_pNode->addr.ToString()); m_endpoint.close(hdl, status, std::string()); } } @@ -1162,7 +1163,7 @@ void ThreadWebSocketMessageHandler() try { pnode->m_spWsEndpoint->close(pnode->m_hdl, (pnode->closeErrorOnSend ? pnode->closeErrorOnSend : pnode->closeErrorOnReceive)); } catch (websocketpp::exception const & e) { // might be already closed from remote site or on a error - std::cout << __func__ << " close websocketpp::exception: " << e.what() << " (could be okay)" << std::endl; + LogPrint("websockets", "%s close websocketpp::exception: %s (could be normal)\n", __func__, e.what()); } } } @@ -1241,17 +1242,17 @@ static void ThreadWebSocketWaitForDisconnectedThreads() } else if (nTime - pnode->nLastSend > WEBSOCKETS_TIMEOUT_INTERVAL) { - LogPrintf("websocket sending timeout: %is\n", nTime - pnode->nLastSend); + LogPrintf("websocket sending timeout: %is peer=%d\n", nTime - pnode->nLastSend, pnode->GetId()); pnode->fDisconnect = true; } else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? WEBSOCKETS_TIMEOUT_INTERVAL : 90*60)) { - LogPrintf("websocket receive timeout: %is\n", nTime - pnode->nLastRecv); + LogPrintf("websocket receive timeout: %is peer=%d\n", nTime - pnode->nLastRecv, pnode->GetId()); pnode->fDisconnect = true; } else if (pnode->nPingNonceSent && pnode->nPingUsecStart + WEBSOCKETS_TIMEOUT_INTERVAL * 1000000 < GetTimeMicros()) { - LogPrintf("websocket ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart)); + LogPrintf("websocket ping timeout: %fs peer=%d\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart), pnode->GetId()); pnode->fDisconnect = true; } @@ -1260,7 +1261,7 @@ static void ThreadWebSocketWaitForDisconnectedThreads() try { pnode->m_spWsEndpoint->close(pnode->m_hdl, websocketpp::close::status::no_status); } catch (websocketpp::exception const & e) { // might be already close from remote site or on a error - std::cout << __func__ << " close websocketpp::exception: " << e.what() << " (could be okay)" << std::endl; + LogPrint("websockets", "%s close websocketpp::exception: %s (this may be normal if peer already remotely closed)\n", __func__, e.what()); LOCK(cs_vWsNodes); RemoveWsNode(pnode); } @@ -1559,7 +1560,7 @@ void StopWebSockets() try { pnode->m_spWsEndpoint->close(pnode->m_hdl, websocketpp::close::status::going_away); } catch (websocketpp::exception const & e) { // might be already close from remote site or on a error - std::cout << __func__ << " close websocketpp::exception: " << e.what() << " (could be okay)" << std::endl; + LogPrint("websockets", "%s close websocketpp::exception: %s (this may be normal)", __func__, e.what()); } } } From 0587904de136fb73db39b799c922c46fcd3cd063 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 10 May 2022 14:01:56 +0500 Subject: [PATCH 269/348] disable DEX rpcs --- src/rpc/server.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index c8645442f4c..35e84591d72 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -417,8 +417,8 @@ static const CRPCCommand vRPCCommands[] = { "FSM", "FSMlist", &FSMlist, true }, { "FSM", "FSMinfo", &FSMinfo, true }, - // DEX - { "DEX", "DEX_broadcast", &DEX_broadcast, true }, + // DEX (disabled) +/* { "DEX", "DEX_broadcast", &DEX_broadcast, true }, { "DEX", "DEX_anonsend", &DEX_anonsend, true }, { "DEX", "DEX_list", &DEX_list, true }, { "DEX", "DEX_get", &DEX_get, true }, @@ -430,7 +430,7 @@ static const CRPCCommand vRPCCommands[] = { "DEX", "DEX_subscribe", &DEX_subscribe, true }, { "DEX", "DEX_stream", &DEX_stream, true }, { "DEX", "DEX_streamsub", &DEX_streamsub, true }, - { "DEX", "DEX_notarize", &DEX_notarize, true }, + { "DEX", "DEX_notarize", &DEX_notarize, true }, */ // fsm { "nSPV", "nspv_getinfo", &nspv_getinfo, true }, From 026f1db52fdd91c9be7939b380531e146bc9a4e4 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 10 May 2022 14:02:26 +0500 Subject: [PATCH 270/348] disable some websockets disconnect options --- src/komodo_websockets.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index bdf434635af..3e8934cf0ac 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -1240,16 +1240,18 @@ static void ThreadWebSocketWaitForDisconnectedThreads() LogPrint("websockets", "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id); pnode->fDisconnect = true; } + /* in websockets we may not send messages for some time, we only do getwsaddr sometimes: else if (nTime - pnode->nLastSend > WEBSOCKETS_TIMEOUT_INTERVAL) { LogPrintf("websocket sending timeout: %is peer=%d\n", nTime - pnode->nLastSend, pnode->GetId()); pnode->fDisconnect = true; - } + } */ + /* in websockets our getwsaddr requests may be not answered: else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? WEBSOCKETS_TIMEOUT_INTERVAL : 90*60)) { LogPrintf("websocket receive timeout: %is peer=%d\n", nTime - pnode->nLastRecv, pnode->GetId()); pnode->fDisconnect = true; - } + } */ else if (pnode->nPingNonceSent && pnode->nPingUsecStart + WEBSOCKETS_TIMEOUT_INTERVAL * 1000000 < GetTimeMicros()) { LogPrintf("websocket ping timeout: %fs peer=%d\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart), pnode->GetId()); From afc8f7383db5d0a30f678d095df05448bac4709b Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 10 May 2022 14:43:57 +0500 Subject: [PATCH 271/348] ping on ws peers enabled --- src/komodo_websockets.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index 3e8934cf0ac..adecfa4fe8d 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -508,6 +508,35 @@ bool SendWsMessages(CWsNode *pto, bool fTrickle) if (pto->nVersion == 0) return true; + + // + // Message: ping on websockets + // + bool pingSend = false; + if (pto->fPingQueued) { + // RPC ping request by user + pingSend = true; + } + if (pto->nPingNonceSent == 0 && pto->nPingUsecStart + PING_INTERVAL * 1000000 < GetTimeMicros()) { + // Ping automatically sent as a latency probe & keepalive. + pingSend = true; + } + if (pingSend) { + uint64_t nonce = 0; + while (nonce == 0) { + GetRandBytes((unsigned char*)&nonce, sizeof(nonce)); + } + pto->fPingQueued = false; + pto->nPingUsecStart = GetTimeMicros(); + if (pto->nVersion > BIP0031_VERSION) { + pto->nPingNonceSent = nonce; + pto->PushMessage("ping", nonce); + } else { + // Peer is too old to support ping command with nonce, pong will never arrive. + pto->nPingNonceSent = 0; + pto->PushMessage("ping"); + } + } // Address refresh broadcast static int64_t nLastRebroadcast; From 23a6275804b1b48698c521679a3d50f0e3e2af9d Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 10 May 2022 20:16:36 +0500 Subject: [PATCH 272/348] fixed token change to R-address --- src/cc/CCtokens_impl.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index c8489e6d03c..0330183f76c 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -400,8 +400,14 @@ UniValue TokenTransferExtDest(const CPubKey &remotepk, CAmount txfee, uint256 to } } - if (CCchange != 0) - mtx.vout.push_back(V::MakeTokensCC1vout(V::EvalCode(), CCchange, mypk)); + if (CCchange != 0) { + if (V::EvalCode() == EVAL_TOKENSV2 && + CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) { + mtx.vout.push_back(V::MakeTokensCCMofNDestVout(V::EvalCode(), 0, CCchange, 1, {mypk.GetID()})); // send change to R-address after the HF + } + else + mtx.vout.push_back(V::MakeTokensCC1vout(V::EvalCode(), CCchange, mypk)); + } // TODO maybe add also opret blobs form vintx // as now this TokenTransfer() allows to transfer only tokens (including NFTs) that are unbound to other cc From 4dc5982679eed85b7055742b416fbcc9eb97802c Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 10 May 2022 20:20:22 +0500 Subject: [PATCH 273/348] removed extra logging --- src/cc/CCutils.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index ab8355eb708..3a33b5dba94 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -1609,12 +1609,9 @@ UniValue CCDecodeMixedMode(const CC *cond) if (cc_typeId(cond) == CC_Secp256k1hash) { std::string fingerprintHex = HexStr(cond->fingerprint, cond->fingerprint + sizeof(uint160)); - std::cerr << __func__ << " fingerprintHex=" << fingerprintHex << std::endl; CKeyID keyid(uint160(vuint8_t(cond->fingerprint, cond->fingerprint + sizeof(uint160)))); CBitcoinAddress addr; addr.Set(keyid); - std::cerr << __func__ << " keyid=" << keyid.ToString() << " addr=" << addr.ToString() << std::endl; - uCond.pushKV("destination", addr.ToString()); } else { From 7514da33042470a39ea8e2555efb0a2265dca56e Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 11 May 2022 12:23:33 +0500 Subject: [PATCH 274/348] some assets py tests re-enabled --- src/tui/tui_assets_orders.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/tui/tui_assets_orders.py b/src/tui/tui_assets_orders.py index 2e67b3bbafc..1dc4951ea80 100644 --- a/src/tui/tui_assets_orders.py +++ b/src/tui/tui_assets_orders.py @@ -152,13 +152,11 @@ def run_tokens_create(rpc1, rpc2, rpc3): call_token_rpc_send_tx(rpc3, "token"+v+"transfer", '', nftf7id3, pubkey1, str(1)) call_token_rpc_send_tx(rpc3, "token"+v+"transfer", '', nftf7id4, pubkey1, str(1)) - - ''' # test tokenlist: check_tokenlist(rpc1, v, [tokenid1, tokenid2, nft00id1, nft00id2, nftf7id1, nftf7id2, nftf7id3, nftf7id4]) # test tokenallbalances: check_tokenallbalances(rpc1, v, {tokenid1: 100, tokenid2: 1000_0000, nft00id1: 1, nft00id2: 1, nftf7id1: 1, nftf7id2: 1, nftf7id3: 1, nftf7id4: 1} ) - + # first try transfer tokens to a pk and back, then run assets tests print("starting transfer tests for tokenid version=" + v + "...") run_transfers(rpc1, rpc2, v, tokenid1, tokenid2, 10) @@ -170,7 +168,7 @@ def run_tokens_create(rpc1, rpc2, rpc3): run_transfers(rpc1, rpc2, v, nftf7id1, nftf7id2, 1) print("token transfers tests finished okay!") time.sleep(3) - ''' + # assets cc tests: print("starting assets tests for tokenid1 version=" + v + "...") @@ -189,7 +187,7 @@ def run_tokens_create(rpc1, rpc2, rpc3): run_assets_expired_orders(rpc1, rpc2, v, tokenid1, 10, 8, 0.0001, False) print("assets tests finished okay!") - ''' + if v == "v2" : # MofN supported for tokens cc v2 only print("running MofN tests for tokens v2:") print("starting MofN tests for tokenid1...") @@ -199,7 +197,7 @@ def run_tokens_create(rpc1, rpc2, rpc3): print("starting MofN tests for nftf7id1...") run_MofN_transfers(rpc1, rpc2, rpc3, nftf7id1, 1) print("token MofN transfer tests finished okay!") - ''' + print("all token/assets tests finished okay!") From 94cd04cc4c12151cf6ea8f92146b383aa9642737 Mon Sep 17 00:00:00 2001 From: dimxy Date: Wed, 11 May 2022 12:54:47 +0500 Subject: [PATCH 275/348] fixed var name after rebase --- src/cc/CCassetstx_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc/CCassetstx_impl.h b/src/cc/CCassetstx_impl.h index f9e607b3eeb..348b393de0b 100644 --- a/src/cc/CCassetstx_impl.h +++ b/src/cc/CCassetstx_impl.h @@ -72,7 +72,7 @@ UniValue AssetOrders(uint256 refassetid, const CPubKey &mypk, const UniValue &pa { LOGSTREAM(ccassets_log, CCLOG_DEBUG2, stream << funcname << " checking ordertx.vout.size()=" << ordertx.vout.size() << " funcid=" << (char)(funcid ? funcid : ' ') << " assetid=" << assetid.GetHex() << std::endl); - if ((!checkPK.IsValid() || checkPK == pubkey2pk(origpubkey)) && (refassetid.IsNull() || assetid == refassetid)) + if ((!checkPK.IsValid() || checkPK == pubkey2pk(vorigpubkey)) && (refassetid.IsNull() || assetid == refassetid)) { uint256 spenttxid; uint256 init_txid = ordertxid; From a67528b8da82ed06bf955029f10ba8d938ee73d3 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 12 May 2022 17:15:30 +0500 Subject: [PATCH 276/348] fixed use of valid burn pubkey; tokenburn rpc added --- src/cc/CCtokens_impl.h | 22 ++++++++++---- src/rpc/tokensrpc.cpp | 65 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index 0330183f76c..bc98d885292 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -297,7 +297,7 @@ UniValue TokenFinalizeTransferTx(CMutableTransaction &mtx, struct CCcontract_inf // total - token amount to transfer // returns: signed transfer tx in hex template -UniValue TokenTransferExtDest(const CPubKey &remotepk, CAmount txfee, uint256 tokenid, const std::vector &tokenaddrs, std::vector> probeconds, uint8_t M, std::vector destinations, CAmount total, bool useMempool) +UniValue TokenTransferExtDest(const CPubKey &remotepk, CAmount txfee, uint256 tokenid, const std::vector &tokenaddrs, std::vector> probeconds, uint8_t M, std::vector destinations, CAmount total, bool useMempool, bool spendMarker) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); @@ -338,6 +338,10 @@ UniValue TokenTransferExtDest(const CPubKey &remotepk, CAmount txfee, uint256 to break; } + if (spendMarker) { + mtx.vin.push_back(CTxIn(tokenid, 0)); // spend tokenlist marker + } + if (CCinputs >= total) { if (CCinputs > total) @@ -437,14 +441,15 @@ template UniValue TokenTransferExt(const CPubKey &remotepk, CAmount txfee, uint256 tokenid, const std::vector &tokenaddrs, std::vector> probeconds, uint8_t M, const std::vector &destpks, CAmount total, bool useMempool) { std::vector destinations; + const bool spendMarker = false; for (auto const &pk : destpks) destinations.push_back(pk); - return TokenTransferExtDest(remotepk, txfee, tokenid, tokenaddrs, probeconds, M, destinations, total, useMempool); + return TokenTransferExtDest(remotepk, txfee, tokenid, tokenaddrs, probeconds, M, destinations, total, useMempool, spendMarker); } // transfer tokens from mypk to a destination template -std::string TokenTransferDest(CAmount txfee, uint256 tokenid, uint8_t M, const std::vector &destinations, CAmount total) +std::string TokenTransferDest(CAmount txfee, uint256 tokenid, uint8_t M, const std::vector &destinations, CAmount total, bool spendMarker) { CPubKey mypk = pubkey2pk(Mypubkey()); @@ -457,7 +462,7 @@ std::string TokenTransferDest(CAmount txfee, uint256 tokenid, uint8_t M, const s //vuint8_t vextraData = std::get<4>(tokenData); std::vector tokenindexkeys = V::GetTokenIndexKeys(mypk); - UniValue sigData = TokenTransferExtDest(CPubKey(), txfee, tokenid, tokenindexkeys, {}, M, destinations, total, false); + UniValue sigData = TokenTransferExtDest(CPubKey(), txfee, tokenid, tokenindexkeys, {}, M, destinations, total, false, spendMarker); return ResultGetTx(sigData); } @@ -466,9 +471,10 @@ template std::string TokenTransfer(CAmount txfee, uint256 tokenid, uint8_t M, const std::vector &destpks, CAmount total) { std::vector destinations; + const bool spendMarker = false; for (auto const &pk : destpks) destinations.push_back(pk); - return TokenTransferDest(txfee, tokenid, M, destinations, total); + return TokenTransferDest(txfee, tokenid, M, destinations, total, spendMarker); } @@ -910,6 +916,8 @@ static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 uint8_t evalCode = V::EvalCode(); // if both payloads are empty maybe it is a transfer to non-payload-one-eval-token vout like GatewaysClaim uint8_t evalCode2 = 0; // will be checked if zero or not + const bool isSubver1 = CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1); + // test vouts for possible token use-cases: std::vector> testVouts; @@ -970,7 +978,9 @@ static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 // try all test vouts: for (const auto &t : testVouts) { - if (t.first == tx.vout[i]) { + //if (t.first == tx.vout[i]) { + if (!isSubver1 && t.first == tx.vout[i] || + isSubver1 && IsEqualDestinations(t.first.scriptPubKey, tx.vout[i].scriptPubKey)) { LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << "burned amount=" << tx.vout[i].nValue << " msg=" << t.second << " evalCode=" << (int)evalCode << " evalCode2=" << (int)evalCode2 << " txid=" << tx.GetHash().GetHex() << " tokenid=" << reftokenid.GetHex() << std::endl); burnedAmount += tx.vout[i].nValue; break; // do not calc vout twice! diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 52ab51d5b96..63353384550 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -567,7 +567,8 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b CAmount amount = atoll(params[2].get_str().c_str()); if( amount <= 0 ) return MakeResultError("amount must be positive"); - hex = TokenTransferDest(0, tokenid, 1, dests, amount); + const bool spendMarker = false; + hex = TokenTransferDest(0, tokenid, 1, dests, amount, spendMarker); RETURN_IF_ERROR(CCerror); if (!hex.empty()) return MakeResultSuccess(hex); @@ -1198,6 +1199,66 @@ UniValue tokenv2addccinputs(const UniValue& params, bool fHelp, const CPubKey& r return result; } +template +static UniValue tokenburn(const std::string& name, const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + UniValue result(UniValue::VOBJ); + std::string hex; + + CCerror.clear(); + + if (fHelp || params.size() != 3) + throw runtime_error( + name + " tokenid amount remove\n" + "to burn token amount by sending to a burn pubkey:\n" + " tokenid - token creation id\n" + " amount - token amount to burn, in satoshi\n" + " remove - remove from tokenlist by burning the marker utxo (true|false)\n\n"); + + if (ensure_CCrequirements(V::EvalCode()) < 0) + throw runtime_error(CC_REQUIREMENTS_MSG); + + if (!remotepk.IsValid() && !EnsureWalletIsAvailable(false)) + throw runtime_error("wallet is required"); + LOCK2(cs_main, pwalletMain->cs_wallet); // remote call not supported, only local wallet + + uint256 tokenid = Parseuint256(params[0].get_str().c_str()); + if( tokenid.IsNull() ) + return MakeResultError("invalid tokenid"); + + std::vector dests; + + CPubKey dest; + vuint8_t vpubkey(ParseHex(CC_BURNPUBKEY_FIXED)); + if (!CPubKey(vpubkey).IsFullyValid()) + return MakeResultError("invalid burn pubkey"); + + dest = CPubKey(vpubkey); + dests.push_back(dest); + + CAmount amount = atoll(params[1].get_str().c_str()); + if( amount <= 0 ) + return MakeResultError("amount must be positive"); + std::string strSpend = params[2].get_str(); + std::transform(strSpend.begin(), strSpend.end(), strSpend.begin(), ::tolower); + const bool spendMarker = strSpend == "true" ? true : false; + hex = TokenTransferDest(0, tokenid, 1, dests, amount, spendMarker); + RETURN_IF_ERROR(CCerror); + if (!hex.empty()) + return MakeResultSuccess(hex); + else + return MakeResultError("could not create burn token transaction"); +} + +UniValue tokenburn(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + return tokenburn(__func__, params, fHelp, remotepk); +} +UniValue tokenv2burn(const UniValue& params, bool fHelp, const CPubKey& remotepk) +{ + return tokenburn(__func__, params, fHelp, remotepk); +} + // cc tx creation helper rpc (test) UniValue CreateCCEvalTx(const CPubKey &mypk, CAmount txfee, const UniValue &txjson) @@ -1390,6 +1451,8 @@ static const CRPCCommand commands[] = { "tokens v2", "tokenv2createtokel", &tokenv2createtokel, true }, { "tokens", "tokeninfotokel", &tokeninfotokel, true }, { "tokens v2", "tokenv2infotokel", &tokenv2infotokel, true }, + { "tokens", "tokenburn", &tokenburn, true }, + { "tokens v2", "tokenv2burn", &tokenv2burn, true }, { "nspv", "tokenv2addccinputs", &tokenv2addccinputs, true }, { "nspv", "createccevaltx", &createccevaltx, true }, From 45d1cd3f18ac918e53dc6ca096305c37828c2119 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 12 May 2022 17:41:25 +0500 Subject: [PATCH 277/348] addrman GetAddr refactored (removed duplicate code) --- src/addrman.cpp | 32 +++++++++++++------------------- src/addrman.h | 2 ++ 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/addrman.cpp b/src/addrman.cpp index 2fe50f7eedf..e09034c582d 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -492,12 +492,9 @@ int CAddrMan::Check_() } #endif -void CAddrMan::GetAddr_(std::vector& vAddr) +// gather a list of random nodes, skipping those of low quality +void CAddrMan::GetAddrLimited(std::vector& vAddr, unsigned int nNodes) { - unsigned int nNodes = ADDRMAN_GETADDR_MAX_PCT * vRandom.size() / 100; - if (nNodes > ADDRMAN_GETADDR_MAX) - nNodes = ADDRMAN_GETADDR_MAX; - // gather a list of random nodes, skipping those of low quality for (unsigned int n = 0; n < vRandom.size(); n++) { if (vAddr.size() >= nNodes) @@ -513,6 +510,15 @@ void CAddrMan::GetAddr_(std::vector& vAddr) } } +void CAddrMan::GetAddr_(std::vector& vAddr) +{ + unsigned int nNodes = ADDRMAN_GETADDR_MAX_PCT * vRandom.size() / 100; + if (nNodes > ADDRMAN_GETADDR_MAX) + nNodes = ADDRMAN_GETADDR_MAX; + + GetAddrLimited(vAddr, nNodes); +} + #ifdef ENABLE_WEBSOCKETS // get no more than N addresses for clients (do not use 23% limit assuming there are no many websockets listeners in the net) void CAddrMan::GetAddrAtMost_(std::vector& vAddr) @@ -521,25 +527,13 @@ void CAddrMan::GetAddrAtMost_(std::vector& vAddr) if (nNodes > 1000) // actually MAX_ADDR_TO_SEND nNodes = 1000; - // gather a list of random nodes, skipping those of low quality - for (unsigned int n = 0; n < vRandom.size(); n++) { - if (vAddr.size() >= nNodes) - break; - - int nRndPos = RandomInt(vRandom.size() - n) + n; - SwapRandom(n, nRndPos); - assert(mapInfo.count(vRandom[n]) == 1); - - const CAddrInfo& ai = mapInfo[vRandom[n]]; - if (!ai.IsTerrible()) - vAddr.push_back(ai); - } + GetAddrLimited(vAddr, nNodes); } // get all addrinfo for printing void CAddrMan::GetAddrInfoAll_(std::vector& vAddrInfo) { - for (auto const i : mapInfo) { + for (auto const &i : mapInfo) { vAddrInfo.push_back(i.second); } } diff --git a/src/addrman.h b/src/addrman.h index e8925c7cd5f..2ee814fd58a 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -263,6 +263,8 @@ friend class CAddrManTest; int Check_(); #endif + void GetAddrLimited(std::vector &vAddr, unsigned int nNodes); + //! Select several addresses at once. void GetAddr_(std::vector &vAddr); From 4e417c0f27041d6025b3ff78ddb34e13d10131be Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 13 May 2022 15:39:20 +0500 Subject: [PATCH 278/348] tkltest2 height is fixed --- src/cc/CCupgrades.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index 0ec36ae25ae..7b455806885 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -34,7 +34,7 @@ namespace CCUpgrades { const int32_t CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT = 100000000; // TBD const int32_t CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT = 100000000; // TBD const int32_t CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT = 100000000; // TBD - const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 57544; // 25 apr 2022 4:10p.m + const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 87400; // approx 15 May 2022 11:00a.m. UTC // latest protocol version: const int CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION = 170010; // pre-upgrade protocol version: From 4c99705ddcba92e51f37fe80473bfad1c5cae56f Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 15 May 2022 15:16:23 +0500 Subject: [PATCH 279/348] refactored on code review (unused code removed, GetBurnPubKeys func added, comments added to AssetsFillOrderIsDust) --- src/bitcoin-cli.cpp | 2 -- src/cc/CCassetsUtils.cpp | 1 + src/cc/CCinclude.h | 11 +++++++++++ src/cc/CCtokens_impl.h | 11 +++-------- src/cc/import.cpp | 5 +---- src/importcoin.cpp | 7 +++---- src/komodo_nSPV_fullnode.h | 1 - src/script/script.h | 1 - 8 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 9c3041faab1..c1229d53a4e 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -32,8 +32,6 @@ #include #include #include "support/events.h" -//uint16_t BITCOIND_RPCPORT = 7771; -//char ASSETCHAINS_SYMBOL[65]; #include diff --git a/src/cc/CCassetsUtils.cpp b/src/cc/CCassetsUtils.cpp index 7364062f2a2..53c1d2b01df 100644 --- a/src/cc/CCassetsUtils.cpp +++ b/src/cc/CCassetsUtils.cpp @@ -504,6 +504,7 @@ CAmount AssetsGetTxTokenInputs(Eval *eval, struct CCcontract_info *cpTokens, con // check if either royalty or paid_value is dust in fill ask // nOutputValue is the total amount of paid_value + royalty +// it is expected that 0 < royaltyFract < TKLROYALTY_DIVISOR (calling validation code should provide that) bool AssetsFillOrderIsDust(int32_t royaltyFract, CAmount nOutputValue, bool &isRoyaltyDust) { // nOutputValue is sum of paid_value + royalty_value diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index b2a954ffd77..4ff0a0ef68f 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -74,6 +74,7 @@ Details. #include "../init.h" #include "../unspentccindex.h" #include "rpc/server.h" +#include "CCupgrades.h" // invalid burn pubkey stop using it #define CC_BURNPUBKEY "02deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead" //!< 'dead' pubkey in hex for burning tokens (if tokens are sent to it, they become 'burned') @@ -1067,6 +1068,16 @@ inline UniValue MakeResultSuccess(const std::string &txhex) { } /*! \endcond */ +/// returns burn pubkey list +/// @param height current height at which some new pubkeys are activated +inline std::vector GetBurnPubKeys(int32_t nHeight) +{ + std::vector vDeadPubkeys; + vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); + if (CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) + vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey + return vDeadPubkeys; +} /// @private bool inline IS_REMOTE(const CPubKey &remotepk) { return remotepk.IsValid(); } diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index bc98d885292..be2f917b22d 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -375,9 +375,7 @@ UniValue TokenTransferExtDest(const CPubKey &remotepk, CAmount txfee, uint256 to // probes for spending from mypk for (const auto &mycond : GetTokenV2Conds(mypk)) CCAddVintxCond(cp, mycond, nullptr); - } - - if (V::EvalCode() == EVAL_TOKENSV2) { + // if this is multisig - build and add multisig probes: // find any token vin, load vin tx and extract M and pubkeys for(int ccvin = 0; ccvin < mtx.vin.size(); ccvin ++) { @@ -908,7 +906,7 @@ static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 { uint8_t dummyEvalCode; uint256 tokenIdOpret; - std::vector vDeadPubkeys, voutPubkeysDummy; + std::vector voutPubkeysDummy; std::vector oprets; TokenDataTuple tokenData; vscript_t vopretExtra, vextraData; @@ -952,10 +950,7 @@ static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 evalCode2 = 0; } - vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) - vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey - + std::vector vDeadPubkeys = GetBurnPubKeys(eval->GetCurrentHeight()); CAmount burnedAmount = 0; diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 4919a7084e5..92f088c60de 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -548,10 +548,7 @@ bool CheckMigration(Eval *eval, const CTransaction &importTx, const CTransaction if (!hasTokenVin) return eval->Invalid("burn-tx-has-no-token-vins"); - std::vector vDeadPubkeys; - vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) - vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey + std::vector vDeadPubkeys = GetBurnPubKeys(eval->GetCurrentHeight()); // calc outputs for burn tx CAmount ccBurnOutputs = 0; diff --git a/src/importcoin.cpp b/src/importcoin.cpp index 1af9ac5f4f4..b81f2fc887d 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -345,10 +345,9 @@ CAmount GetCoinImportValue(const CTransaction &tx, int32_t nHeight) if (!vnonfungibleOpret.empty()) nonfungibleEvalCode = vnonfungibleOpret.begin()[0]; - std::vector vDeadPubkeys; - vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); - if (CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) - vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey + + std::vector vDeadPubkeys = GetBurnPubKeys(nHeight); + // calc outputs for burn tx int64_t ccBurnOutputs = 0; diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 12abe6076c1..be08a7b51e9 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -986,7 +986,6 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re return; } - requestType = request[0]; memcpy(&requestId, &request[1], sizeof(requestId)); uint8_t *requestData = &request[nspvHeaderSize]; int32_t requestDataLen = request.size() - nspvHeaderSize; diff --git a/src/script/script.h b/src/script/script.h index 8d1a096ef12..64bf21a6d0f 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -596,7 +596,6 @@ class CScript : public CScriptBase bool IsPayToCryptoCondition(CScript *ccSubScript) const; bool IsPayToCryptoCondition() const; bool IsPayToCCV2() const; // check scriptPubKey is cryptocondition version 2 - bool IsPayToCCV2(int &subversion) const; // check scriptPubKey is cryptocondition version 2 const std::vector GetCCV2SPK() const; bool SpkHasEvalcodeCCV2(uint8_t eval) const; bool IsCoinImport() const; From 530749939deed79b2d5a3057cad0ad76a32f34af Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 15 May 2022 15:16:54 +0500 Subject: [PATCH 280/348] var to disable cc logging for tests --- src/cc/CCutilbits.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cc/CCutilbits.cpp b/src/cc/CCutilbits.cpp index 67277bd365f..fa7a120940f 100644 --- a/src/cc/CCutilbits.cpp +++ b/src/cc/CCutilbits.cpp @@ -20,6 +20,8 @@ #include "CCinclude.h" #include "komodo_structs.h" +bool fDisableCCLogForTests = false; + // get address for a scriptPubKey bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey) { @@ -132,6 +134,7 @@ CPubKey pubkey2pk(std::vector vpubkey) // like -debug=cctokens (CCLOG_INFO) or -debug=cctokens-2 (CCLOG_DEBUG2 and lower levels) static bool cc_log_accept_category(const char *category, int level) { + if (fDisableCCLogForTests) return false; if (level < 0) return true; // always print errors From 29be177e2d40211d3a3b4653ebae9d8dcbb732f3 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 15 May 2022 15:18:03 +0500 Subject: [PATCH 281/348] cc tests improved: more rules added, added tests for R-address and tokens burn --- src/test-komodo-cc/test-assets.cpp | 2019 ++++++++++++++++++---------- 1 file changed, 1324 insertions(+), 695 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index caf7fba8221..d6674619057 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -27,10 +27,12 @@ #include "txmempool.h" extern Eval* EVAL_TEST; +extern bool fDisableCCLogForTests; namespace CCAssetsTests { static uint8_t testNum = 0; +static const char* cctokens_test_log = "cctokens_test"; uint256 getRandomHash() { @@ -45,25 +47,159 @@ uint256 getRandomHash() class EvalMock : public Eval { +public: + EvalMock() : Eval() {} + typedef std::map txns_type; + typedef std::map blocks_type; private: int currentHeight; - std::map txs; - std::map blocks; - //sstd::map> spends; + txns_type txs; + blocks_type blocks; + //std::map> spends; + public: - void AddTx(const CTransaction &tx) { + bool TestIsOutputSpent(uint256 txid, int32_t v) { + + //EvalMock::txns_type::const_iterator itx = eval.getTxs().find(txid); + //if (itx != eval.getTxs().end()) { + for (auto const &tx : txs) + for(auto const vin : tx.second.vin) + if (vin.prevout.hash == txid && vin.prevout.n == v) + return true; + // } + return false; + } +private: + bool TestBasicTxRules(const CTransaction &tx) + { + CAmount inputs = 0LL; + CAmount outputs = 0LL; + + std::set> duplicates; + for(const auto &vin : tx.vin) { + CTransaction vintx; + uint256 hashBlock; + if (!GetTxUnconfirmedOpt(this, vin.prevout.hash, vintx, hashBlock)) { + std::cerr << __func__ << " can't load vintx" << std::endl; + return false; + } + if (TestIsOutputSpent(vin.prevout.hash, vin.prevout.n)) { + std::cerr << __func__ << " inputs already spent" << std::endl; + return false; + } + duplicates.insert({vin.prevout.hash, vin.prevout.n}); + inputs += vintx.vout[vin.prevout.n].nValue; + } + if (duplicates.size() != tx.vin.size()) { + std::cerr << __func__ << " duplicated inputs" << std::endl; + return false; + } + for(const auto &vout : tx.vout) { + if (vout.nValue < 0) { + std::cerr << __func__ << " vout.nValue < 0" << std::endl; + return false; + } + inputs += vout.nValue; + } + if (inputs < outputs) { + std::cerr << __func__ << " inputs < outputs" << std::endl; + return false; + } + return true; + } + + // run over CC V2 validation + bool TestRunCCEval(const CMutableTransaction &mtx) + { + CTransaction tx(mtx); + PrecomputedTransactionData txdata(tx); + ServerTransactionSignatureChecker checker(&tx, 0, 0, false, 0, nullptr, txdata); + CValidationState verifystate; + VerifyEval verifyEval = [] (CC *cond, void *checker) { + //fprintf(stderr,"checker.%p\n",(TransactionSignatureChecker*)checker); + return ((TransactionSignatureChecker*)checker)->CheckEvalCondition(cond); + }; + + // set some vars used in validation: + KOMODO_CONNECTING = 1; + KOMODO_CCACTIVATE = 1; + (*this).state = CValidationState(); // clear validation state + EVAL_TEST = &(*this); + + for(const auto &vin : tx.vin) { + if (IsCCInput(vin.scriptSig)) { + CC *cond = GetCryptoCondition(vin.scriptSig); + if (cond == NULL) { + LOGSTREAMFN(cctokens_test_log, CCLOG_INFO, stream << " GetCryptoCondition could not decode vin.scriptSig" << std::endl); + return false; + } + + int r = cc_verifyEval(cond, verifyEval, &checker); + if (r == 0) { + LOGSTREAMFN(cctokens_test_log, CCLOG_INFO, stream << " cc_verify error D" << std::endl); + return false; + } + //LOGSTREAMFN(cctokens_test_log, CCLOG_INFO, stream << " cc_verify okay for vin.hash=" << vin.prevout.hash.GetHex() << std::endl); + //break; + } + } + for(const auto &vout : tx.vout) { + if (vout.scriptPubKey.IsPayToCCV2()) { + + ScriptError error; + bool bCheck = checker.CheckCryptoConditionSpk(vout.scriptPubKey.GetCCV2SPK(), &error); + if (!bCheck) { + LOGSTREAMFN(cctokens_test_log, CCLOG_INFO, stream << " CheckCryptoCondition error=" << ScriptErrorString(error) << " eval=" << (*this).state.GetRejectReason() << std::endl); + return false; + } + //LOGSTREAMFN(cctokens_test_log, CCLOG_INFO, stream << " cc_verify okay for vout.nValue=" << vout.nValue << std::endl); + } + } + return true; + } +private: + bool AddTxInternal(const CTransaction &tx, bool bTryOnly) { + if (!tx.IsNull()) { + if (txs.find(tx.GetHash()) != txs.end()) { + std::cerr << __func__ << " transaction already in chain" << std::endl; + return false; + } + if (!TestBasicTxRules(tx)) return false; + if (!TestRunCCEval(tx)) return false; + if (!bTryOnly) + txs[tx.GetHash()] = tx; + return true; + } + std::cerr << __func__ << " transaction is null" << std::endl; + return false; + } +public: + bool AddTx(const CTransaction &tx) { + return AddTxInternal(tx, false); + } + bool TryAddTx(const CTransaction &tx) { + return AddTxInternal(tx, true); + } + bool AddGenesisTx(const CTransaction &tx) { if (!tx.IsNull()) { txs[tx.GetHash()] = tx; + return true; } + std::cerr << __func__ << " transaction is null" << std::endl; + return false; } const std::map & getTxs() { return txs; } + void SetCurrentHeight(int h) + { + currentHeight = h; + } virtual bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const { - //std::cerr <<__func__ << " hash=" << hash.GetHex() << std::endl; + //std::cerr <<__func__ << " hash=" << hash.GetHex() << std::endl); auto r = txs.find(hash); if (r != txs.end()) { - //std::cerr <<__func__ << " hash=" << hash.GetHex() << " found" << std::endl; + //std::cerr <<__func__ << " hash=" << hash.GetHex() << " found" << std::endl); txOut = r->second; if (blocks.count(hash) > 0) hashBlock = hash; @@ -71,8 +207,13 @@ class EvalMock : public Eval } return false; } + virtual unsigned int GetCurrentHeight() const + { + return currentHeight; + } }; + static EvalMock eval; static uint256 tokenid1, tokenid2, tokenid3, tokenid4, tokenidUnused; @@ -94,12 +235,9 @@ std::map testKeys = { { pk3, privkey3 }, }; -//char Tokensv2CChexstr[] = { "032fd27f72591b02f13a7f9701246eb0296b2be7cfdad32c520e594844ec3d4801" }; -//uint8_t Tokensv2CCpriv[] = { 0xb5, 0xba, 0x92, 0x7f, 0x53, 0x45, 0x4f, 0xf8, 0xa4, 0xad, 0x0d, 0x38, 0x30, 0x4f, 0xd0, 0x97, 0xd1, 0xb7, 0x94, 0x1b, 0x1f, 0x52, 0xbd, 0xae, 0xa2, 0xe7, 0x49, 0x06, 0x2e, 0xd2, 0x2d, 0xa5 }; - static CPubKey pkunused = CPubKey(ParseHex("034b082c5819b5bf8798a387630ad236a8e800dbce4c4e24a46f36dfddab3cbff5")); -CAmount TestAddNormalInputs(CMutableTransaction &mtx, CPubKey mypk, CAmount amount) +static CAmount TestAddNormalInputs(CMutableTransaction &mtx, CPubKey mypk, CAmount amount) { CAmount totalInputs = 0LL; char mypkaddr[KOMODO_ADDRESS_BUFSIZE]; @@ -108,48 +246,66 @@ CAmount TestAddNormalInputs(CMutableTransaction &mtx, CPubKey mypk, CAmount amou for (int32_t v = 0; v < t.second.vout.size(); v ++) { char utxoaddr[KOMODO_ADDRESS_BUFSIZE]; Getscriptaddress(utxoaddr, t.second.vout[v].scriptPubKey); - //std::cerr << __func__ << " utxoaddr=" << utxoaddr << " mypkaddr=" << mypkaddr << " tx=" << t.second.GetHash().GetHex() << " v=" << v << std::endl; + LOGSTREAMFN(cctokens_test_log, CCLOG_DEBUG1, stream << " utxoaddr=" << utxoaddr << " mypkaddr=" << mypkaddr << " tx=" << t.second.GetHash().GetHex() << " v=" << v << std::endl); if (strcmp(utxoaddr, mypkaddr) == 0) { - mtx.vin.push_back(CTxIn(t.second.GetHash(), v)); - totalInputs += t.second.vout[v].nValue; - if (totalInputs >= amount) - return totalInputs; + uint256 txid = t.second.GetHash(); + if (!eval.TestIsOutputSpent(txid, v)) { + if (std::find_if(mtx.vin.begin(), mtx.vin.end(), [&](const CTxIn &vin) { return vin.prevout.hash == txid && vin.prevout.n == v; }) == mtx.vin.end()) + { + mtx.vin.push_back(CTxIn(txid, v)); + totalInputs += t.second.vout[v].nValue; + if (totalInputs >= amount) + return totalInputs; + } + } } } } return 0LL; } -CAmount TestAddTokenInputs(CMutableTransaction &mtx, CPubKey mypk, uint256 tokenid, CAmount amount) + +// if amount == 0 returns full available inputs +static CAmount TestAddTokenInputs(CMutableTransaction &mtx, CPubKey mypk, uint256 tokenid, CAmount amount) { CAmount totalInputs = 0LL; struct CCcontract_info *cp, C; cp = CCinit(&C, TokensV2::EvalCode()); - char mypkaddr[KOMODO_ADDRESS_BUFSIZE]; - Getscriptaddress(mypkaddr, TokensV2::MakeCC1vout(EVAL_TOKENSV2, 0, mypk).scriptPubKey); - for (auto const &t : eval.getTxs()) { - for (int32_t v = 0; v < t.second.vout.size(); v ++) { - char utxoaddr[KOMODO_ADDRESS_BUFSIZE]; - Getscriptaddress(utxoaddr, t.second.vout[v].scriptPubKey); - CTransaction tx; - //std::cerr << __func__ << " utxoaddr=" << utxoaddr << " mypkaddr=" << mypkaddr << " tx=" << t.second.GetHash().GetHex() << " v=" << v << std::endl; - if (strcmp(utxoaddr, mypkaddr) == 0 && - IsTokensvout(cp, &eval, t.second, v, tokenid)) { - mtx.vin.push_back(CTxIn(t.second.GetHash(), v)); - totalInputs += t.second.vout[v].nValue; - if (totalInputs >= amount) - return totalInputs; + std::vector tokenaddrs = GetTokenV2IndexKeys(mypk); + for (auto const & tokenaddr : tokenaddrs) + { + for (auto const &t : eval.getTxs()) { + for (int32_t v = 0; v < t.second.vout.size(); v ++) { + if (t.second.vout[v].scriptPubKey.IsPayToCryptoCondition()) + { + char utxoaddr[KOMODO_ADDRESS_BUFSIZE]; + Getscriptaddress(utxoaddr, t.second.vout[v].scriptPubKey); + CTransaction tx; + LOGSTREAMFN(cctokens_test_log, CCLOG_DEBUG1, stream << " utxoaddr=" << utxoaddr << " tokenaddr=" << tokenaddr << " tx=" << t.second.GetHash().GetHex() << " v=" << v << std::endl); + if (tokenaddr == utxoaddr && + IsTokensvout(cp, &eval, t.second, v, tokenid)) { + uint256 txid = t.second.GetHash(); + if (!eval.TestIsOutputSpent(txid, v)) { + if (std::find_if(mtx.vin.begin(), mtx.vin.end(), [&](const CTxIn &vin) { return vin.prevout.hash == txid && vin.prevout.n == v; }) == mtx.vin.end()) + { + mtx.vin.push_back(CTxIn(txid, v)); + totalInputs += t.second.vout[v].nValue; + if (amount > 0 && totalInputs >= amount) + return totalInputs; + } + } + } + } } } } - return 0LL; + return totalInputs; } - bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vini, CAmount utxovalue, const CScript scriptPubKey) { CTransaction txNewConst(mtx); SignatureData sigdata; - auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + auto consensusBranchId = CurrentEpochBranchId(eval.GetCurrentHeight(), Params().GetConsensus()); if (ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, vini, utxovalue, SIGHASH_ALL), scriptPubKey, sigdata, consensusBranchId) != 0) { UpdateTransaction(mtx, vini, sigdata); return true; @@ -165,7 +321,7 @@ bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vin // in functions like cp->ismyvin() or TotalPubkeyNormalAmount() bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_t *myprivkey, CAmount txfee, CScript opret) { - auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + auto consensusBranchId = CurrentEpochBranchId(eval.GetCurrentHeight(), Params().GetConsensus()); CAmount totaloutputs = 0LL; for (int i = 0; i < mtx.vout.size(); i ++) totaloutputs += mtx.vout[i].nValue; @@ -305,8 +461,9 @@ bool TestFinalizeTx(CMutableTransaction& mtx, struct CCcontract_info *cp, uint8_ } uint256 sighash = SignatureHash(CCPubKey(cond.get()), mtx, i, SIGHASH_ALL, vintx.vout[mtx.vin[i].prevout.n].nValue, consensusBranchId, &txdata); - if (cc_signTreeSecp256k1Msg32(cond.get(), privkey, sighash.begin()) == 0) { - fprintf(stderr, "%s vini.%d has CC signing error: cc_signTreeSecp256k1Msg32 returned error, address.(%s) %s\n", __func__, i, destaddr, EncodeHexTx(mtx).c_str()); + if (cc_signTreeSecp256k1Msg32(cond.get(), privkey, sighash.begin()) == 0 && + cc_signTreeSecp256k1HashMsg32(cond.get(), privkey, sighash.begin()) == 0) { + fprintf(stderr, "%s vini.%d has CC signing error: cc_signTreeSecp256k1Msg32 and cc_signTreeSecp256k1HashMsg32 returned error, address.(%s) %s\n", __func__, i, destaddr, EncodeHexTx(mtx).c_str()); return false; } mtx.vin[i].scriptSig = CCSig(cond.get()); @@ -364,26 +521,7 @@ CTxOut TestMakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmou } -class TestAssetsCC : public ::testing::Test { -public: - //uint32_t GetAssetchainsCC() const { return testCcid; } - //std::string GetAssetchainsSymbol() const { return testSymbol; } - -protected: - static void SetUpTestCase() { - // setup eval for tests - ASSETCHAINS_CC = 2; - - CreateMockTransactions(); - } - virtual void SetUp() { - // enable print - fDebug = true; - fPrintToConsole = true; - mapMultiArgs["-debug"] = { "cctokens", "ccassets" }; - } - - // run over CC V2 validation +/*** // run over CC V2 validation bool TestRunCCEval(const CMutableTransaction &mtx) { CTransaction tx(mtx); @@ -431,645 +569,935 @@ class TestAssetsCC : public ::testing::Test { } } return true; - } + }*/ - static void CreateMockTransactions() - { - CTransaction txnormal1 = MakeNormalTx(pk1, 20000); - eval.AddTx(txnormal1); +// create mock tx with normal outputs +static CTransaction MakeNormalTx(CPubKey mypk, CAmount val) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + mtx.vin.push_back(CTxIn(getRandomHash(), 0)); + mtx.vout.push_back(CTxOut(val, GetScriptForDestination(mypk))); + return CTransaction(mtx); +} + +// token create/transfer mock tx helpers - CTransaction txnormal2 = MakeNormalTx(pk1, 20000); - eval.AddTx(txnormal2); +static CMutableTransaction MakeTokenV2CreateTx(CPubKey mypk, CAmount amount, const UniValue &utokeldata = NullUniValue) +{ + struct CCcontract_info *cp, C; + cp = CCinit(&C, TokensV2::EvalCode()); + std::string name = "Test" + std::to_string(rand()); // make tokenid unique for all tests + std::string description = "desc"; + CAmount txfee = 10000; - CTransaction txnormal3 = MakeNormalTx(pk2, 20000); - eval.AddTx(txnormal3); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { + std::cerr << __func__ << " could not add normal inputs" << std::endl; + return CTransaction(); + } + mtx.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, amount, mypk)); - CTransaction txnormal4 = MakeNormalTx(pk2, 20000); - eval.AddTx(txnormal4); + std::vector vextras; + vuint8_t vtokeldata; + if (!utokeldata.isNull()) + vtokeldata = ParseTokelJson(utokeldata); + if (!vtokeldata.empty()) + vextras.push_back(vtokeldata); - CTransaction txnormal5 = MakeNormalTx(pk2, 20000); - eval.AddTx(txnormal5); + if (!TestFinalizeTx(mtx, cp, testKeys[mypk], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(mypk.begin(), mypk.end()), name, description, vextras))) { + std::cerr << __func__ << " could finalize tx" << std::endl; + return CTransaction(); + } + return mtx; +} - struct CCcontract_info *cpTokens, tokensC; - cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - struct CCcontract_info *cpAssets, C; - cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! - - CTransaction txnormalg = MakeNormalTx(GetUnspendable(cpTokens, NULL), 20000); - eval.AddTx(txnormalg); +static CMutableTransaction MakeTokenV2TransferTx(const CPubKey &mypk, CAmount txfee, uint256 tokenid, const std::vector &tokenaddrs, std::vector> probeconds, uint8_t M, std::vector destinations, CAmount total, bool useMempool, bool spendMarker) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction txtokencreate1 = MakeTokenV2CreateTx(pk1, 10); - eval.AddTx(txtokencreate1); - tokenid1 = txtokencreate1.GetHash(); + if (total < 0) { + CCerror = strprintf("negative total"); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << CCerror << "=" << total << std::endl); + return CTransaction(); + } - CTransaction txtokencreate2 = MakeTokenV2CreateTx(pk2, 10); - eval.AddTx(txtokencreate2); - tokenid2 = txtokencreate2.GetHash(); + struct CCcontract_info *cp, C; + cp = CCinit(&C, TokensV2::EvalCode()); - CTransaction txtokencreate3 = MakeTokenV2CreateTx(pk2, 10); - eval.AddTx(txtokencreate3); - tokenid3 = txtokencreate3.GetHash(); + if (txfee == 0) + txfee = 10000; - CTransaction txtokencreate4 = MakeTokenV2CreateTx(pk1, 10); - eval.AddTx(txtokencreate4); - tokenid4 = txtokencreate4.GetHash(); + if (!mypk.IsFullyValid()) { + CCerror = "mypk is not set or invalid"; + return CTransaction(); + } + std::vector destpubkeys; + for (auto const &dest : destinations) + if (dest.which() == TX_PUBKEY) + destpubkeys.push_back(boost::get(dest)); - CTransaction txtokencreateUnused = MakeTokenV2CreateTx(pk1, 10); - eval.AddTx(txtokencreateUnused); - tokenidUnused = txtokencreateUnused.GetHash(); + CAmount normalInputs = TestAddNormalInputs(mtx, mypk, txfee); + if (normalInputs > 0) + { + CAmount CCchange = 0, CCinputs = 0; + for (const auto &addr : tokenaddrs) { + CAmount CCinputsOne = TestAddTokenInputs(mtx, mypk, tokenid, total); + if (CCinputsOne > 0) + CCinputs += CCinputsOne; + if (CCinputs >= total) + break; + } - CTransaction txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); - eval.AddTx(txask1); - askid1 = txask1.GetHash(); + if (spendMarker) { + mtx.vin.push_back(CTxIn(tokenid, 0)); // spend tokenlist marker + } - CTransaction txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); - eval.AddTx(txask2); - askid2 = txask2.GetHash(); + if (CCinputs >= total) + { + if (CCinputs > total) + CCchange = (CCinputs - total); - CTransaction txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 222); - eval.AddTx(txbid1); - bidid1 = txbid1.GetHash(); + if (destinations.size() == 0) { + CCerror = "no dest pubkeys"; + return CTransaction(); + } - CTransaction txbid2 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+2, 222, ASSETS_NORMAL_DUST+1); - eval.AddTx(txbid2); - bidid2 = txbid2.GetHash(); + if (TokensV2::EvalCode() == EVAL_TOKENS) { + if (destinations.size() > 2) { + CCerror = "no more than 2 dest pubkeys supported"; + return CTransaction(); + } + } + if (TokensV2::EvalCode() == EVAL_TOKENSV2) { + if (destinations.size() > 128) { + CCerror = "no more than 128 dest pubkeys supported"; + return CTransaction(); + } + } - CTransaction txbid3 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 222, ASSETS_NORMAL_DUST-1); - eval.AddTx(txbid3); - bidid3 = txbid3.GetHash(); + mtx.vout.push_back(TokensV2::MakeTokensCCMofNDestVout(TokensV2::EvalCode(), 0, total, M, destinations)); + + // add optional custom probe conds to non-usual sign vins + for (const auto &p : probeconds) + CCAddVintxCond(cp, p.first, p.second); + + if (TokensV2::EvalCode() == EVAL_TOKENSV2) { + // probes for spending from mypk + for (const auto &mycond : GetTokenV2Conds(mypk)) + CCAddVintxCond(cp, mycond, nullptr); + + // if this is multisig - build and add multisig probes: + // find any token vin, load vin tx and extract M and pubkeys + for(int ccvin = 0; ccvin < mtx.vin.size(); ccvin ++) { + CTransaction vintx; + uint256 hashBlock; + std::vector vParams; + CScript dummy; + if (myGetTransaction(mtx.vin[ccvin].prevout.hash, vintx, hashBlock) && + vintx.vout[mtx.vin[ccvin].prevout.n].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) && // get opdrop + vintx.vout[mtx.vin[ccvin].prevout.n].scriptPubKey.SpkHasEvalcodeCCV2(TokensV2::EvalCode()) && + vParams.size() > 0) + { + COptCCParams ccparams(vParams[0]); + if (ccparams.version != 0 && ccparams.vKeys.size() > 1) { + if (CCchange != 0) { + mtx.vout.push_back(TokensV2::MakeTokensCCMofNvout(TokensV2::EvalCode(), 0, CCchange, ccparams.m, ccparams.vKeys)); + CCchange = 0; + } + CCwrapper ccprobeMofN( MakeTokensv2CCcondMofN(TokensV2::EvalCode(), 0, ccparams.m, ccparams.vKeys) ); + CCAddVintxCond(cp, ccprobeMofN, nullptr); //add MofN probe to find vins and sign + break; + } + } + } + } + if (CCchange != 0) { + if (TokensV2::EvalCode() == EVAL_TOKENSV2 && + CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) { + mtx.vout.push_back(TokensV2::MakeTokensCCMofNDestVout(TokensV2::EvalCode(), 0, CCchange, 1, {mypk.GetID()})); // send change to R-address after the HF + } + else + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), CCchange, mypk)); + } - //CTransaction txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2, 222); // test dust + // TODO maybe add also opret blobs form vintx + // as now this TokenTransfer() allows to transfer only tokens (including NFTs) that are unbound to other cc + if (!TestFinalizeTx(mtx, cp, testKeys[mypk], txfee, TokensV2::EncodeTokenOpRet(tokenid, destpubkeys, {} ))) + return CTransaction(); + return mtx; + + } + else { + if (CCinputs == 0LL) + CCerror = strprintf("no token inputs"); + else + CCerror = strprintf("insufficient token inputs"); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << CCerror << " for amount=" << total << std::endl); + } } - - static CTransaction MakeNormalTx(CPubKey mypk, CAmount val) - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - mtx.vin.push_back(CTxIn(getRandomHash(), 0)); - mtx.vout.push_back(CTxOut(val, GetScriptForDestination(mypk))); - //eval.txs[mtx.GetHash()] = mtx; - return CTransaction(mtx); + else { + CCerror = strprintf("insufficient normal inputs for tx fee"); + LOGSTREAMFN(cctokens_log, CCLOG_DEBUG1, stream << CCerror << std::endl); } + return CTransaction(); +} - static CMutableTransaction MakeTokenV2CreateTx(CPubKey mypk, CAmount amount, const UniValue &utokeldata = NullUniValue) - { - struct CCcontract_info *cp, C; - cp = CCinit(&C, TokensV2::EvalCode()); - std::string name = "Test" + std::to_string(rand()); - std::string description = "desc"; - CAmount txfee = 10000; - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { - std::cerr << __func__ << " could not add normal inputs" << std::endl; - return CTransaction(); +static CMutableTransaction BeginTokenV2TransferTx(const CPubKey &mypk) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CAmount txfee = 10000; + CAmount normalInputs = TestAddNormalInputs(mtx, mypk, txfee); + if (normalInputs > 0) + return mtx; + else { + LOGSTREAMFN(cctokens_test_log, CCLOG_INFO, stream << "normal inputs" << std::endl); + return CTransaction(); + } +} + +/** + * Add token outputs for tokenid to mtx + * cp CCcontract_info must be preserved until FinalizeTokenV2TransferTx call as it is to store probe conds + * mtx mtable tx + * mypk pubkey to sign inputs + * tokenid token id + * tokenaddress unused for now + * probeconds probe conds to add to cp (to match vintx scriptPubKeys) + * M min number of signers to spend the created outputs + * destpubkeys pubkeys where to send outputs + * total token amount to add + * useOpReturn add tokenid to opreturn (if true) or opdrop + * opretOut returns created opreturn if useOpReturn true + * skipInputs do not add token inputs (to create a bad token tx to test validation code) + * corruptChange change the change value (to create a bad token tx) + * splitOutputs split token amount on several outputs (to test validation code) + **/ +static bool AddTokenV2TransferOutputs(struct CCcontract_info *cp, CMutableTransaction &mtx, const CPubKey &mypk, uint256 tokenid, const char *tokenaddr, std::vector> probeconds, uint8_t M, std::vector destpubkeys, CAmount total, bool useOpReturn, CScript &opretOut, bool skipInputs = false, CAmount corruptChange = 0LL, int32_t splitOutputs = 1) +{ + CAmount CCchange = 0, inputs = 0; + if (skipInputs || (inputs = TestAddTokenInputs(mtx, mypk, tokenid, total)) >= total) // NOTE: AddTokenCCInputs might set cp->additionalEvalCode which is used in FinalizeCCtx! + { + if (inputs > total) + CCchange = (inputs - total); + + { + CScript opret = TokensV2::EncodeTokenOpRet(tokenid, destpubkeys, {}); + vscript_t vData; + GetOpReturnData(opret, vData); + CAmount partAmount = total; + if (splitOutputs > 0) { + partAmount = total / splitOutputs; + } + CAmount acc = 0LL; + for (int i = 0; i < splitOutputs; i ++) { + CAmount outputAmount = i < splitOutputs-1 ? partAmount : total - acc; // compensate round loss + LOGSTREAMFN(cctokens_test_log, CCLOG_DEBUG1, stream << " i=" << i << " outputAmount=" << outputAmount << std::endl); + std::vector vvData{ vData }; + mtx.vout.push_back(TokensV2::MakeTokensCCMofNvout(TokensV2::EvalCode(), 0, outputAmount, M, destpubkeys, useOpReturn ? nullptr : &vvData)); // add opdrop if opreturn not used + acc += outputAmount; + } } - mtx.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cp, NULL))); - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(0, amount, mypk)); - - std::vector vextras; - vuint8_t vtokeldata; - if (!utokeldata.isNull()) - vtokeldata = ParseTokelJson(utokeldata); - if (!vtokeldata.empty()) - vextras.push_back(vtokeldata); - - if (!TestFinalizeTx(mtx, cp, testKeys[mypk], txfee, - TokensV2::EncodeTokenCreateOpRet(vscript_t(mypk.begin(), mypk.end()), name, description, vextras))) { - std::cerr << __func__ << " could finalize tx" << std::endl; - return CTransaction(); + + // add optional custom probe conds to non-usual sign vins + for (const auto &p : probeconds) + CCAddVintxCond(cp, p.first, p.second); + + // if this is multisig - build and add multisig probes: + // find any token vin, load vin tx and extract M and pubkeys + bool ccChangeAdded = false; + for(int ccvin = 0; ccvin < mtx.vin.size(); ccvin ++) { + CTransaction vintx; + uint256 hashBlock; + std::vector vParams; + CScript dummy; + if (myGetTransaction(mtx.vin[ccvin].prevout.hash, vintx, hashBlock) && + vintx.vout[mtx.vin[ccvin].prevout.n].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) && // get opdrop + vintx.vout[mtx.vin[ccvin].prevout.n].scriptPubKey.SpkHasEvalcodeCCV2(TokensV2::EvalCode()) && + vParams.size() > 0) + { + COptCCParams ccparams(vParams[0]); + if (ccparams.version != 0 && ccparams.vKeys.size() > 1) { + if (CCchange != 0 || corruptChange != 0) { + mtx.vout.push_back(TokensV2::MakeTokensCCMofNvout(TokensV2::EvalCode(), 0, CCchange + corruptChange, ccparams.m, ccparams.vKeys)); + CCchange = 0; + ccChangeAdded = true; + } + CCwrapper ccprobeMofN( MakeTokensv2CCcondMofN(TokensV2::EvalCode(), 0, ccparams.m, ccparams.vKeys) ); + CCAddVintxCond(cp, ccprobeMofN, nullptr); //add MofN probe to find vins and sign + break; + } + } } - //eval.txs[mtx.GetHash()] = mtx; - return mtx; + + if (!ccChangeAdded && (CCchange != 0 || corruptChange != 0)) + { + CScript opret = TokensV2::EncodeTokenOpRet(tokenid, {mypk}, {}); + vscript_t vData; + GetOpReturnData(opret, vData); + std::vector vvData{ vData }; + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), CCchange + corruptChange, mypk, useOpReturn ? nullptr : &vvData)); // add opdrop if opreturn not used + } + if (useOpReturn) + opretOut = TokensV2::EncodeTokenOpRet(tokenid, destpubkeys, {}); + return true; + } + else { + if (inputs == 0LL) + CCerror = strprintf("no token inputs"); + else + CCerror = strprintf("insufficient token inputs"); + LOGSTREAMFN(cctokens_test_log, CCLOG_INFO, stream << CCerror << " for amount=" << total << std::endl); } + return false; +} - static CMutableTransaction MakeTokenV2AskTx(struct CCcontract_info *cpTokens, CPubKey mypk, uint256 tokenid, CAmount numtokens, CAmount unit_price, int32_t expiryHeight) - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); +static bool FinalizeTokenV2TransferTx(struct CCcontract_info *cp, CMutableTransaction &mtx, const CPubKey &mypk, const CScript &opret) +{ + CAmount txfee = 10000; - struct CCcontract_info *cpAssets, C; - cpAssets = CCinit(&C, AssetsV2::EvalCode()); + if (!TestFinalizeTx(mtx, cp, testKeys[mypk], txfee, opret)) { + LOGSTREAMFN(cctokens_test_log, CCLOG_INFO, stream << " could finalize tx" << std::endl); + return false; + } + return true; +} - CAmount txfee = 10000; - CAmount askamount = numtokens * unit_price; +static CAmount TokenV2Balance(const CPubKey &mypk, uint256 tokenid) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CAmount balance = TestAddTokenInputs(mtx, mypk, tokenid, 0); + LOGSTREAMFN(cctokens_test_log, CCLOG_DEBUG1, stream << " token v2 balance=" << balance << std::endl); + return balance; +} - if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { - std::cerr << __func__ << " cant add normal inputs" << std::endl; - return CTransaction(); - } +// assets tx create helpers: - TokenDataTuple tokenData; - vuint8_t vextraData; - int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { - std::cerr << __func__ << " cant get tokendata" << std::endl; - return CTransaction(); - } +static CMutableTransaction MakeTokenV2AskTx(struct CCcontract_info *cpTokens, CPubKey mypk, uint256 tokenid, CAmount numtokens, CAmount unit_price, int32_t expiryHeight) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpAssets, C; + cpAssets = CCinit(&C, AssetsV2::EvalCode()); - CAmount inputs = TestAddTokenInputs(mtx, mypk, tokenid, numtokens); - if (inputs == 0) { - std::cerr << __func__ << " cant add token inputs" << std::endl; - return CTransaction(); - } + CAmount txfee = 10000; + CAmount askamount = numtokens * unit_price; - CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), numtokens, unspendableAssetsPubkey)); - mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); - CAmount CCchange = inputs - numtokens; - if (CCchange != 0LL) { - // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), CCchange, mypk)); - } + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { + std::cerr << __func__ << " cant add normal inputs" << std::endl; + return CTransaction(); + } - // cond to spend NFT from mypk - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), mypk)); - CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey + TokenDataTuple tokenData; + vuint8_t vextraData; + int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { + std::cerr << __func__ << " cant get tokendata" << std::endl; + return CTransaction(); + } - // sign vins: - if(!TestFinalizeTx(mtx, cpTokens, testKeys[mypk], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { unspendableAssetsPubkey }, - { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))) { - std::cerr << __func__ << " cant finalize tx" << std::endl; - return CTransaction(); - } - return mtx; + + CAmount inputs = TestAddTokenInputs(mtx, mypk, tokenid, numtokens); + if (inputs == 0) { + std::cerr << __func__ << " cant add token inputs" << std::endl; + return CTransaction(); } - static CMutableTransaction MakeTokenV2BidTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, CAmount numtokens, CAmount unit_price, int32_t expiryHeight, CAmount extraCoins = 0LL) - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - //struct CCcontract_info *cpAssets, C; + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL); + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), numtokens, unspendableAssetsPubkey)); + mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); + CAmount CCchange = inputs - numtokens; + if (CCchange != 0LL) { + // change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible) + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), CCchange, mypk)); + } - CAmount bidamount = numtokens * unit_price; - //CAmount numtokens = 2; - CAmount txfee = 10000; + // cond to spend NFT from mypk + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), mypk)); + CCAddVintxCond(cpTokens, wrCond, NULL); //NULL indicates to use myprivkey - //cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! - //CAmount unit_price = bidamount / numtokens; + // sign vins: + if(!TestFinalizeTx(mtx, cpTokens, testKeys[mypk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { unspendableAssetsPubkey }, + { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))) { + std::cerr << __func__ << " cant finalize tx" << std::endl; + return CTransaction(); + } + return mtx; +} + +static CMutableTransaction MakeTokenV2BidTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, CAmount numtokens, CAmount unit_price, int32_t expiryHeight, CAmount extraCoins = 0LL) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + //struct CCcontract_info *cpAssets, C; + + CAmount bidamount = numtokens * unit_price; + //CAmount numtokens = 2; + CAmount txfee = 10000; + + //cpAssets = CCinit(&C, AssetsV2::EvalCode()); // NOTE: assets here! + //CAmount unit_price = bidamount / numtokens; + + if (TestAddNormalInputs(mtx, mypk, txfee + bidamount + extraCoins) == 0LL) { + std::cerr << __func__ << " cant add normal inputs" << std::endl; + return CTransaction(); + } + CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, nullptr); + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount + extraCoins, unspendableAssetsPubkey)); + mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); // marker for my orders + + // sign vins: + if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, {}, + { AssetsV2::EncodeAssetOpRet('b', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))) { + std::cerr << __func__ << " cant finalize tx" << std::endl; + return CTransaction(); + } + return mtx; +} + +static CMutableTransaction MakeTokenV2FillAskTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, uint256 asktxid, CAmount fill_units, CAmount paid_unit_price, UniValue &data) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpTokens, tokensC; + + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + + CTransaction asktx; + uint256 hashBlock; + if (!GetTxUnconfirmedOpt(&eval, asktxid, asktx, hashBlock)) { + std::cerr << __func__ << " could not load asktx" << std::endl; + return CTransaction(); + } + + CAmount unit_price = 0; + // CAmount fillunits = ask; + CAmount txfee = 10000; + const int32_t askvout = ASSETS_GLOBALADDR_VOUT; + uint256 assetidOpret; + //CAmount paid_unit_price = -1; // not set + CAmount orig_assetoshis = asktx.vout[askvout].nValue; + + TokenDataTuple tokenData; + vuint8_t vextraData; + int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { + std::cerr << __func__ << " cant get tokendata" << std::endl; + return CTransaction(); + } + bool bGetTokelDataAsInt64 = false; + if (vextraData.size() > 0) { + bGetTokelDataAsInt64 = GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); + if (royaltyFract > TKLROYALTY_DIVISOR-1) + royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit + } + //std::cerr << __func__ << " vextraData.size()=" << vextraData.size() << " bGetTokelDataAsInt64=" << bGetTokelDataAsInt64 << std::endl; + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); + + vuint8_t vorigpubkey; + int32_t expiryHeight; + uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, asktx); // get orig pk, orig value + + if (paid_unit_price <= 0LL) + paid_unit_price = unit_price; + + CAmount paid_nValue = paid_unit_price * fill_units; + CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / TKLROYALTY_DIVISOR * royaltyFract : 0; - if (TestAddNormalInputs(mtx, mypk, txfee + bidamount + extraCoins) == 0LL) { - std::cerr << __func__ << " cant add normal inputs" << std::endl; - return CTransaction(); + bool hasDust = false; + bool isRoyaltyDust = true; + if (royaltyFract > 0) { + + if (CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { + // corrected old calculation to allow tx creation and pass to fillask validation code + // (note division on TKLROYALTY_DIVISOR first): + if(paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / (int64_t)TKLROYALTY_DIVISOR * royaltyFract - ASSETS_NORMAL_DUST) { // if value paid to seller less than when the royalty is minimum + royaltyValue = 0; + hasDust = true; + isRoyaltyDust = true; //old code assumes dust always royalty + //std::cerr << __func__ << " old calc corrected, paid_nValue - royaltyValue=" << paid_nValue - royaltyValue << " test dust=" << ASSETS_NORMAL_DUST / (int64_t)TKLROYALTY_DIVISOR * royaltyFract - ASSETS_NORMAL_DUST << std::endl; + } + } + else { + // correct calculation: + if (AssetsFillOrderIsDust(royaltyFract, paid_nValue, isRoyaltyDust)) { + royaltyValue = 0; // all amount (with dust) to go to one pk (depending on which is not dust) + hasDust = true; + } } - CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, nullptr); - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount + extraCoins, unspendableAssetsPubkey)); - mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, mypk, unspendableAssetsPubkey)); // marker for my orders - - // sign vins: - if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, - TokensV2::EncodeTokenOpRet(tokenid, {}, - { AssetsV2::EncodeAssetOpRet('b', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))) { - std::cerr << __func__ << " cant finalize tx" << std::endl; - return CTransaction(); - } - return mtx; } - static CMutableTransaction MakeTokenV2FillAskTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, uint256 asktxid, CAmount fill_units, CAmount paid_unit_price, UniValue &data) + + //std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << std::endl; + + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { + std::cerr << __func__ << " cant add normal inputs" << std::endl; + return CTransaction(); + } + mtx.vin.push_back(CTxIn(asktx.GetHash(), askvout, CScript())); // spend order tx + + // vout.0 tokens remainder to unspendable cc addr: + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), orig_assetoshis - fill_units, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr + + //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, mypk)); + + vuint8_t destpk = (royaltyFract > 0 && hasDust && !isRoyaltyDust) ? vtokenCreatorPubkey : vorigpubkey; // if paid_value is dust send all amount to token owner + mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << destpk << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr + if (royaltyValue > 0) // note it makes the vout even if roaltyValue is 0 + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << vtokenCreatorPubkey << OP_CHECKSIG)); // vout.3 royalty to token owner + + if (orig_assetoshis - fill_units > 0) // we dont need the marker if order is filled + mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(vorigpubkey), GetUnspendable(cpAssets, NULL))); //vout.3(4 if royalty) marker to vorigpubkey (for my tokenorders?) + + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + + CCwrapper wrCond1(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond1, unspendableAssetsPrivkey); + + // probe to spend marker + CCwrapper wrCond2(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vtokenCreatorPubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond2, nullptr); // spend with mypk + + if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { mypk }, + { AssetsV2::EncodeAssetOpRet('S', unit_price, vorigpubkey, expiryHeight) } ))) { + std::cerr << __func__ << " cant finalize tx" << std::endl; + return CTransaction(); + } + data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); + data.pushKV("vorigpubkey", HexStr(vorigpubkey)); + data.pushKV("unit_price", unit_price); + data.pushKV("royaltyFract", royaltyFract); + data.pushKV("royaltyValue", royaltyValue); + data.pushKV("isRoyaltyDust", isRoyaltyDust); + return mtx; +} + +bool TestSetBidFillamounts(CAmount unit_price, CAmount &received_nValue, CAmount orig_nValue, CAmount &paid_units, CAmount orig_units, CAmount paid_unit_price) +{ + if (orig_units == 0) { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cpTokens, tokensC; + received_nValue = paid_units = 0; + return(false); + } + if (paid_units > orig_units) // not + { + paid_units = 0; + // received_nValue = orig_nValue; + received_nValue = (paid_units * paid_unit_price); // as paid unit_price might be less than original unit_price + // remaining_units = 0; + fprintf(stderr, "%s not enough units!\n", __func__); + return(false); + } + + received_nValue = (paid_units * paid_unit_price); + fprintf(stderr, "%s orig_units.%lld - paid_units.%lld, (orig_value.%lld - received_value.%lld)\n", __func__, + (long long)orig_units, (long long)paid_units, (long long)orig_nValue, (long long)received_nValue); + if (unit_price > 0 && received_nValue > 0 && received_nValue <= orig_nValue) + { + CAmount remaining_nValue = (orig_nValue - received_nValue); + return true; + } + else + { + fprintf(stderr, "%s incorrect values: unit_price %lld > 0, orig_value.%lld >= received_value.%lld\n", __func__, + (long long)unit_price, (long long)orig_nValue, (long long)received_nValue); + return(false); + } +} - cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); +static CMutableTransaction MakeTokenV2FillBidTx(struct CCcontract_info *cpTokens, CPubKey mypk, uint256 tokenid, uint256 bidtxid, CAmount fill_units, CAmount paid_unit_price, UniValue &data) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + struct CCcontract_info *cpAssets, C; + //struct CCcontract_info *cpTokens, tokensC; + + const int32_t bidvout = ASSETS_GLOBALADDR_VOUT; + CAmount paid_amount; + //CAmount bid_amount; + CAmount orig_units; + //CAmount unit_price = 0; + //CAmount fill_units = 2; + CAmount txfee = 10000; + uint256 assetidOpret; + + cpAssets = CCinit(&C, AssetsV2::EvalCode()); + //cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); - CTransaction asktx; - uint256 hashBlock; - if (!GetTxUnconfirmedOpt(&eval, asktxid, asktx, hashBlock)) { - std::cerr << __func__ << " could not load asktx" << std::endl; - return CTransaction(); - } + CTransaction bidtx; + uint256 hashBlock; + if (!GetTxUnconfirmedOpt(&eval, bidtxid, bidtx, hashBlock)) { + std::cerr << __func__ << " could not load bidtx" << std::endl; + return CTransaction(); + } - CAmount unit_price = 0; - // CAmount fillunits = ask; - CAmount txfee = 10000; - const int32_t askvout = ASSETS_GLOBALADDR_VOUT; - uint256 assetidOpret; - //CAmount paid_unit_price = -1; // not set - CAmount orig_assetoshis = asktx.vout[askvout].nValue; - - TokenDataTuple tokenData; - vuint8_t vextraData; - int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { - std::cerr << __func__ << " cant get tokendata" << std::endl; - return CTransaction(); - } - bool bGetTokelDataAsInt64 = false; - if (vextraData.size() > 0) { - bGetTokelDataAsInt64 = GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); - if (royaltyFract > TKLROYALTY_DIVISOR-1) - royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit - } - //std::cerr << __func__ << " vextraData.size()=" << vextraData.size() << " bGetTokelDataAsInt64=" << bGetTokelDataAsInt64 << std::endl; - vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); + TokenDataTuple tokenData; + vuint8_t vextraData; + int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction + if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { + std::cerr << __func__ << " cant get token data" << std::endl; + return CTransaction(); + } + if (vextraData.size() > 0) { + GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); + if (royaltyFract > TKLROYALTY_DIVISOR-1) + royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit + } + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); - vuint8_t vorigpubkey; - int32_t expiryHeight; - uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, asktx); // get orig pk, orig value + //std::cerr << __func__ << " bidtx=" << bidtx.GetHash().GetHex() << " " << HexStr(E_MARSHAL(ss << bidtx)) << " vouts=" << bidtx.vout.size() << std::endl; - if (paid_unit_price <= 0LL) - paid_unit_price = unit_price; + CAmount bid_amount = bidtx.vout[bidvout].nValue; + vuint8_t vorigpubkey; + int32_t expiryHeight; + CAmount unit_price; + if (GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, bidtx) == 0) { // get orig pk, orig value + std::cerr << __func__ << " cant get order data" << std::endl; + return CTransaction(); + } + if (unit_price == 0) { + std::cerr << __func__ << " zero unit_price" << std::endl; + return CTransaction(); + } - CAmount paid_nValue = paid_unit_price * fill_units; - CAmount royaltyValue = royaltyFract > 0 ? paid_nValue / TKLROYALTY_DIVISOR * royaltyFract : 0; + orig_units = bid_amount / unit_price; - bool hasDust = false; - bool isRoyaltyDust = true; - if (royaltyFract > 0) { - - if (CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { - // corrected old calculation to allow tx creation and pass to fillask validation code - // (note division on TKLROYALTY_DIVISOR first): - if(paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / (int64_t)TKLROYALTY_DIVISOR * royaltyFract - ASSETS_NORMAL_DUST) { // if value paid to seller less than when the royalty is minimum - royaltyValue = 0; - hasDust = true; - isRoyaltyDust = true; //old code assumes dust always royalty - //std::cerr << __func__ << " old calc corrected, paid_nValue - royaltyValue=" << paid_nValue - royaltyValue << " test dust=" << ASSETS_NORMAL_DUST / (int64_t)TKLROYALTY_DIVISOR * royaltyFract - ASSETS_NORMAL_DUST << std::endl; - } - } - else { - // correct calculation: - if (AssetsFillOrderIsDust(royaltyFract, paid_nValue, isRoyaltyDust)) { - royaltyValue = 0; // all amount (with dust) to go to one pk (depending on which is not dust) - hasDust = true; - } - } - } + if (paid_unit_price <= 0LL) + paid_unit_price = unit_price; + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { + std::cerr << __func__ << " cant add normal inputs" << std::endl; + return CTransaction(); + } + CAmount tokenInputs = TestAddTokenInputs(mtx, mypk, tokenid, fill_units); + if (tokenInputs == 0LL) { + std::cerr << __func__ << " cant add token inputs" << std::endl; + return CTransaction(); + } + //mtx.vin.push_back(CTxIn(tokenid, 1, CScript())); // spend token tx + mtx.vin.push_back(CTxIn(bidtx.GetHash(), bidvout, CScript())); // spend order tx - //std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << std::endl; + if (!SetBidFillamounts(unit_price, paid_amount, bid_amount, fill_units, orig_units, paid_unit_price)) { + std::cerr << __func__ << " SetBidFillamounts returned false, continue..." << std::endl; + } - if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { - std::cerr << __func__ << " cant add normal inputs" << std::endl; - return CTransaction(); + CAmount royaltyValue = royaltyFract > 0 ? paid_amount / TKLROYALTY_DIVISOR * royaltyFract : 0; + //if (royaltyValue <= ASSETS_NORMAL_DUST) + // royaltyValue = 0LL; + bool hasDust = false; + bool isRoyaltyDust = true; + if (royaltyFract > 0) { + // correct calculation: + if (AssetsFillOrderIsDust(royaltyFract, paid_amount, isRoyaltyDust)) { + royaltyValue = 0; // all amount (with dust) to go to one pk (depending on which is not dust) + hasDust = true; } - mtx.vin.push_back(CTxIn(asktx.GetHash(), askvout, CScript())); // spend order tx + } - // vout.0 tokens remainder to unspendable cc addr: - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(AssetsV2::EvalCode(), orig_assetoshis - fill_units, GetUnspendable(cpAssets, NULL))); // token remainder on cc global addr + //std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_amount=" << paid_amount << std::endl; + CAmount tokensChange = tokenInputs - fill_units; - //vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr: - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, mypk)); + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); - vuint8_t destpk = (royaltyFract > 0 && hasDust && !isRoyaltyDust) ? vtokenCreatorPubkey : vorigpubkey; // if paid_value is dust send all amount to token owner - mtx.vout.push_back(CTxOut(paid_nValue - royaltyValue, CScript() << destpk << OP_CHECKSIG)); //vout.2 coins to ask originator's normal addr - if (royaltyValue > 0) // note it makes the vout even if roaltyValue is 0 - mtx.vout.push_back(CTxOut(royaltyValue, CScript() << vtokenCreatorPubkey << OP_CHECKSIG)); // vout.3 royalty to token owner + if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { // bidder has coins for more tokens or only dust is sent back to global address + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bid_amount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder or the dust is sent back to cc global addr + if (orig_units - fill_units == 0) + std::cerr << __func__ << " remainder dust detected, left on global addr (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; + } + else + mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << vorigpubkey << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator + mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << (royaltyFract > 0 && hasDust && !isRoyaltyDust ? vtokenCreatorPubkey : vuint8_t(mypk.begin(), mypk.end())) << OP_CHECKSIG)); // vout1 coins to mypk normal + if (royaltyValue > 0) // note it makes vout even if roaltyValue is 0 + mtx.vout.push_back(CTxOut(royaltyValue, CScript() << vtokenCreatorPubkey << OP_CHECKSIG)); // vout2 trade royalty to token owner + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, pubkey2pk(vorigpubkey))); // vout2(3) single-eval tokens sent to the originator + //specially change to make valid tx if bidder takes tokens for lower price + //if (orig_units - fill_units > 0) // order is not finished yet + if (mtx.vout[0].scriptPubKey.IsPayToCryptoCondition() && mtx.vout[0].nValue / unit_price > 0) + mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(vorigpubkey), unspendableAssetsPk)); // vout3(4 if royalty) marker to vorigpubkey - if (orig_assetoshis - fill_units > 0) // we dont need the marker if order is filled - mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(vorigpubkey), GetUnspendable(cpAssets, NULL))); //vout.3(4 if royalty) marker to vorigpubkey (for my tokenorders?) + if (tokensChange != 0LL) + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), tokensChange, mypk)); // change in single-eval tokens - uint8_t unspendableAssetsPrivkey[32]; - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + CMutableTransaction mtx2(mtx); // copy - CCwrapper wrCond1(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond1, unspendableAssetsPrivkey); + CCwrapper wrCond1(MakeCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); // spend coins + CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); + + CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), mypk)); // spend my tokens to fill buy + CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey + + // probe to spend marker + CCwrapper wrCond3(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vtokenCreatorPubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond3, nullptr); // spend with mypk + + if (!TestFinalizeTx(mtx, cpTokens, testKeys[mypk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { pubkey2pk(vorigpubkey) }, + { AssetsV2::EncodeAssetOpRet('B', unit_price, vorigpubkey, expiryHeight) }))) { + std::cerr << __func__ << " could not finalize tx" << std::endl; + return CTransaction(); + } + data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); + data.pushKV("vorigpubkey", HexStr(vorigpubkey)); + data.pushKV("unit_price", unit_price); + data.pushKV("expiryHeight", expiryHeight); + data.pushKV("royaltyFract", royaltyFract); + data.pushKV("royaltyValue", royaltyValue); + data.pushKV("isRoyaltyDust", isRoyaltyDust); + return mtx; +} - // probe to spend marker - CCwrapper wrCond2(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vtokenCreatorPubkey), unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond2, nullptr); // spend with mypk - if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { mypk }, - { AssetsV2::EncodeAssetOpRet('S', unit_price, vorigpubkey, expiryHeight) } ))) { - std::cerr << __func__ << " cant finalize tx" << std::endl; - return CTransaction(); - } - data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); - data.pushKV("vorigpubkey", HexStr(vorigpubkey)); - data.pushKV("unit_price", unit_price); - data.pushKV("royaltyFract", royaltyFract); - data.pushKV("royaltyValue", royaltyValue); - data.pushKV("isRoyaltyDust", isRoyaltyDust); - return mtx; - } +static CMutableTransaction MakeTokenV2CancelAskTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, uint256 asktxid, UniValue &data) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - bool TestSetBidFillamounts(CAmount unit_price, CAmount &received_nValue, CAmount orig_nValue, CAmount &paid_units, CAmount orig_units, CAmount paid_unit_price) - { - if (orig_units == 0) - { - received_nValue = paid_units = 0; - return(false); - } - if (paid_units > orig_units) // not - { - paid_units = 0; - // received_nValue = orig_nValue; - received_nValue = (paid_units * paid_unit_price); // as paid unit_price might be less than original unit_price - // remaining_units = 0; - fprintf(stderr, "%s not enough units!\n", __func__); - return(false); - } - - received_nValue = (paid_units * paid_unit_price); - fprintf(stderr, "%s orig_units.%lld - paid_units.%lld, (orig_value.%lld - received_value.%lld)\n", __func__, - (long long)orig_units, (long long)paid_units, (long long)orig_nValue, (long long)received_nValue); - if (unit_price > 0 && received_nValue > 0 && received_nValue <= orig_nValue) - { - CAmount remaining_nValue = (orig_nValue - received_nValue); - return true; - } - else - { - fprintf(stderr, "%s incorrect values: unit_price %lld > 0, orig_value.%lld >= received_value.%lld\n", __func__, - (long long)unit_price, (long long)orig_nValue, (long long)received_nValue); - return(false); - } + CTransaction asktx; + uint256 hashBlock; + if (!GetTxUnconfirmedOpt(&eval, asktxid, asktx, hashBlock)) { + std::cerr << __func__ << " could not load asktx" << std::endl; + return CTransaction(); } + CAmount txfee = 10000; + CAmount askamount = asktx.vout[ASSETS_GLOBALADDR_VOUT].nValue; - static CMutableTransaction MakeTokenV2FillBidTx(struct CCcontract_info *cpTokens, CPubKey mypk, uint256 tokenid, uint256 bidtxid, CAmount fill_units, CAmount paid_unit_price, UniValue &data) - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cpAssets, C; - //struct CCcontract_info *cpTokens, tokensC; - - const int32_t bidvout = ASSETS_GLOBALADDR_VOUT; - CAmount paid_amount; - //CAmount bid_amount; - CAmount orig_units; - //CAmount unit_price = 0; - //CAmount fill_units = 2; - CAmount txfee = 10000; - uint256 assetidOpret; + TokenDataTuple tokenData; + vuint8_t vextraData; + if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { + std::cerr << __func__ << " could not load token data" << std::endl; + return CTransaction(); + } + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); - cpAssets = CCinit(&C, AssetsV2::EvalCode()); - //cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { + std::cerr << __func__ << " could not add normal inputs" << std::endl; + return CTransaction(); + } + mtx.vin.push_back(CTxIn(asktxid, ASSETS_GLOBALADDR_VOUT, CScript())); + + uint8_t dummyEvalCode; + uint256 dummyAssetid, dummyAssetid2; + int64_t dummyPrice; + vuint8_t vorigpubkey; + int32_t expiryHeight; + uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(asktx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, vorigpubkey, expiryHeight); + if (funcid == 's' && asktx.vout.size() > 1) + mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // spend marker if funcid='s' + else if (funcid == 'S' && asktx.vout.size() > 3) + mtx.vin.push_back(CTxIn(asktxid, 3, CScript())); // spend marker if funcid='S' + else { + std::cerr << __func__ << "invalid ask tx" << std::endl; + return CTransaction(); + } + + mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), askamount, vorigpubkey)); // one-eval token vout + + // init assets 'unspendable' privkey and pubkey + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + + CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); + + // probe to spend marker + //std::cerr << __func__ << " mypk=" << HexStr(mypk) << " vorigpubkey=" << HexStr(pubkey2pk(vorigpubkey)) << std::endl; + if (mypk == pubkey2pk(vorigpubkey)) { + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk + //std::cerr << __func__ << " use mypk" << std::endl; + } else { + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk + //std::cerr << __func__ << " use unspendableAssetsPrivkey=" << HexStr(unspendableAssetsPrivkey, unspendableAssetsPrivkey+32) << std::endl; + } - CTransaction bidtx; - uint256 hashBlock; - if (!GetTxUnconfirmedOpt(&eval, bidtxid, bidtx, hashBlock)) { - std::cerr << __func__ << " could not load bidtx" << std::endl; - return CTransaction(); - } + if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { vorigpubkey }, + { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(), 0) } ))) { + std::cerr << __func__ << " could not finalize tx" << std::endl; + return CTransaction(); + } + + data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); + data.pushKV("vorigpubkey", HexStr(vorigpubkey)); + data.pushKV("askamount", askamount); - TokenDataTuple tokenData; - vuint8_t vextraData; - int64_t royaltyFract = 0; // royaltyFract is N in N/1000 fraction - if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { - std::cerr << __func__ << " cant get token data" << std::endl; - return CTransaction(); - } - if (vextraData.size() > 0) { - GetTokelDataAsInt64(vextraData, TKLPROP_ROYALTY, royaltyFract); - if (royaltyFract > TKLROYALTY_DIVISOR-1) - royaltyFract = TKLROYALTY_DIVISOR-1; // royalty upper limit - } - vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); + return mtx; +} - //std::cerr << __func__ << " bidtx=" << bidtx.GetHash().GetHex() << " " << HexStr(E_MARSHAL(ss << bidtx)) << " vouts=" << bidtx.vout.size() << std::endl; +static CMutableTransaction MakeTokenV2CancelBidTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, uint256 bidtxid, UniValue &data) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CAmount bid_amount = bidtx.vout[bidvout].nValue; - vuint8_t vorigpubkey; - int32_t expiryHeight; - CAmount unit_price; - if (GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, bidtx) == 0) { // get orig pk, orig value - std::cerr << __func__ << " cant get order data" << std::endl; - return CTransaction(); - } - if (unit_price == 0) { - std::cerr << __func__ << " zero unit_price" << std::endl; - return CTransaction(); - } + CTransaction bidtx; + uint256 hashBlock; + if (!GetTxUnconfirmedOpt(&eval, bidtxid, bidtx, hashBlock)) { + std::cerr << __func__ << " could not load bidtx" << std::endl; + return CTransaction(); + } + CAmount txfee = 10000; + CAmount bidamount = bidtx.vout[ASSETS_GLOBALADDR_VOUT].nValue; - orig_units = bid_amount / unit_price; + TokenDataTuple tokenData; + vuint8_t vextraData; + if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { + std::cerr << __func__ << " could not load token data" << std::endl; + return CTransaction(); + } + vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); - if (paid_unit_price <= 0LL) - paid_unit_price = unit_price; + if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { + std::cerr << __func__ << " could not add normal inputs" << std::endl; + return CTransaction(); + } + mtx.vin.push_back(CTxIn(bidtxid, ASSETS_GLOBALADDR_VOUT, CScript())); + + uint8_t dummyEvalCode; + uint256 dummyAssetid, dummyAssetid2; + int64_t dummyPrice; + vuint8_t vorigpubkey; + int32_t expiryHeight; + uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(bidtx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, vorigpubkey, expiryHeight); + if (funcid == 'b' && bidtx.vout.size() > 1) + mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' + else if (funcid == 'B' && bidtx.vout.size() > 3) + mtx.vin.push_back(CTxIn(bidtxid, 3, CScript())); // spend marker if funcid='B' + else { + std::cerr << __func__ << "invalid bid tx" << std::endl; + return CTransaction(); } + + if (bidamount > ASSETS_NORMAL_DUST) + mtx.vout.push_back(CTxOut(bidamount, CScript() << vorigpubkey << OP_CHECKSIG)); + else { + // send dust back to global addr + mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, GetUnspendable(cpAssets, NULL))); + std::cerr << __func__ << " remainder dust detected, left on global addr, bidamount=" << bidamount << std::endl; + } + + // init assets 'unspendable' privkey and pubkey + uint8_t unspendableAssetsPrivkey[32]; + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + + // probe to spend marker + if (mypk == pubkey2pk(vorigpubkey)) { + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk + } else { + CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); + CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk + } - if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { - std::cerr << __func__ << " cant add normal inputs" << std::endl; - return CTransaction(); - } - CAmount tokenInputs = TestAddTokenInputs(mtx, mypk, tokenid, fill_units); - if (tokenInputs == 0LL) { - std::cerr << __func__ << " cant add token inputs" << std::endl; - return CTransaction(); - } - //mtx.vin.push_back(CTxIn(tokenid, 1, CScript())); // spend token tx - mtx.vin.push_back(CTxIn(bidtx.GetHash(), bidvout, CScript())); // spend order tx - - if (!SetBidFillamounts(unit_price, paid_amount, bid_amount, fill_units, orig_units, paid_unit_price)) { - std::cerr << __func__ << " SetBidFillamounts return false, continue..." << std::endl; - } + // sign, add change, add opreturn + if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, + TokensV2::EncodeTokenOpRet(tokenid, { vorigpubkey }, + { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(), 0) } ))) { + std::cerr << __func__ << " could not finalise tx" << std::endl; + return CTransaction(); + } + data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); + data.pushKV("vorigpubkey", HexStr(vorigpubkey)); + data.pushKV("bidamount", bidamount); + return mtx; +} - CAmount royaltyValue = royaltyFract > 0 ? paid_amount / TKLROYALTY_DIVISOR * royaltyFract : 0; - //if (royaltyValue <= ASSETS_NORMAL_DUST) - // royaltyValue = 0LL; - bool hasDust = false; - bool isRoyaltyDust = true; - if (royaltyFract > 0) { - // correct calculation: - if (AssetsFillOrderIsDust(royaltyFract, paid_amount, isRoyaltyDust)) { - royaltyValue = 0; // all amount (with dust) to go to one pk (depending on which is not dust) - hasDust = true; - } - } +static void CreateMockTransactions() +{ + struct CCcontract_info *cpTokens, tokensC; + struct CCcontract_info *cpAssets, C; + cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); + cpAssets = CCinit(&C, AssetsV2::EvalCode()); - std::cerr << __func__ << " royaltyFract=" << royaltyFract << " royaltyValue=" << royaltyValue << " paid_amount=" << paid_amount << std::endl; - CAmount tokensChange = tokenInputs - fill_units; + eval.SetCurrentHeight(11); - uint8_t unspendableAssetsPrivkey[32]; - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + CTransaction txnormal1 = MakeNormalTx(pk1, 200000000); + eval.AddGenesisTx(txnormal1); - if (orig_units - fill_units > 0 || bid_amount - paid_amount <= ASSETS_NORMAL_DUST) { // bidder has coins for more tokens or only dust is sent back to global address - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bid_amount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder or the dust is sent back to cc global addr - if (orig_units - fill_units == 0) - std::cerr << __func__ << " remainder dust detected, left on global addr (bid_amount - paid_amount)=" << (bid_amount - paid_amount) << std::endl; - } - else - mtx.vout.push_back(CTxOut(bid_amount - paid_amount, CScript() << vorigpubkey << OP_CHECKSIG)); // vout0 if no more tokens to buy, send the remainder to originator - mtx.vout.push_back(CTxOut(paid_amount - royaltyValue, CScript() << (royaltyFract > 0 && hasDust && !isRoyaltyDust ? vtokenCreatorPubkey : vuint8_t(mypk.begin(), mypk.end())) << OP_CHECKSIG)); // vout1 coins to mypk normal - if (royaltyValue > 0) // note it makes vout even if roaltyValue is 0 - mtx.vout.push_back(CTxOut(royaltyValue, CScript() << vtokenCreatorPubkey << OP_CHECKSIG)); // vout2 trade royalty to token owner - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), fill_units, pubkey2pk(vorigpubkey))); // vout2(3) single-eval tokens sent to the originator - //specially change to make valid tx if bidder takes tokens for lower price - //if (orig_units - fill_units > 0) // order is not finished yet - if (mtx.vout[0].scriptPubKey.IsPayToCryptoCondition() && mtx.vout[0].nValue / unit_price > 0) - mtx.vout.push_back(TokensV2::MakeCC1of2vout(AssetsV2::EvalCode(), ASSETS_MARKER_AMOUNT, pubkey2pk(vorigpubkey), unspendableAssetsPk)); // vout3(4 if royalty) marker to vorigpubkey - - if (tokensChange != 0LL) - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), tokensChange, mypk)); // change in single-eval tokens - - CMutableTransaction mtx2(mtx); // copy - - CCwrapper wrCond1(MakeCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); // spend coins - CCAddVintxCond(cpTokens, wrCond1, unspendableAssetsPrivkey); - - CCwrapper wrCond2(TokensV2::MakeTokensCCcond1(TokensV2::EvalCode(), mypk)); // spend my tokens to fill buy - CCAddVintxCond(cpTokens, wrCond2, NULL); //NULL indicates to use myprivkey - - // probe to spend marker - CCwrapper wrCond3(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vtokenCreatorPubkey), unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond3, nullptr); // spend with mypk - - if (!TestFinalizeTx(mtx, cpTokens, testKeys[mypk], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { pubkey2pk(vorigpubkey) }, - { AssetsV2::EncodeAssetOpRet('B', unit_price, vorigpubkey, expiryHeight) }))) { - std::cerr << __func__ << " could not finalize tx" << std::endl; - return CTransaction(); - } - data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); - data.pushKV("vorigpubkey", HexStr(vorigpubkey)); - data.pushKV("unit_price", unit_price); - data.pushKV("expiryHeight", expiryHeight); - data.pushKV("royaltyFract", royaltyFract); - data.pushKV("royaltyValue", royaltyValue); - data.pushKV("isRoyaltyDust", isRoyaltyDust); - return mtx; - } + CTransaction txnormal2 = MakeNormalTx(pk1, 200000000); + eval.AddGenesisTx(txnormal2); + CTransaction txnormal3 = MakeNormalTx(pk2, 200000000); + eval.AddGenesisTx(txnormal3); - static CMutableTransaction MakeTokenV2CancelAskTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, uint256 asktxid, UniValue &data) - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CTransaction txnormal4 = MakeNormalTx(pk2, 200000000); + eval.AddGenesisTx(txnormal4); - CTransaction asktx; - uint256 hashBlock; - if (!GetTxUnconfirmedOpt(&eval, asktxid, asktx, hashBlock)) { - std::cerr << __func__ << " could not load asktx" << std::endl; - return CTransaction(); - } - CAmount txfee = 10000; - CAmount askamount = asktx.vout[ASSETS_GLOBALADDR_VOUT].nValue; + CTransaction txnormal5 = MakeNormalTx(pk2, 200000000); + eval.AddGenesisTx(txnormal5); - TokenDataTuple tokenData; - vuint8_t vextraData; - if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { - std::cerr << __func__ << " could not load token data" << std::endl; - return CTransaction(); - } - vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); + CTransaction txnormalg = MakeNormalTx(GetUnspendable(cpTokens, NULL), 200000000); + eval.AddGenesisTx(txnormalg); - if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { - std::cerr << __func__ << " could not add normal inputs" << std::endl; - return CTransaction(); - } - mtx.vin.push_back(CTxIn(asktxid, ASSETS_GLOBALADDR_VOUT, CScript())); - - uint8_t dummyEvalCode; - uint256 dummyAssetid, dummyAssetid2; - int64_t dummyPrice; - vuint8_t vorigpubkey; - int32_t expiryHeight; - uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(asktx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, vorigpubkey, expiryHeight); - if (funcid == 's' && asktx.vout.size() > 1) - mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // spend marker if funcid='s' - else if (funcid == 'S' && asktx.vout.size() > 3) - mtx.vin.push_back(CTxIn(asktxid, 3, CScript())); // spend marker if funcid='S' - else { - std::cerr << __func__ << "invalid ask tx" << std::endl; - return CTransaction(); - } + CTransaction txtokencreate1 = MakeTokenV2CreateTx(pk1, 100); + ASSERT_TRUE(eval.AddTx(txtokencreate1)); + tokenid1 = txtokencreate1.GetHash(); - mtx.vout.push_back(TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), askamount, vorigpubkey)); // one-eval token vout + CTransaction txtokencreate2 = MakeTokenV2CreateTx(pk2, 10); + eval.AddTx(txtokencreate2); + tokenid2 = txtokencreate2.GetHash(); - // init assets 'unspendable' privkey and pubkey - uint8_t unspendableAssetsPrivkey[32]; - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + CTransaction txtokencreate3 = MakeTokenV2CreateTx(pk2, 10); + eval.AddTx(txtokencreate3); + tokenid3 = txtokencreate3.GetHash(); - CCwrapper wrCond(TokensV2::MakeTokensCCcond1(AssetsV2::EvalCode(), unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); + CTransaction txtokencreate4 = MakeTokenV2CreateTx(pk1, 10); + eval.AddTx(txtokencreate4); + tokenid4 = txtokencreate4.GetHash(); - // probe to spend marker - //std::cerr << __func__ << " mypk=" << HexStr(mypk) << " vorigpubkey=" << HexStr(pubkey2pk(vorigpubkey)) << std::endl; - if (mypk == pubkey2pk(vorigpubkey)) { - CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk - //std::cerr << __func__ << " use mypk" << std::endl; - } else { - CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk - //std::cerr << __func__ << " use unspendableAssetsPrivkey=" << HexStr(unspendableAssetsPrivkey, unspendableAssetsPrivkey+32) << std::endl; - } + CTransaction txtokencreateUnused = MakeTokenV2CreateTx(pk1, 10); + eval.AddTx(txtokencreateUnused); + tokenidUnused = txtokencreateUnused.GetHash(); - if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { vorigpubkey }, - { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(), 0) } ))) { - std::cerr << __func__ << " could not finalize tx" << std::endl; - return CTransaction(); - } - - data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); - data.pushKV("vorigpubkey", HexStr(vorigpubkey)); - data.pushKV("askamount", askamount); + CTransaction txask1 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); + eval.AddTx(txask1); + askid1 = txask1.GetHash(); - return mtx; - } + CTransaction txask2 = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, ASSETS_NORMAL_DUST+1, 222); + eval.AddTx(txask2); + askid2 = txask2.GetHash(); - static CMutableTransaction MakeTokenV2CancelBidTx(struct CCcontract_info *cpAssets, CPubKey mypk, uint256 tokenid, uint256 bidtxid, UniValue &data) - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CTransaction txbid1 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 222); + eval.AddTx(txbid1); + bidid1 = txbid1.GetHash(); - CTransaction bidtx; - uint256 hashBlock; - if (!GetTxUnconfirmedOpt(&eval, bidtxid, bidtx, hashBlock)) { - std::cerr << __func__ << " could not load bidtx" << std::endl; - return CTransaction(); - } - CAmount txfee = 10000; - CAmount bidamount = bidtx.vout[ASSETS_GLOBALADDR_VOUT].nValue; + CTransaction txbid2 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+2, 222, ASSETS_NORMAL_DUST+1); + eval.AddTx(txbid2); + bidid2 = txbid2.GetHash(); - TokenDataTuple tokenData; - vuint8_t vextraData; - if (!GetTokenData(&eval, tokenid, tokenData, vextraData)) { - std::cerr << __func__ << " could not load token data" << std::endl; - return CTransaction(); - } - vuint8_t vtokenCreatorPubkey = std::get<0>(tokenData); + CTransaction txbid3 = MakeTokenV2BidTx(cpAssets, pk2, tokenid2, 2, ASSETS_NORMAL_DUST+1, 222, ASSETS_NORMAL_DUST-1); + eval.AddTx(txbid3); + bidid3 = txbid3.GetHash(); - if (TestAddNormalInputs(mtx, mypk, txfee) == 0LL) { - std::cerr << __func__ << " could not add normal inputs" << std::endl; - return CTransaction(); - } - mtx.vin.push_back(CTxIn(bidtxid, ASSETS_GLOBALADDR_VOUT, CScript())); - - uint8_t dummyEvalCode; - uint256 dummyAssetid, dummyAssetid2; - int64_t dummyPrice; - vuint8_t vorigpubkey; - int32_t expiryHeight; - uint8_t funcid = AssetsV2::DecodeAssetTokenOpRet(bidtx.vout.back().scriptPubKey, dummyEvalCode, dummyAssetid, dummyPrice, vorigpubkey, expiryHeight); - if (funcid == 'b' && bidtx.vout.size() > 1) - mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' - else if (funcid == 'B' && bidtx.vout.size() > 3) - mtx.vin.push_back(CTxIn(bidtxid, 3, CScript())); // spend marker if funcid='B' - else { - std::cerr << __func__ << "invalid bid tx" << std::endl; - return CTransaction(); } - if (bidamount > ASSETS_NORMAL_DUST) - mtx.vout.push_back(CTxOut(bidamount, CScript() << vorigpubkey << OP_CHECKSIG)); - else { - // send dust back to global addr - mtx.vout.push_back(TokensV2::MakeCC1vout(AssetsV2::EvalCode(), bidamount, GetUnspendable(cpAssets, NULL))); - std::cerr << __func__ << " remainder dust detected, left on global addr, bidamount=" << bidamount << std::endl; - } + //CTransaction txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2, 222); // test dust +} - // init assets 'unspendable' privkey and pubkey - uint8_t unspendableAssetsPrivkey[32]; - CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); +// test setup +class TestAssetsCC : public ::testing::Test { +public: + //uint32_t GetAssetchainsCC() const { return testCcid; } + //std::string GetAssetchainsSymbol() const { return testSymbol; } - // probe to spend marker - if (mypk == pubkey2pk(vorigpubkey)) { - CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, nullptr); // spend with mypk - } else { - CCwrapper wrCond(::MakeCCcond1of2(AssetsV2::EvalCode(), pubkey2pk(vorigpubkey), unspendableAssetsPk)); - CCAddVintxCond(cpAssets, wrCond, unspendableAssetsPrivkey); // spend with shared pk - } +protected: + static void SetUpTestCase() { + // setup eval for tests + ASSETCHAINS_CC = 2; + fDisableCCLogForTests = true; + fDebug = false; + fPrintToConsole = true; + mapMultiArgs["-debug"] = { "cctokens", "ccassets", "cctokens_test" }; - // sign, add change, add opreturn - if (!TestFinalizeTx(mtx, cpAssets, testKeys[mypk], txfee, - TokensV2::EncodeTokenOpRet(tokenid, { vorigpubkey }, - { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(), 0) } ))) { - std::cerr << __func__ << " could not finalise tx" << std::endl; - return CTransaction(); - } - data.pushKV("vtokenCreatorPubkey", HexStr(vtokenCreatorPubkey)); - data.pushKV("vorigpubkey", HexStr(vorigpubkey)); - data.pushKV("bidamount", bidamount); - return mtx; + CreateMockTransactions(); + } + virtual void SetUp() { + // enable print + //fDebug = true; + //fPrintToConsole = true; + //mapMultiArgs["-debug"] = { "cctokens", "ccassets", "cctokens_test" }; } virtual void TearDown() @@ -1078,11 +1506,8 @@ class TestAssetsCC : public ::testing::Test { strcpy(ASSETCHAINS_SYMBOL, ""); CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); // select default } - - }; - // -------------------------------------------------- // assets cc tests: @@ -1111,7 +1536,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) uint8_t funcid = GetOrderParams(vorigpubkey, unit_price, assetidOpret, expiryHeight, mtx); // test: valid tokenv2ask - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); { // test: invalid unit_price == 0 @@ -1120,7 +1545,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); + EXPECT_FALSE(eval.TryAddTx(mtx1)); } { // test: invalid token dest pubkey (not global) @@ -1129,7 +1554,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pkunused }, // bad pk instead of global { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); - EXPECT_TRUE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 + EXPECT_TRUE(eval.TryAddTx(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { // test: bad origpk in opreturn (not the tx signer) @@ -1138,7 +1563,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(pkunused.begin(), pkunused.end()), expiryHeight) }))); // not matched origpk (should be pk1) - EXPECT_FALSE(TestRunCCEval(mtx1)); + EXPECT_FALSE(eval.TryAddTx(mtx1)); } { // test: only one opreturn supported @@ -1147,7 +1572,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); + EXPECT_FALSE(eval.TryAddTx(mtx1)); } { // test: send to non-global assets destination @@ -1157,7 +1582,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 + EXPECT_FALSE(eval.TryAddTx(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { // test: add extra global addr vout @@ -1169,7 +1594,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 + EXPECT_FALSE(eval.TryAddTx(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { // test: add extra global addr null vout @@ -1181,7 +1606,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 + EXPECT_FALSE(eval.TryAddTx(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { // test: add extra marker @@ -1192,7 +1617,7 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); // == true as pk in token opreturn not used in tokens v2 + EXPECT_FALSE(eval.TryAddTx(mtx1)); // == true as pk in token opreturn not used in tokens v2 } { // test: different tokenid in opdrop @@ -1220,8 +1645,8 @@ TEST_F(TestAssetsCC, tokenv2ask_basic) ASSERT_TRUE(TestFinalizeTx(mtx, cpTokens, testKeys[mypk], 10000, TokensV2::EncodeTokenOpRet(tokenid2, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); - std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop.." << " GetRejectReason=" << eval.state.GetRejectReason() << std::endl; - EXPECT_TRUE(!TestRunCCEval(mtx) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // fail: can't ask for different tokenid + //std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop.." << " GetRejectReason=" << eval.state.GetRejectReason() << std::endl; + EXPECT_TRUE(!eval.TryAddTx(mtx) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // fail: can't ask for different tokenid } } @@ -1238,7 +1663,7 @@ TEST_F(TestAssetsCC, tokenv2bid_basic) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2bid - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); { CMutableTransaction mtx1(mtx); @@ -1250,7 +1675,7 @@ TEST_F(TestAssetsCC, tokenv2bid_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], txfee, TokensV2::EncodeTokenOpRet(tokenid1, {}, { AssetsV2::EncodeAssetOpRet('b', 10000, vuint8_t(pk2.begin(), pk2.end()), 0) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx1)); // must fail } } @@ -1269,7 +1694,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2fillask - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); } CTransaction txask1; @@ -1302,7 +1727,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) TokensV2::EncodeTokenOpRet(tokenidUnused, { pk2 }, { AssetsV2::EncodeAssetOpRet('S', unit_price, vorigpubkey, expiryHeight) } ))); - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx1)); // must fail } { // test: use opposite funcid @@ -1320,7 +1745,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(vorigpubkey) }, { AssetsV2::EncodeAssetOpRet('B', unit_price, vorigpubkey, expiryHeight) }))); // 'S' -> 'B' - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid + EXPECT_FALSE(eval.TryAddTx(mtx1)); // must fail: incorrect funcid } // test: spend yet another order { @@ -1337,7 +1762,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, { AssetsV2::EncodeAssetOpRet('S', unit_price, vorigpubkey, expiryHeight) } ))); - EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx2)); // must fail } { // test: change unit_price in opret @@ -1356,7 +1781,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, { AssetsV2::EncodeAssetOpRet('S', unit_price+1, vorigpubkey, expiryHeight) } ))); - EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx2)); // must fail } { // test: changed origpk in assets opreturn @@ -1370,7 +1795,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpAssets, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(tokenid1, { pk2 }, { AssetsV2::EncodeAssetOpRet('S', unit_price, vuint8_t(pkunused.begin(), pkunused.end()), expiryHeight) }))); // not matched origpk (should be pk1) - EXPECT_FALSE(TestRunCCEval(mtx1)); + EXPECT_FALSE(eval.TryAddTx(mtx1)); } { vuint8_t vorigpubkey; @@ -1383,7 +1808,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: invalid tokenv2fillask with a lower price - EXPECT_FALSE(TestRunCCEval(mtx)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx)); // must fail } { vuint8_t vorigpubkey; @@ -1396,7 +1821,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2fillask with a bigger price - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); } { for (CAmount fillUnits : { 1, 2 }) { // fill partially and totally @@ -1448,9 +1873,9 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, { AssetsV2::EncodeAssetOpRet('S', unit_price, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), expiryHeight) }))); - std::cerr << __func__ << " test: tokenfillask with different tokenid in opdrop, fillUnuts=" << fillUnits << std::endl; + //std::cerr << __func__ << " test: tokenfillask with different tokenid in opdrop, fillUnuts=" << fillUnits << std::endl; EXPECT_FALSE(assetidOpret == tokenid3); - EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid in opdrop + EXPECT_TRUE(!eval.TryAddTx(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid in opdrop } } @@ -1492,8 +1917,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) TokensV2::EncodeTokenOpRet(tokenid2, { unspendableAssetsPubkey }, { AssetsV2::EncodeAssetOpRet('s', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))); std::cerr << __func__ << " tokenv2ask_basic different tokenid in opdrop - should work before HF fix:" << std::endl; - EXPECT_TRUE(TestRunCCEval(mtx)); // work for tokel before CCASSETS_OPDROP_FIX_TOKEL_HEIGHT - eval.AddTx(mtx); + EXPECT_TRUE(eval.AddTx(mtx)); // work for tokel before CCASSETS_OPDROP_FIX_TOKEL_HEIGHT uint256 askid = mtx.GetHash(); // add fill ask @@ -1525,8 +1949,8 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) TokensV2::EncodeTokenOpRet(tokenid2, { pk2 }, { AssetsV2::EncodeAssetOpRet('S', unit_price, vuint8_t(mypk.begin(), mypk.end()), expiryHeight) }))); - std::cerr << __func__ << " test: tokenfillask with different tokenid in opdrop, fillUnuts=" << fillUnits << " should fail with 'invalid tokenid' error:" << std::endl; - EXPECT_TRUE(!TestRunCCEval(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must work before TOKEL activation height + //std::cerr << __func__ << " test: tokenfillask with different tokenid in opdrop, fillUnuts=" << fillUnits << " should fail with 'invalid tokenid' error:" << std::endl; + EXPECT_TRUE(!eval.TryAddTx(mtx2) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must work before TOKEL activation height } { // test: try to send remainder to 2of3 token/asset eval/secp threshold (must be 3of3) @@ -1535,8 +1959,8 @@ TEST_F(TestAssetsCC, tokenv2fillask_basic) vscript_t vopret; GetOpReturnData(opret, vopret); mtx1.vout[0] = TestMakeTokensCCMofNvoutMixed(AssetsV2::EvalCode(), TokensV2::EvalCode(), mtx1.vout[0].nValue, 1, { unspendableAssetsPubkey }, &vopret); // replace with 1of2 eval threshold - std::cerr << __func__ << " test: tokenfillask with incorrect eval threshold:" << std::endl; - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid + //std::cerr << __func__ << " test: tokenfillask with incorrect eval threshold:" << std::endl; + EXPECT_FALSE(eval.TryAddTx(mtx1)); // must fail: incorrect funcid } } @@ -1561,7 +1985,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2fillbid - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); { // test: fill with another tokenid CMutableTransaction mtx1(mtx); @@ -1578,7 +2002,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) TokensV2::EncodeTokenOpRet(tokenid3, { pubkey2pk(vorigpubkey) }, { AssetsV2::EncodeAssetOpRet('B', unit_price, vorigpubkey, expiryHeight) }))); - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: can't fill with another tokenid3 + EXPECT_FALSE(eval.TryAddTx(mtx1)); // must fail: can't fill with another tokenid3 } { // test: use opposite funcid @@ -1596,7 +2020,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(vorigpubkey) }, { AssetsV2::EncodeAssetOpRet('S', unit_price, vorigpubkey, expiryHeight) }))); // 'B' -> 'S' - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail: incorrect funcid + EXPECT_FALSE(eval.TryAddTx(mtx1)); // must fail: incorrect funcid } { // test: changed origpk in opreturn @@ -1610,7 +2034,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk2], 10000, TokensV2::EncodeTokenOpRet(assetidOpret, { pk2 }, { AssetsV2::EncodeAssetOpRet('B', unit_price, vuint8_t(pkunused.begin(), pkunused.end()), expiryHeight) }))); // not matched origpk (should be pk1) - EXPECT_FALSE(TestRunCCEval(mtx1)); // must fail changed origpk + EXPECT_FALSE(eval.TryAddTx(mtx1)); // must fail changed origpk } { vuint8_t vorigpubkey; @@ -1624,7 +2048,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: invalid tokenv2fillbid with lower price but invalid cc inputs != cc outputs - EXPECT_FALSE(TestRunCCEval(mtx)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx)); // must fail } { vuint8_t vorigpubkey; @@ -1637,7 +2061,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2fillbid with lower sell price than requested - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); } { vuint8_t vorigpubkey; @@ -1650,7 +2074,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: invalid tokenv2fillbid with bigger sell price than requested - EXPECT_FALSE(TestRunCCEval(mtx)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx)); // must fail } { // test: fillbid with different tokenid in opdrop @@ -1689,13 +2113,13 @@ TEST_F(TestAssetsCC, tokenv2fillbid_basic) TokensV2::EncodeTokenOpRet(assetidOpret, { pubkey2pk(vorigpubkey) }, { AssetsV2::EncodeAssetOpRet('B', unit_price, vorigpubkey, expiryHeight) }))); - std::cerr << __func__ << " test: tokenfillbid with different tokenid in opdrop, tokenid3=" << tokenid3.GetHex() << " assetidOpret=" << assetidOpret.GetHex() << std::endl; - std::cerr << __func__ << " i=" << i++ << std::endl; + //std::cerr << __func__ << " test: tokenfillbid with different tokenid in opdrop, tokenid3=" << tokenid3.GetHex() << " assetidOpret=" << assetidOpret.GetHex() << std::endl; + //std::cerr << __func__ << " i=" << i++ << std::endl; EXPECT_FALSE(assetidOpret == tokenid3); - //EXPECT_TRUE(TestRunCCEval(mtx2)); + //EXPECT_TRUE(eval.TryAddTx(mtx2)); bool b = false; - EXPECT_TRUE(!(b=TestRunCCEval(mtx2)) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid3 in opdrop - std::cerr <<__func__ << " b=" << b << " eval.state.GetRejectReason()=" << eval.state.GetRejectReason() << " mtx2=" << HexStr(E_MARSHAL(ss << mtx2)) << std::endl; + EXPECT_TRUE(!(b=eval.TryAddTx(mtx2)) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't fill with another tokenid3 in opdrop + //std::cerr <<__func__ << " b=" << b << " eval.state.GetRejectReason()=" << eval.state.GetRejectReason() << " mtx2=" << HexStr(E_MARSHAL(ss << mtx2)) << std::endl; } } } @@ -1736,7 +2160,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_royalty_fixed) if (filltokens * price / (int64_t)TKLROYALTY_DIVISOR * std::min(r, (int32_t)TKLROYALTY_DIVISOR - r) <= ASSETS_NORMAL_DUST) { // have dust EXPECT_TRUE(data["royaltyValue"].get_int64() == 0); - EXPECT_TRUE(TestRunCCEval(mytxfillbid)); + EXPECT_TRUE(eval.TryAddTx(mytxfillbid)); EXPECT_TRUE(mytxfillbid.vout[1].nValue == filltokens * price); EXPECT_TRUE(r < TKLROYALTY_DIVISOR/2 ? data["isRoyaltyDust"].get_bool() : !data["isRoyaltyDust"].get_bool()); // is dust royalty or paid_value // if royalty is not dust then the value should go either to tokenowner @@ -1746,12 +2170,12 @@ TEST_F(TestAssetsCC, tokenv2fillbid_royalty_fixed) else { // no dust EXPECT_TRUE(data["royaltyValue"].get_int64() > 0); - EXPECT_TRUE(TestRunCCEval(mytxfillbid)); + EXPECT_TRUE(eval.TryAddTx(mytxfillbid)); EXPECT_TRUE(mytxfillbid.vout[1].nValue + mytxfillbid.vout[2].nValue == filltokens * price); } // test: valid tokenv2fillbid - EXPECT_TRUE(TestRunCCEval(mytxfillbid)); + EXPECT_TRUE(eval.TryAddTx(mytxfillbid)); } } @@ -1791,9 +2215,9 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty_non_fixed) ASSERT_TRUE(data["royaltyValue"].get_int64() > 0); // must not be dust for this test if (r <= 500) - EXPECT_TRUE(TestRunCCEval(mytxfillask)); // valid fillask if royalty <= 50% + EXPECT_TRUE(eval.TryAddTx(mytxfillask)); // valid fillask if royalty <= 50% else - EXPECT_FALSE(TestRunCCEval(mytxfillask)); + EXPECT_FALSE(eval.TryAddTx(mytxfillask)); } } @@ -1836,14 +2260,14 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty_fixed) if (filltokens * price / (int64_t)TKLROYALTY_DIVISOR * std::min(r, (int32_t)TKLROYALTY_DIVISOR - r) <= ASSETS_NORMAL_DUST) { // have dust EXPECT_TRUE(data["royaltyValue"].get_int64() == 0); - EXPECT_TRUE(TestRunCCEval(mytxfillask)); + EXPECT_TRUE(eval.TryAddTx(mytxfillask)); EXPECT_TRUE(mytxfillask.vout[2].nValue == filltokens * price); EXPECT_TRUE(r < TKLROYALTY_DIVISOR/2 ? data["isRoyaltyDust"].get_bool() : !data["isRoyaltyDust"].get_bool()); // is dust royalty or paid_value } else { // no dust EXPECT_TRUE(data["royaltyValue"].get_int64() > 0); - EXPECT_TRUE(TestRunCCEval(mytxfillask)); + EXPECT_TRUE(eval.TryAddTx(mytxfillask)); EXPECT_TRUE(mytxfillask.vout[2].nValue + mytxfillask.vout[3].nValue == filltokens * price); } } @@ -1883,14 +2307,14 @@ TEST_F(TestAssetsCC, tokenv2cancelask) CAmount askamount = data["askamount"].get_int64(); // test: valid tokenv2cancelask - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); { // test: invalid pk2 in assets opreturn CMutableTransaction mtx2(mtx); mtx2.vout.pop_back(); mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(pk2.begin(), pk2.end()), 0) } ))); - EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret not checked + EXPECT_TRUE(eval.TryAddTx(mtx2)); // pk in opret not checked } { // test: some unused pk in token opret @@ -1898,13 +2322,13 @@ TEST_F(TestAssetsCC, tokenv2cancelask) mtx3.vout.pop_back(); mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { pkunused }, { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); - EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked for token v2, it is only for a hint + EXPECT_TRUE(eval.TryAddTx(mtx3)); // pk in opret is not checked for token v2, it is only for a hint } { // test: invalid pk where to funds sent CMutableTransaction mtx4(mtx); mtx4.vout[0] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), askamount, pk2); - EXPECT_FALSE(TestRunCCEval(mtx4)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx4)); // must fail } { // test: invalid tokenid in token opret @@ -1912,7 +2336,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask) mtx5.vout.pop_back(); mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); - EXPECT_FALSE(TestRunCCEval(mtx5)); // must fail: cant send to another tokenid + EXPECT_FALSE(eval.TryAddTx(mtx5)); // must fail: cant send to another tokenid } { // test: invalid funcid in token opret @@ -1920,7 +2344,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask) mtx6.vout.pop_back(); mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid1, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); - EXPECT_FALSE(TestRunCCEval(mtx6)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx6)); // must fail } { eval.SetCurrentHeight(CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT); @@ -1941,7 +2365,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask) std::vector vData { vopret }; mtx7.vout[0] = TokensV2::MakeTokensCC1vout(TokensV2::EvalCode(), mtx7.vout[0].nValue, vorigpubkey, &vData); // replace remainder with tokenid4 - std::cerr << __func__ << " tokenid4=" << tokenid4.GetHex() << " assetidOpret=" << assetidOpret.GetHex() << " otherAmount=" << otherAmount << " mtx7.vin.size()=" << mtx7.vin.size() << std::endl; + //std::cerr << __func__ << " tokenid4=" << tokenid4.GetHex() << " assetidOpret=" << assetidOpret.GetHex() << " otherAmount=" << otherAmount << " mtx7.vin.size()=" << mtx7.vin.size() << std::endl; if (otherAmount > mtx7.vout[0].nValue) { // if tokenid4 change exists CScript opret = TokensV2::EncodeTokenOpRet(tokenid4, { vorigpubkey }, {}); vscript_t vopret; @@ -1959,9 +2383,9 @@ TEST_F(TestAssetsCC, tokenv2cancelask) TokensV2::EncodeTokenOpRet(assetidOpret, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(), 0) }))); - std::cerr << __func__ << " test: tokencancelask with different tokenid in opdrop" << std::endl; + //std::cerr << __func__ << " test: tokencancelask with different tokenid in opdrop" << std::endl; EXPECT_FALSE(assetidOpret == tokenid4); - EXPECT_TRUE(!TestRunCCEval(mtx7) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't cancel with another tokenid in opdrop + EXPECT_TRUE(!eval.TryAddTx(mtx7) && eval.state.GetRejectReason().find("invalid tokenid") != std::string::npos); // must fail: can't cancel with another tokenid in opdrop } } } @@ -1976,8 +2400,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txaskexp).IsNull()); - eval.AddTx(txaskexp); - EXPECT_TRUE(TestRunCCEval(txaskexp)); + EXPECT_TRUE(eval.AddTx(txaskexp)); UniValue data(UniValue::VOBJ); uint256 asktxid = txaskexp.GetHash(); @@ -1990,7 +2413,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2cancelask with mypk - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); } { struct CCcontract_info *cpTokens, tokensC; @@ -1998,8 +2421,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txaskexp).IsNull()); - eval.AddTx(txaskexp); - EXPECT_TRUE(TestRunCCEval(txaskexp)); + EXPECT_TRUE(eval.AddTx(txaskexp)); UniValue data(UniValue::VOBJ); uint256 asktxid = txaskexp.GetHash(); @@ -2012,7 +2434,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: try tokenv2cancelask not yet expired with globalpk - EXPECT_FALSE(TestRunCCEval(mtx)); // should fail + EXPECT_FALSE(eval.TryAddTx(mtx)); // should fail } { struct CCcontract_info *cpTokens, tokensC; @@ -2021,8 +2443,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) // use static mtx as it is added to static eval CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txaskexp).IsNull()); - eval.AddTx(txaskexp); - EXPECT_TRUE(TestRunCCEval(txaskexp)); + EXPECT_TRUE(eval.AddTx(txaskexp)); UniValue data(UniValue::VOBJ); uint256 asktxid = txaskexp.GetHash(); @@ -2035,7 +2456,7 @@ TEST_F(TestAssetsCC, tokenv2cancelask_expired) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: try tokenv2cancelask already expired with globalpk - EXPECT_TRUE(TestRunCCEval(mtx)); // should not fail + EXPECT_TRUE(eval.TryAddTx(mtx)); // should not fail } } @@ -2049,8 +2470,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_expired) CTransaction txaskexp = MakeTokenV2AskTx(cpTokens, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txaskexp).IsNull()); - eval.AddTx(txaskexp); - EXPECT_TRUE(TestRunCCEval(txaskexp)); + EXPECT_TRUE(eval.AddTx(txaskexp)); UniValue data(UniValue::VOBJ); uint256 asktxid = txaskexp.GetHash(); @@ -2064,7 +2484,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_expired) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: try tokenv2fillask already expired - EXPECT_FALSE(TestRunCCEval(mtx)); // should fail + EXPECT_FALSE(eval.TryAddTx(mtx)); // should fail } } @@ -2101,14 +2521,14 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) CAmount bidamount = data["bidamount"].get_int64(); // test: valid tokenv2cancelbid - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); { // test: invalid pk in assets opreturn CMutableTransaction mtx2(mtx); mtx2.vout.pop_back(); mtx2.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(pk1.begin(), pk1.end()), 0) } ))); - EXPECT_TRUE(TestRunCCEval(mtx2)); // pk in opret is not checked + EXPECT_TRUE(eval.TryAddTx(mtx2)); // pk in opret is not checked } { // test: invalid pk in token opret @@ -2116,13 +2536,13 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) mtx3.vout.pop_back(); mtx3.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pkunused }, { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); - EXPECT_TRUE(TestRunCCEval(mtx3)); // pk in opret is not checked + EXPECT_TRUE(eval.TryAddTx(mtx3)); // pk in opret is not checked } { // test: invalid pk where to funds sent CMutableTransaction mtx4(mtx); mtx4.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(pkunused)) << OP_CHECKSIG); - EXPECT_FALSE(TestRunCCEval(mtx4)); // must fail as can't send the remainder to another pk + EXPECT_FALSE(eval.TryAddTx(mtx4)); // must fail as can't send the remainder to another pk } { // test: invalid tokenid in token opret @@ -2130,7 +2550,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) mtx5.vout.pop_back(); mtx5.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenidUnused, { vorigpubkey }, { AssetsV2::EncodeAssetOpRet('o', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); - EXPECT_FALSE(TestRunCCEval(mtx5)); + EXPECT_FALSE(eval.TryAddTx(mtx5)); } { // test: invalid funcid in token opret @@ -2138,13 +2558,13 @@ TEST_F(TestAssetsCC, tokenv2cancelbid) mtx6.vout.pop_back(); mtx6.vout.push_back(CTxOut(0, TokensV2::EncodeTokenOpRet(tokenid2, { pk2 }, { AssetsV2::EncodeAssetOpRet('x', 0, vuint8_t(vorigpubkey.begin(), vorigpubkey.end()), 0) } ))); - EXPECT_FALSE(TestRunCCEval(mtx6)); + EXPECT_FALSE(eval.TryAddTx(mtx6)); } { // test: send dust to normals - bad test params here //CMutableTransaction mtx7(mtx); //mtx7.vout[0] = CTxOut(bidamount, CScript() << ParseHex(HexStr(vtokenCreatorPubkey)) << OP_CHECKSIG); - //EXPECT_FALSE(TestRunCCEval(mtx7)); // must fail: dust should stay on cc global output + //EXPECT_FALSE(eval.TryAddTx(mtx7)); // must fail: dust should stay on cc global output } } } @@ -2161,8 +2581,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid_expired) // use static mtx as it is added to static eval CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txbidexp).IsNull()); - eval.AddTx(txbidexp); - EXPECT_TRUE(TestRunCCEval(txbidexp)); + EXPECT_TRUE(eval.AddTx(txbidexp)); UniValue data(UniValue::VOBJ); @@ -2176,7 +2595,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid_expired) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: valid tokenv2cancelbid with mypk - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); } { struct CCcontract_info *cpAssets0, C0; @@ -2184,8 +2603,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid_expired) CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txbidexp).IsNull()); - eval.AddTx(txbidexp); - EXPECT_TRUE(TestRunCCEval(txbidexp)); + EXPECT_TRUE(eval.AddTx(txbidexp)); UniValue data(UniValue::VOBJ); uint256 bidtxid = txbidexp.GetHash(); @@ -2198,7 +2616,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid_expired) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: try tokenv2cancelbid not yet expired with globalpk - EXPECT_FALSE(TestRunCCEval(mtx)); // should fail + EXPECT_FALSE(eval.TryAddTx(mtx)); // should fail } { struct CCcontract_info *cpAssets0, C0; @@ -2207,8 +2625,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid_expired) // use static mtx as it is added to static eval CTransaction txbidexp = MakeTokenV2BidTx(cpAssets0, pk1, tokenid1, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txbidexp).IsNull()); - eval.AddTx(txbidexp); - EXPECT_TRUE(TestRunCCEval(txbidexp)); + EXPECT_TRUE(eval.AddTx(txbidexp)); UniValue data(UniValue::VOBJ); uint256 bidtxid = txbidexp.GetHash(); @@ -2221,7 +2638,7 @@ TEST_F(TestAssetsCC, tokenv2cancelbid_expired) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: try tokenv2cancelbid already expired with globalpk - EXPECT_TRUE(TestRunCCEval(mtx)); // should not fail + EXPECT_TRUE(eval.TryAddTx(mtx)); // should not fail } } @@ -2235,8 +2652,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_expired) CTransaction txbidexp = MakeTokenV2BidTx(cpAssets, pk1, tokenid2, 2, 10000, 222); // set expiry height 222 ASSERT_FALSE(CTransaction(txbidexp).IsNull()); - eval.AddTx(txbidexp); - EXPECT_TRUE(TestRunCCEval(txbidexp)); + EXPECT_TRUE(eval.AddTx(txbidexp)); UniValue data(UniValue::VOBJ); uint256 bidtxid = txbidexp.GetHash(); @@ -2250,7 +2666,7 @@ TEST_F(TestAssetsCC, tokenv2fillbid_expired) ASSERT_FALSE(CTransaction(mtx).IsNull()); // test: try tokenv2fillask already expired - EXPECT_FALSE(TestRunCCEval(mtx)); // should fail + EXPECT_FALSE(eval.TryAddTx(mtx)); // should fail } } @@ -2268,7 +2684,7 @@ TEST_F(TestAssetsCC, tokenv2create) CMutableTransaction mtx = MakeTokenV2CreateTx(pk1, 10); ASSERT_FALSE(CTransaction(mtx).IsNull()); - EXPECT_TRUE(TestRunCCEval(mtx)); + EXPECT_TRUE(eval.TryAddTx(mtx)); CAmount txfee = 0; std::string name = "T2"; @@ -2280,7 +2696,74 @@ TEST_F(TestAssetsCC, tokenv2create) mtx1.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk1], txfee, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); - EXPECT_TRUE(TestRunCCEval(mtx1)); // allow sending created tokens to any pk!! + EXPECT_TRUE(eval.TryAddTx(mtx1)); // allow sending created tokens to any pk!! + } + { + // test: invalid pk in opreturn: + CMutableTransaction mtx2(mtx); + mtx2.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { }))); + EXPECT_FALSE(eval.TryAddTx(mtx2)); // must fail + } + { + // test: no token vouts, sent to normal + CMutableTransaction mtx3(mtx); + mtx3.vout[1] = CTxOut(10, CScript() << ParseHex(HexStr(pk1)) << OP_CHECKSIG); + mtx3.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx3, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + EXPECT_FALSE(eval.TryAddTx(mtx3)); // fail for no token cc vouts + } + { + // test: no token vouts, sent to cc v1 + CMutableTransaction mtx4(mtx); + mtx4.vout[1] = TokensV1::MakeCC1vout(EVAL_ASSETS, 10, pk2); // sent to cc v1 vout + mtx4.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx4, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + EXPECT_FALSE(eval.TryAddTx(mtx4)); // fail for no token cc vouts + } + { + // test: invalid token created with global pk: + CMutableTransaction mtx5 = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + uint8_t privkeyg[32]; + CPubKey pkg = GetUnspendable(cpTokens, privkeyg); + + ASSERT_TRUE(TestAddNormalInputs(mtx5, pkg, TOKENS_MARKER_VALUE + 10 + txfee) > 0); + //mtx5.vin.push_back(CTxIn(txnormalg.GetHash(), 0)); + mtx5.vout.push_back(TokensV2::MakeCC1vout(TokensV2::EvalCode(), TOKENS_MARKER_VALUE, GetUnspendable(cpTokens, NULL))); + mtx5.vout.push_back(TokensV2::MakeTokensCC1vout(0, 10, pk1)); + + ASSERT_TRUE(TestFinalizeTx(mtx5, cpTokens, privkeyg, txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pkg.begin(), pkg.end()), name, description, { }))); + EXPECT_FALSE(eval.TryAddTx(mtx5)); // must fail + } +} + + +TEST_F(TestAssetsCC, tokenv2create_bad) +{ + struct CCcontract_info *cpTokens, C; + cpTokens = CCinit(&C, TokensV2::EvalCode()); + + eval.SetCurrentHeight(111); //set height + + CMutableTransaction mtx = MakeTokenV2CreateTx(pk1, 10); + ASSERT_FALSE(CTransaction(mtx).IsNull()); + + CAmount txfee = 10000; + std::string name = "T2"; + std::string description = "desc2"; + { + // test: token sent to another pk + CMutableTransaction mtx1(mtx); + mtx1.vout[1] = TokensV2::MakeTokensCC1vout(0, 10, pk2); + mtx1.vout.pop_back(); + ASSERT_TRUE(TestFinalizeTx(mtx1, cpTokens, testKeys[pk1], txfee, + TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); + EXPECT_TRUE(eval.TryAddTx(mtx1)); // allow sending created tokens to any pk!! } { // test: invalid pk in opreturn: @@ -2288,7 +2771,7 @@ TEST_F(TestAssetsCC, tokenv2create) mtx2.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx2, cpTokens, testKeys[pk1], txfee, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk2.begin(), pk2.end()), name, description, { }))); - EXPECT_FALSE(TestRunCCEval(mtx2)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx2)); // must fail } { // test: no token vouts, sent to normal @@ -2297,7 +2780,7 @@ TEST_F(TestAssetsCC, tokenv2create) mtx3.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx3, cpTokens, testKeys[pk1], txfee, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); - EXPECT_FALSE(TestRunCCEval(mtx3)); // fail for no token cc vouts + EXPECT_FALSE(eval.TryAddTx(mtx3)); // fail for no token cc vouts } { // test: no token vouts, sent to cc v1 @@ -2306,7 +2789,7 @@ TEST_F(TestAssetsCC, tokenv2create) mtx4.vout.pop_back(); ASSERT_TRUE(TestFinalizeTx(mtx4, cpTokens, testKeys[pk1], txfee, TokensV2::EncodeTokenCreateOpRet(vscript_t(pk1.begin(), pk1.end()), name, description, { }))); - EXPECT_FALSE(TestRunCCEval(mtx4)); // fail for no token cc vouts + EXPECT_FALSE(eval.TryAddTx(mtx4)); // fail for no token cc vouts } { // test: invalid token created with global pk: @@ -2322,8 +2805,154 @@ TEST_F(TestAssetsCC, tokenv2create) ASSERT_TRUE(TestFinalizeTx(mtx5, cpTokens, privkeyg, txfee, TokensV2::EncodeTokenCreateOpRet(vscript_t(pkg.begin(), pkg.end()), name, description, { }))); - EXPECT_FALSE(TestRunCCEval(mtx5)); // must fail + EXPECT_FALSE(eval.TryAddTx(mtx5)); // must fail + } +} + +TEST_F(TestAssetsCC, tokenv2transfer) +{ + struct CCcontract_info *cpTokens, C; + cpTokens = CCinit(&C, TokensV2::EvalCode()); + CAmount crAmount = 10, trAmount = 1; + uint8_t M_1 = 1; + + + eval.SetCurrentHeight(111); //set height + + CMutableTransaction mtxCreate = MakeTokenV2CreateTx(pk1, crAmount); + ASSERT_FALSE(CTransaction(mtxCreate).IsNull()); + EXPECT_TRUE(eval.AddTx(mtxCreate)); + uint256 mytokenid = mtxCreate.GetHash(); + + CScript opret; + CMutableTransaction mtxTransfer = BeginTokenV2TransferTx(pk1); + ASSERT_FALSE(CTransaction(mtxTransfer).IsNull()); + ASSERT_TRUE(AddTokenV2TransferOutputs(cpTokens, mtxTransfer, pk1, mytokenid, "", {}, M_1, {pk2}, trAmount, true, opret)); + ASSERT_TRUE(FinalizeTokenV2TransferTx(cpTokens, mtxTransfer, pk1, opret)); + EXPECT_TRUE(eval.AddTx(mtxTransfer)); + + EXPECT_TRUE(TokenV2Balance(pk1, mytokenid) == crAmount - trAmount); + EXPECT_TRUE(TokenV2Balance(pk2, mytokenid) == trAmount); +} + +TEST_F(TestAssetsCC, tokenv2transfermany) +{ + uint8_t M_1 = 1; + eval.SetCurrentHeight(111); //set height + + CAmount values[][3] = { { 1, 1, 1 }, { 100, 2, 2 } }; + + for (int i = 0; i < sizeof(values)/sizeof(values[0]); i ++) + { + CAmount crAmount = values[i][0]; + CAmount trAmount = values[i][1]; + int32_t splitOutputs = values[i][2]; + for (const auto skipInputs : { false, true }) + { + for(const auto corruptChange : { 0LL, 1LL, -1LL }) + { + for (const auto useOpReturn : { false, true }) // try 1) both vouts opdrop and 2) one opdrop, second opreturn + { + CMutableTransaction mtxCreate1 = MakeTokenV2CreateTx(pk1, crAmount); + ASSERT_FALSE(CTransaction(mtxCreate1).IsNull()); + EXPECT_TRUE(eval.AddTx(mtxCreate1)); + + CMutableTransaction mtxCreate2 = MakeTokenV2CreateTx(pk1, crAmount); + ASSERT_FALSE(CTransaction(mtxCreate2).IsNull()); + EXPECT_TRUE(eval.AddTx(mtxCreate2)); + + uint256 mytokenid1 = mtxCreate1.GetHash(); + uint256 mytokenid2 = mtxCreate2.GetHash(); + + CScript opret1; + struct CCcontract_info *cpTokens1, C1; + cpTokens1 = CCinit(&C1, TokensV2::EvalCode()); + CMutableTransaction mtxTransfer1 = BeginTokenV2TransferTx(pk1); + ASSERT_FALSE(CTransaction(mtxTransfer1).IsNull()); + ASSERT_TRUE(AddTokenV2TransferOutputs(cpTokens1, mtxTransfer1, pk1, mytokenid1, "", {}, M_1, {pk2}, trAmount, false, opret1)); + ASSERT_TRUE(AddTokenV2TransferOutputs(cpTokens1, mtxTransfer1, pk1, mytokenid2, "", {}, M_1, {pk2}, trAmount, useOpReturn, opret1, false, 0LL, splitOutputs)); + ASSERT_TRUE(FinalizeTokenV2TransferTx(cpTokens1, mtxTransfer1, pk1, opret1)); + EXPECT_TRUE(eval.AddTx(mtxTransfer1)); + + EXPECT_TRUE(TokenV2Balance(pk1, mytokenid1) == crAmount - trAmount); + EXPECT_TRUE(TokenV2Balance(pk2, mytokenid1) == trAmount); + EXPECT_TRUE(TokenV2Balance(pk1, mytokenid2) == crAmount - trAmount); + EXPECT_TRUE(TokenV2Balance(pk2, mytokenid2) == trAmount); + + // transfer back: + CScript opret2; + struct CCcontract_info *cpTokens2, C2; + cpTokens2 = CCinit(&C2, TokensV2::EvalCode()); + CMutableTransaction mtxTransfer2 = BeginTokenV2TransferTx(pk2); + ASSERT_FALSE(CTransaction(mtxTransfer2).IsNull()); + ASSERT_TRUE(AddTokenV2TransferOutputs(cpTokens2, mtxTransfer2, pk2, mytokenid1, "", {}, M_1, {pk1}, trAmount, false, opret2)); + ASSERT_TRUE(AddTokenV2TransferOutputs(cpTokens2, mtxTransfer2, pk2, mytokenid2, "", {}, M_1, {pk1}, trAmount, useOpReturn, opret2, skipInputs, corruptChange)); + ASSERT_TRUE(FinalizeTokenV2TransferTx(cpTokens2, mtxTransfer2, pk2, opret2)); + + if (skipInputs || corruptChange != 0LL) { + EXPECT_FALSE(eval.AddTx(mtxTransfer2)); + continue; // invalid tx, continue... + } + else + EXPECT_TRUE(eval.AddTx(mtxTransfer2)); + + EXPECT_TRUE(TokenV2Balance(pk1, mytokenid1) == crAmount); + EXPECT_TRUE(TokenV2Balance(pk2, mytokenid1) == 0); + EXPECT_TRUE(TokenV2Balance(pk1, mytokenid2) == crAmount); + EXPECT_TRUE(TokenV2Balance(pk2, mytokenid2) == 0); + } + } + } } } +// test transfer to R-address +TEST_F(TestAssetsCC, tokenv2transfer_raddress) +{ + struct CCcontract_info *cpTokens, C; + cpTokens = CCinit(&C, TokensV2::EvalCode()); + + eval.SetCurrentHeight(111); + + UniValue tokeldata(UniValue::VOBJ); + tokeldata.pushKV("id", 1); // add nft extra data as burning tokens works only if there is extra data in tokencreate + CMutableTransaction mcreatetx = MakeTokenV2CreateTx(pk1, 1, tokeldata); + ASSERT_FALSE(CTransaction(mcreatetx).IsNull()); + EXPECT_TRUE(eval.AddTx(mcreatetx)); + uint256 tokenid = mcreatetx.GetHash(); + + std::vector dests = { pk2 }; + + std::vector tokenaddrs = GetTokenV2IndexKeys(pk1); + CMutableTransaction mtransfertx = MakeTokenV2TransferTx(pk1, 0, tokenid, tokenaddrs, {}, 1, dests, 1, false, false); + ASSERT_FALSE(CTransaction(mtransfertx).IsNull()); + EXPECT_TRUE(eval.AddTx(mtransfertx)); + CAmount bal = TokenV2Balance(pk2, tokenid); + // std::cerr << __func__ << " TokenV2Balance(pk2, tokenid)=" << bal << " mtransfertxid=" << mtransfertx.GetHash().GetHex() << " reason=" << eval.state.GetRejectReason() << std::endl; + EXPECT_TRUE(bal == 1); +} + +// test burn pk +TEST_F(TestAssetsCC, tokenv2burn) +{ + struct CCcontract_info *cpTokens, C; + cpTokens = CCinit(&C, TokensV2::EvalCode()); + + eval.SetCurrentHeight(111); + + UniValue tokeldata(UniValue::VOBJ); + tokeldata.pushKV("id", 1); + CMutableTransaction mcreatetx = MakeTokenV2CreateTx(pk1, 1, tokeldata); // burning tokens works only if there is extra data in tokencreate + ASSERT_FALSE(CTransaction(mcreatetx).IsNull()); + EXPECT_TRUE(eval.AddTx(mcreatetx)); + uint256 tokenid = mcreatetx.GetHash(); + + std::vector dests = { pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED)) }; + + std::vector tokenaddrs = GetTokenV2IndexKeys(pk1); + CMutableTransaction mburntx = MakeTokenV2TransferTx(pk1, 0, tokenid, tokenaddrs, {}, 1, dests, 1, false, true); + ASSERT_FALSE(CTransaction(mburntx).IsNull()); + EXPECT_TRUE(eval.TryAddTx(mburntx)); +} + } /* namespace CCAssetsTests */ From 35a432227a6f2cf90361914d213188fed51faffa Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 15 May 2022 15:24:13 +0500 Subject: [PATCH 282/348] reset TKLTEST2 activation height --- src/cc/CCupgrades.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index 7b455806885..43390a36cb8 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -34,7 +34,7 @@ namespace CCUpgrades { const int32_t CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT = 100000000; // TBD const int32_t CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT = 100000000; // TBD const int32_t CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT = 100000000; // TBD - const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 87400; // approx 15 May 2022 11:00a.m. UTC + const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 89940; // approx 17 May 2022 10:00a.m. UTC // latest protocol version: const int CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION = 170010; // pre-upgrade protocol version: From 8aa484af0e6bf4b441e1706c8cfd379057f5c539 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 17 May 2022 17:31:47 +0500 Subject: [PATCH 283/348] fixed services literal suffix (build on windows error) --- src/protocol.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/protocol.h b/src/protocol.h index b730cb73cf6..cd480e10bb4 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -85,15 +85,15 @@ enum : uint64_t { // NODE_NETWORK means that the node is capable of serving the block chain. It is currently // set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want // network services but don't provide them. - NODE_NETWORK = (1UL << 0), + NODE_NETWORK = (1ULL << 0), // NODE_BLOOM means the node is capable and willing to handle bloom-filtered connections. // Zcash nodes used to support this by default, without advertising this bit, // but no longer do as of protocol version 170004 (= NO_BLOOM_VERSION) - NODE_BLOOM = (1UL << 2), + NODE_BLOOM = (1ULL << 2), - NODE_NSPV = (1UL << 30), - NODE_ADDRINDEX = (1UL << 29), - NODE_SPENTINDEX = (1UL << 28), + NODE_NSPV = (1ULL << 30), + NODE_ADDRINDEX = (1ULL << 29), + NODE_SPENTINDEX = (1ULL << 28), // Bits 24-31 are reserved for temporary experiments. Just pick a bit that // isn't getting used, or one not being used much, and notify the @@ -103,8 +103,8 @@ enum : uint64_t { // do not actually support. Other service bits should be allocated via the // BIP process. - NODE_WEBSOCKETS = (1UL << 31), // nspv listening on websockets - NODE_WEBSOCKETS_TLS = (1UL << 32) // websockets tls + NODE_WEBSOCKETS = (1ULL << 31), // nspv listening on websockets + NODE_WEBSOCKETS_TLS = (1ULL << 32) // websockets tls }; /** A CService with information about it as peer */ From 8fac876763d19a171b35f42253654cbc479b58c0 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 17 May 2022 21:48:31 +0500 Subject: [PATCH 284/348] fix boost build with glibc 2.34 on Linux platforms https://github.com/KomodoPlatform/komodo/pull/532 --- depends/packages/boost.mk | 3 +++ depends/patches/boost/commit-74fb0a2.patch | 19 ++++++++++++++++ depends/patches/boost/commit-f9d0e59.patch | 26 ++++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 depends/patches/boost/commit-74fb0a2.patch create mode 100644 depends/patches/boost/commit-f9d0e59.patch diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 3981e98d203..ee8ccb269e7 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -4,6 +4,7 @@ $(package)_version=1_72_0 $(package)_download_path=https://github.com/KomodoPlatform/boost/releases/download/boost-1.72.0-kmd $(package)_sha256_hash=59c9b274bc451cf91a9ba1dd2c7fdcaf5d60b1b3aa83f2c9fa143417cc660722 $(package)_file_name=$(package)_$($(package)_version).tar.bz2 +$(package)_patches=commit-74fb0a2.patch commit-f9d0e59.patch define $(package)_set_vars $(package)_config_opts_release=variant=release @@ -27,6 +28,8 @@ endef define $(package)_preprocess_cmds + patch -p2 -i $($(package)_patch_dir)/commit-74fb0a2.patch && \ + patch -p2 -i $($(package)_patch_dir)/commit-f9d0e59.patch && \ echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cxxflags) $($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$(boost_archiver_$(host_os))\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;" > user-config.jam endef diff --git a/depends/patches/boost/commit-74fb0a2.patch b/depends/patches/boost/commit-74fb0a2.patch new file mode 100644 index 00000000000..4efe81fb00e --- /dev/null +++ b/depends/patches/boost/commit-74fb0a2.patch @@ -0,0 +1,19 @@ +From 74fb0a26099bc51d717f5f154b37231ce7df3e98 Mon Sep 17 00:00:00 2001 +From: Rob Boehne +Date: Wed, 20 Nov 2019 11:25:20 -0600 +Subject: Revert change to elide a warning that caused Solaris builds to fail. + + +diff --git a/include/boost/thread/pthread/thread_data.hpp b/include/boost/thread/pthread/thread_data.hpp +index aefbeb43..bc9b1367 100644 +--- a/include/boost/thread/pthread/thread_data.hpp ++++ b/include/boost/thread/pthread/thread_data.hpp +@@ -57,7 +57,7 @@ namespace boost + #else + std::size_t page_size = ::sysconf( _SC_PAGESIZE); + #endif +-#if PTHREAD_STACK_MIN > 0 ++#ifdef PTHREAD_STACK_MIN + if (size +Date: Tue, 10 Aug 2021 14:22:28 +0000 +Subject: Fix -Wsign-compare warning with glibc 2.34 on Linux platforms. + +In file included from /data/mwrep/res/osp/Boost/21-0-0-0/include/boost/thread/thread_only.hpp:17, + from /data/mwrep/res/osp/Boost/21-0-0-0/include/boost/thread/thread.hpp:12, + from src/GetTest.cpp:12: +/data/mwrep/res/osp/Boost/21-0-0-0/include/boost/thread/pthread/thread_data.hpp: In member function 'void boost::thread_attributes::set_stack_size(std::size_t)': +/data/mwrep/res/osp/Boost/21-0-0-0/include/boost/thread/pthread/thread_data.hpp:61:19: error: comparison of integer expressions of different signedness: 'std::size_t' {aka 'long unsigned int'} and 'long int' [-Werror=sign-compare] + 61 | if (size(PTHREAD_STACK_MIN)) size=PTHREAD_STACK_MIN; + #endif + size = ((size+page_size-1)/page_size)*page_size; + int res = pthread_attr_setstacksize(&val_, size); \ No newline at end of file From 50b795d12cd29e9b88c8d3264630d244dc27d608 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 17 May 2022 21:49:39 +0500 Subject: [PATCH 285/348] fix cJSON* pointer compare with int --- src/komodo_bitcoind.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 8226a76080c..ac8ad798f53 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -519,7 +519,7 @@ int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t { if ( (json= cJSON_Parse(jsonstr)) != 0 ) { - if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) > 0 ) + if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) != 0 ) { vout = jitem(vouts,n-1); if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) From b814ec5f69627f2f653d484eedc3b9913fcb720d Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 20 May 2022 22:40:09 +0500 Subject: [PATCH 286/348] added timestamp activation option to CCUpgrades (added test June 2022 timestamp for TOKEL) --- src/cc/CCassetsCore_impl.h | 2 +- src/cc/CCinclude.h | 4 +- src/cc/CCtokens_impl.h | 6 +- src/cc/CCupgrades.cpp | 51 ++++++++++++----- src/cc/CCupgrades.h | 36 +++++++----- src/cc/assets.cpp | 8 +-- src/cc/eval.cpp | 8 ++- src/cc/eval.h | 8 ++- src/cc/import.cpp | 2 +- src/coins.cpp | 4 +- src/importcoin.cpp | 4 +- src/importcoin.h | 2 +- src/komodo_websockets.cpp | 17 +++++- src/komodo_websockets.h | 18 ++++-- src/main.cpp | 67 +++++++++++++++-------- src/main.h | 22 +++++--- src/miner.cpp | 8 +-- src/rpc/tokensrpc.cpp | 6 +- src/script/serverchecker.cpp | 2 +- src/script/serverchecker.h | 5 +- src/test-komodo/test_coinimport.cpp | 4 +- src/test-komodo/test_cryptoconditions.cpp | 2 +- src/test-komodo/test_eval_bet.cpp | 2 +- src/test/coins_tests.cpp | 4 +- src/txmempool.cpp | 5 +- 25 files changed, 197 insertions(+), 100 deletions(-) diff --git a/src/cc/CCassetsCore_impl.h b/src/cc/CCassetsCore_impl.h index 6c5efc1d559..d84fc786cff 100644 --- a/src/cc/CCassetsCore_impl.h +++ b/src/cc/CCassetsCore_impl.h @@ -304,7 +304,7 @@ bool AssetsValidateTokenId(Eval *eval, struct CCcontract_info *cp, const CTransa template bool AssetsValidateTokenId_Activated(Eval *eval, struct CCcontract_info *cpTokens, const CTransaction &tx, int32_t v, uint256 assetid) { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_ASSETS_OPDROP_VALIDATE_FIX)) + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentTime(), eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_ASSETS_OPDROP_VALIDATE_FIX)) return AssetsValidateTokenId(eval, cpTokens, tx, v, assetid); else return true; diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 4ff0a0ef68f..d8c43ebce64 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -1070,11 +1070,11 @@ inline UniValue MakeResultSuccess(const std::string &txhex) { /// returns burn pubkey list /// @param height current height at which some new pubkeys are activated -inline std::vector GetBurnPubKeys(int32_t nHeight) +inline std::vector GetBurnPubKeys(int32_t nTime, int32_t nHeight) { std::vector vDeadPubkeys; vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); - if (CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) + if (CCUpgrades::IsUpgradeActive(nTime, nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) vDeadPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY_FIXED))); // activate new burn pubkey return vDeadPubkeys; } diff --git a/src/cc/CCtokens_impl.h b/src/cc/CCtokens_impl.h index be2f917b22d..dee742aca2e 100644 --- a/src/cc/CCtokens_impl.h +++ b/src/cc/CCtokens_impl.h @@ -404,7 +404,7 @@ UniValue TokenTransferExtDest(const CPubKey &remotepk, CAmount txfee, uint256 to if (CCchange != 0) { if (V::EvalCode() == EVAL_TOKENSV2 && - CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) { + CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetMedianTimePast(), chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) { mtx.vout.push_back(V::MakeTokensCCMofNDestVout(V::EvalCode(), 0, CCchange, 1, {mypk.GetID()})); // send change to R-address after the HF } else @@ -914,7 +914,7 @@ static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 uint8_t evalCode = V::EvalCode(); // if both payloads are empty maybe it is a transfer to non-payload-one-eval-token vout like GatewaysClaim uint8_t evalCode2 = 0; // will be checked if zero or not - const bool isSubver1 = CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1); + const bool isSubver1 = CCUpgrades::IsUpgradeActive(eval->GetCurrentTime(), eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1); // test vouts for possible token use-cases: std::vector> testVouts; @@ -950,7 +950,7 @@ static CAmount HasBurnedTokensvouts(Eval *eval, const CTransaction& tx, uint256 evalCode2 = 0; } - std::vector vDeadPubkeys = GetBurnPubKeys(eval->GetCurrentHeight()); + std::vector vDeadPubkeys = GetBurnPubKeys(eval->GetCurrentTime(), eval->GetCurrentHeight()); CAmount burnedAmount = 0; diff --git a/src/cc/CCupgrades.cpp b/src/cc/CCupgrades.cpp index df3ebf9751c..473c73c5c0f 100644 --- a/src/cc/CCupgrades.cpp +++ b/src/cc/CCupgrades.cpp @@ -15,47 +15,51 @@ #include #include +#include "script/standard.h" #include "CCupgrades.h" namespace CCUpgrades { class CUpgradesContainer { - private: - + public: + // init protocol version for a chain if non-default void init(const std::string &chainName, int nProtocolVersion) { assert(mChainUpgrades.find(chainName) == mChainUpgrades.end()); // mChainUpgrades[chainName] must be empty - mChainUpgrades[chainName].setActivationHeight(CCUPGID_ASSETS_INITIAL_CHAIN, 0, UPGRADE_ACTIVE, nProtocolVersion); + mChainUpgrades[chainName].setActivationPoint(CCUPGID_ASSETS_INITIAL_CHAIN, 0LL, UPGRADE_ACTIVE, nProtocolVersion); } - void addUpgradeActive(const std::string &chainName, UPGRADE_ID upgradeId, int32_t nHeight, int nProtocolVersion) + // for a chain add time or height activation point and new protocol version + void addUpgradeActive(const std::string &chainName, UPGRADE_ID upgradeId, int64_t nTimeOrHeight, int nProtocolVersion) { assert(mChainUpgrades.find(chainName) != mChainUpgrades.end()); // mChainUpgrades[chainName] must be initialised - mChainUpgrades[chainName].setActivationHeight(upgradeId, nHeight, UPGRADE_ACTIVE, nProtocolVersion); + mChainUpgrades[chainName].setActivationPoint(upgradeId, nTimeOrHeight, UPGRADE_ACTIVE, nProtocolVersion); } public: CUpgradesContainer() { - // default upgrades: always enable all fixes + // init a chain if you plan to upgrade it init("TOKEL", CCOLDDEFAULT_PROTOCOL_VERSION); init("TKLTEST", CCOLDDEFAULT_PROTOCOL_VERSION); init("DIMXY24", CCOLDDEFAULT_PROTOCOL_VERSION); init("DIMXY28", CCOLDDEFAULT_PROTOCOL_VERSION); init("TKLTEST2", CCOLDDEFAULT_PROTOCOL_VERSION); init("DIMXY32", CCOLDDEFAULT_PROTOCOL_VERSION); + init("DIMXY33", CCOLDDEFAULT_PROTOCOL_VERSION); // CCUPGID_ASSETS_OPDROP_VALIDATE_FIX activation addUpgradeActive("TOKEL", CCUPGID_ASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TOKEL_HEIGHT, CCOLDDEFAULT_PROTOCOL_VERSION); addUpgradeActive("TKLTEST", CCUPGID_ASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT, CCOLDDEFAULT_PROTOCOL_VERSION); // CCUPGID_MIXEDMODE_SUBVER_1 activation - addUpgradeActive("TOKEL", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("TOKEL", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); // bound to S6 NN HF addUpgradeActive("TKLTEST", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); addUpgradeActive("DIMXY24", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); addUpgradeActive("DIMXY28", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); addUpgradeActive("DIMXY32", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); addUpgradeActive("TKLTEST2", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + addUpgradeActive("DIMXY33", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY33_TIMESTAMP, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); // add more chains here... // ... @@ -84,27 +88,46 @@ namespace CCUpgrades { return *pSelectedUpgrades; } + void InitUpgrade(const std::string &chainName, int nProtocolVersion) + { + ccChainsUpgrades.init(chainName, nProtocolVersion); + } - bool IsUpgradeActive(int32_t nHeight, const ChainUpgrades &chainUpgrades, UPGRADE_ID id) { + void AddUpgradeActive(const std::string &chainName, UPGRADE_ID upgradeId, int64_t nTimeOrHeight, int nProtocolVersion) + { + ccChainsUpgrades.addUpgradeActive(chainName, upgradeId, nTimeOrHeight, nProtocolVersion); + } + + bool IsUpgradeActive(int64_t nTime, int32_t nHeight, const ChainUpgrades &chainUpgrades, UPGRADE_ID id) { if (chainUpgrades.mUpgrades.size() == 0) return chainUpgrades.defaultUpgrade.status == UPGRADE_ACTIVE; else { std::map::const_iterator it = chainUpgrades.mUpgrades.find(id); - if (it != chainUpgrades.mUpgrades.end()) - return nHeight >= it->second.nActivationHeight ? it->second.status == UPGRADE_ACTIVE : false; + if (it != chainUpgrades.mUpgrades.end()) { + if (it->second.nActivationPoint >= LOCKTIME_THRESHOLD) // time + return nTime >= it->second.nActivationPoint ? it->second.status == UPGRADE_ACTIVE : false; + else // height + return nHeight >= it->second.nActivationPoint ? it->second.status == UPGRADE_ACTIVE : false; + } return false; } } - UpgradeInfo GetCurrentUpgradeInfo(int32_t nHeight, const ChainUpgrades &chainUpgrades) + // get latest upgrade for current height or time + UpgradeInfo GetCurrentUpgradeInfo(int64_t nTime, int32_t nHeight, const ChainUpgrades &chainUpgrades) { if (chainUpgrades.mUpgrades.size() == 0) return chainUpgrades.defaultUpgrade; else { UpgradeInfo current = chainUpgrades.mUpgrades.find(CCUPGID_ASSETS_INITIAL_CHAIN)->second; // set as initial chain info - for (auto const & it : chainUpgrades.mUpgrades) { - if (nHeight >= it.second.nActivationHeight) - current = it.second; // find latest active upgrade + for (auto const & upgr : chainUpgrades.mUpgrades) { // upgrades are ordered + if (upgr.second.nActivationPoint >= LOCKTIME_THRESHOLD) { // time + if (nTime >= upgr.second.nActivationPoint) + current = upgr.second; // find latest active upgrade + } else { // height + if (nHeight >= upgr.second.nActivationPoint) + current = upgr.second; // find latest active upgrade + } } return current; } diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index 43390a36cb8..c74264effba 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -26,15 +26,17 @@ namespace CCUpgrades { // asset chain activation heights - const int32_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 286359; // 26 Nov + 90 days - const int32_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 243159; // 26 Nov + 60 days + const int64_t CCASSETS_OPDROP_FIX_TOKEL_HEIGHT = 286359; // 26 Nov + 90 days + const int64_t CCASSETS_OPDROP_FIX_TKLTEST_HEIGHT = 243159; // 26 Nov + 60 days + + const int64_t CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT = 100000000; // TBD + const int64_t CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT = 100000000; // TBD + const int64_t CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT = 100000000; // TBD + const int64_t CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT = 100000000; // TBD + const int64_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 89940; // approx 17 May 2022 10:00a.m. UTC + const int64_t CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP = 1655212904; // test 14 June 2022, to be actualised + const int64_t CCMIXEDMODE_SUBVER_1_DIMXY33_TIMESTAMP = 1653064202; // test HF 20 May 2022 - const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT = 100000000; // TBD - const int32_t CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT = 100000000; // TBD - const int32_t CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT = 100000000; // TBD - const int32_t CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT = 100000000; // TBD - const int32_t CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT = 100000000; // TBD - const int32_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 89940; // approx 17 May 2022 10:00a.m. UTC // latest protocol version: const int CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION = 170010; // pre-upgrade protocol version: @@ -52,7 +54,7 @@ namespace CCUpgrades { }; struct UpgradeInfo { - int32_t nActivationHeight; + int64_t nActivationPoint; UPGRADE_STATUS status; int nProtocolVersion; // used for disconnecting old nodes }; @@ -60,8 +62,8 @@ namespace CCUpgrades { class ChainUpgrades { public: ChainUpgrades() : defaultUpgrade({0, UPGRADE_ACTIVE, CCNEWCHAIN_PROTOCOL_VERSION}) { } - void setActivationHeight(UPGRADE_ID upgId, int32_t nHeight, UPGRADE_STATUS upgStatus, int nProtocolVersion) { - mUpgrades[upgId] = { nHeight, upgStatus, nProtocolVersion }; + void setActivationPoint(UPGRADE_ID upgId, int64_t nTimeOrHeight, UPGRADE_STATUS upgStatus, int nProtocolVersion) { + mUpgrades[upgId] = { nTimeOrHeight, upgStatus, nProtocolVersion }; } public: @@ -69,10 +71,18 @@ namespace CCUpgrades { const UpgradeInfo defaultUpgrade; }; + /** init a protocol version for a chain (if it will be upgraded) */ + void InitUpgrade(const std::string &chainName, int nProtocolVersion); + /** for a chain add an upgrade activation point and new protocol version */ + void AddUpgradeActive(const std::string &chainName, UPGRADE_ID upgradeId, int64_t nTimeOrHeight, int nProtocolVersion); + /** select upgrades for a chain */ void SelectUpgrades(const std::string &chainName); + /** get selected upgrades */ const ChainUpgrades &GetUpgrades(); - bool IsUpgradeActive(int32_t nHeight, const ChainUpgrades &chainUpgrades, UPGRADE_ID upgId); - UpgradeInfo GetCurrentUpgradeInfo(int32_t nHeight, const ChainUpgrades &chainUpgrades); + /** check if an upgrade is active for selected upgrades */ + bool IsUpgradeActive(int64_t nTime, int32_t nHeight, const ChainUpgrades &chainUpgrades, UPGRADE_ID upgId); + /** get currently active upgrade for selected upgrades */ + UpgradeInfo GetCurrentUpgradeInfo(int64_t nTime, int32_t nHeight, const ChainUpgrades &chainUpgrades); }; // namespace CCUpgrades diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 6930bda129b..ad23f894bcd 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -364,7 +364,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // check if royalty or paid_value is not dust if (royaltyFract > 0) { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentTime(), eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { // old bad calc: // incorrect use of vin_coins to calculate royalty (this is true only for nfts) CAmount royaltyValue = royaltyFract > 0 ? vin_coins / TKLROYALTY_DIVISOR * royaltyFract : 0; @@ -448,7 +448,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const return eval->Invalid("vout2 invalid royalty detination for fillask"); } else { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentTime(), eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) { // validate that the paid value to go to the token owner if amount to seller is dust if (royaltyFract > 0 && r == 0 && !isRoyaltyDust) { // there is royalty dust and royalty is not dust --> send to token owner @@ -581,7 +581,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const // check if royalty or paid_value is not dust if (royaltyFract > 0) { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentTime(), eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { // old bad calc: only if royalty<=50% works bcz of loss of significance bcz of division by royaltyFract first. // also wrong assumption that paid_value is subtracted by the royalty (in fact it is sum of both if the royalty is dust) // suppose the nValue is such that the royalty_value is assets' dust: @@ -610,7 +610,7 @@ static bool AssetsValidateInternal(struct CCcontract_info *cp, Eval* eval,const else if (!AssetsValidateTokenId_Activated(eval, cp, tx, 1, assetid)) return eval->Invalid("invalid tokenid in vout1 for fillask"); else { - if (CCUpgrades::IsUpgradeActive(eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { + if (CCUpgrades::IsUpgradeActive(eval->GetCurrentTime(), eval->GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { if (!A::ConstrainVout(tx.vout[2], NORMALVOUT, origNormalAddr, 0LL, 0)) // coins to originator normal addr return eval->Invalid("vout2 should be cc for fillask"); } diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 908584a3e33..50f3d54b026 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -34,9 +34,10 @@ Eval* EVAL_TEST = 0; struct CCcontract_info CCinfos[0x100]; extern pthread_mutex_t KOMODO_CC_mutex; -bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, int32_t nHeight, std::shared_ptr evalcodeChecker) +bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, int64_t nTime, int32_t nHeight, std::shared_ptr evalcodeChecker) { EvalRef eval; + eval->SetCurrentTime(nTime); eval->SetCurrentHeight(nHeight); pthread_mutex_lock(&KOMODO_CC_mutex); bool out = eval->Dispatch(cond, tx, nIn, evalcodeChecker); @@ -151,6 +152,11 @@ bool Eval::GetTxConfirmed(const uint256 &hash, CTransaction &txOut, CBlockIndex return true; } +int64_t Eval::GetCurrentTime() const +{ + return nCurrentTime; +} + unsigned int Eval::GetCurrentHeight() const { return nCurrentHeight; diff --git a/src/cc/eval.h b/src/cc/eval.h index ee4a06a69fe..5d5672d9047 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -79,7 +79,7 @@ class CCheckCCEvalCodes; class Eval { public: - Eval() : nCurrentHeight(0) {} + Eval() : nCurrentTime(0LL), nCurrentHeight(0) {} CValidationState state; bool Invalid(std::string s) { return state.Invalid(false, 0, s); } @@ -111,6 +111,8 @@ class Eval */ virtual bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const; virtual bool GetTxConfirmed(const uint256 &hash, CTransaction &txOut, CBlockIndex &block) const; + virtual int64_t GetCurrentTime() const; + void SetCurrentTime(int64_t nTimeIn) { nCurrentTime = nTimeIn; } virtual unsigned int GetCurrentHeight() const; void SetCurrentHeight(int32_t nHeightIn) { nCurrentHeight = nHeightIn; } virtual bool GetSpendsConfirmed(uint256 hash, std::vector &spends) const; @@ -122,8 +124,8 @@ class Eval virtual std::string GetAssetchainsSymbol() const; private: + int64_t nCurrentTime; int32_t nCurrentHeight; - }; @@ -144,7 +146,7 @@ class EvalRef : public EvalRef_ -bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, int32_t nHeight, std::shared_ptr evalcodeChecker); +bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, int64_t nTime, int32_t nHeight, std::shared_ptr evalcodeChecker); /* diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 92f088c60de..a8117275f7b 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -548,7 +548,7 @@ bool CheckMigration(Eval *eval, const CTransaction &importTx, const CTransaction if (!hasTokenVin) return eval->Invalid("burn-tx-has-no-token-vins"); - std::vector vDeadPubkeys = GetBurnPubKeys(eval->GetCurrentHeight()); + std::vector vDeadPubkeys = GetBurnPubKeys(eval->GetCurrentTime(), eval->GetCurrentHeight()); // calc outputs for burn tx CAmount ccBurnOutputs = 0; diff --git a/src/coins.cpp b/src/coins.cpp index 57363c8bc39..1c404ef5954 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -596,14 +596,14 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTr if ( interestp != 0 ) *interestp = 0; if ( tx.IsCoinImport() ) - return GetCoinImportValue(tx, nHeight); + return GetCoinImportValue(tx, tiptime, nHeight); if ( tx.IsCoinBase() != 0 ) return 0; for (unsigned int i = 0; i < tx.vin.size(); i++) { if (tx.IsPegsImport() && i==0) { - nResult = GetCoinImportValue(tx, nHeight); + nResult = GetCoinImportValue(tx, tiptime, nHeight); continue; } value = GetOutputFor(tx.vin[i]).nValue; diff --git a/src/importcoin.cpp b/src/importcoin.cpp index b81f2fc887d..0ad7f295c4d 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -314,7 +314,7 @@ bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &pegstxid,uint256 &tokeni /* * Required by main */ -CAmount GetCoinImportValue(const CTransaction &tx, int32_t nHeight) +CAmount GetCoinImportValue(const CTransaction &tx, int64_t nTime, int32_t nHeight) { ImportProof proof; CTransaction burnTx; std::vector payouts; bool isNewImportTx = false; @@ -346,7 +346,7 @@ CAmount GetCoinImportValue(const CTransaction &tx, int32_t nHeight) nonfungibleEvalCode = vnonfungibleOpret.begin()[0]; - std::vector vDeadPubkeys = GetBurnPubKeys(nHeight); + std::vector vDeadPubkeys = GetBurnPubKeys(nTime, nHeight); // calc outputs for burn tx diff --git a/src/importcoin.h b/src/importcoin.h index 690fe118e87..79672934f8c 100644 --- a/src/importcoin.h +++ b/src/importcoin.h @@ -92,7 +92,7 @@ class ImportProof { -CAmount GetCoinImportValue(const CTransaction &tx, int32_t nHeight); +CAmount GetCoinImportValue(const CTransaction &tx, int64_t nTime, int32_t nHeight); CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride = 0); CTransaction MakePegsImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride = 0); diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index adecfa4fe8d..5dd3d0a7f2c 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -81,11 +81,20 @@ int GetHeight() { LOCK(cs_main); CBlockIndex* pindex; - if ((pindex = chainActive.LastTip()) != 0) + if ((pindex = chainActive.LastTip()) != nullptr) return pindex->GetHeight(); else return 0; } +int64_t GetTipTime() +{ + LOCK(cs_main); + CBlockIndex* pindex; + if ((pindex = chainActive.LastTip()) != nullptr) + return pindex->nTime; + else + return 0; +} CAddress GetLocalWebSocketAddress(const CNetAddr *paddrPeer) { @@ -285,13 +294,15 @@ bool ProcessWsMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, return false; }*/ + const int64_t nTipTime = GetTipTime(); + const int nHeight = GetHeight(); // check min cc version - if (nVersion < GetCurrentUpgradeInfo(GetHeight(), CCUpgrades::GetUpgrades()).nProtocolVersion) + if (nVersion < GetCurrentUpgradeInfo(nTipTime, nHeight, CCUpgrades::GetUpgrades()).nProtocolVersion) { LogPrint("websockets", "wspeer=%d using obsolete version %i; disconnecting by ccupgrades\n", pfrom->id, nVersion); pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", - GetCurrentUpgradeInfo(GetHeight(), CCUpgrades::GetUpgrades()).nProtocolVersion)); + GetCurrentUpgradeInfo(nTipTime, nHeight, CCUpgrades::GetUpgrades()).nProtocolVersion)); pfrom->fDisconnect = true; return true; } diff --git a/src/komodo_websockets.h b/src/komodo_websockets.h index f2256e730f8..30945ac5ed7 100644 --- a/src/komodo_websockets.h +++ b/src/komodo_websockets.h @@ -1,7 +1,17 @@ - -// Copyright (c) 2020 The SuperNet developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2022 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. * + * * + ******************************************************************************/ #ifndef __KOMODO_WEBSOCKETS_H__ #define __KOMODO_WEBSOCKETS_H__ diff --git a/src/main.cpp b/src/main.cpp index 3ded0af23f6..d1e037eb1af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -355,9 +355,18 @@ namespace { int GetHeight() { CBlockIndex *pindex; - if ( (pindex= chainActive.LastTip()) != 0 ) + if ( (pindex= chainActive.LastTip()) != nullptr ) return pindex->GetHeight(); - else return(0); + else + return(0); + } + int64_t GetTipTime() + { + CBlockIndex *pindex; + if ( (pindex= chainActive.LastTip()) != nullptr ) + return pindex->nTime; + else + return(0); } void UpdatePreferredDownload(CNode* node, CNodeState* state) @@ -2083,7 +2092,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // This is done last to help prevent CPU exhaustion denial-of-service attacks. PrecomputedTransactionData txdata(tx); std::shared_ptr evalcodeChecker(new CCheckCCEvalCodes()); - if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, chainActive.LastTip()->GetHeight() + 1, evalcodeChecker)) + if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, GetTime(), chainActive.LastTip()->GetHeight() + 1, evalcodeChecker)) // we can use GetTime() here, does not make big difference as this time is used to activate HF code for txns in mempool { //fprintf(stderr,"accept failure.9\n"); LogPrint("mempool-tx", "%s ConnectInputs failed for tx %s\n", __func__, HexStr(E_MARSHAL(ss << tx)).c_str()); @@ -2107,14 +2116,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } //fprintf(stderr,"addmempool 7\n"); - if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, chainActive.LastTip()->GetHeight() + 1, evalcodeChecker)) + if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, GetTime(), chainActive.LastTip()->GetHeight() + 1, evalcodeChecker)) { if (flag != 0) KOMODO_CONNECTING = -1; return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString()); } - if (!ContextualCheckOutputs(tx, state, true, txdata, chainActive.LastTip()->GetHeight() + 1, evalcodeChecker)) + if (!ContextualCheckOutputs(tx, state, true, txdata, GetTime(), chainActive.LastTip()->GetHeight() + 1, evalcodeChecker)) return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ContextualCheckOutputs failed %s", hash.ToString()); if (flag != 0) KOMODO_CONNECTING = -1; @@ -2799,13 +2808,13 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { if (vout != 0) { //check cc output - ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, nHeight, evalcodeChecker, *txdata); + ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, nTime, nHeight, evalcodeChecker, *txdata); if (checker.CheckCryptoConditionSpk(scriptPubKey.GetCCV2SPK(), &error) != 1) { return ::error("CScriptCheck(): %s:%d CC output validation failed: %s", ptxTo->GetHash().ToString(), n, ScriptErrorString(error)); } } else { // check cc input const CScript& scriptSig = ptxTo->vin[n].scriptSig; - ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, nHeight, evalcodeChecker, *txdata); + ServerTransactionSignatureChecker checker(ptxTo, n, amount, cacheStore, nTime, nHeight, evalcodeChecker, *txdata); if (!VerifyScript(scriptSig, scriptPubKey, nFlags, checker, consensusBranchId, &error)) { return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), n, ScriptErrorString(error)); } @@ -2813,15 +2822,25 @@ bool CScriptCheck::operator()() return true; } -int GetSpendHeight(const CCoinsViewCache& inputs) +int GetSpendHeight(const CCoinsViewCache& inputs) // dimxy why inputs? { LOCK(cs_main); CBlockIndex* pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second; return pindexPrev->GetHeight() + 1; } +/// @author dimxy +/// get estimated next block time (assuming it would be a spending block) +/// this value would be used for timestamp-activating HF code in coins cache code +int64_t GetSpendTime(const CCoinsViewCache& coins) +{ + LOCK(cs_main); + CBlockIndex* pindexPrev = mapBlockIndex.find(coins.GetBestBlock())->second; + return pindexPrev->GetMedianTimePast(); +} + namespace Consensus { - bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams) + bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, int64_t nSpendTime, const Consensus::Params& consensusParams) { // This doesn't trigger the DoS code on purpose; if it did, it would make it easier // for an attacker to attempt to split the network. @@ -2836,7 +2855,7 @@ namespace Consensus { { if (tx.IsPegsImport() && i==0) { - nValueIn=GetCoinImportValue(tx, nSpendHeight); + nValueIn=GetCoinImportValue(tx, nSpendTime, nSpendHeight); continue; } const COutPoint &prevout = tx.vin[i].prevout; @@ -2930,13 +2949,14 @@ bool ContextualCheckInputs( PrecomputedTransactionData& txdata, const Consensus::Params& consensusParams, uint32_t consensusBranchId, + int64_t nTime, int32_t nHeight, std::shared_ptr evalcodeChecker, std::vector *pvChecks) { if (!tx.IsMint()) { - if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs), consensusParams)) { + if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs), GetSpendTime(inputs), consensusParams)) { return false; } @@ -2958,7 +2978,7 @@ bool ContextualCheckInputs( assert(coins); // Verify signature - CScriptCheck check(*coins, tx, i, flags, cacheStore, consensusBranchId, nHeight, evalcodeChecker, &txdata); + CScriptCheck check(*coins, tx, i, flags, cacheStore, consensusBranchId, nTime, nHeight, evalcodeChecker, &txdata); if (pvChecks) { pvChecks->push_back(CScriptCheck()); check.swap(pvChecks->back()); @@ -2971,7 +2991,7 @@ bool ContextualCheckInputs( // avoid splitting the network between upgraded and // non-upgraded nodes. CScriptCheck check2(*coins, tx, i, - flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, consensusBranchId, nHeight, evalcodeChecker, &txdata); + flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, consensusBranchId, nTime, nHeight, evalcodeChecker, &txdata); if (check2()) return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); } @@ -2991,7 +3011,7 @@ bool ContextualCheckInputs( if (tx.IsCoinImport() || tx.IsPegsImport()) { LOCK(cs_main); - ServerTransactionSignatureChecker checker(&tx, 0, 0, false, nHeight, NULL, txdata); + ServerTransactionSignatureChecker checker(&tx, 0, 0, false, nTime, nHeight, NULL, txdata); return VerifyCoinImport(tx.vin[0].scriptSig, checker, state); } @@ -3003,6 +3023,7 @@ bool ContextualCheckOutputs( CValidationState &state, bool fScriptChecks, PrecomputedTransactionData& txdata, + int64_t nTime, int32_t nHeight, std::shared_ptr evalcodeChecker, std::vector *pvChecks) @@ -3019,11 +3040,11 @@ bool ContextualCheckOutputs( { // check if secp256hash and eval param in action: int subversion = CC_MixedModeSubVersion(tx.vout[i].scriptPubKey[0]); - if (subversion >= CC_MIXED_MODE_SECHASH_SUBVER_1 && !CCUpgrades::IsUpgradeActive(nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) + if (subversion >= CC_MIXED_MODE_SECHASH_SUBVER_1 && !CCUpgrades::IsUpgradeActive(nTime, nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) { return state.DoS(100,false, REJECT_INVALID, std::string("cc v2 subversion 1 or more not yet enabled")); } - CScriptCheck check(tx.vout[i].scriptPubKey, tx.vout[i].nValue, tx, i, nHeight, evalcodeChecker, &txdata); + CScriptCheck check(tx.vout[i].scriptPubKey, tx.vout[i].nValue, tx, i, nTime, nHeight, evalcodeChecker, &txdata); if (pvChecks) { pvChecks->push_back(CScriptCheck()); @@ -3867,13 +3888,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin //fprintf(stderr, "tx.%s nFees.%li interest.%li\n", tx.GetHash().ToString().c_str(), stakeTxValue, interest); std::vector vChecks; - if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, pindex->GetHeight(), evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) + if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, pindex->GetBlockTime(), pindex->GetHeight(), evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) return false; } { // check tx outputs including coinbases std::vector vChecks; - if (!ContextualCheckOutputs(tx, state, fExpensiveChecks, txdata[i], pindex->GetHeight(), evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) + if (!ContextualCheckOutputs(tx, state, fExpensiveChecks, txdata[i], pindex->GetBlockTime(), pindex->GetHeight(), evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) return false; control.Add(vChecks); } @@ -7575,9 +7596,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return false; } + const int64_t nTipTime = GetTipTime(); + const int nHeight = GetHeight(); // Reject incoming connections from nodes that don't know about the current epoch const Consensus::Params& params = Params().GetConsensus(); - auto currentEpoch = CurrentEpoch(GetHeight(), params); + auto currentEpoch = CurrentEpoch(nHeight, params); if (nVersion < params.vUpgrades[currentEpoch].nProtocolVersion) { LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, nVersion); @@ -7589,12 +7612,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // check min cc version - if (nVersion < GetCurrentUpgradeInfo(GetHeight(), CCUpgrades::GetUpgrades()).nProtocolVersion) + if (nVersion < GetCurrentUpgradeInfo(nTipTime, nHeight, CCUpgrades::GetUpgrades()).nProtocolVersion) { - LogPrintf("peer=%d using obsolete version %i, needed %d; disconnecting by ccupgrades\n", pfrom->id, nVersion, GetCurrentUpgradeInfo(GetHeight(), CCUpgrades::GetUpgrades()).nProtocolVersion); + LogPrintf("peer=%d using obsolete version %i, needed %d; disconnecting by ccupgrades\n", pfrom->id, nVersion, GetCurrentUpgradeInfo(nTipTime, nHeight, CCUpgrades::GetUpgrades()).nProtocolVersion); pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", - GetCurrentUpgradeInfo(GetHeight(), CCUpgrades::GetUpgrades()).nProtocolVersion)); + GetCurrentUpgradeInfo(nTipTime, nHeight, CCUpgrades::GetUpgrades()).nProtocolVersion)); pfrom->fDisconnect = true; return false; } diff --git a/src/main.h b/src/main.h index 02e55bf5714..a4a52ae671d 100644 --- a/src/main.h +++ b/src/main.h @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2022 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -741,6 +741,7 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons PrecomputedTransactionData& txdata, const Consensus::Params& consensusParams, uint32_t consensusBranchId, + int64_t nTime, int32_t nHeight, std::shared_ptr evalcodeChecker, std::vector *pvChecks = NULL); @@ -749,6 +750,7 @@ bool ContextualCheckOutputs( CValidationState &state, bool fScriptChecks, PrecomputedTransactionData& txdata, + int64_t nTime, int32_t nHeight, std::shared_ptr evalcodeChecker, std::vector *pvChecks = NULL); @@ -778,7 +780,7 @@ namespace Consensus { * This does not modify the UTXO set. This does not check scripts and sigs. * Preconditions: tx.IsCoinBase() is false. */ -bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams); +bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, int64_t nSpendTime, const Consensus::Params& consensusParams); } // namespace Consensus @@ -817,6 +819,7 @@ class CScriptCheck unsigned int nFlags; bool cacheStore; uint32_t consensusBranchId; + int64_t nTime; int32_t nHeight; ScriptError error; PrecomputedTransactionData *txdata; @@ -824,12 +827,12 @@ class CScriptCheck bool vout; public: - CScriptCheck(): amount(0), ptxTo(0), n(0), nFlags(0), cacheStore(false), consensusBranchId(0), nHeight(0), error(SCRIPT_ERR_UNKNOWN_ERROR), vout(false) {} - CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nIn, unsigned int nFlagsIn, bool cacheIn, uint32_t consensusBranchIdIn, int32_t nHeightIn, std::shared_ptr evalcodeCheckerIn,PrecomputedTransactionData* txdataIn) : + CScriptCheck(): amount(0), ptxTo(0), n(0), nFlags(0), cacheStore(false), consensusBranchId(0), nTime(0LL), nHeight(0), error(SCRIPT_ERR_UNKNOWN_ERROR), vout(false) {} + CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nIn, unsigned int nFlagsIn, bool cacheIn, uint32_t consensusBranchIdIn, int32_t nTimeIn, int32_t nHeightIn, std::shared_ptr evalcodeCheckerIn,PrecomputedTransactionData* txdataIn) : scriptPubKey(CCoinsViewCache::GetSpendFor(&txFromIn, txToIn.vin[nIn])), amount(txFromIn.vout[txToIn.vin[nIn].prevout.n].nValue), - ptxTo(&txToIn), n(nIn), nFlags(nFlagsIn), cacheStore(cacheIn), consensusBranchId(consensusBranchIdIn), nHeight(nHeightIn), error(SCRIPT_ERR_UNKNOWN_ERROR), evalcodeChecker(evalcodeCheckerIn),txdata(txdataIn), vout(false) { } - CScriptCheck(const CScript& scriptPubKeyIn, const CAmount& amountIn, const CTransaction& txToIn, unsigned int nIn, int32_t nHeightIn, std::shared_ptr evalcodeCheckerIn,PrecomputedTransactionData* txdataIn) : - scriptPubKey(scriptPubKeyIn), amount(amountIn), ptxTo(&txToIn), n(nIn), nFlags(0), cacheStore(false), consensusBranchId(0), nHeight(nHeightIn), + ptxTo(&txToIn), n(nIn), nFlags(nFlagsIn), cacheStore(cacheIn), consensusBranchId(consensusBranchIdIn), nTime(nTimeIn), nHeight(nHeightIn), error(SCRIPT_ERR_UNKNOWN_ERROR), evalcodeChecker(evalcodeCheckerIn),txdata(txdataIn), vout(false) { } + CScriptCheck(const CScript& scriptPubKeyIn, const CAmount& amountIn, const CTransaction& txToIn, unsigned int nIn, int32_t nTimeIn, int32_t nHeightIn, std::shared_ptr evalcodeCheckerIn,PrecomputedTransactionData* txdataIn) : + scriptPubKey(scriptPubKeyIn), amount(amountIn), ptxTo(&txToIn), n(nIn), nFlags(0), cacheStore(false), consensusBranchId(0), nTime(nTimeIn), nHeight(nHeightIn), error(SCRIPT_ERR_UNKNOWN_ERROR), evalcodeChecker(evalcodeCheckerIn), txdata(txdataIn), vout(true) { } bool operator()(); @@ -841,6 +844,7 @@ class CScriptCheck std::swap(nFlags, check.nFlags); std::swap(cacheStore, check.cacheStore); std::swap(consensusBranchId, check.consensusBranchId); + std::swap(nTime, check.nTime); std::swap(nHeight, check.nHeight); std::swap(error, check.error); std::swap(txdata, check.txdata); @@ -1002,6 +1006,10 @@ extern CBlockTreeDB *pblocktree; */ int GetSpendHeight(const CCoinsViewCache& inputs); +/** get next block time for coins */ +int64_t GetSpendTime(const CCoinsViewCache& coins); + + uint64_t CalculateCurrentUsage(); /** Return a CMutableTransaction with contextual default values based on set of consensus rules at height */ diff --git a/src/miner.cpp b/src/miner.cpp index 1cc7d4ac187..fc64e480152 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -321,7 +321,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 std::vector TMP_NotarisationNotaries; if (tx.IsCoinImport()) { - CAmount nValueIn = GetCoinImportValue(tx, nHeight); // burn amount + CAmount nValueIn = GetCoinImportValue(tx, pblock->nTime, nHeight); // burn amount nTotalIn += nValueIn; dPriority += (double)nValueIn * 1000; // flat multiplier... max = 1e16. } else { @@ -334,7 +334,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 { if (tx.IsPegsImport() && txin.prevout.n==10e8) { - CAmount nValueIn = GetCoinImportValue(tx, nHeight); // burn amount + CAmount nValueIn = GetCoinImportValue(tx, pblock->nTime, nHeight); // burn amount nTotalIn += nValueIn; dPriority += (double)nValueIn * 1000; // flat multiplier... max = 1e16. continue; @@ -565,8 +565,8 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 // create only contains transactions that are valid in new blocks. CValidationState state; PrecomputedTransactionData txdata(tx); - std::shared_ptr evalcodeChecker(new CCheckCCEvalCodes()); - if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, nHeight, evalcodeChecker)) + std::shared_ptr evalcodeChecker(new CCheckCCEvalCodes()); // evalcodeChecker pblock->nTime, nHeight are not used as no cc checks are performed (only MANDATORY_SCRIPT_VERIFY_FLAGS) + if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId, pblock->nTime, nHeight, evalcodeChecker)) { //fprintf(stderr,"context failure\n"); continue; diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 63353384550..f44fd3014b3 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -548,18 +548,20 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b std::vector dests; CTxDestination dest; + const int64_t nTime = GetTime(); + const int32_t nHeight = chainActive.LastTip()->GetHeight() + 1; vuint8_t vpubkey(ParseHex(params[1].get_str())); if (vpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE && CPubKey(vpubkey).IsValid()) dest = CPubKey(vpubkey); else dest = DecodeDestination(params[1].get_str()); - if (dest.which() == TX_PUBKEYHASH && !CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) + if (dest.which() == TX_PUBKEYHASH && !CCUpgrades::IsUpgradeActive(nTime, nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) return MakeResultError("destination as address not active yet"); if (dest.which() != TX_PUBKEYHASH && dest.which() != TX_PUBKEY) return MakeResultError("invalid destination pubkey or address"); // after subver_1 upgrade only addresses always will be used as destination, pubkeys are converted to addresses - if (dest.which() == TX_PUBKEY && CCUpgrades::IsUpgradeActive(chainActive.LastTip()->GetHeight() + 1, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) + if (dest.which() == TX_PUBKEY && CCUpgrades::IsUpgradeActive(nTime, nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) dests.push_back(boost::get(dest).GetID()); else dests.push_back(dest); // address or pubkey diff --git a/src/script/serverchecker.cpp b/src/script/serverchecker.cpp index 6070692c695..99bcbb6b363 100644 --- a/src/script/serverchecker.cpp +++ b/src/script/serverchecker.cpp @@ -119,7 +119,7 @@ bool ServerTransactionSignatureChecker::VerifySignature(const std::vector &condBin, ScriptError *serror) const diff --git a/src/script/serverchecker.h b/src/script/serverchecker.h index f198b8e4d03..c829381ca04 100644 --- a/src/script/serverchecker.h +++ b/src/script/serverchecker.h @@ -33,11 +33,12 @@ class ServerTransactionSignatureChecker : public TransactionSignatureChecker private: bool store; std::shared_ptr evalcodeChecker; + int64_t nTime; int32_t nHeight; public: - ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn, int32_t nHeightIn, std::shared_ptr evalcodeCheckerIn, const PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nIn, amount, txdataIn), store(storeIn), nHeight(nHeightIn), evalcodeChecker(evalcodeCheckerIn) {} - ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nIn, amount), store(storeIn), nHeight(0) {} + ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn, int64_t nTimeIn, int32_t nHeightIn, std::shared_ptr evalcodeCheckerIn, const PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nIn, amount, txdataIn), store(storeIn), nTime(nTimeIn), nHeight(nHeightIn), evalcodeChecker(evalcodeCheckerIn) {} + ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nIn, amount), store(storeIn), nTime(0), nHeight(0) {} bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; int CheckEvalCondition(const CC *cond) const; diff --git a/src/test-komodo/test_coinimport.cpp b/src/test-komodo/test_coinimport.cpp index 9411b721010..9ce2e5f3564 100644 --- a/src/test-komodo/test_coinimport.cpp +++ b/src/test-komodo/test_coinimport.cpp @@ -71,7 +71,7 @@ class TestCoinImport : public ::testing::Test, public Eval { { CTransaction importTx(mtx); PrecomputedTransactionData txdata(importTx); - ServerTransactionSignatureChecker checker(&importTx, 0, 0, false, 1, NULL, txdata); + ServerTransactionSignatureChecker checker(&importTx, 0, 0, false, 0, 1, NULL, txdata); CValidationState verifystate; if (!VerifyCoinImport(importTx.vin[0].scriptSig, checker, verifystate)) printf("TestRunCCEval: %s\n", verifystate.GetRejectReason().data()); @@ -251,7 +251,7 @@ TEST_F(TestCoinImport, DISABLED_testMomomCheckFail) TEST_F(TestCoinImport, testGetCoinImportValue) { - ASSERT_EQ(100, GetCoinImportValue(importTx, 1)); + ASSERT_EQ(100, GetCoinImportValue(importTx, 0, 1)); } } /* namespace TestCoinImport */ diff --git a/src/test-komodo/test_cryptoconditions.cpp b/src/test-komodo/test_cryptoconditions.cpp index 22170844559..c31fb0b4b2e 100644 --- a/src/test-komodo/test_cryptoconditions.cpp +++ b/src/test-komodo/test_cryptoconditions.cpp @@ -88,7 +88,7 @@ static bool CCVerify(const CMutableTransaction &mtxTo, const CC *cond) { ScriptError error; CTransaction txTo(mtxTo); PrecomputedTransactionData txdata(txTo); - auto checker = ServerTransactionSignatureChecker(&txTo, 0, amount, false, 1, NULL, txdata); + auto checker = ServerTransactionSignatureChecker(&txTo, 0, amount, false, 0, 1, NULL, txdata); return VerifyScript(CCSig(cond), CCPubKey(cond), 0, checker, 0, &error); }; diff --git a/src/test-komodo/test_eval_bet.cpp b/src/test-komodo/test_eval_bet.cpp index a9c6fffebc6..7c3830cb5f7 100644 --- a/src/test-komodo/test_eval_bet.cpp +++ b/src/test-komodo/test_eval_bet.cpp @@ -44,7 +44,7 @@ int TestCC(CMutableTransaction &mtxTo, unsigned int nIn, CC *cond) ScriptError error; CTransaction txTo(mtxTo); PrecomputedTransactionData txdata(txTo); - auto checker = ServerTransactionSignatureChecker(&txTo, nIn, amount, false, 1, NULL, txdata); + auto checker = ServerTransactionSignatureChecker(&txTo, nIn, amount, false, 0, 1, NULL, txdata); return VerifyScript(txTo.vin[nIn].scriptSig, CCPubKey(cond), 0, checker, 0, &error); } diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index dc795ad7a7b..10bc48826d9 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -899,7 +899,7 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends) { CTransaction tx2(mtx2); - BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); + BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, 0, Params().GetConsensus())); } mtx2.vout.resize(1); @@ -908,7 +908,7 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends) { CTransaction tx2(mtx2); - BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); + BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, 0, Params().GetConsensus())); BOOST_CHECK(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs"); } } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 8947096e699..e4919cdc4d6 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -768,6 +768,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const CCoinsViewCache mempoolDuplicate(const_cast(pcoins)); const int64_t nSpendHeight = GetSpendHeight(mempoolDuplicate); + const int64_t nSpendTime = GetSpendTime(mempoolDuplicate); LOCK(cs); list waitingOnDependants; @@ -829,7 +830,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const else { CValidationState state; bool fCheckResult = tx.IsCoinBase() || - Consensus::CheckTxInputs(tx, state, mempoolDuplicate, nSpendHeight, Params().GetConsensus()); + Consensus::CheckTxInputs(tx, state, mempoolDuplicate, nSpendHeight, nSpendTime, Params().GetConsensus()); assert(fCheckResult); UpdateCoins(tx, mempoolDuplicate, 1000000); } @@ -845,7 +846,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const assert(stepsSinceLastRemove < waitingOnDependants.size()); } else { bool fCheckResult = entry->GetTx().IsCoinBase() || - Consensus::CheckTxInputs(entry->GetTx(), state, mempoolDuplicate, nSpendHeight, Params().GetConsensus()); + Consensus::CheckTxInputs(entry->GetTx(), state, mempoolDuplicate, nSpendHeight, nSpendTime, Params().GetConsensus()); assert(fCheckResult); UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000); stepsSinceLastRemove = 0; From d5d878049396d981be19e5178d9f1a78620b8388 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 20 May 2022 22:43:53 +0500 Subject: [PATCH 287/348] added default timestamp activation; tests for CCUpgrades to test-assets --- src/test-komodo-cc/test-assets.cpp | 146 ++++++++++++++--------------- 1 file changed, 70 insertions(+), 76 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index d6674619057..b2eed97dd33 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -113,7 +113,7 @@ class EvalMock : public Eval { CTransaction tx(mtx); PrecomputedTransactionData txdata(tx); - ServerTransactionSignatureChecker checker(&tx, 0, 0, false, 0, nullptr, txdata); + ServerTransactionSignatureChecker checker(&tx, 0, 0, false, this->GetCurrentTime(), this->GetCurrentHeight(), nullptr, txdata); CValidationState verifystate; VerifyEval verifyEval = [] (CC *cond, void *checker) { //fprintf(stderr,"checker.%p\n",(TransactionSignatureChecker*)checker); @@ -189,10 +189,10 @@ class EvalMock : public Eval return false; } const std::map & getTxs() { return txs; } - void SetCurrentHeight(int h) - { - currentHeight = h; - } + //void SetCurrentHeight(int h) + //{ + // currentHeight = h; + //} virtual bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const { @@ -207,10 +207,10 @@ class EvalMock : public Eval } return false; } - virtual unsigned int GetCurrentHeight() const - { - return currentHeight; - } + //virtual unsigned int GetCurrentHeight() const + //{ + // return currentHeight; + //} }; @@ -520,57 +520,6 @@ CTxOut TestMakeTokensCCMofNvoutMixed(uint8_t evalcode1, uint8_t evalcode2, CAmou return vout; } - -/*** // run over CC V2 validation - bool TestRunCCEval(const CMutableTransaction &mtx) - { - CTransaction tx(mtx); - PrecomputedTransactionData txdata(tx); - ServerTransactionSignatureChecker checker(&tx, 0, 0, false, eval.GetCurrentHeight(), NULL, txdata); - CValidationState verifystate; - VerifyEval verifyEval = [] (CC *cond, void *checker) { - //fprintf(stderr,"checker.%p\n",(TransactionSignatureChecker*)checker); - return ((TransactionSignatureChecker*)checker)->CheckEvalCondition(cond); - }; - - // set some vars used in validation: - KOMODO_CONNECTING = 1; - KOMODO_CCACTIVATE = 1; - eval.state = CValidationState(); // clear validation state - EVAL_TEST = &eval; - - for(const auto &vin : tx.vin) { - if (IsCCInput(vin.scriptSig)) { - CC *cond = GetCryptoCondition(vin.scriptSig); - if (cond == NULL) { - std::cerr << __func__ << " GetCryptoCondition could not decode vin.scriptSig" << std::endl; - return false; - } - - int r = cc_verifyEval(cond, verifyEval, &checker); - if (r == 0) { - std::cerr << __func__ << " cc_verify error D" << std::endl; - return false; - } - //std::cerr << __func__ << " cc_verify okay for vin.hash=" << vin.prevout.hash.GetHex() << std::endl; - } - } - for(const auto &vout : tx.vout) { - if (vout.scriptPubKey.IsPayToCCV2()) { - - ScriptError error; - - bool bCheck = checker.CheckCryptoConditionSpk(vout.scriptPubKey.GetCCV2SPK(), &error); - if (!bCheck) { - std::cerr << __func__ << " CheckCryptoConditionSpk error=" << ScriptErrorString(error) << " eval=" << eval.state.GetRejectReason() << std::endl; - return false; - } - //std::cerr << __func__ << " cc_verify okay for vout.nValue=" << vout.nValue << std::endl; - } - } - return true; - }*/ - // create mock tx with normal outputs static CTransaction MakeNormalTx(CPubKey mypk, CAmount val) { @@ -716,7 +665,7 @@ static CMutableTransaction MakeTokenV2TransferTx(const CPubKey &mypk, CAmount tx if (CCchange != 0) { if (TokensV2::EvalCode() == EVAL_TOKENSV2 && - CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) { + CCUpgrades::IsUpgradeActive(eval.GetCurrentTime(), eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) { mtx.vout.push_back(TokensV2::MakeTokensCCMofNDestVout(TokensV2::EvalCode(), 0, CCchange, 1, {mypk.GetID()})); // send change to R-address after the HF } else @@ -1011,7 +960,7 @@ static CMutableTransaction MakeTokenV2FillAskTx(struct CCcontract_info *cpAssets bool isRoyaltyDust = true; if (royaltyFract > 0) { - if (CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { + if (CCUpgrades::IsUpgradeActive(eval.GetCurrentTime(), eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1) == false) { // corrected old calculation to allow tx creation and pass to fillask validation code // (note division on TKLROYALTY_DIVISOR first): if(paid_nValue - royaltyValue <= ASSETS_NORMAL_DUST / (int64_t)TKLROYALTY_DIVISOR * royaltyFract - ASSETS_NORMAL_DUST) { // if value paid to seller less than when the royalty is minimum @@ -1412,8 +1361,6 @@ static void CreateMockTransactions() cpTokens = CCinit(&tokensC, TokensV2::EvalCode()); cpAssets = CCinit(&C, AssetsV2::EvalCode()); - eval.SetCurrentHeight(11); - CTransaction txnormal1 = MakeNormalTx(pk1, 200000000); eval.AddGenesisTx(txnormal1); @@ -1472,7 +1419,6 @@ static void CreateMockTransactions() eval.AddTx(txbid3); bidid3 = txbid3.GetHash(); - //CTransaction txbid2 = MakeTokenV2BidTx(pk2, 1000+1, 2, 1000/2, 222); // test dust } @@ -1486,25 +1432,32 @@ class TestAssetsCC : public ::testing::Test { static void SetUpTestCase() { // setup eval for tests ASSETCHAINS_CC = 2; - fDisableCCLogForTests = true; + fDisableCCLogForTests = true; // disable LOGSTREAM prints, enable for tests debug fDebug = false; - fPrintToConsole = true; + fPrintToConsole = true; // enable print to console mapMultiArgs["-debug"] = { "cctokens", "ccassets", "cctokens_test" }; + strcpy(ASSETCHAINS_SYMBOL, ""); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); // select default + eval.SetCurrentHeight(11); // base height for tests + eval.SetCurrentTime(1652932911LL); // base block time for tests CreateMockTransactions(); } + + // called on each test startup virtual void SetUp() { // enable print //fDebug = true; //fPrintToConsole = true; //mapMultiArgs["-debug"] = { "cctokens", "ccassets", "cctokens_test" }; + strcpy(ASSETCHAINS_SYMBOL, ""); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); // select default } + // called on each test finish virtual void TearDown() { // clean up - strcpy(ASSETCHAINS_SYMBOL, ""); - CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); // select default } }; @@ -2182,11 +2135,11 @@ TEST_F(TestAssetsCC, tokenv2fillbid_royalty_fixed) // test old incorrect validation rule that failed royalties > 50% TEST_F(TestAssetsCC, tokenv2fillask_royalty_non_fixed) { - eval.SetCurrentHeight(CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT - 1); + eval.SetCurrentTime(CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP - 1); strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); - ASSERT_FALSE(CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)); + ASSERT_FALSE(CCUpgrades::IsUpgradeActive(eval.GetCurrentTime(), eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)); for(int r = 100; r < 1000; r += 100) { UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FillBidTx @@ -2205,8 +2158,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty_non_fixed) CAmount asktokens = 1; CAmount filltokens = 1; - // CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); - CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, asktokens, price, CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT + 222); + CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, asktokens, price, eval.GetCurrentHeight() + 222); eval.AddTx(mytxask); CMutableTransaction mytxfillask = MakeTokenV2FillAskTx(cpAssets, pk2, mytokenid, mytxask.GetHash(), filltokens, 0, data); @@ -2224,11 +2176,11 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty_non_fixed) // test fill ask updated validation rule TEST_F(TestAssetsCC, tokenv2fillask_royalty_fixed) { - eval.SetCurrentHeight(CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT); + eval.SetCurrentTime(CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP); strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); - ASSERT_TRUE(CCUpgrades::IsUpgradeActive(eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)); // fix in action + ASSERT_TRUE(CCUpgrades::IsUpgradeActive(eval.GetCurrentTime(), eval.GetCurrentHeight(), CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)); // fix in action for(int r = 100; r < 1000; r += 100) { UniValue data(UniValue::VOBJ); // some data returned from MakeTokenV2FilAskTx @@ -2246,7 +2198,7 @@ TEST_F(TestAssetsCC, tokenv2fillask_royalty_fixed) CAmount asktokens = 1; CAmount filltokens = 1; // CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, 1, ASSETS_NORMAL_DUST*2+1, 222); - CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, asktokens, price, CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_HEIGHT + 222); + CTransaction mytxask = MakeTokenV2AskTx(cpTokens, pk1, mytokenid, asktokens, price, eval.GetCurrentHeight() + 222); eval.AddTx(mytxask); CMutableTransaction mytxfillask = MakeTokenV2FillAskTx(cpAssets, pk2, mytokenid, mytxask.GetHash(), filltokens, 0, data); @@ -2955,4 +2907,46 @@ TEST_F(TestAssetsCC, tokenv2burn) EXPECT_TRUE(eval.TryAddTx(mburntx)); } +// test CCupgrade frameworks +TEST_F(TestAssetsCC, ccupgrade_test) +{ + // init for a fictious chain + strcpy(ASSETCHAINS_SYMBOL, "TESTASSETSCHAIN9876543210"); + CCUpgrades::InitUpgrade(ASSETCHAINS_SYMBOL, 170009); + const int32_t nUpg1Height = 111; + const int64_t nUpg2Time = 1652932911LL; // 19 May 2022; + CCUpgrades::AddUpgradeActive(ASSETCHAINS_SYMBOL, CCUpgrades::CCUPGID_ASSETS_OPDROP_VALIDATE_FIX, nUpg1Height, 170010); + CCUpgrades::AddUpgradeActive(ASSETCHAINS_SYMBOL, CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1, nUpg2Time, 170011); + + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); + EXPECT_FALSE(CCUpgrades::IsUpgradeActive(1652932911LL, nUpg1Height-1, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_ASSETS_OPDROP_VALIDATE_FIX)); + EXPECT_TRUE(CCUpgrades::IsUpgradeActive(1652932911LL, nUpg1Height, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_ASSETS_OPDROP_VALIDATE_FIX)); + + EXPECT_FALSE(CCUpgrades::IsUpgradeActive(nUpg2Time-1, nUpg1Height+100, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)); + EXPECT_TRUE(CCUpgrades::IsUpgradeActive(nUpg2Time, nUpg1Height+100, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)); + + EXPECT_EQ(GetCurrentUpgradeInfo(nUpg2Time-1, nUpg1Height-1, CCUpgrades::GetUpgrades()).nProtocolVersion, 170009); + EXPECT_EQ(GetCurrentUpgradeInfo(nUpg2Time-1, nUpg1Height, CCUpgrades::GetUpgrades()).nProtocolVersion, 170010); + EXPECT_EQ(GetCurrentUpgradeInfo(nUpg2Time, nUpg1Height, CCUpgrades::GetUpgrades()).nProtocolVersion, 170011); +} + + +TEST_F(TestAssetsCC, ccupgrade_tokel) +{ + // TOKEL already initialized in CCUpgrades.cpp + strcpy(ASSETCHAINS_SYMBOL, "TOKEL"); + CCUpgrades::SelectUpgrades(ASSETCHAINS_SYMBOL); + + const int64_t nTime = 1652932911LL; // 19 May 2022; + EXPECT_FALSE(CCUpgrades::IsUpgradeActive(nTime, CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT-1, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_ASSETS_OPDROP_VALIDATE_FIX)); + EXPECT_TRUE(CCUpgrades::IsUpgradeActive(nTime, CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_ASSETS_OPDROP_VALIDATE_FIX)); + + EXPECT_FALSE(CCUpgrades::IsUpgradeActive(CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP-1, CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT+100, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)); + EXPECT_TRUE(CCUpgrades::IsUpgradeActive(CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP, CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT+100, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)); + + EXPECT_EQ(GetCurrentUpgradeInfo(nTime, CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT-1, CCUpgrades::GetUpgrades()).nProtocolVersion, CCUpgrades::CCOLDDEFAULT_PROTOCOL_VERSION); + EXPECT_EQ(GetCurrentUpgradeInfo(CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP-1, CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT, CCUpgrades::GetUpgrades()).nProtocolVersion, CCUpgrades::CCOLDDEFAULT_PROTOCOL_VERSION); // we did not change the protocol ver at this moment yet + EXPECT_EQ(GetCurrentUpgradeInfo(CCUpgrades::CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP, CCUpgrades::CCASSETS_OPDROP_FIX_TOKEL_HEIGHT+1, CCUpgrades::GetUpgrades()).nProtocolVersion, CCUpgrades::CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); +} + } /* namespace CCAssetsTests */ From 918db2c764cbc4e82e23236636372d725a2f88da Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 30 May 2022 14:40:43 +0500 Subject: [PATCH 288/348] improved conditions to json encoding: for anon cond_type used instead of asn_type and no subtypes for simple conds, no url char replacement in base64 by default; trace code removed --- .../include/cryptoconditions.h | 1 + src/cryptoconditions/src/anon.c | 48 ++++++++++++------- src/cryptoconditions/src/cryptoconditions.c | 10 ++-- src/cryptoconditions/src/internal.h | 2 + src/cryptoconditions/src/secp256k1hash.c | 2 +- src/cryptoconditions/src/threshold.c | 18 +++---- src/cryptoconditions/src/utils.c | 39 ++++++++++----- 7 files changed, 75 insertions(+), 45 deletions(-) diff --git a/src/cryptoconditions/include/cryptoconditions.h b/src/cryptoconditions/include/cryptoconditions.h index 33320dbc567..5f0865cb4e9 100644 --- a/src/cryptoconditions/include/cryptoconditions.h +++ b/src/cryptoconditions/include/cryptoconditions.h @@ -121,6 +121,7 @@ int cc_isAnon(const CC *cond); struct CC* cc_anon(const CC *cond); void cc_free(struct CC *cond); struct CC* cc_copy(const CC *cond); +int cc_hasSubtypes(enum CCTypeId cctypeid); #ifdef __cplusplus } diff --git a/src/cryptoconditions/src/anon.c b/src/cryptoconditions/src/anon.c index 196f420e361..b6b4c15dec1 100644 --- a/src/cryptoconditions/src/anon.c +++ b/src/cryptoconditions/src/anon.c @@ -36,7 +36,7 @@ CC* cc_anon(const CC *cond) { return out; } - +// assumes the root condition is a threshold CC *mkAnon(const Condition_t *asnCond) { CCType *realType = getTypeByAsnEnum(asnCond->present); @@ -46,7 +46,7 @@ CC *mkAnon(const Condition_t *asnCond) { } CC *cond = cc_new(CC_Anon); cond->conditionType = realType; - const CompoundSha256Condition_t *deets = &asnCond->choice.thresholdSha256; + const CompoundSha256Condition_t *deets = &asnCond->choice.thresholdSha256; // assumes CompoundSha256Condition_t and SimpleSha256Condition_t are same for fingerprint and cost memcpy(cond->fingerprint, deets->fingerprint.buf, 32); cond->cost = deets->cost; if (realType->getSubtypes) { @@ -73,25 +73,34 @@ static CC* anonFromJSON(const cJSON *params, char *err) { strcpy(err, "cost must be a number"); return NULL; } - cJSON *subtypes_item = cJSON_GetObjectItem(params, "subtypes"); - if (!cJSON_IsNumber(subtypes_item)) { - strcpy(err, "subtypes must be a number"); + + /* it was not good to use asnType as it is just an internal utility var: + cJSON *asnType_item = cJSON_GetObjectItem(params, "asnType"); */ + cJSON *condType_item = cJSON_GetObjectItem(params, "cond_type"); + if (!cJSON_IsNumber(condType_item)) { + strcpy(err, "cond_type must be a number"); return NULL; } - CCType *realType = NULL; - cJSON *asnType_item = cJSON_GetObjectItem(params, "asnType"); - if (asnType_item) { - if (!cJSON_IsNumber(asnType_item)) { - strcpy(err, "asnType must be a number"); - return NULL; - } - realType = getTypeByAsnEnum(asnType_item->valueint); + if (condType_item->valueint < 0 || condType_item->valueint >= CCTypeRegistryLength) { + strcpy(err, "cond_type invalid"); + return NULL; } + CCType * realType = CCTypeRegistry[condType_item->valueint]; + CC* cond=cc_new(CC_Anon); memcpy(cond->fingerprint,fing,len); cond->cost = (long) cost_item->valuedouble; - cond->subtypes = subtypes_item->valueint; + cond->subtypes = 0; cond->conditionType = realType; + + if (cc_hasSubtypes(realType->typeId)) { + cJSON *subtypes_item = cJSON_GetObjectItem(params, "subtypes"); + if (!cJSON_IsNumber(subtypes_item)) { + strcpy(err, "subtypes must be a number"); + return NULL; + } + cond->subtypes = subtypes_item->valueint; + } return cond; } @@ -100,8 +109,15 @@ static void anonToJSON(const CC *cond, cJSON *params) { cJSON_AddItemToObject(params, "fingerprint", cJSON_CreateString(b64)); free(b64); cJSON_AddItemToObject(params, "cost", cJSON_CreateNumber(cond->cost)); - cJSON_AddItemToObject(params, "subtypes", cJSON_CreateNumber(cond->subtypes)); - cJSON_AddItemToObject(params, "asnType", cJSON_CreateNumber((int)cond->conditionType->asnType)); + if (cc_hasSubtypes(cc_typeId(cond))) + cJSON_AddItemToObject(params, "subtypes", cJSON_CreateNumber(cond->subtypes)); + + // cJSON_AddItemToObject(params, "asnType", cJSON_CreateNumber((int)cond->conditionType->asnType)); + // this was not good as asnType is not stored into any cc asn1 encoding, + // it is just an internal variable for indexing in the asn_MBR_Condition_1 array: + // better to use a persistent conditionType, + // the same field is used in the rust cryptocondition lib: + cJSON_AddItemToObject(params, "cond_type", cJSON_CreateNumber((int) cc_typeId(cond))); } diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index be0d5c3df0f..fe27e0e9a01 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -67,7 +67,7 @@ char *cc_conditionUri(const CC *cond) { unsigned char *fp = calloc(1, 32); cond->type->fingerprint(cond, fp); - unsigned char *encoded = base64_encode(fp, 32); + unsigned char *encoded = base64_encode_url_safe(fp, 32); unsigned char *out = calloc(1, 1000); sprintf(out, "ni:///sha-256;%s?fpt=%s&cost=%lu",encoded, cc_typeName(cond), cc_getCost(cond)); @@ -154,7 +154,7 @@ void asnCondition(const CC *cond, Condition_t *asn) { // Fixed previous implementation as it was treating every asn as thresholdSha256 type and it was memory leaking // because SimpleSha256Condition_t types do not have subtypes so it couldn't free it in the end. - int typeId = cond->type->typeId; + // int typeId = cond->type->typeId; if (asn->present==Condition_PR_thresholdSha256 || asn->present==Condition_PR_prefixSha256) { CompoundSha256Condition_t* sequence = asn->present == Condition_PR_thresholdSha256 ? &asn->choice.thresholdSha256 : &asn->choice.prefixSha256; @@ -194,8 +194,6 @@ Condition_t *asnConditionNew(const CC *cond) { Fulfillment_t *asnFulfillmentNew(const CC *cond, FulfillmentFlags flags) { - //printf("%s type ptr %p\n", __func__, cond->type); - //printf("%s type %d\n", __func__, cond->type->typeId); return cond->type->toFulfillment(cond, flags); } @@ -375,3 +373,7 @@ CC* cc_copy(const CC *cond) { CCcopy=cond->type->copy(cond); return (CCcopy); } + +int cc_hasSubtypes(enum CCTypeId cctypeid) { + return (cctypeid == CC_Threshold || cctypeid == CC_Prefix) ? 1 : 0; +} diff --git a/src/cryptoconditions/src/internal.h b/src/cryptoconditions/src/internal.h index 649ef547cf4..dcb0e4f19f3 100644 --- a/src/cryptoconditions/src/internal.h +++ b/src/cryptoconditions/src/internal.h @@ -85,6 +85,8 @@ struct CCType *getTypeByAsnEnum(Condition_PR present); */ unsigned char *base64_encode(const unsigned char *data, size_t input_length); unsigned char *base64_decode(const unsigned char *data_, size_t *output_length); +unsigned char *base64_encode_url_safe(const unsigned char *data, size_t input_length); +unsigned char *base64_decode_url_safe(const unsigned char *data_, size_t *output_length); void hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp, uint8_t* out); void dumpStr(unsigned char *str, size_t len); int checkString(const cJSON *value, char *key, char *err); diff --git a/src/cryptoconditions/src/secp256k1hash.c b/src/cryptoconditions/src/secp256k1hash.c index 6b94d76b8bf..b5e54d73f75 100644 --- a/src/cryptoconditions/src/secp256k1hash.c +++ b/src/cryptoconditions/src/secp256k1hash.c @@ -259,7 +259,7 @@ static CC *secp256k1hashFromJSON(const cJSON *params, char *err) { size_t pkSize, sigSize; // try get pk - jsonGetHex(params, "publicKey", err, &pk, &pkSize); + jsonGetHexOptional(params, "publicKey", err, &pk, &pkSize); // try get sig jsonGetHexOptional(params, "signature", err, &sig, &sigSize); if (sig && SECP256K1_SIG_SIZE != sigSize) { diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 79a477ca42a..a7bc78b6834 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -134,7 +134,7 @@ static CC *thresholdFromFulfillmentMixed(const Fulfillment_t *ffill) { if (nffills == 0) { free(cond); - fprintf(stderr, "%s nffills == 0\n", __func__); + //fprintf(stderr, "%s nffills == 0\n", __func__); return NULL; } @@ -195,8 +195,8 @@ static CC *thresholdFromFulfillment(const Fulfillment_t *ffill, FulfillmentFlags if (!subconditions[i]) { for (int j=0; jcode = calloc(1, 2); - t->code[0] = cond->threshold; + t->code[0] = cond->threshold; // store threshold value in a special purpose preimage cond t->preimageLength = 1; asn_set_add(&tf->subfulfillments, asnFulfillmentNew(t, flags)); for (int i=0; isize; i++) { CC *sub = cond->subconditions[i]; - //printf("%s sub->type=%d sub->dontFulfill=%d\n", __func__, sub->type->typeId, sub->dontFulfill); if (fulfillment = asnFulfillmentNew(sub, flags)) { - //printf("%s sub->type=%d added as ffill\n", __func__, sub->type->typeId); - asn_set_add(&tf->subfulfillments, fulfillment); + asn_set_add(&tf->subfulfillments, fulfillment); // always first try to add as fulfillment } else { - //printf("%s sub->type=%d added as cond\n", __func__, sub->type->typeId); asn_set_add(&tf->subconditions, asnConditionNew(sub)); } } @@ -239,7 +236,6 @@ static Fulfillment_t *thresholdToFulfillmentMixed(const CC *cond, FulfillmentFla static Fulfillment_t *thresholdToFulfillment(const CC *cond, FulfillmentFlags flags) { - //printf("%s flags & MixedMode %d\n", __func__, (flags & MixedMode)); if (flags & MixedMode) return thresholdToFulfillmentMixed(cond, flags); Fulfillment_t *fulfillment; @@ -256,10 +252,10 @@ static Fulfillment_t *thresholdToFulfillment(const CC *cond, FulfillmentFlags fl for (int i=0; isize; i++) { CC *sub = subconditions[i]; if (needed && !sub->dontFulfill && (fulfillment = asnFulfillmentNew(sub, flags))) { - asn_set_add(&tf->subfulfillments, fulfillment); + asn_set_add(&tf->subfulfillments, fulfillment); // add as a fulfillment for as many as the thershold number needed--; } else { - asn_set_add(&tf->subconditions, asnConditionNew(sub)); + asn_set_add(&tf->subconditions, asnConditionNew(sub)); // the rest add as anon conds } } diff --git a/src/cryptoconditions/src/utils.c b/src/cryptoconditions/src/utils.c index 0baa88da446..dd07dd9e993 100644 --- a/src/cryptoconditions/src/utils.c +++ b/src/cryptoconditions/src/utils.c @@ -72,17 +72,11 @@ unsigned char *base64_encode(const unsigned char *data, size_t input_length) { // make sure there's a null termination for string protocol encoded_data[output_length] = '\0'; - - // url safe - for (int i=0; i Date: Thu, 2 Jun 2022 18:58:56 +0500 Subject: [PATCH 289/348] added pubkey check in tokenbalance --- src/rpc/tokensrpc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index f44fd3014b3..363d3e36417 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -293,6 +293,7 @@ static UniValue tokenbalance(const std::string& name, const UniValue& params, bo vpubkey = Mypubkey(); CPubKey pk = pubkey2pk(vpubkey); + if (!pk.IsValid()) return MakeResultError("invalid pubkey"); CAmount balance = GetTokenBalance(pk, tokenid, false); if (CCerror.empty()) { From cdb33a9135575e29973befc37fb36ef504a3d029 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 2 Jun 2022 18:59:20 +0500 Subject: [PATCH 290/348] debug log removed --- src/main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d1e037eb1af..949052131a8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7925,7 +7925,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // the getaddr message mitigates the attack. else if ((strCommand == "getaddr") && (pfrom->fInbound)) { - std::cerr << __func__ << " in getaddr, node=" << pfrom->id << std::endl; // Only send one GetAddr response per connection to reduce resource waste // and discourage addr stamping of INV announcements. if (pfrom->fSentAddr) { @@ -7938,7 +7937,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vector vAddr = addrman.GetAddr(); BOOST_FOREACH(const CAddress &addr, vAddr) pfrom->PushAddress(addr); - std::cerr << __func__ << " on getaddr pushed addresses=" << vAddr.size() << " node=" << pfrom->id << std::endl; } // temporary optional nspv message processing else if ((nLocalServices & NODE_NSPV) && From 1bb4835fe87bb6c5471aa8733b4a50fe4ecd9678 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 2 Jun 2022 18:59:49 +0500 Subject: [PATCH 291/348] more space for nspv reqs in rate limiter --- src/net.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.h b/src/net.h index 86fbc5c5f83..3383cdc1990 100644 --- a/src/net.h +++ b/src/net.h @@ -287,7 +287,7 @@ class CNode struct { uint32_t prevtime; uint32_t nreqs; - } nspvdata[16]; + } nspvdata[32]; uint32_t dexlastping; // Address of this peer CAddress addr; From 478c5d6624d01aa3cc66b268ef283a0c23963603 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 2 Jun 2022 19:01:34 +0500 Subject: [PATCH 292/348] added NSPV_TXIDS_V2 request (begin/end ht param); nspv requests documented; deprecated NSPV_MEMPOOL NSPV_CCMODULEUTXOS --- src/komodo_nSPV.h | 2 +- src/komodo_nSPV_defs.h | 211 +++++++++++++++++++++++++++++++----- src/komodo_nSPV_fullnode.h | 74 ++++++++----- src/komodo_nSPV_superlite.h | 14 +-- src/komodo_nSPV_wallet.h | 2 +- 5 files changed, 237 insertions(+), 66 deletions(-) diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index 5c19ce89cbc..377f6012f7d 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -214,7 +214,7 @@ int32_t NSPV_rwtxidresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidresp int32_t len = 0; len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->satoshis),&ptr->satoshis); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->index),&ptr->index); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); return(len); } diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index bd14bde5ddb..7d850644719 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -36,30 +36,153 @@ // nSPV defines and struct definitions with serialization and purge functions +// nSPV request/response message ids: + +// get info request +// params: +// int32 requestHeight - chain height to return info at #define NSPV_INFO 0x00 + +// get info response +// see: NSPV_inforesp struct #define NSPV_INFORESP 0x01 + +// get utxos for an address +// params: +// char coinaddr[KOMODO_ADDRESS_BUFSIZE] address or index key to get utxos from +// int32_t skipcount - how many records to skip +// int32_t maxrecords - max records to return (max is 32767) +// uint8_t isCC = 0; #define NSPV_UTXOS 0x02 + +// get utxos response +// see NSPV_utxosresp struct #define NSPV_UTXOSRESP 0x03 + +// get notarisation transaction id for a height +// params: +// int32_t height - chain height to search a nota for #define NSPV_NTZS 0x04 + +// get notarisation transaction id response +// see NSPV_ntzsresp struct #define NSPV_NTZSRESP 0x05 + +// get notarisation proof for a notarisation txid +// params: +// uint256 ntztxid #define NSPV_NTZSPROOF 0x06 + +// get notarisation proof response +// see NSPV_ntzsproofresp struct #define NSPV_NTZSPROOFRESP 0x07 + +// get transaction proof for a txid +// params +// uint256 txid - txid of a transaction +// int32_t height - ignored +// int32_t vout - returns the output amount for this output index #define NSPV_TXPROOF 0x08 + +// get tx proof response +// see NSPV_txproof struct #define NSPV_TXPROOFRESP 0x09 + +// get spent info for a tx output from spent index +// params: +// int32_t vout - tx output index +// uint256 txid - txid #define NSPV_SPENTINFO 0x0a + +// get spent info response +// see NSPV_spentinfo struct #define NSPV_SPENTINFORESP 0x0b + +// broadcast a transaction +// params: +// uint256 txid - txid of the broadcasted transaction +// int32_t txlen - length of the transaction in bytes +// uint8_t txbin[txlen] - serialised transaction #define NSPV_BROADCAST 0x0c + +// broadcast a transaction response +// see NSPV_broadcastresp #define NSPV_BROADCASTRESP 0x0d + +// get transactions inputs and outputs for an address/index key +// returns spending transactions inputs' txid/index and amount and transactions outputs txid/index and amount +// params: +// char coinaddr[KOMODO_ADDRESS_BUFSIZE] - address or index key to get inputs outputs for +// int32_t skipCount - how many records to skip +// int32_t maxRecords - how many records to return +// uint8_t isCC - is CC (1) or normal (0) address #define NSPV_TXIDS 0x0e + +// get transactions inputs and outputs response +// see NSPV_txidsresp #define NSPV_TXIDSRESP 0x0f + +// get mempool transaction inputs/outputs (deprecated) +// params: +// char coinaddr[KOMODO_ADDRESS_BUFSIZE] - address or index key to get tx for +// int32_t vout - encoded evalcode or funcid (for cc transactions) +// uint256 txid - filter results by txid (may be null) +// uint8_t funcid - filter by funcId in opreturn (for cc ) +// uint8_t isCC - is cc or normal address #define NSPV_MEMPOOL 0x10 + +// get mempool transaction inputs/outputs response +// see NSPV_mempoolresp #define NSPV_MEMPOOLRESP 0x11 + +// get cc utxos by filter (deprecated) +// params: +// char coinaddr[KOMODO_ADDRESS_BUFSIZE] - address or index key to get tx for +// CAmount amount - amount to find utxos for +// uint8_t evalcode - cc module evalcode +// uint8_t funcid[27] - funcids array to filter by funcId in opreturn (for cc ) +// uint256 filtertxid - filter results by txid (may be null) #define NSPV_CCMODULEUTXOS 0x12 + +// get cc utxos by filter response +// see NSPV_utxosresp struct #define NSPV_CCMODULEUTXOSRESP 0x13 + +// call an rpc from enabled list +// param: +// json object with rpc params (can also contain "mypk: parameter if getting tx inputs for this pubkey is requested in the rpc) #define NSPV_REMOTERPC 0x14 + +// call an rpc response +// see NSPV_remoterpcresp struct #define NSPV_REMOTERPCRESP 0x15 + +// reserved +#define NSPV_TRANSACTIONS 0x16 +// reserved +#define NSPV_TRANSACTIONSRESP 0x17 + +// get transactions inputs and outputs for an address/index key (yet another version) +// returns spending transactions inputs' txid/index and amount and transactions outputs txid/index and amount +// params: +// char coinaddr[KOMODO_ADDRESS_BUFSIZE] - address or index key to get inputs outputs for +// int32_t beginHeight - starting height to search txid from +// int32_t endHeight - ending height to search txid up to (inclusive) +// uint8_t isCC - is CC (1) or normal (0) address +#define NSPV_TXIDS_V2 0x18 + +// get transactions inputs and outputs response +// see NSPV_txidsresp +#define NSPV_TXIDSRESP_V2 0x19 + +// error response for an NSPV request +// params: +// int32_t errorId +// string errorDesc - network serialised error description #define NSPV_ERRORRESP 0xff -#define NSPV_MAX_REQ NSPV_REMOTERPC + +#define NSPV_MAX_REQ NSPV_TXIDS_V2 + #define NSPV_MEMPOOL_ALL 0 #define NSPV_MEMPOOL_ADDRESS 1 @@ -77,6 +200,7 @@ #define NSPV_ERROR_INVALID_RESPONSE (-15) #define NSPV_ERROR_BROADCAST (-16) #define NSPV_ERROR_REMOTE_RPC (-17) +#define NSPV_ERROR_DEPRECATED (-18) #define NSPV_MAXREQSPERSEC 15 @@ -92,6 +216,7 @@ UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); extern uint256 SIG_TXHASH; uint32_t NSPV_blocktime(int32_t hdrheight); +// komodo block header struct NSPV_equihdr { int32_t nVersion; @@ -105,38 +230,54 @@ struct NSPV_equihdr uint8_t nSolution[1344]; }; +// utxo data struct NSPV_utxoresp { - uint256 txid; - int64_t satoshis,extradata; - int32_t vout,height; - uint8_t *script; uint64_t script_size; + uint256 txid; // transaction id + int64_t satoshis, // output amount + extradata; // some data impl dependent + int32_t vout, // output index + height; // block height + uint8_t *script; // output script + uint64_t script_size; // output script size }; +// unspent transaction outputs response struct for NSPV_UTXOSRESP struct NSPV_utxosresp { - struct NSPV_utxoresp *utxos; - char coinaddr[64]; - int64_t total,interest; - int32_t nodeheight,skipcount,maxrecords; - uint16_t numutxos, CCflag; + struct NSPV_utxoresp *utxos; // returned utxo array + char coinaddr[64]; // utxo address/index key + int64_t total, // total amount for the utxos + interest; // interest for the amount for KMD chain + int32_t nodeheight, // current height for this node + skipcount, // how many was skipped + maxrecords; // max records used to return + uint16_t numutxos, // number of the returned utxos + CCflag; // is cc (if 1) or normal (if 0) outputs were found }; +// spending input or unspent output data struct NSPV_txidresp { - uint256 txid; - int64_t satoshis; - int32_t vout, height; + uint256 txid; // transaction id + int64_t satoshis; // spent input amount (if negative) or output amount (if positive) + int32_t index; // input/output index + int32_t height; // tx block height }; +// transaction inputs/outputs response struct for NSPV_TXIDSRESP / NSPV_TXIDSRESP_V2 struct NSPV_txidsresp { - struct NSPV_txidresp *txids; + struct NSPV_txidresp *txids; // tx inputs/ouputs array char coinaddr[64]; - int32_t nodeheight, skipcount, maxrecords; - uint16_t numtxids, CCflag; + int32_t nodeheight, + skipcount, + maxrecords; + uint16_t numtxids, + CCflag; }; +// mempool inputs/outputs info for NSPV_MEMPOOLRESP struct NSPV_mempoolresp { uint256 *txids; @@ -146,6 +287,7 @@ struct NSPV_mempoolresp uint16_t numtxids; uint8_t CCflag, funcid; }; +// notarisation tx data for NSPV_INFORESP struct NSPV_ntz { uint256 txid; // notarization txid @@ -159,22 +301,25 @@ struct NSPV_ntz uint32_t timestamp; // timestamp of the notarization tx block }; +// response struct for NSPV_NTZRESP struct NSPV_ntzsresp { struct NSPV_ntz ntz; int32_t reqheight; }; +// response struct for NSPV_INFORESP struct NSPV_inforesp { - struct NSPV_ntz ntz; // last notarisation - uint256 blockhash; // chain tip blockhash - int32_t height; // chain tip height - int32_t hdrheight; // requested block height (it will be the tip height if requested height is 0) - struct NSPV_equihdr H; // requested block header (it will be the tip if requested height is 0) + struct NSPV_ntz ntz; // last notarisation + uint256 blockhash; // chain tip blockhash + int32_t height; // chain tip height + int32_t hdrheight; // requested block height (tip height if the requested height is 0) + struct NSPV_equihdr H; // requested block header (tip if the requested height is 0) uint32_t version; // NSPV protocol version }; +// response struct for NSPV_TXPROOFRESP struct NSPV_txproof { uint256 txid; @@ -184,27 +329,34 @@ struct NSPV_txproof uint256 hashblock; }; +// block headers notarised by a notary tx struct NSPV_ntzproofshared { - struct NSPV_equihdr *hdrs; - int32_t nextht /*, pad32*/; - uint16_t numhdrs /*, pad16*/; + struct NSPV_equihdr *hdrs; // notarised komodo headers (consecutive) + int32_t nextht; // first block height + /* int32_t pad32; */ + uint16_t numhdrs; // headers number + /* uint16_t pad16; */ }; +// response struct for NSPV_NTZSPROOFRESP struct NSPV_ntzsproofresp { - struct NSPV_ntzproofshared common; - uint256 nexttxid; - int32_t nexttxidht, nexttxlen; - uint8_t *nextntz; + struct NSPV_ntzproofshared common; // block headers in the notarisation MoM + uint256 nexttxid; // notarisation txid + int32_t nexttxidht, // notarised block height + nexttxlen; // notarisation tx length + uint8_t *nextntz; // notarisation tx }; +// reserved struct NSPV_MMRproof { struct NSPV_ntzproofshared common; // tbd }; +// response struct for NSPV_SPENTINFORESP struct NSPV_spentinfo { struct NSPV_txproof spent; @@ -212,18 +364,21 @@ struct NSPV_spentinfo int32_t vout,spentvini; }; +// response struct for NSPV_BROADCASTRESP struct NSPV_broadcastresp { uint256 txid; int32_t retcode; }; +// response struct for NSPV_CCMODULEUTXOSRESP struct NSPV_CCmtxinfo { struct NSPV_utxosresp U; struct NSPV_utxoresp used[NSPV_MAXVINS]; }; +// response struct for NSPV_REMOTERPCRESP struct NSPV_remoterpcresp { char method[64]; diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index be08a7b51e9..eb5a3607f14 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -38,6 +38,7 @@ std::map nspvErrors = { { NSPV_ERROR_INVALID_RESPONSE, "could not create response message" }, { NSPV_ERROR_BROADCAST, "could not broadcast transaction" }, { NSPV_ERROR_REMOTE_RPC, "could not execute rpc" }, + { NSPV_ERROR_DEPRECATED, "request deprecated" }, }; static std::map nspv_remote_commands = { @@ -376,7 +377,7 @@ static std::map ccCheckerTable = }; // implements SPV server's part, gets cc module utxos, filtered by evalcode, funcid and txid on opret, for the specified amount -// if the amount param is 0 returns total available filtere utxo amount and returns no utxos +// if the amount param is 0 returns total available filtered utxos amount and returns no utxos // first char funcid in the string param is considered as the creation tx funcid so filtertxid is compared to the creation txid itself // for other funcids filtertxid is compared to the txid in opreturn int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_t amount, uint8_t evalcode, std::string funcids, uint256 filtertxid) @@ -505,18 +506,28 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ } } -int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool isCC, int32_t skipcount, int32_t maxrecords) +int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool isCC, bool isParamsToSkip, int32_t param1, int32_t param2) { int32_t txheight, ind = 0, len = 0; //CTransaction tx; //uint256 hashBlock; - std::vector> txids; - SetAddressIndexOutputs(txids, coinaddr, isCC); - { - LOCK(cs_main); - ptr->nodeheight = chainActive.LastTip()->GetHeight(); + int32_t skipcount = 0; + int32_t maxrecords = 0; + int32_t beginHeight = 0; + int32_t endHeight = 0; + + if (isParamsToSkip) { + skipcount = param1; + maxrecords = param2; + } else { + beginHeight = param1; + endHeight = param2; } + std::vector> txids; + SetAddressIndexOutputs(txids, coinaddr, isCC, beginHeight, endHeight); + std::cerr << __func__ << " isParamsToSkip=" << isParamsToSkip << " beginHeight=" << beginHeight << " endHeight=" << endHeight << std::endl; + // using maxrecords instead: //maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; //maxlen /= sizeof(*ptr->txids); @@ -529,6 +540,10 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is if (skipcount < 0) skipcount = 0; ptr->skipcount = skipcount; + { + LOCK(cs_main); + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + } ptr->txids = nullptr; if (txids.size() >= 0 && skipcount < txids.size()) { @@ -536,7 +551,7 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp* ptr, char* coinaddr, bool is for (std::vector>::const_iterator it = txids.begin() + skipcount; it != txids.end() && ind < maxrecords; it++) { ptr->txids[ind].txid = it->first.txhash; - ptr->txids[ind].vout = (int32_t)it->first.index; + ptr->txids[ind].index = (int32_t)it->first.index; ptr->txids[ind].satoshis = (int64_t)it->second; ptr->txids[ind].height = (int64_t)it->first.blockHeight; @@ -1139,18 +1154,17 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re break; case NSPV_TXIDS: + case NSPV_TXIDS_V2: { struct NSPV_txidsresp T; char coinaddr[KOMODO_ADDRESS_BUFSIZE]; - int32_t skipcount = 0; - int32_t maxrecords = 0; + int32_t param1 = 0; + int32_t param2 = 0; uint8_t isCC = 0; int32_t respEstimated; - //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); - if (requestDataLen < 1) { - LogPrint("nspv", "NSPV_TXIDS bad request too short len.%d, node %d\n", requestDataLen, pfrom->id); + LogPrint("nspv", "NSPV_TXIDS[_V2] bad request too short len.%d, node %d\n", requestDataLen, pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } @@ -1159,40 +1173,39 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re int32_t offset = 1; if (offset + addrlen > requestDataLen || addrlen > sizeof(coinaddr) - 1) // out of bounds { - LogPrint("nspv", "NSPV_TXIDS bad request len.%d too short or addrlen.%d out of bounds, node=%d\n", requestDataLen, addrlen, pfrom->id); + LogPrint("nspv", "NSPV_TXIDS[_V2] bad request len.%d too short or addrlen.%d out of bounds, node=%d\n", requestDataLen, addrlen, pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } memcpy(coinaddr, &requestData[offset], addrlen); - coinaddr[addrlen] = 0; + coinaddr[addrlen] = '\0'; offset += addrlen; if (offset + sizeof(isCC) <= requestDataLen) // TODO: a bit different from others format - allows omitted params, maybe better have fixed { isCC = (requestData[offset] != 0); offset += sizeof(isCC); - if (offset + sizeof(skipcount) <= requestDataLen) { - iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(skipcount), &skipcount); - offset += sizeof(skipcount); - if (offset + sizeof(maxrecords) <= requestDataLen) { - iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(maxrecords), &maxrecords); - offset += sizeof(maxrecords); + if (offset + sizeof(param1) <= requestDataLen) { + iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(param1), ¶m1); + offset += sizeof(param1); + if (offset + sizeof(param2) <= requestDataLen) { + iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(param2), ¶m2); + offset += sizeof(param2); } } } if (offset != requestDataLen) { - LogPrint("nspv", "NSPV_TXIDS bad request parameters format: len.%d, offset.%d, addrlen.%d, node=%d\n", requestDataLen, offset, addrlen, pfrom->id); + LogPrint("nspv", "NSPV_TXIDS[_V2] bad request parameters format: len.%d, offset.%d, addrlen.%d, node=%d\n", requestDataLen, offset, addrlen, pfrom->id); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_REQUEST_DATA); return; } - LogPrint("nspv-details", "NSPV_TXIDS address=%s isCC.%d skipcount.%d maxrecords.%x\n", coinaddr, isCC, skipcount, maxrecords); + LogPrint("nspv-details", "NSPV_TXIDS[_V2] requestType=0x%02x address=%s isCC.%d param1.%d param2.%d\n", (int)requestType, coinaddr, isCC, param1, param2); memset(&T, 0, sizeof(T)); - if ((respEstimated = NSPV_getaddresstxids(&T, coinaddr, isCC, skipcount, maxrecords)) > 0) { - //fprintf(stderr,"respLen.%d\n",respLen); + if ((respEstimated = NSPV_getaddresstxids(&T, coinaddr, isCC, (requestType == NSPV_TXIDS), param1, param2)) > 0) { response.resize(nspvHeaderSize + respEstimated); - response[0] = NSPV_TXIDSRESP; + response[0] = requestType == NSPV_TXIDS ? NSPV_TXIDSRESP : NSPV_TXIDSRESP_V2; memcpy(&response[1], &requestId, sizeof(requestId)); int32_t respWritten = NSPV_rwtxidsresp(IGUANA_WRITE, &response[nspvHeaderSize], &T); if (respWritten > 0 && respWritten <= respEstimated) { @@ -1200,14 +1213,14 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; - LogPrint("nspv-details", "NSPV_TXIDS response: numtxids=%d to node=%d\n", (int)T.numtxids, pfrom->id); + LogPrint("nspv-details", "NSPV_TXIDS[_V2] response: numtxids=%d to node=%d\n", (int)T.numtxids, pfrom->id); } else { - LogPrint("nspv", "NSPV_rwtxidsresp incorrect response written len.%d\n", respWritten); + LogPrint("nspv", "NSPV_TXIDS[_V2] NSPV_rwtxidsresp incorrect response written len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); } NSPV_txidsresp_purge(&T); } else { - LogPrint("nspv", "NSPV_getaddresstxids error.%d\n", respEstimated); + LogPrint("nspv", "NSPV_TXIDS[_V2] NSPV_getaddresstxids error.%d\n", respEstimated); NSPV_senderror(pfrom, requestId, NSPV_ERROR_READ_DATA); } } @@ -1223,6 +1236,8 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re int8_t addrlen; int32_t respEstimated; + NSPV_senderror(pfrom, requestId, NSPV_ERROR_DEPRECATED); + if (requestDataLen > sizeof(isCC) + sizeof(funcid) + sizeof(vout) + sizeof(txid) + sizeof(addrlen)) { uint32_t offset = 0; offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(isCC), &isCC); @@ -1514,6 +1529,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re bool errorFormat = false; int32_t respEstimated; + NSPV_senderror(pfrom, requestId, NSPV_ERROR_DEPRECATED); //fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->nspvdata[ind].prevtime,ind,len); if (requestDataLen < sizeof(int32_t)) { diff --git a/src/komodo_nSPV_superlite.h b/src/komodo_nSPV_superlite.h index 15a0bedf1c8..a9310c20113 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -429,19 +429,19 @@ UniValue NSPV_utxosresp_json(struct NSPV_utxosresp *ptr) return(result); } -UniValue NSPV_txidresp_json(struct NSPV_txidresp *utxos,int32_t numutxos) +UniValue NSPV_txidresp_json(struct NSPV_txidresp *txids,int32_t numutxos) { UniValue array(UniValue::VARR); int32_t i; for (i=0; i 0) - item.push_back(Pair("vout", (int64_t)utxos[i].vout)); + item.push_back(Pair("height",(int64_t)txids[i].height)); + item.push_back(Pair("txid",txids[i].txid.GetHex())); + item.push_back(Pair("value",(double)txids[i].satoshis/COIN)); + if (txids[i].satoshis > 0) + item.push_back(Pair("vout", (int64_t)txids[i].index)); else - item.push_back(Pair("vin", (int64_t)utxos[i].vout)); + item.push_back(Pair("vin", (int64_t)txids[i].index)); array.push_back(item); } return(array); diff --git a/src/komodo_nSPV_wallet.h b/src/komodo_nSPV_wallet.h index b460abac792..a9574b571af 100644 --- a/src/komodo_nSPV_wallet.h +++ b/src/komodo_nSPV_wallet.h @@ -538,7 +538,7 @@ void NSPV_resp2indexOutputs(struct NSPV_txidsresp* ptr, std::vectortxids[i].txid; - key.index = ptr->txids[i].vout; + key.index = ptr->txids[i].index; key.blockHeight = ptr->txids[i].height; value = ptr->txids[i].satoshis; indexOutputs.push_back(std::make_pair(key, value)); From 4d505972af1bcd2c50f7bb8a261fcfae0f6f973a Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 2 Jun 2022 22:31:14 +0500 Subject: [PATCH 293/348] more nspv struct docs --- src/komodo_nSPV_defs.h | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 7d850644719..79569feef10 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -88,7 +88,8 @@ // see NSPV_txproof struct #define NSPV_TXPROOFRESP 0x09 -// get spent info for a tx output from spent index +// get spent info for a tx output from the addressindex +// returns txproof and spending txid // params: // int32_t vout - tx output index // uint256 txid - txid @@ -322,11 +323,15 @@ struct NSPV_inforesp // response struct for NSPV_TXPROOFRESP struct NSPV_txproof { - uint256 txid; - int64_t unspentvalue; - int32_t height, vout, txlen, txprooflen; - uint8_t *tx, *txproof; - uint256 hashblock; + uint256 txid; // txid of the tx + int64_t unspentvalue; // amount of the tx vout + int32_t height, // block height for the tx + vout, // + txlen, // spending tx length + txprooflen; // txproof length + uint8_t *tx, // serialised spending tx + *txproof; // serialised tx proof + uint256 hashblock; // hash of the block with the spending tx }; // block headers notarised by a notary tx @@ -359,9 +364,10 @@ struct NSPV_MMRproof // response struct for NSPV_SPENTINFORESP struct NSPV_spentinfo { - struct NSPV_txproof spent; - uint256 txid; - int32_t vout,spentvini; + struct NSPV_txproof spent; // transaction proof of the spending tx + uint256 txid; // txid of the tx to get spending info of + int32_t vout, // tx output index to get spending info of + spentvini; // spending tx vin index }; // response struct for NSPV_BROADCASTRESP @@ -371,7 +377,7 @@ struct NSPV_broadcastresp int32_t retcode; }; -// response struct for NSPV_CCMODULEUTXOSRESP +// response struct for NSPV_CCMODULEUTXOSRESP (deprecated) struct NSPV_CCmtxinfo { struct NSPV_utxosresp U; From e011317f3d9a63aacc4d388b7422f92df2605091 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 2 Jun 2022 22:31:40 +0500 Subject: [PATCH 294/348] nspv spent info logging fixed --- src/komodo_nSPV_fullnode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index eb5a3607f14..17ac535d0ba 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -1420,7 +1420,7 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re pfrom->PushMessage("nSPV", response); pfrom->nspvdata[idata].prevtime = timestamp; pfrom->nspvdata[idata].nreqs++; - LogPrint("nspv-details", "NSPV_SPENTINFO response: spent txid=%s vout=%d node=%d\n", S.txid.GetHex().c_str(), S.vout, pfrom->id); + LogPrint("nspv-details", "NSPV_SPENTINFO response: spending txid=%s vini=%d node=%d\n", S.spent.txid.GetHex(), S.spentvini, pfrom->id); } else { LogPrint("nspv", "NSPV_rwspentinfo incorrect response written len.%d\n", respWritten); NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); From b8645d72a4eb70a5db295d4347145bf27921dadb Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 3 Jun 2022 02:38:12 +0500 Subject: [PATCH 295/348] added adding to mempool eval error propagation to nspv --- src/cc/CCinclude.h | 2 +- src/cc/eval.cpp | 2 ++ src/cc/eval.h | 35 ++++++++++++++++++ src/komodo_nSPV.h | 2 +- src/komodo_nSPV_fullnode.h | 72 +++++++++++++++++++++++++++----------- src/main.cpp | 21 +++++++---- src/main.h | 31 ++-------------- 7 files changed, 107 insertions(+), 58 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index d8c43ebce64..faae94b78a5 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -415,7 +415,7 @@ int64_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag,int32_t lockfla /// \cond INTERNAL bool myIsutxo_spentinmempool(uint256 &spenttxid,int32_t &spentvini,uint256 txid,int32_t vout); -bool myAddtomempool(const CTransaction &tx, CValidationState *pstate = NULL, bool fSkipExpiry = false); +bool myAddtomempool(const CTransaction &tx, CValidationState *pstate = NULL, bool *pMissingInputs = nullptr, bool fSkipExpiry = false); bool mytxid_inmempool(uint256 txid); int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout); int32_t myGet_mempool_txs(std::vector &txs,uint8_t evalcode,uint8_t funcid); diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 50f3d54b026..f0b408f9bb4 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -48,6 +48,8 @@ bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, int64_t if (eval->state.IsValid()) return true; + evalcodeChecker->lastEvalErrorState = eval->state; + // report cc error: std::string lvl = eval->state.IsInvalid() ? "Invalid" : "Error!"; LOGSTREAMFN("cc", CCLOG_ERROR, stream << "CC Eval evalcode: " << EvalToStr(cond->code[0]) << " " << lvl << ", reason: " << eval->state.GetRejectReason() << std::endl); diff --git a/src/cc/eval.h b/src/cc/eval.h index 5d5672d9047..6686c83fed5 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -16,6 +16,9 @@ #ifndef CC_EVAL_H #define CC_EVAL_H +#include +#include + #include #include "cc/utils.h" @@ -298,6 +301,38 @@ class MerkleBranch typedef std::pair TxProof; +// collect already validated evalcodes in a tx being validated +// to prevent repeated validation of the same evalcode +class CCheckCCEvalCodes +{ + //! The set of evalcodes that are already processed in CC validation. + std::map> evalcodes; + + //! Mutex to protect evalcodes map + boost::mutex mutex_eval; + +public: + void MarkEvalCode(uint256 txid, uint8_t ecode) + { + boost::unique_lock lock(mutex_eval); + auto search = evalcodes.find(txid); + if (search == evalcodes.end()) { + std::set tmp; + tmp.insert(ecode); + evalcodes[txid] = tmp; + } else + search->second.insert(ecode); + } + + bool CheckEvalCode(uint256 txid, uint8_t ecode) + { + boost::unique_lock lock(mutex_eval); + auto search = evalcodes.find(txid); + return search == evalcodes.end() ? false : (search->second.find(ecode) != search->second.end()); + } + CValidationState lastEvalErrorState; // store last eval error aborting the validation process +}; + uint256 GetMerkleRoot(const std::vector& vLeaves); struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode); diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index 377f6012f7d..6f06a895011 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -537,7 +537,7 @@ int32_t NSPV_txextract(CTransaction &tx,uint8_t *data,int32_t datalen) { rawdata.resize(datalen); memcpy(&rawdata[0],data,datalen); - if ( DecodeHexTx(tx,HexStr(rawdata)) != 0 ) + if ( DecodeHexTx(tx,HexStr(rawdata)) != false ) return(0); } return(-1); diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 17ac535d0ba..5e2209b4667 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -818,26 +818,32 @@ uint8_t *NSPV_getrawtx(CTransaction &tx,uint256 &hashBlock,int32_t *txlenp,uint2 return(rawtx); } -int32_t NSPV_sendrawtransaction(struct NSPV_broadcastresp *ptr,uint8_t *data,int32_t n) +int32_t NSPV_sendrawtransaction(struct NSPV_broadcastresp *ptr, uint8_t *data, int32_t n, CValidationState *pstate) { CTransaction tx; ptr->retcode = 0; if ( NSPV_txextract(tx,data,n) == 0 ) { - //LOCK(cs_main); + LOCK(cs_main); // required by AcceptToMemoryPool + + bool fMissingInputs = false; ptr->txid = tx.GetHash(); //fprintf(stderr,"try to addmempool transaction %s\n",ptr->txid.GetHex().c_str()); - if (myAddtomempool(tx) != 0) + if (myAddtomempool(tx, pstate, &fMissingInputs) != false) { ptr->retcode = 1; //int32_t i; //for (i=0; itxid.GetHex().c_str(),ptr->retcode); + //fprintf(stderr," relay transaction %s retcode.%d\n",ptr->txid.GetHex().c_str(),ptr->retcode); RelayTransaction(tx); } - else - ptr->retcode = -3; + else { + if (fMissingInputs) + ptr->retcode = -4; + else + ptr->retcode = -3; + } } else @@ -987,6 +993,18 @@ static void NSPV_senderror(CNode* pfrom, uint32_t requestId, int32_t err) pfrom->PushMessage("nSPV", response); } +static void NSPV_senderror(CNode* pfrom, uint32_t requestId, int32_t err, const std::string &errDesc) +{ + const uint8_t respCode = NSPV_ERRORRESP; + + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << respCode << requestId << err << errDesc; + + std::vector response = vuint8_t(ss.begin(), ss.end()); + pfrom->PushMessage("nSPV", response); +} + + // processing nspv requests void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a request { @@ -1445,25 +1463,39 @@ void komodo_nSPVreq(CNode* pfrom, std::vector request) // received a re if (requestDataLen > sizeof(txid) + sizeof(txlen)) { int32_t offset = 0; int32_t respEstimated; + CValidationState state; offset += iguana_rwbignum(IGUANA_READ, &requestData[offset], sizeof(txid), (uint8_t*)&txid); offset += iguana_rwnum(IGUANA_READ, &requestData[offset], sizeof(txlen), &txlen); memset(&B, 0, sizeof(B)); - if (txlen < MAX_TX_SIZE_AFTER_SAPLING && requestDataLen == offset + txlen && (respEstimated = NSPV_sendrawtransaction(&B, &requestData[offset], txlen)) > 0) { - response.resize(nspvHeaderSize + respEstimated); - response[0] = NSPV_BROADCASTRESP; - memcpy(&response[1], &requestId, sizeof(requestId)); + if (txlen < MAX_TX_SIZE_AFTER_SAPLING && requestDataLen == offset + txlen && (respEstimated = NSPV_sendrawtransaction(&B, &requestData[offset], txlen, &state)) > 0) { + if (B.retcode >= 0) { + response.resize(nspvHeaderSize + respEstimated); + response[0] = NSPV_BROADCASTRESP; + memcpy(&response[1], &requestId, sizeof(requestId)); - int32_t respWritten = NSPV_rwbroadcastresp(IGUANA_WRITE, &response[nspvHeaderSize], &B); - if (respWritten > 0 && respWritten <= respEstimated) { - response.resize(nspvHeaderSize + respWritten); - pfrom->PushMessage("nSPV", response); - pfrom->nspvdata[idata].prevtime = timestamp; - pfrom->nspvdata[idata].nreqs++; - LogPrint("nspv-details", "NSPV_BROADCAST response: txid=%s vout=%d to node=%d\n", B.txid.GetHex().c_str(), pfrom->id); - } else { - LogPrint("nspv", "NSPV_rwbroadcastresp incorrect response written len.%d\n", respWritten); - NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + int32_t respWritten = NSPV_rwbroadcastresp(IGUANA_WRITE, &response[nspvHeaderSize], &B); + if (respWritten > 0 && respWritten <= respEstimated) { + response.resize(nspvHeaderSize + respWritten); + pfrom->PushMessage("nSPV", response); + pfrom->nspvdata[idata].prevtime = timestamp; + pfrom->nspvdata[idata].nreqs++; + LogPrint("nspv-details", "NSPV_BROADCAST response: txid=%s vout=%d to node=%d\n", B.txid.GetHex().c_str(), pfrom->id); + } else { + LogPrint("nspv", "NSPV_rwbroadcastresp incorrect response written len.%d\n", respWritten); + NSPV_senderror(pfrom, requestId, NSPV_ERROR_INVALID_RESPONSE); + } + } + else { + std::string errDesc = "unknown-error"; + if (B.retcode == -1) + errDesc = "tx-decode-failed"; + else if (B.retcode == -3) + errDesc = strprintf("add-to-mempool-error: validation code=%d reason=%s", state.GetRejectCode(), state.GetRejectReason()); + else if (B.retcode == -4) + errDesc = "add-to-mempool-error: missing inputs"; + NSPV_senderror(pfrom, requestId, NSPV_ERROR_BROADCAST, errDesc); + LogPrint("nspv", "NSPV_sendrawtransaction error retcode %d state code=%d reason=%s node=%d\n", B.retcode, state.GetRejectCode(), state.GetRejectReason(), pfrom->id); } NSPV_broadcast_purge(&B); } else { diff --git a/src/main.cpp b/src/main.cpp index 949052131a8..08d4058e754 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2252,16 +2252,17 @@ struct CompareBlocksByHeightMain else return(coins.vout[n].nValue); }*/ -bool myAddtomempool(const CTransaction &tx, CValidationState *pstate, bool fSkipExpiry) +bool myAddtomempool(const CTransaction &tx, CValidationState *pstate, bool *pMissingInputs, bool fSkipExpiry) { CValidationState state; if (!pstate) pstate = &state; - CTransaction Ltx; bool fMissingInputs,fOverrideFees = false; - if ( mempool.lookup(tx.GetHash(),Ltx) == 0 ) + CTransaction Ltx; + bool fOverrideFees = false; + if (mempool.lookup(tx.GetHash(), Ltx) == false) { if ( !fSkipExpiry ) - return(AcceptToMemoryPool(mempool, *pstate, tx, false, &fMissingInputs, !fOverrideFees, -1)); + return(AcceptToMemoryPool(mempool, *pstate, tx, false, pMissingInputs, !fOverrideFees, -1)); else return(CCTxFixAcceptToMemPoolUnchecked(mempool,tx)); } @@ -3002,7 +3003,10 @@ bool ContextualCheckInputs( // as to the correct behavior - we may want to continue // peering with non-upgraded nodes even after a soft-fork // super-majority vote has passed. - return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError()))); + return state.DoS(100,false, REJECT_INVALID, + strprintf("mandatory-script-verify-flag-failed (%s)%s", + ScriptErrorString(check.GetScriptError()), + evalcodeChecker->lastEvalErrorState.IsValid() == false ? strprintf(", eval errcode=%d reason=%s", evalcodeChecker->lastEvalErrorState.GetRejectCode(), evalcodeChecker->lastEvalErrorState.GetRejectReason()) : "")); } } } @@ -3052,7 +3056,10 @@ bool ContextualCheckOutputs( } else if (!check()) { - return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError()))); + return state.DoS(100,false, REJECT_INVALID, + strprintf("mandatory-script-verify-flag-failed (%s)%s", + ScriptErrorString(check.GetScriptError()), + evalcodeChecker->lastEvalErrorState.IsValid() == false ? strprintf(", eval errcode=%d reason=%s", evalcodeChecker->lastEvalErrorState.GetRejectCode(), evalcodeChecker->lastEvalErrorState.GetRejectReason()) : "")); } } } @@ -5571,7 +5578,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C if ( tx.IsCoinBase() || !tx.vjoinsplit.empty() || !tx.vShieldedSpend.empty() || (i == block.vtx.size()-1 && komodo_isPoS((CBlock *)&block,height,0) != 0) ) continue; Tx = tx; - if ( myAddtomempool(Tx, &state, true) == false ) // happens with out of order tx in block on resync + if ( myAddtomempool(Tx, &state, nullptr, true) == false ) // happens with out of order tx in block on resync { //LogPrintf("Rejected by mempool, reason: .%s.\n", state.GetRejectReason().c_str()); // take advantage of other checks, but if we were only rejected because it is a valid staking diff --git a/src/main.h b/src/main.h index a4a52ae671d..5a618d69221 100644 --- a/src/main.h +++ b/src/main.h @@ -65,6 +65,8 @@ class CValidationInterface; class CValidationState; class PrecomputedTransactionData; +class CCheckCCEvalCodes; + struct CNodeStateStats; #define DEFAULT_MEMPOOL_EXPIRY 1 #define _COINBASE_MATURITY 100 @@ -665,35 +667,6 @@ struct CDiskTxPos : public CDiskBlockPos CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); -class CCheckCCEvalCodes -{ - //! The set of evalcodes that are already processed in CC validation. - std::map> evalcodes; - - //! Mutex to protect evalcodes map - boost::mutex mutex_eval; - -public: - void MarkEvalCode(uint256 txid, uint8_t ecode) - { - boost::unique_lock lock(mutex_eval); - auto search = evalcodes.find(txid); - if (search == evalcodes.end()) { - std::set tmp; - tmp.insert(ecode); - evalcodes[txid] = tmp; - } else - search->second.insert(ecode); - } - - bool CheckEvalCode(uint256 txid, uint8_t ecode) - { - boost::unique_lock lock(mutex_eval); - auto search = evalcodes.find(txid); - return search == evalcodes.end() ? false : (search->second.find(ecode) != search->second.end()); - } -}; - /** * Check transaction inputs, and make sure any * pay-to-script-hash transactions are evaluating IsStandard scripts From be947347cd2fe18d7b353d80cb7d56092a7e3b1a Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 3 Jun 2022 11:00:56 +0500 Subject: [PATCH 296/348] adde check not null for evalcodeChecker --- src/cc/eval.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index f0b408f9bb4..350647d5472 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -48,7 +48,8 @@ bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn, int64_t if (eval->state.IsValid()) return true; - evalcodeChecker->lastEvalErrorState = eval->state; + if (evalcodeChecker != nullptr) + evalcodeChecker->lastEvalErrorState = eval->state; // report cc error: std::string lvl = eval->state.IsInvalid() ? "Invalid" : "Error!"; From 1b8b2520d136327fcbc0943418ac22c196e12812 Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Fri, 3 Jun 2022 16:40:33 +1000 Subject: [PATCH 297/348] Updated information Multiple changes --- README.md | 60 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 7f7c9d2d518..f08c388114f 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,59 @@ ![Tokel Header](https://github.com/TokelPlatform/tokel_app/blob/development/assets/tokel-header.png "Tokel Header") -## Komodo's 'Tokel' Branch +## The Tokel Blockchain +This repository is required to run and use the main Tokel blockchain and hosts Tokel specific developments. -This is the `tokel` branch of Komodo's sourcecode repository. This branch is required to run and use the main Tokel blockchain and hosts Tokel specific developments. - -To run Tokel's test chain, please use the repository below instead. -- https://github.com/TokelPlatform/komodo/ +To run Tokel's test chain (TKLTEST), please use the 'tkltest' branch instead. +- [https://github.com/TokelPlatform/tokel](https://github.com/TokelPlatform/tokel/tree/tkltest) ## What is the Tokel Platform? -Tokel is a dedicated token platform. This platform will provide a solid foundation, using existing Komodo Technologies, for token projects to launch and succeed from by offering end-to-end token solutions for fixed supply and non-fungible tokens (NFT's). Furthermore Tokel aims to provide a wealth of knowledge, information and assistance for open-sourced applications, projects and businesses looking to capitalize on token economics or token applications. The Tokel platform will provide simple to use, streamlined token creation, explorer and wallet integration, decentralized exchange integration assistance and more. - -#### What Tokel aims to offer: -- The blockchain that facilitates the tokens. -- An open-sourced all-in-one GUI application. -- A tokenDEX for all tokens on Tokel. -- An NFT marketplace for NFTs on Tokel. -- A free-to-use token test blockchain. -- Easy to use integrations -- Easy to use token creation, usage and management tools. -- Immediate token explorer integration. +Tokel is an open-source, decentralized, token & NFT platform. + +The Tokel platform makes tokenization easy and affordable for creators, businesses and projects by offering inexpensive, user-friendly solutions for token/NFT creation, asset management, and an on-chain decentralized trading functionality without the need for complicated smart contracts or expensive gas fees. + +Utilizing cutting edge UTXO based technology, the Tokel blockchain offers an array of layer 1 blockchain features, removing the need for expensive smart contract development. + +Tokel's super-lite, next-gen SPV technology gives users the ability to interact with their tokens in a decentralized & trust-less fashion on any device, without the inconvenience and energy cost of downloading the entire blockchain. + +Tokel provides universal, accessible, and easy-to-use tokenization technology to people all over the world. + +To NFT and Beyond + +#### What Tokel offers: +- The blockchain that facilitates the tokens and NFTs. +- An open-sourced all-in-one ]GUI application](https://github.com/TokelPlatform/tokel_dapp). +- DEX functionality for all tokens/NFTs created on Tokel. +- A free-to-use test blockchain (TKLTEST). +- Easy to use integrations (nSPV) +- Easy to use token/NFT creation, usage and management tools [(within the dApp)](https://github.com/TokelPlatform/tokel_dapp). +- Immediate [token explorer integration](https://explorer.tokel.io/tokens). - Immediate token wallet integration. -- Open source Discord bot integration. #### The benefits of creating a token on the Tokel blockchain: -- There are no requirements to create and manage your own blockchain. -- Free, simple to use GUI for token usage, management and creation. +- There are no requirements to create and manage your own blockchain or complicated smart contracts. +- No gas fees! +- Free, simple to use [dApp](https://github.com/TokelPlatform/tokel_dapp) for token usage, management and creation. - Extremely cheap token creation and transaction fees (1 satoshi of TKL per token created and 0.0001 TKL txfee by default). - Free to use TKLTEST chain for any token or custom consensus testing prior to launch or integration. -- Your token will have immediate token wallet integration. +- Your token will have immediate token wallet integration within the dApp. - Your token will have immediate token explorer integration. -- Your token is safe from 51% attacks as Tokel is secured through dPoW. -- You will have the ability to sell your tokens immediately after creation with Tokel’s inbuilt tokenDEX and NFT marketplace integration. +- Your token is safe from 51% attacks as Tokel is secured through [dPoW](https://komodoplatform.com/en/blog/delayed-proof-of-work/). +- You will have the ability to sell your tokens immediately after creation with Tokel’s inbuilt decentralized exchange mechanism. - Tokel exchange partnerships mean your token will have a centralized exchange listing option. The exchanges are only required to run the Tokel chain to access every single token on it. -## The Tokel Application +## The Tokel Decentralized Application The all-in-one Tokel application is an open-sourced application that will be the one stop shop for all Tokel related features. This application is built using nSPV superlite wallet technology that has been developed by the Komodo platform, for an incredibly fast and reliable experience. This application accesses all of the features offered on the Tokel blockchain whilst keeping users funds in their own wallets (completely non-custodial). -This application is in development. You can keep up with progress on the github, or find out more by having a chat in our discord. +You can keep up with progress on the github, or find out more by having a chat in our discord. https://github.com/TokelPlatform/tokel_dapp #### Application features include: - A TKL coin wallet - A multi-token wallet (you are able to hold all tokens that are in existence on the Tokel blockchain) -- A tokenDEX trading platform -- A decentralized NFT marketplace +- Decentralized exchanging functionality - A simple to use Token creation tool -- A token explorer for all tokens on the Tokel blockchain ## Tokel Resources From 6de7b4176e2dc22d5f1281292d22e5c9f658ee1e Mon Sep 17 00:00:00 2001 From: Alright Date: Thu, 9 Jun 2022 08:54:12 -0400 Subject: [PATCH 298/348] dpow season 6 activation --- src/komodo_defs.h | 78 +++++++++++++++++++++++++++++++++++++++++--- src/komodo_globals.h | 3 ++ 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 621e6179692..b65b7d07f9d 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -60,7 +60,7 @@ // 7113400 = 5x current KMD blockheight. // to add 4th season, change NUM_KMD_SEASONS to 4, and add timestamp and height of activation to these arrays. -#define NUM_KMD_SEASONS 6 +#define NUM_KMD_SEASONS 7 #define NUM_KMD_NOTARIES 64 extern const uint32_t nStakedDecemberHardforkTimestamp; //December 2019 hardfork @@ -72,8 +72,11 @@ extern const int32_t nS4HardforkHeight; //dPoW Season 4 2020 hardfork extern const uint32_t nS5Timestamp; //dPoW Season 5 June 14th, 2021 hardfork (03:00:00 PM UTC) (defined in komodo_globals.h) extern const int32_t nS5HardforkHeight; //dPoW Season 5 June 14th, 2021 hardfork estimated block height (defined in komodo_globals.h) -static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, 1751328000}; -static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, 7113400}; +extern const uint32_t nS6Timestamp; // dPoW Season 6 Fri Jun 24 2022 13:37:33 GMT+0000 +extern const int32_t nS6HardforkHeight; // estimated June 24 2022 + +static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, nS6Timestamp, 1751328000}; +static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, nS6HardforkHeight, 7113400}; // Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = @@ -476,7 +479,74 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = {"strob_SH", "0213751a1c59d3489ca85b3d62a3d606dcef7f0428aa021c1978ea16fb38a2fad6" }, {"strobnidan_SH", "033e33ef18effb979437cd202bb87dc32385e16ebd52d6f762d8a3b308d6f89c52" }, {"dragonhound_DEV", "02b3c168ed4acd96594288cee3114c77de51b6afe1ab6a866887a13a96ee80f33c" } - } + }, + { + // Season 6 + {"blackice_DEV", "03e2de3418c88be0cfe2fa0dcfdaea001b5a36ad86e6833ad284d79021ae7e2b94"}, + {"blackice_AR", "03949b06c2773b4573aeb0b52e70ccc2d98dc5794a47e24eeb902c9d28e0e8d28b"}, + {"alien_EU", "022b85908191788f409506ebcf96a892f3274f352864c3ed566c5a16de63953236"}, + {"alien_NA", "022f62b56ddfd07c9860921c701285ac39bb3ac8f6f083d1b59c8f4943be3de162"}, + {"alien_SH", "024f20c096b085308e21893383f44b4faf1cdedea9ad53cc7d7e7fbfa0c30c1e71"}, + {"alienx_EU", "025de0911bab55616c307f02ea8a5915a2e0c8e479aa97968e7f00d1025cbe6c6d"}, + {"alienx_NA", "025d5e11725233ab161f4f63d697c5f9f0c6b9d3aa2b9c68299638f8cc63faa9c2"}, + {"artem.pikulin_AR", "03a45c4ad7f279cbc50acb48d81fc0eb63c4c5f556e3a4393fb3d6414df09c6e4c"}, + {"artem.pikulin_DEV", "025ee88d1c12f546c1c8942d7a3e0678f10bc27cc566e27bf4a2d2178e018d18c6"}, + {"blackice_EU", "025f8de3a6181270ceb5c31654e6a6e95d0339bc14b46b5e3050e8a69861c91baa"}, + {"chmex_AR", "030cd487e10fbf142e0e8d582e702ecb775f378569c3cb5acd0ff97b6b12803588"}, + {"chmex_EU", "030bf7bd7ad0515c33b5d5d9a91e0729baf801b9002f80495ae535ea1cebb352cb"}, + {"chmex_NA", "024e88a36d729352a391e07d1821dbfda1fca6409320cf9c2869b6fb99f05fbddd"}, + {"chmex_SH", "03e09c8ee6ae20cde64857d116c4bb5d50db6de2887ac39ea3ccf6434b1abf8698"}, + {"chmex1_SH", "02d59db293de6c7da6673beeb373ebce62fd6d3522f715ea1356b5a2624fbd11a2"}, + {"cipi_1_EU", "033a812d6cccdc4208378728f3a0e15db5b12074def9ab686ddc3752715ff1a194"}, + {"cipi_2_EU", "0302ca28a041ed00544de737651bdec9bafe3b7f1c0bf2c6092f2368d59fec75c2"}, + {"cipi_AR", "02336758998f474659020e6887ece61ac7b8567f9b2d38724ebf77ae800c1fb2b7"}, + {"cipi_NA", "0335352862da521bd90b99d394db1ee3ecde379db9cf7ba2f28b16fa76153e289f"}, + {"computergenie_EU", "033a2474a762700b452b96a49730280040a9872070bc51461e3727f6f118ff5358"}, + {"computergenie_NA", "02f945d87b7cd6e9f2173a110399d36b369edb1f10bdf5a4ba6fd4923e2986e137"}, + {"dimxy_AR", "0337e443df52f278f313f90628aaaa7a8db777f17bc7ce519069eb72717c1c2755"}, + {"dimxy_DEV", "03a7edd6d0ba188960e39eced4d6b4ca6946bd98323ab40cbc13d6e52696de7dc4"}, + {"dragonhound_NA", "0366a87a476a09e05560c5aae0e44d2ab9ba56e69701cee24307871ddd37c86258"}, + {"fediakash_AR", "035be6a54242a53e3ca55bd63430ac9b960fbfaad336d8c1464b5802f03ab184be"}, + {"gcharang_DEV", "03a3878af1152f648e6084fd3fbe697a26b1c2e92d407dd96c375f45f7d3ca13bf"}, + {"gcharang_SH", "0321868e0eb39271330fa2c3a9f4e542275d9719f8b87773c5432448ab10d6943d"}, + {"goldenman_AR", "03e027927dd1e379c2f45624ed9b057b187fe094595fee55c53f36ed665ed566ab"}, + {"kolo_AR", "032c2a6aeaf8176f9630abe2e1bbea5e481da23ab1f9a5b10f220a9b2bc9607bd6"}, + {"kolo_EU", "03b21717e84c0a6cf22b557b198daba4f78980048211b9139b4517fa08f9f17359"}, + {"kolox_AR", "038010e24e6d53f26871d31287f446f407fa87596d946bcd1f7b7b8458e34ad73f"}, + {"komodopioneers_EU", "02fb31b130babe79ac780a6118702555a8c66875835f35c2232a6cb8b1438fe71d"}, + {"madmax_DEV", "02d1ace4a25794de5a5287edeb9df9619dc97020114801c5cb287b1efdd49ddbb3"}, + {"marmarachain_EU", "02ca3e0618bc7c75afa6359ae476ee639682adfaa6fc463bbe7016c4f00da23ccf"}, + {"mcrypt_AR", "02845d016c68c3e5ce924b164abc271511f3092ae359677a515e8f81a9533472f4"}, + {"mcrypt_SH", "027a4ca7b11d3456ff558c08bb04483a89c7f383448461fd0b6b3b07424aabe9a4"}, + {"metaphilibert_SH", "03b21ff042bf1730b28bde43f44c064578b41996117ac7634b567c3773089e3be3"}, + {"mylo_NA", "02493412e6014d2bb985b1026e31204e7634a211a16454fc696f4dc4dfe409e998"}, + {"mylo_SH", "026a52dba25ca4deb225a5ef7fca117d59e20ef2319b00e1bb6750a5d61e5ed601"}, + {"nodeone_NA", "0310a249c6c2dcc29f2135715138a9ddb8e01c0eab701cbd0b96d9cec660dbdc58"}, + {"nutellalicka_AR", "03a5502c61839a34edc8443aee5c16c67d4a958874e13d9b6b69d29075354739ad"}, + {"nutellalicka_SH", "03c7822f0c3434037fa17bfa4d3b7f9d3e0eb9abe49e8cc1188d92c6b3c360a675"}, + {"ocean_AR", "02d216e72d37a38449d661413cbc6e1f008b21cffdb06865f7be636e2cbc1e5346"}, + {"pbca26_NA", "030b6515e80aaa489215875e2aa6f2a15fa36cb3342580e885275f8c636252cbc8"}, + {"pbca26_SH", "02d17840724692a9d5e72d61d001c31eb5ddc4d2f0f104b760e6854bf144e63fb8"}, + {"phit_SH", "021b893b7978284e3d73701a623f23104fcce27e70fb49427c215f9a7481f652da"}, + {"ptyx_NA", "025d72ef0f1c5103de306d536360bcf3c5b6129c2046334b21cec8202e9bfc4baf"}, + {"ptyx2_NA", "02913b3af6f67453eaff2318f3eed0fa0ea60eb2b37c8da64c575fec972f178d9b"}, + {"sheeba_SH", "030dd2c3c02cbc5b3c25e3c54ed02c1541951a6f5ecf8adbd353e8d9052d08b8fc"}, + {"smdmitry_AR", "0397b7584cb29717b721c0c587d4462477efc1f36a56921f133c9d17b0cd7f278a"}, + {"smdmitry_EU", "0338f30ca34d0aca0d79b69abde447036aaaa75f482b6c75801fd382e984337d01"}, + {"smdmitry_SH", "03f7d5ac650baaccedab959adf7c4f416584f4c05a37bf079f710227560c456978"}, + {"strob_SH", "0213751a1c59d3489ca85b3d62a3d606dcef7f0428aa021c1978ea16fb38a2fad6"}, + {"strobnidan_SH", "033e33ef18effb979437cd202bb87dc32385e16ebd52d6f762d8a3b308d6f89c52"}, + {"tokel_NA", "0315d866c09e15709e2036a05faec6aaf28e0ecf67329b2adb922b746f22e694bc"}, + {"tonyl_AR", "02e2d9ecdc9f462a4767f7dfe8ed243c98fcccc1511989a60e3f859dc6fda42d16"}, + {"tonyl_DEV", "0399c4f8c5b604cda64c1ccb8fdbd7a89730131519f87491a79b0811e619102d8f"}, + {"van_EU", "0370305b9e91d46331da202ae733d6050d01038ef6eceb2036ada394a48fae84b9"}, + {"webworker01_EU", "0390ba250f20b5849b9d37ad2bcb58d3d9a3a0385937e652c26511ba9f445f5db1"}, + {"webworker01_NA", "03bde0df98de0ff9697b7d5ecea225fd7267f55c061caa2c43a47b313e35c9b6c6"}, + {"who-biz_NA", "0268d30efafc6ac84b1c8210e99fd4936e178794581d348b87f64fcbbfa8d5e73b"}, + {"yurii-khi_DEV", "0243977da0533c7c1a37f0f6e30175225c9012d9f3f426180ff6e5710f5a50e32b"}, + {"ca333_EU", "03c34a62c8c89889e4529962578e0b75a010a6e1d9bcbe8f4bb9cc680d82c7261e"}, + {"dragonhound_DEV", "02b3c168ed4acd96594288cee3114c77de51b6afe1ab6a866887a13a96ee80f33c"}, + }, }; #define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7))) diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 87c94052dd7..9c366153918 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -35,6 +35,9 @@ const int32_t nS4HardforkHeight = 1922000; //dPoW Season 4 2020 hardfork Sunda const uint32_t nS5Timestamp = 1627466969; //dPoW Season 5 Wed Jul 28 2021 10:09:29 GMT+0000 (timestamp of TOKEL block #1) const int32_t nS5HardforkHeight = 2437300; //dPoW Season 5 Monday, June 14th, 2021 +const uint32_t nS6Timestamp = 1656077853; // dPoW Season 6 Fri Jun 24 2022 13:37:33 GMT+0000 +const int32_t nS6HardforkHeight = 2963330; // estimated June 24 2022 + #define _COINBASE_MATURITY 100 int COINBASE_MATURITY = _COINBASE_MATURITY;//100; unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; From 526634ee03131e468d4087b3e65ad828c76c8941 Mon Sep 17 00:00:00 2001 From: Alright Date: Thu, 9 Jun 2022 08:54:12 -0400 Subject: [PATCH 299/348] dpow season 6 activation --- src/komodo_defs.h | 78 +++++++++++++++++++++++++++++++++++++++++--- src/komodo_globals.h | 3 ++ 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 621e6179692..b65b7d07f9d 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -60,7 +60,7 @@ // 7113400 = 5x current KMD blockheight. // to add 4th season, change NUM_KMD_SEASONS to 4, and add timestamp and height of activation to these arrays. -#define NUM_KMD_SEASONS 6 +#define NUM_KMD_SEASONS 7 #define NUM_KMD_NOTARIES 64 extern const uint32_t nStakedDecemberHardforkTimestamp; //December 2019 hardfork @@ -72,8 +72,11 @@ extern const int32_t nS4HardforkHeight; //dPoW Season 4 2020 hardfork extern const uint32_t nS5Timestamp; //dPoW Season 5 June 14th, 2021 hardfork (03:00:00 PM UTC) (defined in komodo_globals.h) extern const int32_t nS5HardforkHeight; //dPoW Season 5 June 14th, 2021 hardfork estimated block height (defined in komodo_globals.h) -static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, 1751328000}; -static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, 7113400}; +extern const uint32_t nS6Timestamp; // dPoW Season 6 Fri Jun 24 2022 13:37:33 GMT+0000 +extern const int32_t nS6HardforkHeight; // estimated June 24 2022 + +static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, nS6Timestamp, 1751328000}; +static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, nS6HardforkHeight, 7113400}; // Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = @@ -476,7 +479,74 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = {"strob_SH", "0213751a1c59d3489ca85b3d62a3d606dcef7f0428aa021c1978ea16fb38a2fad6" }, {"strobnidan_SH", "033e33ef18effb979437cd202bb87dc32385e16ebd52d6f762d8a3b308d6f89c52" }, {"dragonhound_DEV", "02b3c168ed4acd96594288cee3114c77de51b6afe1ab6a866887a13a96ee80f33c" } - } + }, + { + // Season 6 + {"blackice_DEV", "03e2de3418c88be0cfe2fa0dcfdaea001b5a36ad86e6833ad284d79021ae7e2b94"}, + {"blackice_AR", "03949b06c2773b4573aeb0b52e70ccc2d98dc5794a47e24eeb902c9d28e0e8d28b"}, + {"alien_EU", "022b85908191788f409506ebcf96a892f3274f352864c3ed566c5a16de63953236"}, + {"alien_NA", "022f62b56ddfd07c9860921c701285ac39bb3ac8f6f083d1b59c8f4943be3de162"}, + {"alien_SH", "024f20c096b085308e21893383f44b4faf1cdedea9ad53cc7d7e7fbfa0c30c1e71"}, + {"alienx_EU", "025de0911bab55616c307f02ea8a5915a2e0c8e479aa97968e7f00d1025cbe6c6d"}, + {"alienx_NA", "025d5e11725233ab161f4f63d697c5f9f0c6b9d3aa2b9c68299638f8cc63faa9c2"}, + {"artem.pikulin_AR", "03a45c4ad7f279cbc50acb48d81fc0eb63c4c5f556e3a4393fb3d6414df09c6e4c"}, + {"artem.pikulin_DEV", "025ee88d1c12f546c1c8942d7a3e0678f10bc27cc566e27bf4a2d2178e018d18c6"}, + {"blackice_EU", "025f8de3a6181270ceb5c31654e6a6e95d0339bc14b46b5e3050e8a69861c91baa"}, + {"chmex_AR", "030cd487e10fbf142e0e8d582e702ecb775f378569c3cb5acd0ff97b6b12803588"}, + {"chmex_EU", "030bf7bd7ad0515c33b5d5d9a91e0729baf801b9002f80495ae535ea1cebb352cb"}, + {"chmex_NA", "024e88a36d729352a391e07d1821dbfda1fca6409320cf9c2869b6fb99f05fbddd"}, + {"chmex_SH", "03e09c8ee6ae20cde64857d116c4bb5d50db6de2887ac39ea3ccf6434b1abf8698"}, + {"chmex1_SH", "02d59db293de6c7da6673beeb373ebce62fd6d3522f715ea1356b5a2624fbd11a2"}, + {"cipi_1_EU", "033a812d6cccdc4208378728f3a0e15db5b12074def9ab686ddc3752715ff1a194"}, + {"cipi_2_EU", "0302ca28a041ed00544de737651bdec9bafe3b7f1c0bf2c6092f2368d59fec75c2"}, + {"cipi_AR", "02336758998f474659020e6887ece61ac7b8567f9b2d38724ebf77ae800c1fb2b7"}, + {"cipi_NA", "0335352862da521bd90b99d394db1ee3ecde379db9cf7ba2f28b16fa76153e289f"}, + {"computergenie_EU", "033a2474a762700b452b96a49730280040a9872070bc51461e3727f6f118ff5358"}, + {"computergenie_NA", "02f945d87b7cd6e9f2173a110399d36b369edb1f10bdf5a4ba6fd4923e2986e137"}, + {"dimxy_AR", "0337e443df52f278f313f90628aaaa7a8db777f17bc7ce519069eb72717c1c2755"}, + {"dimxy_DEV", "03a7edd6d0ba188960e39eced4d6b4ca6946bd98323ab40cbc13d6e52696de7dc4"}, + {"dragonhound_NA", "0366a87a476a09e05560c5aae0e44d2ab9ba56e69701cee24307871ddd37c86258"}, + {"fediakash_AR", "035be6a54242a53e3ca55bd63430ac9b960fbfaad336d8c1464b5802f03ab184be"}, + {"gcharang_DEV", "03a3878af1152f648e6084fd3fbe697a26b1c2e92d407dd96c375f45f7d3ca13bf"}, + {"gcharang_SH", "0321868e0eb39271330fa2c3a9f4e542275d9719f8b87773c5432448ab10d6943d"}, + {"goldenman_AR", "03e027927dd1e379c2f45624ed9b057b187fe094595fee55c53f36ed665ed566ab"}, + {"kolo_AR", "032c2a6aeaf8176f9630abe2e1bbea5e481da23ab1f9a5b10f220a9b2bc9607bd6"}, + {"kolo_EU", "03b21717e84c0a6cf22b557b198daba4f78980048211b9139b4517fa08f9f17359"}, + {"kolox_AR", "038010e24e6d53f26871d31287f446f407fa87596d946bcd1f7b7b8458e34ad73f"}, + {"komodopioneers_EU", "02fb31b130babe79ac780a6118702555a8c66875835f35c2232a6cb8b1438fe71d"}, + {"madmax_DEV", "02d1ace4a25794de5a5287edeb9df9619dc97020114801c5cb287b1efdd49ddbb3"}, + {"marmarachain_EU", "02ca3e0618bc7c75afa6359ae476ee639682adfaa6fc463bbe7016c4f00da23ccf"}, + {"mcrypt_AR", "02845d016c68c3e5ce924b164abc271511f3092ae359677a515e8f81a9533472f4"}, + {"mcrypt_SH", "027a4ca7b11d3456ff558c08bb04483a89c7f383448461fd0b6b3b07424aabe9a4"}, + {"metaphilibert_SH", "03b21ff042bf1730b28bde43f44c064578b41996117ac7634b567c3773089e3be3"}, + {"mylo_NA", "02493412e6014d2bb985b1026e31204e7634a211a16454fc696f4dc4dfe409e998"}, + {"mylo_SH", "026a52dba25ca4deb225a5ef7fca117d59e20ef2319b00e1bb6750a5d61e5ed601"}, + {"nodeone_NA", "0310a249c6c2dcc29f2135715138a9ddb8e01c0eab701cbd0b96d9cec660dbdc58"}, + {"nutellalicka_AR", "03a5502c61839a34edc8443aee5c16c67d4a958874e13d9b6b69d29075354739ad"}, + {"nutellalicka_SH", "03c7822f0c3434037fa17bfa4d3b7f9d3e0eb9abe49e8cc1188d92c6b3c360a675"}, + {"ocean_AR", "02d216e72d37a38449d661413cbc6e1f008b21cffdb06865f7be636e2cbc1e5346"}, + {"pbca26_NA", "030b6515e80aaa489215875e2aa6f2a15fa36cb3342580e885275f8c636252cbc8"}, + {"pbca26_SH", "02d17840724692a9d5e72d61d001c31eb5ddc4d2f0f104b760e6854bf144e63fb8"}, + {"phit_SH", "021b893b7978284e3d73701a623f23104fcce27e70fb49427c215f9a7481f652da"}, + {"ptyx_NA", "025d72ef0f1c5103de306d536360bcf3c5b6129c2046334b21cec8202e9bfc4baf"}, + {"ptyx2_NA", "02913b3af6f67453eaff2318f3eed0fa0ea60eb2b37c8da64c575fec972f178d9b"}, + {"sheeba_SH", "030dd2c3c02cbc5b3c25e3c54ed02c1541951a6f5ecf8adbd353e8d9052d08b8fc"}, + {"smdmitry_AR", "0397b7584cb29717b721c0c587d4462477efc1f36a56921f133c9d17b0cd7f278a"}, + {"smdmitry_EU", "0338f30ca34d0aca0d79b69abde447036aaaa75f482b6c75801fd382e984337d01"}, + {"smdmitry_SH", "03f7d5ac650baaccedab959adf7c4f416584f4c05a37bf079f710227560c456978"}, + {"strob_SH", "0213751a1c59d3489ca85b3d62a3d606dcef7f0428aa021c1978ea16fb38a2fad6"}, + {"strobnidan_SH", "033e33ef18effb979437cd202bb87dc32385e16ebd52d6f762d8a3b308d6f89c52"}, + {"tokel_NA", "0315d866c09e15709e2036a05faec6aaf28e0ecf67329b2adb922b746f22e694bc"}, + {"tonyl_AR", "02e2d9ecdc9f462a4767f7dfe8ed243c98fcccc1511989a60e3f859dc6fda42d16"}, + {"tonyl_DEV", "0399c4f8c5b604cda64c1ccb8fdbd7a89730131519f87491a79b0811e619102d8f"}, + {"van_EU", "0370305b9e91d46331da202ae733d6050d01038ef6eceb2036ada394a48fae84b9"}, + {"webworker01_EU", "0390ba250f20b5849b9d37ad2bcb58d3d9a3a0385937e652c26511ba9f445f5db1"}, + {"webworker01_NA", "03bde0df98de0ff9697b7d5ecea225fd7267f55c061caa2c43a47b313e35c9b6c6"}, + {"who-biz_NA", "0268d30efafc6ac84b1c8210e99fd4936e178794581d348b87f64fcbbfa8d5e73b"}, + {"yurii-khi_DEV", "0243977da0533c7c1a37f0f6e30175225c9012d9f3f426180ff6e5710f5a50e32b"}, + {"ca333_EU", "03c34a62c8c89889e4529962578e0b75a010a6e1d9bcbe8f4bb9cc680d82c7261e"}, + {"dragonhound_DEV", "02b3c168ed4acd96594288cee3114c77de51b6afe1ab6a866887a13a96ee80f33c"}, + }, }; #define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7))) diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 87c94052dd7..9c366153918 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -35,6 +35,9 @@ const int32_t nS4HardforkHeight = 1922000; //dPoW Season 4 2020 hardfork Sunda const uint32_t nS5Timestamp = 1627466969; //dPoW Season 5 Wed Jul 28 2021 10:09:29 GMT+0000 (timestamp of TOKEL block #1) const int32_t nS5HardforkHeight = 2437300; //dPoW Season 5 Monday, June 14th, 2021 +const uint32_t nS6Timestamp = 1656077853; // dPoW Season 6 Fri Jun 24 2022 13:37:33 GMT+0000 +const int32_t nS6HardforkHeight = 2963330; // estimated June 24 2022 + #define _COINBASE_MATURITY 100 int COINBASE_MATURITY = _COINBASE_MATURITY;//100; unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; From c56bc7b2b23a073e059bf43ccbb8e1e0c571f561 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 14 Jun 2022 11:55:18 +0500 Subject: [PATCH 300/348] s6 timestamp set for token raddress activation --- src/cc/CCupgrades.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cc/CCupgrades.h b/src/cc/CCupgrades.h index c74264effba..30b485b4245 100644 --- a/src/cc/CCupgrades.h +++ b/src/cc/CCupgrades.h @@ -22,6 +22,7 @@ #include #include "version.h" +#include "komodo_defs.h" namespace CCUpgrades { @@ -34,7 +35,7 @@ namespace CCUpgrades { const int64_t CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT = 100000000; // TBD const int64_t CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT = 100000000; // TBD const int64_t CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT = 89940; // approx 17 May 2022 10:00a.m. UTC - const int64_t CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP = 1655212904; // test 14 June 2022, to be actualised + const int64_t CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP = nS6Timestamp; // bound to annual NN S6 update const int64_t CCMIXEDMODE_SUBVER_1_DIMXY33_TIMESTAMP = 1653064202; // test HF 20 May 2022 // latest protocol version: From 557dff588178eed0a613f4813a6eb18ca56f86ac Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 14 Jun 2022 12:11:09 +0500 Subject: [PATCH 301/348] remove tests chain upgrades --- src/cc/CCupgrades.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cc/CCupgrades.cpp b/src/cc/CCupgrades.cpp index 473c73c5c0f..7cc2c5f9bd2 100644 --- a/src/cc/CCupgrades.cpp +++ b/src/cc/CCupgrades.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2021 The SuperNET Developers. * + * Copyright © 2022 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -42,11 +42,11 @@ namespace CCUpgrades { // init a chain if you plan to upgrade it init("TOKEL", CCOLDDEFAULT_PROTOCOL_VERSION); init("TKLTEST", CCOLDDEFAULT_PROTOCOL_VERSION); - init("DIMXY24", CCOLDDEFAULT_PROTOCOL_VERSION); - init("DIMXY28", CCOLDDEFAULT_PROTOCOL_VERSION); + //init("DIMXY24", CCOLDDEFAULT_PROTOCOL_VERSION); + //init("DIMXY28", CCOLDDEFAULT_PROTOCOL_VERSION); init("TKLTEST2", CCOLDDEFAULT_PROTOCOL_VERSION); - init("DIMXY32", CCOLDDEFAULT_PROTOCOL_VERSION); - init("DIMXY33", CCOLDDEFAULT_PROTOCOL_VERSION); + //init("DIMXY32", CCOLDDEFAULT_PROTOCOL_VERSION); + //init("DIMXY33", CCOLDDEFAULT_PROTOCOL_VERSION); // CCUPGID_ASSETS_OPDROP_VALIDATE_FIX activation addUpgradeActive("TOKEL", CCUPGID_ASSETS_OPDROP_VALIDATE_FIX, CCASSETS_OPDROP_FIX_TOKEL_HEIGHT, CCOLDDEFAULT_PROTOCOL_VERSION); @@ -55,11 +55,11 @@ namespace CCUpgrades { // CCUPGID_MIXEDMODE_SUBVER_1 activation addUpgradeActive("TOKEL", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TOKEL_TIMESTAMP, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); // bound to S6 NN HF addUpgradeActive("TKLTEST", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); - addUpgradeActive("DIMXY24", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); - addUpgradeActive("DIMXY28", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); - addUpgradeActive("DIMXY32", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + //addUpgradeActive("DIMXY24", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY24_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + //addUpgradeActive("DIMXY28", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY28_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + //addUpgradeActive("DIMXY32", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY32_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); addUpgradeActive("TKLTEST2", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_TKLTEST2_HEIGHT, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); - addUpgradeActive("DIMXY33", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY33_TIMESTAMP, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); + //addUpgradeActive("DIMXY33", CCUPGID_MIXEDMODE_SUBVER_1, CCMIXEDMODE_SUBVER_1_DIMXY33_TIMESTAMP, CCMIXEDMODE_SUBVER_1_PROTOCOL_VERSION); // add more chains here... // ... From 2d046c16a8f23772207684624977c9367054c2f7 Mon Sep 17 00:00:00 2001 From: dimxy Date: Thu, 16 Jun 2022 19:35:37 +0500 Subject: [PATCH 302/348] check nspv response allocated var --- src/komodo_nSPV_fullnode.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 5e2209b4667..800ff039a1f 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -770,6 +770,8 @@ int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n) rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id); response=rpc_result.write(); ptr->json = (char*)malloc(response.size()+1); + if (ptr->json == nullptr) + throw JSONRPCError(RPC_OUT_OF_MEMORY, "Cannot allocate memory for response"); strcpy(ptr->json, response.c_str()); len+=response.size(); return (len); From 655ec8261d89a3f31d2ad281a2c586c6dcdd4215 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 17 Jun 2022 12:25:02 +0500 Subject: [PATCH 303/348] removed unused komodo_opreturn call --- src/komodo_events.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/komodo_events.h b/src/komodo_events.h index 5500a341eb2..2afb0e1c989 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -103,8 +103,8 @@ void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t heigh O.oplen = (int32_t)(opretlen + sizeof(O)); komodo_eventadd(sp,height,symbol,KOMODO_EVENT_OPRETURN,opret,O.oplen); free(opret); - if ( sp != 0 ) - komodo_opreturn(height,value,buf,opretlen,txid,vout,symbol); + //if ( sp != 0 ) + // komodo_opreturn(height,value,buf,opretlen,txid,vout,symbol); } } From 79dbc20aac4a0f168c74d4d2223a6a74c1c9dc21 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 17 Jun 2022 16:08:38 +0500 Subject: [PATCH 304/348] check nft data evalcode value --- src/cc/CCtokens.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 79d9c5b8774..bb6bbe61dd3 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -141,7 +141,7 @@ CAmount TokensV1::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const // call extra data validators for (auto const &vd : vdatas) - if (vd.size() > 0 && vd[0] != 0) + if (vd.size() > 0 && vd[0] != 0 && vd[0] != cp->evalcode) // vd[0] is additional evalcode to validate tokendata if (!SubcallCCValidate(eval, vd[0], tx, 0)) return -1; @@ -568,7 +568,7 @@ CAmount TokensV2::CheckTokensvout(struct CCcontract_info *cp, Eval* eval, const */ // call extra data validators for (auto const &vd : vdatas) - if (vd.size() > 0 && vd[0] != 0) + if (vd.size() > 0 && vd[0] != 0 && vd[0] != cp->evalcode) // vd[0] is additional evalcode to validate tokendata if (!SubcallCCValidate(eval, vd[0], tx, 0)) return -1; From 610b68823443cca7e6ebcbf9f7129aeeccc337a4 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 17 Jun 2022 20:31:23 +0500 Subject: [PATCH 305/348] json param parsing in token rpcs --- src/rpc/tokensrpc.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index 363d3e36417..c68f2b57adf 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -138,8 +138,10 @@ UniValue tokenv2list(const UniValue& params, bool fHelp, const CPubKey& remotepk { if (params[0].getType() == UniValue::VOBJ) jsonParams = params[0].get_array(); - else if (params[0].getType() == UniValue::VSTR) // json in quoted string '{...}' - jsonParams.read(params[0].get_str().c_str()); + else if (params[0].getType() == UniValue::VSTR) { // json in quoted string '{...}' + if (!jsonParams.read(params[0].get_str().c_str())) + return MakeResultError("parameter must be a valid json object\n"); + } if (jsonParams.getType() != UniValue::VOBJ) throw runtime_error("parameter 1 must be a json object"); @@ -222,8 +224,10 @@ UniValue tokenorders(const std::string& name, const UniValue& params, bool fHelp { if (params[1].getType() == UniValue::VOBJ) jsonParams = params[1].get_array(); - else if (params[1].getType() == UniValue::VSTR) // json in quoted string '{...}' - jsonParams.read(params[1].get_str().c_str()); + else if (params[1].getType() == UniValue::VSTR) { // json in quoted string '{...}' + if (!jsonParams.read(params[1].get_str().c_str())) + return MakeResultError("parameter 2 must be a valid json object\n"); + } if (jsonParams.getType() != UniValue::VOBJ) throw runtime_error("parameter 2 must be a json object"); @@ -711,8 +715,10 @@ UniValue tokenv2transferMofN(const UniValue& params, bool fHelp, const CPubKey& UniValue jsonParams(UniValue::VOBJ); if (params[0].getType() == UniValue::VOBJ) jsonParams = params[0].get_obj(); - else if (params[0].getType() == UniValue::VSTR) // json in quoted string '{...}' - jsonParams.read(params[0].get_str().c_str()); + else if (params[0].getType() == UniValue::VSTR) { // json in quoted string '{...}' + if (!jsonParams.read(params[0].get_str().c_str())) + return MakeResultError("parameter 1 must be a valid json object\n"); + } if (jsonParams.getType() != UniValue::VOBJ) return MakeResultError("parameter 1 must be object\n"); @@ -1148,8 +1154,10 @@ UniValue addccv2signature(const UniValue& params, bool fHelp, const CPubKey& rem vuint8_t vtx = ParseHex(params[0].get_str().c_str()); if (params[1].getType() == UniValue::VARR) jsonParams = params[1].get_array(); - else if (params[1].getType() == UniValue::VSTR) // json in quoted string '{...}' - jsonParams.read(params[1].get_str().c_str()); + else if (params[1].getType() == UniValue::VSTR) { // json in quoted string '{...}' + if (!jsonParams.read(params[1].get_str().c_str())) + return MakeResultError("parameter 2 must be a valid json object\n"); + } if (jsonParams.getType() != UniValue::VARR) throw runtime_error("parameter 2 must be array\n"); @@ -1390,8 +1398,10 @@ UniValue createccevaltx(const UniValue& params, bool fHelp, const CPubKey& remot UniValue jsonParams(UniValue::VOBJ); if (params[0].getType() == UniValue::VOBJ) jsonParams = params[0].get_obj(); - else if (params[0].getType() == UniValue::VSTR) // json in quoted string '{...}' - jsonParams.read(params[0].get_str().c_str()); + else if (params[0].getType() == UniValue::VSTR) { // json in quoted string '{...}' + if (!jsonParams.read(params[0].get_str().c_str())) + return MakeResultError("parameter must be a valid json object\n"); + } if (jsonParams.getType() != UniValue::VOBJ) return MakeResultError("parameter must be an object\n"); From c32a70a28d85c7e1fcd4e502c826f76476bb0ef0 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 19 Jun 2022 12:56:23 +0500 Subject: [PATCH 306/348] faucetaddccinputs has the fixed amount --- src/rpc/ccutilsrpc.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/rpc/ccutilsrpc.cpp b/src/rpc/ccutilsrpc.cpp index 35f6bbd58c0..2f994b5ba4b 100644 --- a/src/rpc/ccutilsrpc.cpp +++ b/src/rpc/ccutilsrpc.cpp @@ -282,22 +282,17 @@ UniValue searchforpubkey(const UniValue& params, bool fHelp, const CPubKey& remo UniValue faucetaddccinputs(const UniValue& params, bool fHelp, const CPubKey& remotepk) { - if (fHelp || params.size() != 1) + if (fHelp || params.size() > 1) { - string msg = "faucetaddccinputs amount\n" + string msg = "faucetaddccinputs [amount]\n" "\nReturns a new tx with added normal inputs and previous txns. Note that the caller must add the change output\n" "\nArguments:\n" //"address which utxos are added from\n" - "amount (in satoshi) which will be added as normal inputs (equal or more)\n" + "amount is deprecated and set to FAUCETSIZE\n" "Result: json object with created tx and added vin txns\n\n"; throw runtime_error(msg); } - /*std::string address = params[0].get_str(); - if (!CBitcoinAddress(address.c_str()).IsValid()) - throw runtime_error("address invalid");*/ - CAmount amount = atoll(params[0].get_str().c_str()); - if (amount <= 0) - throw runtime_error("amount invalid"); + CAmount amount = FAUCETSIZE; CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::vector vintxns; @@ -316,7 +311,6 @@ UniValue faucetaddccinputs(const UniValue& params, bool fHelp, const CPubKey& re vintxns.push_back(tx); } - UniValue result (UniValue::VOBJ); UniValue array (UniValue::VARR); From 5f447945bf97a58ec37d8a659e51199e5930914e Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 19 Jun 2022 12:57:19 +0500 Subject: [PATCH 307/348] disabled internal rpcs --- src/komodo_websockets.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/komodo_websockets.cpp b/src/komodo_websockets.cpp index 5dd3d0a7f2c..a6bd09a34f3 100644 --- a/src/komodo_websockets.cpp +++ b/src/komodo_websockets.cpp @@ -247,7 +247,6 @@ static void RemoveWsNode(CWsNodePtr pNode) // returns true if message was recognized bool ProcessWsMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, int64_t nTimeReceived) { - if (strCommand == "version") { // Each connection can only send one version message @@ -806,9 +805,10 @@ class CWebSocketServer : public CWsEndpointWrapper { return !fWebSocketsInWarmup; } + /* test password std::string get_password() { return "test"; - } + } */ /* enable for tls context_ptr on_tls_init(tls_mode mode, websocketpp::connection_hdl hdl) { @@ -1661,6 +1661,7 @@ UniValue GetWsPeers() } // temp rpc to dump addrman table. TODO: remove this code +/* UniValue printaddrman(const UniValue& params, bool fHelp, const CPubKey& remotepk) { if (fHelp || params.size() != 0) @@ -1690,7 +1691,9 @@ UniValue printaddrman(const UniValue& params, bool fHelp, const CPubKey& remotep return result; } +*/ +/* // temp rpc to dump addrman table. TODO: remove this code UniValue printwsaddrman(const UniValue& params, bool fHelp, const CPubKey& remotepk) { @@ -1722,6 +1725,7 @@ UniValue printwsaddrman(const UniValue& params, bool fHelp, const CPubKey& remot return result; } +*/ UniValue getwspeers(const UniValue& params, bool fHelp, const CPubKey& remotepk) { @@ -1734,8 +1738,8 @@ UniValue getwspeers(const UniValue& params, bool fHelp, const CPubKey& remotepk) static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- - { "hidden", "printaddrman", &ws::printaddrman, true }, - { "hidden", "printwsaddrman", &ws::printwsaddrman, true }, +// { "hidden", "printaddrman", &ws::printaddrman, true }, +// { "hidden", "printwsaddrman", &ws::printwsaddrman, true }, { "hidden", "getwspeers", &ws::getwspeers, true }, }; From ecca8165a36d9b0508c5ee4159a1ff9532fc994e Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 20 Jun 2022 00:52:18 +0500 Subject: [PATCH 308/348] websockets temp disabled --- configure.ac | 6 ++++-- depends/packages/packages.mk | 4 ++-- zcutil/build-mac.sh | 14 +++++++------- zcutil/build-win.sh | 14 +++++++------- zcutil/build.sh | 14 +++++++------- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index 08372eb4a14..4177bee26da 100644 --- a/configure.ac +++ b/configure.ac @@ -634,8 +634,10 @@ fi dnl enable websockets AC_MSG_CHECKING([if websockets should be enabled]) if test x$enable_websockets != xno; then - AC_MSG_RESULT(yes) - AC_DEFINE_UNQUOTED([ENABLE_WEBSOCKETS],[1],[Define to 1 to enable websockets listener]) + AC_MSG_RESULT(no) + # AC_MSG_RESULT(yes) + # disable websockets for full code audit + # AC_DEFINE_UNQUOTED([ENABLE_WEBSOCKETS],[1],[Define to 1 to enable websockets listener]) else AC_MSG_RESULT(no) fi diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 88369698bce..480540416bb 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -47,8 +47,8 @@ native_packages := native_ccache wallet_packages=bdb ifeq ($(host_os),linux) - packages := boost openssl libevent zeromq $(zcash_packages) googletest libcurl websocketspp #googlemock + packages := boost openssl libevent zeromq $(zcash_packages) googletest libcurl # websocketspp #googlemock else - packages := boost openssl libevent zeromq $(zcash_packages) libcurl googletest websocketspp #googlemock + packages := boost openssl libevent zeromq $(zcash_packages) libcurl googletest # websocketspp #googlemock endif diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index 458e16caf50..89bda70d76e 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -28,7 +28,7 @@ $0 [ --enable-lcov ] [ --enable-websockets ] [ --enable-debug ] [ MAKEARGS... ] source. MAKEARGS are applied to both dependencies and Komodo itself. If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. - If --enable-websockets is passed then websockets support is added for nSPV protocol + If --enable-websockets is passed then websockets support is added for nSPV protocol (disabled for now) If --enable-debug is passed, Komodo is built with debugging information. It must be passed after the previous arguments, if present. EOF @@ -46,12 +46,12 @@ then fi # If --enable-websockets is the next argument, enable websockets support for nspv clients: -WEBSOCKETS_ARG='' -if [ "x${1:-}" = 'x--enable-websockets' ] -then - WEBSOCKETS_ARG='--enable-websockets=yes' - shift -fi +# WEBSOCKETS_ARG='' +# if [ "x${1:-}" = 'x--enable-websockets' ] +# then +# WEBSOCKETS_ARG='--enable-websockets=yes' +# shift +#fi # If --enable-debug is the next argument, enable debugging DEBUGGING_ARG='' diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index b625b26f534..9d76f71b956 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -10,14 +10,14 @@ UTIL_DIR="$(dirname "$(readlink -f "$0")")" BASE_DIR="$(dirname "$(readlink -f "$UTIL_DIR")")" PREFIX="$BASE_DIR/depends/$HOST" - +# disable for code audit # If --enable-websockets is the next argument, enable websockets support for nspv clients: -WEBSOCKETS_ARG='' -if [ "x${1:-}" = 'x--enable-websockets' ] -then -WEBSOCKETS_ARG='--enable-websockets=yes' -shift -fi +# WEBSOCKETS_ARG='' +# if [ "x${1:-}" = 'x--enable-websockets' ] +# then +# WEBSOCKETS_ARG='--enable-websockets=yes' +# shift +# fi # make dependences cd depends/ && make HOST=$HOST V=1 NO_QT=1 diff --git a/zcutil/build.sh b/zcutil/build.sh index 8ec5c3255cb..9d0e444d70a 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -55,7 +55,7 @@ $0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] If --enable-proton is passed, Komodo is configured to build the Apache Qpid Proton library required for AMQP support. This library is not built by default. It must be passed after the test/mining arguments, if present. - If --enable-websockets is passed, Komodo is configured to build with websockets support for nspv protocol + If --enable-websockets is passed, Komodo is configured to build with websockets support for nspv protocol (disabled for now) If --enable-debug is passed, Komodo is built with debugging information. It must be passed after the previous arguments, if present. EOF @@ -112,12 +112,12 @@ else fi # If --enable-websockets is the next argument, enable websockets support for nspv clients: -WEBSOCKETS_ARG='' -if [ "x${1:-}" = 'x--enable-websockets' ] -then -WEBSOCKETS_ARG='--enable-websockets=yes' -shift -fi +# WEBSOCKETS_ARG='' +# if [ "x${1:-}" = 'x--enable-websockets' ] +# then +# WEBSOCKETS_ARG='--enable-websockets=yes' +# shift +# fi eval "$MAKE" --version as --version From 369a0fe187d4ca2fc8f7725c1b73f8f975671b21 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 20 Jun 2022 00:57:10 +0500 Subject: [PATCH 309/348] fixed unbound websocket var --- zcutil/build-mac.sh | 2 +- zcutil/build-win.sh | 2 +- zcutil/build.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index 89bda70d76e..c4e0cb518df 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -46,7 +46,7 @@ then fi # If --enable-websockets is the next argument, enable websockets support for nspv clients: -# WEBSOCKETS_ARG='' +WEBSOCKETS_ARG='' # if [ "x${1:-}" = 'x--enable-websockets' ] # then # WEBSOCKETS_ARG='--enable-websockets=yes' diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index 9d76f71b956..e1546d18bae 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -12,7 +12,7 @@ PREFIX="$BASE_DIR/depends/$HOST" # disable for code audit # If --enable-websockets is the next argument, enable websockets support for nspv clients: -# WEBSOCKETS_ARG='' +WEBSOCKETS_ARG='' # if [ "x${1:-}" = 'x--enable-websockets' ] # then # WEBSOCKETS_ARG='--enable-websockets=yes' diff --git a/zcutil/build.sh b/zcutil/build.sh index 9d0e444d70a..8b40d0bab8f 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -112,7 +112,7 @@ else fi # If --enable-websockets is the next argument, enable websockets support for nspv clients: -# WEBSOCKETS_ARG='' +WEBSOCKETS_ARG='' # if [ "x${1:-}" = 'x--enable-websockets' ] # then # WEBSOCKETS_ARG='--enable-websockets=yes' From 2dc57d10832a320fe9f287aacd8f37a6851f9e02 Mon Sep 17 00:00:00 2001 From: NutellaLicka Date: Mon, 20 Jun 2022 16:54:13 +1000 Subject: [PATCH 310/348] README updates Readme updates only addition of blog link Random link fix --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f08c388114f..9a00be2da70 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ To NFT and Beyond #### What Tokel offers: - The blockchain that facilitates the tokens and NFTs. -- An open-sourced all-in-one ]GUI application](https://github.com/TokelPlatform/tokel_dapp). +- An open-sourced all-in-one [GUI application](https://github.com/TokelPlatform/tokel_dapp). - DEX functionality for all tokens/NFTs created on Tokel. - A free-to-use test blockchain (TKLTEST). - Easy to use integrations (nSPV) @@ -60,6 +60,7 @@ https://github.com/TokelPlatform/tokel_dapp - Tokel Website: [https://tokel.io](https://tokel.io) - Tokel Block Explorer: [https://explorer.tokel.io](https://explorer.tokel.io) - Tokel Discord: [Tokel Discord Invitation](http://discord.tokel.io) +- Tokel Blog: [Tokel Blog](https://tokel.io/blog/) - Email: [contact@tokel.io](mailto:contact@tokel.io) - Whitepaper: [Tokel Paper](https://tokel.io/TokelPaper1stEdition.pdf) - Knowledgebase & How-to: [Tokel Documentation](https://docs.tokel.io) From d2e98de9d1ac6e26c20d540d5a8d7a493e2cf5fd Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 28 Jun 2022 22:20:42 +0500 Subject: [PATCH 311/348] fix fingerprint buf size --- src/cryptoconditions/src/cryptoconditions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index fe27e0e9a01..451a938f693 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -179,7 +179,7 @@ void asnCondition(const CC *cond, Condition_t *asn) { default: return; }; choice->cost = cc_getCost(cond); - choice->fingerprint.buf = calloc(1, fingerprintSize); + choice->fingerprint.buf = calloc(1, 32); cond->type->fingerprint(cond, choice->fingerprint.buf); choice->fingerprint.size = fingerprintSize; } From e0982435d8346ab9ffd58d5c04c29e14ff42bf75 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 28 Jun 2022 21:04:59 +0500 Subject: [PATCH 312/348] ext test for token Raddress --- src/test-komodo-cc/test-assets.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index b2eed97dd33..13df21a8c33 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -2873,15 +2873,24 @@ TEST_F(TestAssetsCC, tokenv2transfer_raddress) EXPECT_TRUE(eval.AddTx(mcreatetx)); uint256 tokenid = mcreatetx.GetHash(); - std::vector dests = { pk2 }; + std::vector dests = { pk2.GetID() }; // dest R-address - std::vector tokenaddrs = GetTokenV2IndexKeys(pk1); - CMutableTransaction mtransfertx = MakeTokenV2TransferTx(pk1, 0, tokenid, tokenaddrs, {}, 1, dests, 1, false, false); - ASSERT_FALSE(CTransaction(mtransfertx).IsNull()); - EXPECT_TRUE(eval.AddTx(mtransfertx)); - CAmount bal = TokenV2Balance(pk2, tokenid); + std::vector tokenaddrs1 = GetTokenV2IndexKeys(pk1); + CMutableTransaction mtransfertx1 = MakeTokenV2TransferTx(pk1, 0, tokenid, tokenaddrs1, {}, 1, dests, 1, false, false); + ASSERT_FALSE(CTransaction(mtransfertx1).IsNull()); + EXPECT_TRUE(eval.AddTx(mtransfertx1)); + CAmount bal1 = TokenV2Balance(pk2, tokenid); // std::cerr << __func__ << " TokenV2Balance(pk2, tokenid)=" << bal << " mtransfertxid=" << mtransfertx.GetHash().GetHex() << " reason=" << eval.state.GetRejectReason() << std::endl; - EXPECT_TRUE(bal == 1); + EXPECT_TRUE(bal1 == 1); + + // try to spend + std::vector tokenaddrs2 = GetTokenV2IndexKeys(pk2); + CMutableTransaction mtransfertx2 = MakeTokenV2TransferTx(pk2, 0, tokenid, tokenaddrs2, {}, 1, dests, 1, false, false); + ASSERT_FALSE(CTransaction(mtransfertx2).IsNull()); + EXPECT_TRUE(eval.AddTx(mtransfertx2)); + CAmount bal2 = TokenV2Balance(pk2, tokenid); + EXPECT_TRUE(bal2 == 1); + } // test burn pk From 55f743677aaf17f46e8c2653b4e6e3d0a5386a1c Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 00:12:44 +0500 Subject: [PATCH 313/348] fix ccv1 validation --- src/cc/CCutils.cpp | 2 +- src/main.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 3a33b5dba94..edf8867e883 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -378,7 +378,7 @@ bool _GetCCaddress(char *destaddr,uint8_t evalcode,CPubKey pk,bool mixed) if (payoutCond.get() != 0 ) { //if (mixed) CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr,CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); + Getscriptaddress(destaddr,CCPubKey(payoutCond.get(), mixed ? CC_MIXED_MODE_SUBVER_0 : CC_OLD_V1_SUBVER)); } return(destaddr[0] != 0); } diff --git a/src/main.cpp b/src/main.cpp index 08d4058e754..443097bba4a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3897,6 +3897,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::vector vChecks; if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, pindex->GetBlockTime(), pindex->GetHeight(), evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) return false; + control.Add(vChecks); } { // check tx outputs including coinbases From 59b087b704e266e691c3faea0e44a8abe0ef4862 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 00:13:27 +0500 Subject: [PATCH 314/348] added GetCurrentHeightCompat old style for oracles rewards --- src/cc/betprotocol.cpp | 2 +- src/cc/disputepayout.cpp | 2 +- src/cc/eval.cpp | 4 ++++ src/cc/eval.h | 1 + src/cc/oracles.cpp | 2 +- src/cc/rewards.cpp | 2 +- 6 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/cc/betprotocol.cpp b/src/cc/betprotocol.cpp index 0724f2fea7c..bc2875adfcb 100644 --- a/src/cc/betprotocol.cpp +++ b/src/cc/betprotocol.cpp @@ -264,7 +264,7 @@ bool Eval::DisputePayout(AppVM &vm, std::vector params, const CTransact if (!GetTxConfirmed(disputeTx.vin[0].prevout.hash, sessionTx, sessionBlock)) return Error("couldnt-get-parent"); - if (GetCurrentHeight() < sessionBlock.GetHeight() + waitBlocks) + if (GetCurrentHeightCompat() < sessionBlock.GetHeight() + waitBlocks) return Invalid("dispute-too-soon"); // Not yet } diff --git a/src/cc/disputepayout.cpp b/src/cc/disputepayout.cpp index 60924b00bae..1d0f8f1f8d9 100644 --- a/src/cc/disputepayout.cpp +++ b/src/cc/disputepayout.cpp @@ -61,7 +61,7 @@ bool Eval::DisputePayout(AppVM &vm, std::vector params, const CTransact if (!GetTxConfirmed(disputeTx.vin[0].prevout.hash, sessionTx, sessionBlock)) return Error("couldnt-get-parent"); - if (GetCurrentHeight() < sessionBlock.GetHeight() + waitBlocks) + if (GetCurrentHeightCompat() < sessionBlock.GetHeight() + waitBlocks) return Invalid("dispute-too-soon"); // Not yet } diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 350647d5472..e0e78cf130a 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -164,6 +164,10 @@ unsigned int Eval::GetCurrentHeight() const { return nCurrentHeight; } +unsigned int Eval::GetCurrentHeightCompat() const +{ + return chainActive.Height(); +} bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const { diff --git a/src/cc/eval.h b/src/cc/eval.h index 6686c83fed5..224dc9f0e66 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -117,6 +117,7 @@ class Eval virtual int64_t GetCurrentTime() const; void SetCurrentTime(int64_t nTimeIn) { nCurrentTime = nTimeIn; } virtual unsigned int GetCurrentHeight() const; + virtual unsigned int GetCurrentHeightCompat() const; void SetCurrentHeight(int32_t nHeightIn) { nCurrentHeight = nHeightIn; } virtual bool GetSpendsConfirmed(uint256 hash, std::vector &spends) const; virtual bool GetBlock(uint256 hash, CBlockIndex& blockIdx) const; diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 18fe528e25f..4cca6ebb088 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -498,7 +498,7 @@ bool OraclesValidate(struct CCcontract_info* cp, Eval* eval, const CTransaction& // vout.2: marker from oraclesfund tx to normal pubkey address (activation on Jul 15th 2019 00:00) // vout.n-2: change, if any // vout.n-1: opreturn with createtxid, pubkey and price per data point - if (GetLatestTimestamp(eval->GetCurrentHeight()) > PUBKEY_SPOOFING_FIX_ACTIVATION) { + if (GetLatestTimestamp(eval->GetCurrentHeightCompat()) > PUBKEY_SPOOFING_FIX_ACTIVATION) { if (tx.vout.size() < 1 || DecodeOraclesOpRet(tx.vout.back().scriptPubKey, oracletxid, tmppk, amount) != 'R') return eval->Invalid("invalid oraclesregister OP_RETURN data!"); else if (!eval->GetTxUnconfirmed(oracletxid, tmptx, hashblock)) diff --git a/src/cc/rewards.cpp b/src/cc/rewards.cpp index 7fc86d1f2d4..3b498ff7185 100644 --- a/src/cc/rewards.cpp +++ b/src/cc/rewards.cpp @@ -297,7 +297,7 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime, dummy) ) return eval->Invalid("txfee is too high"); amount = vinTx.vout[0].nValue; - reward = RewardsCalc((int64_t)amount,tx.vin[0].prevout.hash,(int64_t)APR,(int64_t)minseconds,(int64_t)maxseconds,GetLatestTimestamp(eval->GetCurrentHeight())); + reward = RewardsCalc((int64_t)amount,tx.vin[0].prevout.hash,(int64_t)APR,(int64_t)minseconds,(int64_t)maxseconds,GetLatestTimestamp(eval->GetCurrentHeightCompat())); if ( reward == 0 ) return eval->Invalid("no eligible rewards"); if ( numvins == 1 && tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) From 0eeb59beaba268a14cc1af316ad235baf9710b43 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 02:19:41 +0500 Subject: [PATCH 315/348] fix py ci tests for 'C' addresses --- qa/pytest_komodo/cc_modules/test_oracles.py | 5 +++-- qa/pytest_komodo/cc_modules/test_token.py | 8 ++++---- qa/pytest_komodo/cc_modules/test_unspentccundex.py | 6 +++--- qa/pytest_komodo/cc_modules/util.py | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/qa/pytest_komodo/cc_modules/test_oracles.py b/qa/pytest_komodo/cc_modules/test_oracles.py index 71c078ed7a9..8b7a5ce3da8 100644 --- a/qa/pytest_komodo/cc_modules/test_oracles.py +++ b/qa/pytest_komodo/cc_modules/test_oracles.py @@ -27,14 +27,14 @@ def test_oracles(test_params): for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' result = rpc.oraclesaddress(pubkey) assert_success(result) for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' # there are no oracles created yet if is_fresh_chain: @@ -247,6 +247,7 @@ def test_oracles(test_params): # checking data for s type result = rpc.oraclessamples(globals()["oracle_{}".format("s")], batonaddr_s, "1") + print('result=', result) assert "['Anton']" == str(result["samples"][0]['data']) # checking data for S type diff --git a/qa/pytest_komodo/cc_modules/test_token.py b/qa/pytest_komodo/cc_modules/test_token.py index 376247db756..5f8e7c5a9b7 100644 --- a/qa/pytest_komodo/cc_modules/test_token.py +++ b/qa/pytest_komodo/cc_modules/test_token.py @@ -34,25 +34,25 @@ def test_token(test_params): assert_success(result) for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' result = call_token_rpc(rpc, "token"+v+"address", pubkey) assert_success(result) for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' result = call_token_rpc(rpc, "assetsaddress") assert_success(result) for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' result = call_token_rpc(rpc, "assetsaddress", pubkey) assert_success(result) for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' # there are no tokens created yet # TODO: this test conflicts with heir test because token creating for heir diff --git a/qa/pytest_komodo/cc_modules/test_unspentccundex.py b/qa/pytest_komodo/cc_modules/test_unspentccundex.py index bf72dd61793..9e50074f724 100644 --- a/qa/pytest_komodo/cc_modules/test_unspentccundex.py +++ b/qa/pytest_komodo/cc_modules/test_unspentccundex.py @@ -28,7 +28,7 @@ def test_ccindex(test_params): assert_success(result) for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' # get token cc address for pubkey: result = rpc.tokenaddress(pubkey) @@ -36,7 +36,7 @@ def test_ccindex(test_params): pubkeyTokenCCAddress = "" for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' if x == 'pubkey Tokens CC Address': pubkeyTokenCCAddress = result[x] @@ -46,7 +46,7 @@ def test_ccindex(test_params): pubkey1TokenCCAddress = "" for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' if x == 'pubkey Tokens CC Address': pubkey1TokenCCAddress = result[x] diff --git a/qa/pytest_komodo/cc_modules/util.py b/qa/pytest_komodo/cc_modules/util.py index 001817b1cdf..accdb16de01 100644 --- a/qa/pytest_komodo/cc_modules/util.py +++ b/qa/pytest_komodo/cc_modules/util.py @@ -34,7 +34,7 @@ def mine_and_waitconfirms(txid, proxy, confs_req=2): # should be used after tx try: confirmations_amount = proxy.getrawtransaction(txid, 1)['confirmations'] if confirmations_amount < confs_req: - print("\ntx is not confirmed yet! Let's wait a little more") + print("\ntx is not confirmed yet! Let's wait a little more", txid) time.sleep(5) else: print("\ntx confirmed") From dedd1c4165dc8c6e41e9839d15eaebf23715ac69 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 19:24:31 +0500 Subject: [PATCH 316/348] fix tokentransfer[many] v1 (for tests) --- src/rpc/tokensrpc.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index c68f2b57adf..919715e1bf6 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -564,9 +564,11 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b return MakeResultError("destination as address not active yet"); if (dest.which() != TX_PUBKEYHASH && dest.which() != TX_PUBKEY) return MakeResultError("invalid destination pubkey or address"); + if (V::EvalCode() == EVAL_TOKENS && dest.which() != TX_PUBKEY) // address not supported for tokens 1 + return MakeResultError("invalid destination pubkey"); - // after subver_1 upgrade only addresses always will be used as destination, pubkeys are converted to addresses - if (dest.which() == TX_PUBKEY && CCUpgrades::IsUpgradeActive(nTime, nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) + // after subver_1 upgrade only addresses always will be used as destination, pubkeys are converted to addresses (for tokens v2) + if (V::EvalCode() == EVAL_TOKENSV2 && dest.which() == TX_PUBKEY && CCUpgrades::IsUpgradeActive(nTime, nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) dests.push_back(boost::get(dest).GetID()); else dests.push_back(dest); // address or pubkey @@ -643,12 +645,14 @@ UniValue tokentransfermany(const std::string& name, const UniValue& params, bool Myprivkey(mypriv); std::vector srctokenaddrs; std::vector> probes; - if (V::IsMixed() == EVAL_TOKENS) { + if (V::EvalCode() == EVAL_TOKENS) { CCwrapper probeCond; probeCond.reset( MakeCCcond1(V::EvalCode(), mypk) ); - char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; - GetTokensCCaddress(cpTokens, tokenaddr, mypk, V::IsMixed()); - srctokenaddrs.push_back(tokenaddr); + //char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; + //GetTokensCCaddress(cpTokens, tokenaddr, mypk, V::IsMixed()); + //srctokenaddrs.push_back(tokenaddr); + srctokenaddrs = GetTokenV1IndexKeys(mypk); + probes.push_back({probeCond, mypriv}); } From 2ec926601bd0aa19f2f33c2114da24e8afa4a9ea Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 19:25:17 +0500 Subject: [PATCH 317/348] fix GetTokenAddress for tokens v1 --- src/cc/CCutils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index edf8867e883..daa2597106e 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -404,7 +404,7 @@ static bool _GetTokensCCaddress(char *destaddr, uint8_t evalcode1, uint8_t evalc { //if (mixed) // CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); + Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), mixed ? CC_MIXED_MODE_SUBVER_0 : CC_OLD_V1_SUBVER)); } return(destaddr[0] != 0); } @@ -425,7 +425,7 @@ bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubK if ( payoutCond.get() != 0 ) { //if (mixed) CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr,CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); + Getscriptaddress(destaddr,CCPubKey(payoutCond.get(), mixed ? CC_MIXED_MODE_SUBVER_0 : CC_OLD_V1_SUBVER)); } return(destaddr[0] != 0); } @@ -443,7 +443,7 @@ bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey { //if (mixed) // CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); + Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), mixed ? CC_MIXED_MODE_SUBVER_0 : CC_OLD_V1_SUBVER)); } return(destaddr[0] != 0); } From 7d1c516f78ea19042b981d6157af8e55ae975e7e Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 19:25:51 +0500 Subject: [PATCH 318/348] fix token py tests for tokens v1 --- qa/pytest_komodo/basic/pytest_util.py | 2 +- qa/pytest_komodo/cc_modules/test_token.py | 44 +++++++++++------------ qa/pytest_komodo/cc_modules/util.py | 2 +- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/qa/pytest_komodo/basic/pytest_util.py b/qa/pytest_komodo/basic/pytest_util.py index 27af5501ef0..e9c9d9c3091 100644 --- a/qa/pytest_komodo/basic/pytest_util.py +++ b/qa/pytest_komodo/basic/pytest_util.py @@ -80,7 +80,7 @@ def mine_and_waitconfirms(txid, proxy, confs_req=2): # should be used after tx try: confirmations_amount = proxy.getrawtransaction(txid, 1)['confirmations'] if confirmations_amount < confs_req: - print("\ntx is not confirmed yet! Let's wait a little more") + print("\ntx is not confirmed yet! Let's wait a little more", txid, 'confs=', confirmations_amount, 'required=', confirmations_amount) time.sleep(5) else: print("\ntx confirmed") diff --git a/qa/pytest_komodo/cc_modules/test_token.py b/qa/pytest_komodo/cc_modules/test_token.py index 5f8e7c5a9b7..3c857618016 100644 --- a/qa/pytest_komodo/cc_modules/test_token.py +++ b/qa/pytest_komodo/cc_modules/test_token.py @@ -30,29 +30,24 @@ def test_token(test_params): for v in ["", "v2"] : - result = call_token_rpc(rpc, "token"+v+"address") - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' or result[x][0] == 'C' - - result = call_token_rpc(rpc, "token"+v+"address", pubkey) - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' or result[x][0] == 'C' - - result = call_token_rpc(rpc, "assetsaddress") - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' or result[x][0] == 'C' - - result = call_token_rpc(rpc, "assetsaddress", pubkey) - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' or result[x][0] == 'C' + result = call_token_rpc(rpc, "token"+v+"indexkey", pubkey) + if v == '': # for v2 a diff result + assert_success(result) + for x in result.keys(): + if x.find('ddress') > 0: + assert result[x][0] == 'R' or result[x][0] == 'C' + else : # v2 index keys: + for x in result: + assert x[0] == 'C' + + result = call_token_rpc(rpc, "assets"+v+"indexkey", pubkey) + if v == '': # for v2 a diff result + assert_success(result) + for x in result.keys(): + if x.find('ddress') > 0: + assert result[x][0] == 'R' or result[x][0] == 'C' + else : # v2 index key + assert result[0] == 'C' # there are no tokens created yet # TODO: this test conflicts with heir test because token creating for heir @@ -299,6 +294,7 @@ def test_token(test_params): # valid token transfer sendtokens = call_token_rpc(rpc, "token"+v+"transfer", tokenid, randompubkey, "1") assert sendtokens['hex'], "token"+v+"transfer tx not created" + print('tx1=', sendtokens["hex"]) send_and_mine(sendtokens["hex"], rpc) result = call_token_rpc(rpc, "token"+v+"balance", tokenid, randompubkey) assert result["balance"] == 1 @@ -306,7 +302,9 @@ def test_token(test_params): print("making valid token" + v + "transfermany...") # valid token transfer sendtokens = call_token_rpc(rpc, "token"+v+"transfermany", tokenid, randompubkey, "1") + print('transfermany result', sendtokens) assert sendtokens['hex'], "token"+v+"transfermany tx not created" + print('tx2=', sendtokens["hex"]) send_and_mine(sendtokens["hex"], rpc) result = call_token_rpc(rpc, "token"+v+"balance", tokenid, randompubkey) assert result["balance"] == 2 \ No newline at end of file diff --git a/qa/pytest_komodo/cc_modules/util.py b/qa/pytest_komodo/cc_modules/util.py index accdb16de01..92bfb960e0f 100644 --- a/qa/pytest_komodo/cc_modules/util.py +++ b/qa/pytest_komodo/cc_modules/util.py @@ -34,7 +34,7 @@ def mine_and_waitconfirms(txid, proxy, confs_req=2): # should be used after tx try: confirmations_amount = proxy.getrawtransaction(txid, 1)['confirmations'] if confirmations_amount < confs_req: - print("\ntx is not confirmed yet! Let's wait a little more", txid) + print("\ntx is not confirmed yet! Let's wait a little more", txid, 'confs=', confirmations_amount, 'required=', confs_req) time.sleep(5) else: print("\ntx confirmed") From 1943e7384357ecfc00188a413f792216e1d13f2b Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 19:36:24 +0500 Subject: [PATCH 319/348] del extra logs in py test --- qa/pytest_komodo/cc_modules/test_token.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/qa/pytest_komodo/cc_modules/test_token.py b/qa/pytest_komodo/cc_modules/test_token.py index 3c857618016..462d3a34b23 100644 --- a/qa/pytest_komodo/cc_modules/test_token.py +++ b/qa/pytest_komodo/cc_modules/test_token.py @@ -294,7 +294,6 @@ def test_token(test_params): # valid token transfer sendtokens = call_token_rpc(rpc, "token"+v+"transfer", tokenid, randompubkey, "1") assert sendtokens['hex'], "token"+v+"transfer tx not created" - print('tx1=', sendtokens["hex"]) send_and_mine(sendtokens["hex"], rpc) result = call_token_rpc(rpc, "token"+v+"balance", tokenid, randompubkey) assert result["balance"] == 1 @@ -302,9 +301,7 @@ def test_token(test_params): print("making valid token" + v + "transfermany...") # valid token transfer sendtokens = call_token_rpc(rpc, "token"+v+"transfermany", tokenid, randompubkey, "1") - print('transfermany result', sendtokens) assert sendtokens['hex'], "token"+v+"transfermany tx not created" - print('tx2=', sendtokens["hex"]) send_and_mine(sendtokens["hex"], rpc) result = call_token_rpc(rpc, "token"+v+"balance", tokenid, randompubkey) assert result["balance"] == 2 \ No newline at end of file From 71fcbe55bc3291f253ec5a92e3f757a7e9d487d5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 20:57:35 +0500 Subject: [PATCH 320/348] fix py test C address check --- qa/pytest_komodo/basic/pytest_util.py | 2 +- qa/pytest_komodo/cc_modules/test_faucet.py | 2 +- qa/pytest_komodo/cc_modules/test_heir.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qa/pytest_komodo/basic/pytest_util.py b/qa/pytest_komodo/basic/pytest_util.py index e9c9d9c3091..0ea96650eee 100644 --- a/qa/pytest_komodo/basic/pytest_util.py +++ b/qa/pytest_komodo/basic/pytest_util.py @@ -249,7 +249,7 @@ def validate_tx_pattern(txid): def validate_raddr_pattern(addr): if not isinstance(addr, str): return False - address_pattern = re.compile(r"R[a-zA-Z0-9]{33}\Z") + address_pattern = re.compile(r"[RC][a-zA-Z0-9]{33}\Z") if address_pattern.match(addr): return True else: diff --git a/qa/pytest_komodo/cc_modules/test_faucet.py b/qa/pytest_komodo/cc_modules/test_faucet.py index 876c69bf89b..7169fb32cf2 100644 --- a/qa/pytest_komodo/cc_modules/test_faucet.py +++ b/qa/pytest_komodo/cc_modules/test_faucet.py @@ -100,7 +100,7 @@ class TestFaucetCCe2e: def test_faucet_addresses(self, test_params): rpc1 = test_params.get('node1').get('rpc') pubkey = test_params.get('node1').get('pubkey') - address_pattern = re.compile(r"R[a-zA-Z0-9]{33}\Z") # normal R-addr + address_pattern = re.compile(r"[RC][a-zA-Z0-9]{33}\Z") # normal R-addr res = rpc1.faucetaddress() for key in res.keys(): diff --git a/qa/pytest_komodo/cc_modules/test_heir.py b/qa/pytest_komodo/cc_modules/test_heir.py index a5659cf9a5f..bac1c33e9fa 100644 --- a/qa/pytest_komodo/cc_modules/test_heir.py +++ b/qa/pytest_komodo/cc_modules/test_heir.py @@ -189,7 +189,7 @@ class TestHeirFunc: def test_heir_addresses(self, test_params): rpc1 = test_params.get('node1').get('rpc') pubkey = test_params.get('node2').get('pubkey') - address_pattern = re.compile(r"R[a-zA-Z0-9]{33}\Z") # normal R-addr + address_pattern = re.compile(r"[RC][a-zA-Z0-9]{33}\Z") # normal R-addr # verify all keys look like valid AC addrs res = rpc1.faucetaddress('') From 27562996fb82ec3a2a715b680ca68732c6c88ea0 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 21:18:53 +0500 Subject: [PATCH 321/348] inc tokel subversion --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4177bee26da..71ae7c0a4ae 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ dnl komodo codebase version define(_KOMODO_VERSION, 60000) dnl tokel codebase version -define(_TOKEL_VERSION, 30100) +define(_TOKEL_VERSION, 30200) AC_DEFINE(KOMODO_VERSION, _KOMODO_VERSION, [Komodo Version]) AC_DEFINE(TOKEL_VERSION, _TOKEL_VERSION, [Tokel Version]) From e52fa755e1bb707804ec77cb3b111cb895eb8190 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 22:21:22 +0500 Subject: [PATCH 322/348] py test log fixed --- qa/pytest_komodo/basic/pytest_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/pytest_komodo/basic/pytest_util.py b/qa/pytest_komodo/basic/pytest_util.py index 0ea96650eee..453758e39da 100644 --- a/qa/pytest_komodo/basic/pytest_util.py +++ b/qa/pytest_komodo/basic/pytest_util.py @@ -80,7 +80,7 @@ def mine_and_waitconfirms(txid, proxy, confs_req=2): # should be used after tx try: confirmations_amount = proxy.getrawtransaction(txid, 1)['confirmations'] if confirmations_amount < confs_req: - print("\ntx is not confirmed yet! Let's wait a little more", txid, 'confs=', confirmations_amount, 'required=', confirmations_amount) + print("\ntx is not confirmed yet! Let's wait a little more", txid, 'confs=', confirmations_amount, 'required=', confs_req) time.sleep(5) else: print("\ntx confirmed") From 0114751c30d158cd5f4cc01e54d5a2f08cf12107 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 23:33:08 +0500 Subject: [PATCH 323/348] fix cryptocondition check threshold ffil non null --- src/cryptoconditions/src/threshold.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index a7bc78b6834..f29b614182a 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -140,6 +140,10 @@ static CC *thresholdFromFulfillmentMixed(const Fulfillment_t *ffill) { { // Get the real threshold from the first ffill CC *tc = fulfillmentToCC(arrFulfills[0], flags); + if (tc == NULL) { + free(cond); + return NULL; + } if (tc->type->typeId != CC_Preimage || tc->preimageLength != 1) { cc_free(tc); free(cond); From 41646c4d2eb65ce695a6869181443b71033f0263 Mon Sep 17 00:00:00 2001 From: dimxy Date: Fri, 8 Jul 2022 23:33:45 +0500 Subject: [PATCH 324/348] disable unsupported kv py test --- qa/pytest_komodo/basic/test_blocks.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qa/pytest_komodo/basic/test_blocks.py b/qa/pytest_komodo/basic/test_blocks.py index 4117421930a..99d0bfafa1f 100644 --- a/qa/pytest_komodo/basic/test_blocks.py +++ b/qa/pytest_komodo/basic/test_blocks.py @@ -342,6 +342,8 @@ def test_getrawmempool(self, test_params): res = rpc.getrawmempool(True) assert res.get(txid).get('height') == kvheight + ''' + # kv not supported def test_kvsearch(self, test_params): test_values = { 'key': 'search_key', @@ -358,6 +360,7 @@ def test_kvsearch(self, test_params): assert res.get('key') == test_values['key'] assert res.get('keylen') == keylen assert res.get('value') == test_values['value'] + ''' def test_notaries(self, test_params): rpc = test_params.get('node1').get('rpc') From e6166b2d9ffd53200e2bae4368d41d432d33c6b0 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 9 Jul 2022 18:33:13 +0500 Subject: [PATCH 325/348] CI: added install openssl --- .github/workflows/komodo_mac_ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index 61b4b2f0a33..1af6e58b263 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -28,6 +28,7 @@ jobs: brew install wget brew install python3 brew install gmp + brew install openssl@1.1 ./zcutil/fetch-params.sh - name: Build (macOS) @@ -43,7 +44,7 @@ jobs: name: komodo-macos path: ./komodo-macos.tar.gz - macos-test-dice-token-reards-faucet-cc: + macos-test-dice-token-rewards-faucet-cc: name: Test (MacOS/Dice, Token, Faucet, Rewards) runs-on: macos-latest From d566a032c7cbda1d43fd77d8ca5ba0f727616459 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 9 Jul 2022 20:03:14 +0500 Subject: [PATCH 326/348] add openssl include to build-mac-test.sh --- .github/workflows/komodo_mac_ci.yml | 1 - zcutil/build-mac-dtest.sh | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index 1af6e58b263..fa262ef2fdc 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -28,7 +28,6 @@ jobs: brew install wget brew install python3 brew install gmp - brew install openssl@1.1 ./zcutil/fetch-params.sh - name: Build (macOS) diff --git a/zcutil/build-mac-dtest.sh b/zcutil/build-mac-dtest.sh index e1a5ece470f..0f8c88d6414 100755 --- a/zcutil/build-mac-dtest.sh +++ b/zcutil/build-mac-dtest.sh @@ -57,7 +57,7 @@ make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64 -DTESTMODE" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ +CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -I/usr/local/opt/openssl/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ ./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$DEBUGGING_ARG" make "$@" V=1 NO_GTEST=1 STATIC=1 From 6662f98d8967cb62b17efec74d58d9b630aa155f Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 9 Jul 2022 20:03:40 +0500 Subject: [PATCH 327/348] fix cpuid build for WIN32 --- src/cc/eval.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cc/eval.h b/src/cc/eval.h index 224dc9f0e66..7165b6e727f 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -16,6 +16,9 @@ #ifndef CC_EVAL_H #define CC_EVAL_H +#ifdef _WIN32 +#undef __cpuid +#endif #include #include From 79e72c37262b7a3e14d271d058d3a4fb00ccb175 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 9 Jul 2022 20:05:16 +0500 Subject: [PATCH 328/348] catch RPCError in py test --- qa/pytest_komodo/basic/pytest_util.py | 2 +- qa/pytest_komodo/cc_modules/util.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/qa/pytest_komodo/basic/pytest_util.py b/qa/pytest_komodo/basic/pytest_util.py index 453758e39da..b673fd59718 100644 --- a/qa/pytest_komodo/basic/pytest_util.py +++ b/qa/pytest_komodo/basic/pytest_util.py @@ -85,7 +85,7 @@ def mine_and_waitconfirms(txid, proxy, confs_req=2): # should be used after tx else: print("\ntx confirmed") return True - except KeyError as e: + except (KeyError, RPCError) as e: print("\ntx is in mempool still probably, let's wait a little bit more\nError: ", e) time.sleep(5) attempts += 1 diff --git a/qa/pytest_komodo/cc_modules/util.py b/qa/pytest_komodo/cc_modules/util.py index 92bfb960e0f..a1d5ea33e34 100644 --- a/qa/pytest_komodo/cc_modules/util.py +++ b/qa/pytest_komodo/cc_modules/util.py @@ -5,9 +5,10 @@ from string import ascii_uppercase try: from slickrpc import Proxy + from slickrpc.exc import RpcException as RPCError except ImportError: from bitcoinrpc.authproxy import AuthServiceProxy as Proxy - + from bitcoinrpc.authproxy import JSONRPCException as RPCError def assert_success(result): assert result['result'] == 'success' @@ -39,7 +40,7 @@ def mine_and_waitconfirms(txid, proxy, confs_req=2): # should be used after tx else: print("\ntx confirmed") return True - except KeyError as e: + except (KeyError, RPCError) as e: print("\ntx is in mempool still probably, let's wait a little bit more\nError: ", e) time.sleep(5) attempts += 1 From 0b9ebaca46495a0be66c105a4f89ec9da44c0986 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 9 Jul 2022 21:50:16 +0500 Subject: [PATCH 329/348] add openssl dir to pycurl setup for tests --- .github/workflows/komodo_mac_ci.yml | 5 +++ .github/workflows/komodo_win_ci.yml | 47 ++++++++++++++++------------- zcutil/build-mac-dtest.sh | 2 +- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index fa262ef2fdc..28f688cff2f 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -55,6 +55,7 @@ jobs: - name: Install deps (Dice, Token, Faucet, Rewards CC) run: | brew install python3 curl + python3 -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl python3 -m pip install setuptools wheel python3 -m pip install slick-bitcoinrpc pytest wget jsonschema @@ -84,6 +85,7 @@ jobs: - name: Install deps (OraclesCC) run: | brew install python3 curl + python3 -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl python3 -m pip install setuptools wheel python3 -m pip install slick-bitcoinrpc pytest wget jsonschema - name: Download komodo-macos.tar.gz @@ -112,6 +114,7 @@ jobs: - name: Install deps (BasicRPC) run: | brew install python3 curl + python3 -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl python3 -m pip install setuptools wheel python3 -m pip install slick-bitcoinrpc pytest wget jsonschema - name: Download komodo-macos.tar.gz @@ -140,6 +143,7 @@ jobs: - name: Install deps (ChannelsCC) run: | brew install python3 curl + python3 -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl python3 -m pip install setuptools wheel python3 -m pip install slick-bitcoinrpc pytest wget jsonschema - name: Download komodo-macos.tar.gz @@ -168,6 +172,7 @@ jobs: - name: Install deps (HeirCC) run: | brew install python3 curl + python3 -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl python3 -m pip install setuptools wheel python3 -m pip install slick-bitcoinrpc pytest wget jsonschema - name: Download komodo-macos.tar.gz diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index b74370575bf..1e16511b09d 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -32,7 +32,7 @@ jobs: libncurses-dev \ unzip \ git \ - python \ + python3 \ zlib1g-dev \ wget \ bsdmainutils \ @@ -92,10 +92,11 @@ jobs: move komodod_win\komodod_win.zip 7z e komodod_win.zip move komodod.exe src\ - python.exe -m pip install --upgrade setuptools - python.exe -m pip install --upgrade pip - python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install slick-bitcoinrpc + python3.exe -m pip install --upgrade setuptools + python3.exe -m pip install --upgrade pip + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3.exe -m pip install pytest wget jsonschema + python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat - name: Base RPC Test (Windows) shell: cmd @@ -122,10 +123,11 @@ jobs: move komodod_win\komodod_win.zip 7z e komodod_win.zip move komodod.exe src\ - python.exe -m pip install --upgrade setuptools - python.exe -m pip install --upgrade pip - python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install slick-bitcoinrpc + python3.exe -m pip install --upgrade setuptools + python3.exe -m pip install --upgrade pip + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3.exe -m pip install pytest wget jsonschema + python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat - name: CC Dice Faucet Tokens Rewards (Windows) shell: cmd @@ -152,10 +154,11 @@ jobs: move komodod_win\komodod_win.zip 7z e komodod_win.zip move komodod.exe src\ - python.exe -m pip install --upgrade setuptools - python.exe -m pip install --upgrade pip - python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install slick-bitcoinrpc + python3.exe -m pip install --upgrade setuptools + python3.exe -m pip install --upgrade pip + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3.exe -m pip install pytest wget jsonschema + python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat - name: CC Oracles (Windows) shell: cmd @@ -182,10 +185,11 @@ jobs: move komodod_win\komodod_win.zip 7z e komodod_win.zip move komodod.exe src\ - python.exe -m pip install --upgrade setuptools - python.exe -m pip install --upgrade pip - python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install slick-bitcoinrpc + python3.exe -m pip install --upgrade setuptools + python3.exe -m pip install --upgrade pip + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3.exe -m pip install pytest wget jsonschema + python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat - name: CC Heir (Windows) shell: cmd @@ -212,10 +216,11 @@ jobs: move komodod_win\komodod_win.zip 7z e komodod_win.zip move komodod.exe src\ - python.exe -m pip install --upgrade setuptools - python.exe -m pip install --upgrade pip - python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install slick-bitcoinrpc + python3.exe -m pip install --upgrade setuptools + python3.exe -m pip install --upgrade pip + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3.exe -m pip install pytest wget jsonschema + python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat - name: ChannelsCC (Windows) shell: cmd diff --git a/zcutil/build-mac-dtest.sh b/zcutil/build-mac-dtest.sh index 0f8c88d6414..e1a5ece470f 100755 --- a/zcutil/build-mac-dtest.sh +++ b/zcutil/build-mac-dtest.sh @@ -57,7 +57,7 @@ make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64 -DTESTMODE" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -I/usr/local/opt/openssl/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ +CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ ./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$DEBUGGING_ARG" make "$@" V=1 NO_GTEST=1 STATIC=1 From 3ea0b5ef5f6d54d4a51d959da7d7eaf7314d2567 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 9 Jul 2022 23:18:58 +0500 Subject: [PATCH 330/348] fix openssl path in py tests --- .github/workflows/komodo_mac_ci.yml | 2 +- .github/workflows/komodo_win_ci.yml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index 28f688cff2f..b3cf158da54 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -55,7 +55,7 @@ jobs: - name: Install deps (Dice, Token, Faucet, Rewards CC) run: | brew install python3 curl - python3 -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3 -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl python3 -m pip install setuptools wheel python3 -m pip install slick-bitcoinrpc pytest wget jsonschema diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 1e16511b09d..2f69ebe3f55 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -94,7 +94,7 @@ jobs: move komodod.exe src\ python3.exe -m pip install --upgrade setuptools python3.exe -m pip install --upgrade pip - python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" pycurl python3.exe -m pip install pytest wget jsonschema python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat @@ -125,7 +125,7 @@ jobs: move komodod.exe src\ python3.exe -m pip install --upgrade setuptools python3.exe -m pip install --upgrade pip - python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" pycurl python3.exe -m pip install pytest wget jsonschema python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat @@ -156,7 +156,7 @@ jobs: move komodod.exe src\ python3.exe -m pip install --upgrade setuptools python3.exe -m pip install --upgrade pip - python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" pycurl python3.exe -m pip install pytest wget jsonschema python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat @@ -187,7 +187,7 @@ jobs: move komodod.exe src\ python3.exe -m pip install --upgrade setuptools python3.exe -m pip install --upgrade pip - python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" pycurl python3.exe -m pip install pytest wget jsonschema python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat @@ -218,7 +218,7 @@ jobs: move komodod.exe src\ python3.exe -m pip install --upgrade setuptools python3.exe -m pip install --upgrade pip - python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --install-option="--openssl-dir=/usr/local/opt/openssl@1.1" pycurl + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" pycurl python3.exe -m pip install pytest wget jsonschema python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat From b91eb1cd100d93a0edafc77a35274aae6b823744 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sat, 9 Jul 2022 23:19:29 +0500 Subject: [PATCH 331/348] change py test chain port (to avoid conflict) --- qa/pytest_komodo/chainconfig.json | 4 ++-- qa/pytest_komodo/chainstart.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qa/pytest_komodo/chainconfig.json b/qa/pytest_komodo/chainconfig.json index 233211860b8..73350c9c2cb 100644 --- a/qa/pytest_komodo/chainconfig.json +++ b/qa/pytest_komodo/chainconfig.json @@ -3,8 +3,8 @@ "rpc_user": "test", "rpcpassword": "test", "rpcallowip": "0.0.0.0/0", - "rpcport": 7000, - "port": 6000, + "rpcport": 7001, + "port": 6001, "rpcbind": "0.0.0.0", "ac_name": "TONYCI", "ac_reward": "100000000000", diff --git a/qa/pytest_komodo/chainstart.py b/qa/pytest_komodo/chainstart.py index eeebb6cf350..b49548daafa 100644 --- a/qa/pytest_komodo/chainstart.py +++ b/qa/pytest_komodo/chainstart.py @@ -81,7 +81,7 @@ def create_configs(asset, node=0): with open(confpath, 'a') as conf: conf.write("rpcuser=test\n") conf.write("rpcpassword=test\n") - conf.write('rpcport=' + str(7000 + node) + '\n') + conf.write('rpcport=' + str(7001 + node) + '\n') conf.write("rpcbind=0.0.0.0\n") conf.write("rpcallowip=0.0.0.0/0\n") @@ -149,7 +149,7 @@ def main(): 'rpc_user': 'test', 'rpc_password': 'test', 'rpc_ip': '127.0.0.1', - 'rpc_port': 7000 + i + 'rpc_port': 7001 + i } rpc_p = create_proxy(node_params) validate_proxy(env_params, rpc_p, i) From b22573802090feb44869ff92a4b6952532891cda Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 10 Jul 2022 11:12:12 +0500 Subject: [PATCH 332/348] fix port in test chain nodeconfig --- qa/pytest_komodo/nodesconfig.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/qa/pytest_komodo/nodesconfig.json b/qa/pytest_komodo/nodesconfig.json index df8792e4c26..1141da27196 100644 --- a/qa/pytest_komodo/nodesconfig.json +++ b/qa/pytest_komodo/nodesconfig.json @@ -3,8 +3,8 @@ "rpc_user" : "test", "rpc_password" : "test", "rpc_ip" : "127.0.0.1", - "rpc_port": 7000, - "net_port": 6000, + "rpc_port": 7001, + "net_port": 6001, "pubkey" : "02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7", "address": "RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd", "txid": "e9945094eb1a9028afd310719aea21966425ceccc3f8c0972277a96201ca1b81" @@ -13,8 +13,8 @@ "rpc_user" : "test", "rpc_password" : "test", "rpc_ip" : "127.0.0.1", - "rpc_port": 7001, - "net_port": 6001, + "rpc_port": 7002, + "net_port": 6002, "pubkey" : "0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149", "address": "RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH", "txid": "3376a48a7daf543d8401e072102d4e93f53f300a101bd67e82820d2da0f2729e" @@ -23,8 +23,8 @@ "rpc_user" : "test", "rpc_password" : "test", "rpc_ip" : "127.0.0.1", - "rpc_port": 7002, - "net_port": 6002, + "rpc_port": 7003, + "net_port": 6003, "pubkey" : "02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9", "address": "RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein", "txid": "3376a48a7daf543d8401e072102d4e93f53f300a101bd67e82820d2da0f2729e" From 53338839e74ccbc3b4f6cf8862ad7b1e1b42745c Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 10 Jul 2022 18:10:11 +0500 Subject: [PATCH 333/348] try to fix libcurl build on windows CI --- .github/workflows/komodo_linux_ci.yml | 4 +- .github/workflows/komodo_mac_ci.yml | 4 +- .github/workflows/komodo_win_ci.yml | 120 +++++++------------------- 3 files changed, 35 insertions(+), 93 deletions(-) diff --git a/.github/workflows/komodo_linux_ci.yml b/.github/workflows/komodo_linux_ci.yml index 948a1b7b07d..65903aca9bb 100644 --- a/.github/workflows/komodo_linux_ci.yml +++ b/.github/workflows/komodo_linux_ci.yml @@ -1,8 +1,8 @@ name: Komodo Linux CI on: - pull_request: - types: [opened, synchronize, reopened] +# pull_request: +# types: [opened, synchronize, reopened] schedule: - cron: '0 0 * * 1' diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index b3cf158da54..ab56158ec8f 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -1,8 +1,8 @@ name: Komodo MacOS CI on: - pull_request: - types: [opened, synchronize, reopened] +# pull_request: +# types: [opened, synchronize, reopened] schedule: - cron: '0 0 * * 1' diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 2f69ebe3f55..1a14168ae9b 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -72,13 +72,13 @@ jobs: name: komodod_win path: ./komodod_win.zip - windows-test-baserpc: - - name: Test (Win/BasicRPC) + windows-build-prereqs: + name: Get Prereqs needs: windows-build runs-on: windows-latest steps: + - uses: actions/checkout@v2 - name: Download komodo_win.zip @@ -86,142 +86,84 @@ jobs: with: name: komodod_win - - name: Install deps (Base) + - name: Unpack Komodo shell: cmd run: | move komodod_win\komodod_win.zip 7z e komodod_win.zip move komodod.exe src\ + + - name: Install deps (Base) + shell: cmd + run: | + git clone https://github.com/Microsoft/vcpkg + cd vcpkg + .\bootstrap-vcpkg.bat + vcpkg integrate install + vcpkg install curl[*]:x64-windows + cd .. + dir /s vcpkg\packages\curl_x64-windows python3.exe -m pip install --upgrade setuptools python3.exe -m pip install --upgrade pip - python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" pycurl + python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" --curl-dir="vcpkg\packages\curl_x64-windows\lib" pycurl python3.exe -m pip install pytest wget jsonschema python3.exe -m pip install slick-bitcoinrpc zcutil\fetch-params.bat + + windows-test-baserpc: + name: Test (Win/BasicRPC) + needs: [windows-build, windows-build-prereqs] + runs-on: windows-latest + + steps: - name: Base RPC Test (Windows) shell: cmd run: | cd qa\pytest_komodo start_ci.bat basic - windows-test-dice-faucet-tok-rewCC: + windows-test-dice-faucet-tok-rewCC: name: Test (Win/Dice Faucet Token Rewards) runs-on: windows-latest - needs: windows-build + needs: [windows-build, windows-build-prereqs] steps: - - uses: actions/checkout@v2 - - - name: Download komodo_win.zip - uses: actions/download-artifact@v1 - with: - name: komodod_win - - - name: Install deps (MainCC) - shell: cmd - run: | - move komodod_win\komodod_win.zip - 7z e komodod_win.zip - move komodod.exe src\ - python3.exe -m pip install --upgrade setuptools - python3.exe -m pip install --upgrade pip - python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" pycurl - python3.exe -m pip install pytest wget jsonschema - python3.exe -m pip install slick-bitcoinrpc - zcutil\fetch-params.bat - name: CC Dice Faucet Tokens Rewards (Windows) shell: cmd run: | cd qa\pytest_komodo start_ci.bat cc_modules\test_dice.py cc_modules\test_faucet.py cc_modules\test_token.py cc_modules\test_rewards.py - windows-test-oracles-cc: + windows-test-oracles-cc: name: Test (Win/OraclesCC) runs-on: windows-latest - needs: windows-build + needs: [windows-build, windows-build-prereqs] steps: - - uses: actions/checkout@v2 - - - name: Download komodo_win.zip - uses: actions/download-artifact@v1 - with: - name: komodod_win - - - name: Install deps (OraclesCC) - shell: cmd - run: | - move komodod_win\komodod_win.zip - 7z e komodod_win.zip - move komodod.exe src\ - python3.exe -m pip install --upgrade setuptools - python3.exe -m pip install --upgrade pip - python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" pycurl - python3.exe -m pip install pytest wget jsonschema - python3.exe -m pip install slick-bitcoinrpc - zcutil\fetch-params.bat - name: CC Oracles (Windows) shell: cmd run: | cd qa\pytest_komodo start_ci.bat cc_modules\test_oracles.py - windows-test-heir-cc: + windows-test-heir-cc: name: Test (Win/HeirCC) runs-on: windows-latest - needs: windows-build + needs: [windows-build, windows-build-prereqs] steps: - - uses: actions/checkout@v2 - - - name: Download komodo_win.zip - uses: actions/download-artifact@v1 - with: - name: komodod_win - - - name: Install deps (CC Heir) - shell: cmd - run: | - move komodod_win\komodod_win.zip - 7z e komodod_win.zip - move komodod.exe src\ - python3.exe -m pip install --upgrade setuptools - python3.exe -m pip install --upgrade pip - python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" pycurl - python3.exe -m pip install pytest wget jsonschema - python3.exe -m pip install slick-bitcoinrpc - zcutil\fetch-params.bat - name: CC Heir (Windows) shell: cmd run: | cd qa\pytest_komodo start_ci.bat cc_modules\test_heir.py - windows-test-channels-cc: + windows-test-channels-cc: name: Test (Win/ChannelsCC) runs-on: windows-latest - needs: windows-build + needs: [windows-build, windows-build-prereqs] steps: - - uses: actions/checkout@v2 - - - name: Download komodo_win.zip - uses: actions/download-artifact@v1 - with: - name: komodod_win - - - name: Install deps (ChannelsCC) - shell: cmd - run: | - move komodod_win\komodod_win.zip - 7z e komodod_win.zip - move komodod.exe src\ - python3.exe -m pip install --upgrade setuptools - python3.exe -m pip install --upgrade pip - python3.exe -m pip install --no-cache-dir --compile --ignore-installed --install-option="--with-openssl" pycurl - python3.exe -m pip install pytest wget jsonschema - python3.exe -m pip install slick-bitcoinrpc - zcutil\fetch-params.bat - name: ChannelsCC (Windows) shell: cmd run: | From e265454b5b87d274c6570d0af51dc90f6110685c Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 10 Jul 2022 20:19:41 +0500 Subject: [PATCH 334/348] CI fix vcpkg --- .github/workflows/komodo_win_ci.yml | 39 ++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 1a14168ae9b..6876907e027 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -93,15 +93,20 @@ jobs: 7z e komodod_win.zip move komodod.exe src\ +# - name: Restore vcpkg packages +# working-directory: ${{env.GITHUB_WORKSPACE}} +# run: vcpkg integrate install + + - name: Install libcurl + uses: lukka/run-vcpkg@v4 + with: + vcpkgArguments: 'curl' + vcpkgDirectory: '${{ github.workspace }}/vcpkg' + working-directory: ${{env.GITHUB_WORKSPACE}} + - name: Install deps (Base) shell: cmd run: | - git clone https://github.com/Microsoft/vcpkg - cd vcpkg - .\bootstrap-vcpkg.bat - vcpkg integrate install - vcpkg install curl[*]:x64-windows - cd .. dir /s vcpkg\packages\curl_x64-windows python3.exe -m pip install --upgrade setuptools python3.exe -m pip install --upgrade pip @@ -112,8 +117,10 @@ jobs: windows-test-baserpc: name: Test (Win/BasicRPC) - needs: [windows-build, windows-build-prereqs] runs-on: windows-latest + needs: [windows-build-prereqs] + with: + working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: Base RPC Test (Windows) @@ -125,7 +132,9 @@ jobs: windows-test-dice-faucet-tok-rewCC: name: Test (Win/Dice Faucet Token Rewards) runs-on: windows-latest - needs: [windows-build, windows-build-prereqs] + needs: [windows-build-prereqs] + with: + working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: CC Dice Faucet Tokens Rewards (Windows) @@ -137,7 +146,9 @@ jobs: windows-test-oracles-cc: name: Test (Win/OraclesCC) runs-on: windows-latest - needs: [windows-build, windows-build-prereqs] + needs: [windows-build-prereqs] + with: + working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: CC Oracles (Windows) @@ -149,7 +160,9 @@ jobs: windows-test-heir-cc: name: Test (Win/HeirCC) runs-on: windows-latest - needs: [windows-build, windows-build-prereqs] + needs: [windows-build-prereqs] + with: + working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: CC Heir (Windows) @@ -161,8 +174,10 @@ jobs: windows-test-channels-cc: name: Test (Win/ChannelsCC) runs-on: windows-latest - needs: [windows-build, windows-build-prereqs] - + needs: [windows-build-prereqs] + with: + working-directory: ${{env.GITHUB_WORKSPACE}} + steps: - name: ChannelsCC (Windows) shell: cmd From d00230900dfbf9aeccbbc4f28b4855d2c6940b50 Mon Sep 17 00:00:00 2001 From: dimxy Date: Sun, 10 Jul 2022 20:35:12 +0500 Subject: [PATCH 335/348] fix komodo_win yml --- .github/workflows/komodo_win_ci.yml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 6876907e027..a992ece6d37 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -78,8 +78,9 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + with: + submodules: 'recursive' - name: Download komodo_win.zip uses: actions/download-artifact@v1 @@ -93,10 +94,6 @@ jobs: 7z e komodod_win.zip move komodod.exe src\ -# - name: Restore vcpkg packages -# working-directory: ${{env.GITHUB_WORKSPACE}} -# run: vcpkg integrate install - - name: Install libcurl uses: lukka/run-vcpkg@v4 with: @@ -118,7 +115,7 @@ jobs: windows-test-baserpc: name: Test (Win/BasicRPC) runs-on: windows-latest - needs: [windows-build-prereqs] + needs: windows-build-prereqs with: working-directory: ${{env.GITHUB_WORKSPACE}} @@ -132,7 +129,7 @@ jobs: windows-test-dice-faucet-tok-rewCC: name: Test (Win/Dice Faucet Token Rewards) runs-on: windows-latest - needs: [windows-build-prereqs] + needs: windows-build-prereqs with: working-directory: ${{env.GITHUB_WORKSPACE}} @@ -146,7 +143,7 @@ jobs: windows-test-oracles-cc: name: Test (Win/OraclesCC) runs-on: windows-latest - needs: [windows-build-prereqs] + needs: windows-build-prereqs with: working-directory: ${{env.GITHUB_WORKSPACE}} @@ -160,7 +157,7 @@ jobs: windows-test-heir-cc: name: Test (Win/HeirCC) runs-on: windows-latest - needs: [windows-build-prereqs] + needs: windows-build-prereqs with: working-directory: ${{env.GITHUB_WORKSPACE}} @@ -174,10 +171,10 @@ jobs: windows-test-channels-cc: name: Test (Win/ChannelsCC) runs-on: windows-latest - needs: [windows-build-prereqs] + needs: windows-build-prereqs with: working-directory: ${{env.GITHUB_WORKSPACE}} - + steps: - name: ChannelsCC (Windows) shell: cmd From ee576a0ec6db9934ab6be3a2d87c7182ecd1f817 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 11 Jul 2022 15:54:39 +0500 Subject: [PATCH 336/348] disable libcurl --- .github/workflows/komodo_win_ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index a992ece6d37..3d57db8817d 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -94,12 +94,12 @@ jobs: 7z e komodod_win.zip move komodod.exe src\ - - name: Install libcurl - uses: lukka/run-vcpkg@v4 - with: - vcpkgArguments: 'curl' - vcpkgDirectory: '${{ github.workspace }}/vcpkg' - working-directory: ${{env.GITHUB_WORKSPACE}} +# - name: Install libcurl +# uses: lukka/run-vcpkg@v4 +# with: +# vcpkgArguments: 'curl' +# vcpkgDirectory: '${{ github.workspace }}/vcpkg' +# working-directory: ${{env.GITHUB_WORKSPACE}} - name: Install deps (Base) shell: cmd From 7fbfaf27e818b6d261a966850bde68200b3abe5b Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 11 Jul 2022 15:59:03 +0500 Subject: [PATCH 337/348] dev yml --- .github/workflows/komodo_win_ci.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 3d57db8817d..68e7ca8dd39 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -79,8 +79,8 @@ jobs: steps: - uses: actions/checkout@v2 - with: - submodules: 'recursive' + # with: + # submodules: 'recursive' - name: Download komodo_win.zip uses: actions/download-artifact@v1 @@ -116,8 +116,8 @@ jobs: name: Test (Win/BasicRPC) runs-on: windows-latest needs: windows-build-prereqs - with: - working-directory: ${{env.GITHUB_WORKSPACE}} + #with: + # working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: Base RPC Test (Windows) @@ -130,8 +130,8 @@ jobs: name: Test (Win/Dice Faucet Token Rewards) runs-on: windows-latest needs: windows-build-prereqs - with: - working-directory: ${{env.GITHUB_WORKSPACE}} + #with: + # working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: CC Dice Faucet Tokens Rewards (Windows) @@ -144,8 +144,8 @@ jobs: name: Test (Win/OraclesCC) runs-on: windows-latest needs: windows-build-prereqs - with: - working-directory: ${{env.GITHUB_WORKSPACE}} + #with: + # working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: CC Oracles (Windows) @@ -158,8 +158,8 @@ jobs: name: Test (Win/HeirCC) runs-on: windows-latest needs: windows-build-prereqs - with: - working-directory: ${{env.GITHUB_WORKSPACE}} + #with: + # working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: CC Heir (Windows) @@ -172,8 +172,8 @@ jobs: name: Test (Win/ChannelsCC) runs-on: windows-latest needs: windows-build-prereqs - with: - working-directory: ${{env.GITHUB_WORKSPACE}} + #with: + # working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: ChannelsCC (Windows) From c9113503a680097342c693279c8a48e4db81493c Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 11 Jul 2022 16:00:20 +0500 Subject: [PATCH 338/348] dev yml win --- .github/workflows/komodo_win_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 68e7ca8dd39..645db0b4924 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -116,8 +116,8 @@ jobs: name: Test (Win/BasicRPC) runs-on: windows-latest needs: windows-build-prereqs - #with: - # working-directory: ${{env.GITHUB_WORKSPACE}} + with: + working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: Base RPC Test (Windows) From 9e69f3683d3e5e7b8a78afc6649e419f4d4be228 Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 11 Jul 2022 16:01:38 +0500 Subject: [PATCH 339/348] dev yml win --- .github/workflows/komodo_win_ci.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 645db0b4924..4b18803d0cc 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -79,8 +79,8 @@ jobs: steps: - uses: actions/checkout@v2 - # with: - # submodules: 'recursive' + with: + submodules: 'recursive' - name: Download komodo_win.zip uses: actions/download-artifact@v1 @@ -94,12 +94,12 @@ jobs: 7z e komodod_win.zip move komodod.exe src\ -# - name: Install libcurl -# uses: lukka/run-vcpkg@v4 -# with: -# vcpkgArguments: 'curl' -# vcpkgDirectory: '${{ github.workspace }}/vcpkg' -# working-directory: ${{env.GITHUB_WORKSPACE}} + - name: Install libcurl + uses: lukka/run-vcpkg@v4 + with: + vcpkgArguments: 'curl' + vcpkgDirectory: '${{ github.workspace }}/vcpkg' + working-directory: ${{env.GITHUB_WORKSPACE}} - name: Install deps (Base) shell: cmd @@ -116,8 +116,8 @@ jobs: name: Test (Win/BasicRPC) runs-on: windows-latest needs: windows-build-prereqs - with: - working-directory: ${{env.GITHUB_WORKSPACE}} + #with: + # working-directory: ${{env.GITHUB_WORKSPACE}} steps: - name: Base RPC Test (Windows) From 6d6070a258f6dc9d6adc98b066dc473d47a8cafd Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 11 Jul 2022 21:40:22 +0500 Subject: [PATCH 340/348] ci win yml curl git id --- .github/workflows/komodo_win_ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 4b18803d0cc..9db5c28ebb3 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -98,6 +98,7 @@ jobs: uses: lukka/run-vcpkg@v4 with: vcpkgArguments: 'curl' + vcpkgGitCommitId: '6b951a6928811507d493303b2878e848c077b471' vcpkgDirectory: '${{ github.workspace }}/vcpkg' working-directory: ${{env.GITHUB_WORKSPACE}} From a38b3664f5aa623495acee615a9f41eb4a5b54a0 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Jul 2022 12:56:36 +0500 Subject: [PATCH 341/348] fix vcpkg git id --- .github/workflows/komodo_win_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 9db5c28ebb3..92dbff66d2a 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -98,9 +98,9 @@ jobs: uses: lukka/run-vcpkg@v4 with: vcpkgArguments: 'curl' - vcpkgGitCommitId: '6b951a6928811507d493303b2878e848c077b471' + vcpkgGitCommitId: 80ab37ed1b60a9adae6d46b4d7b982c05d594d07 vcpkgDirectory: '${{ github.workspace }}/vcpkg' - working-directory: ${{env.GITHUB_WORKSPACE}} + # working-directory: ${{env.GITHUB_WORKSPACE}} - name: Install deps (Base) shell: cmd From b8c9b5853ac7f7c1871d9e4244bf23380e5752e5 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Jul 2022 15:03:56 +0500 Subject: [PATCH 342/348] ci yml win fix vcpkg commit id --- .github/workflows/komodo_win_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 92dbff66d2a..35d91af970d 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -95,10 +95,10 @@ jobs: move komodod.exe src\ - name: Install libcurl - uses: lukka/run-vcpkg@v4 + uses: lukka/run-vcpkg@main with: vcpkgArguments: 'curl' - vcpkgGitCommitId: 80ab37ed1b60a9adae6d46b4d7b982c05d594d07 + vcpkgCommitId: '5568f110b509a9fd90711978a7cb76bae75bb092' vcpkgDirectory: '${{ github.workspace }}/vcpkg' # working-directory: ${{env.GITHUB_WORKSPACE}} From 20a89f8642b87b8bc5b40353c14a1e570b675c1a Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Jul 2022 16:31:37 +0500 Subject: [PATCH 343/348] ci win yml try run-vcpkg v4 --- .github/workflows/komodo_win_ci.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 35d91af970d..2051d7a9f47 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -95,12 +95,15 @@ jobs: move komodod.exe src\ - name: Install libcurl - uses: lukka/run-vcpkg@main + uses: lukka/run-vcpkg@v4 with: - vcpkgArguments: 'curl' - vcpkgCommitId: '5568f110b509a9fd90711978a7cb76bae75bb092' - vcpkgDirectory: '${{ github.workspace }}/vcpkg' + setupOnly: true + # vcpkgArguments: 'curl' + # vcpkgGitCommitId: '5568f110b509a9fd90711978a7cb76bae75bb092' + # vcpkgDirectory: '${{ github.workspace }}/vcpkg' # working-directory: ${{env.GITHUB_WORKSPACE}} + run: | + vcpkg install curl - name: Install deps (Base) shell: cmd From 300e6ce070e171dc0a48f024b1944cdcfa46af59 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Jul 2022 16:33:35 +0500 Subject: [PATCH 344/348] ci yml try fix --- .github/workflows/komodo_win_ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 2051d7a9f47..e1430b31d0b 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -104,6 +104,7 @@ jobs: # working-directory: ${{env.GITHUB_WORKSPACE}} run: | vcpkg install curl + shell: cmd - name: Install deps (Base) shell: cmd From 0e75dba9cd702aec2b5f154946fee7eb6fcaaf41 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Jul 2022 19:30:42 +0500 Subject: [PATCH 345/348] github ci win yml run fix --- .github/workflows/komodo_win_ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index e1430b31d0b..a25706f8101 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -94,7 +94,7 @@ jobs: 7z e komodod_win.zip move komodod.exe src\ - - name: Install libcurl + - name: Install vcpkg uses: lukka/run-vcpkg@v4 with: setupOnly: true @@ -102,6 +102,8 @@ jobs: # vcpkgGitCommitId: '5568f110b509a9fd90711978a7cb76bae75bb092' # vcpkgDirectory: '${{ github.workspace }}/vcpkg' # working-directory: ${{env.GITHUB_WORKSPACE}} + + - name: Install libcurl run: | vcpkg install curl shell: cmd From 54aa54b62b570af80c4744ce8b16d00d1e74707f Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 12 Jul 2022 20:49:50 +0500 Subject: [PATCH 346/348] github ci add vcpkg git commit id --- .github/workflows/komodo_win_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index a25706f8101..5a7d02c7019 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -99,7 +99,7 @@ jobs: with: setupOnly: true # vcpkgArguments: 'curl' - # vcpkgGitCommitId: '5568f110b509a9fd90711978a7cb76bae75bb092' + vcpkgGitCommitId: 'f46f924c08b1fca7ad450ff0b1b26dc9554a3c8e' # vcpkgDirectory: '${{ github.workspace }}/vcpkg' # working-directory: ${{env.GITHUB_WORKSPACE}} From 2d7c47a3d234e336e5fd5ebdd5d10f5ce75674c1 Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 11 Oct 2022 21:28:03 +0500 Subject: [PATCH 347/348] enable back ci macos --- .github/workflows/komodo_mac_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index ab56158ec8f..b3cf158da54 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -1,8 +1,8 @@ name: Komodo MacOS CI on: -# pull_request: -# types: [opened, synchronize, reopened] + pull_request: + types: [opened, synchronize, reopened] schedule: - cron: '0 0 * * 1' From 9d3f84da776499457ecd581f2e38742f22f597ff Mon Sep 17 00:00:00 2001 From: dimxy Date: Tue, 11 Oct 2022 23:06:45 +0500 Subject: [PATCH 348/348] print cpu info --- .github/workflows/komodo_mac_ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index b3cf158da54..9bb994963ca 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -69,6 +69,7 @@ jobs: mv komodo-macos/komodo-macos.tar.gz . mkdir -p src tar xzvf komodo-macos.tar.gz + sysctl -n machdep.cpu.brand_string ./zcutil/fetch-params.sh cd qa/pytest_komodo ./ci_setup.sh "cc_modules/test_dice.py cc_modules/test_faucet.py cc_modules/test_token.py cc_modules/test_rewards.py"