Skip to content

Commit

Permalink
Added unspent cc index and cc txns in mempool improvements (#64)
Browse files Browse the repository at this point in the history
* fixed name conflict (global namespace)

* CCtokens_impl.h renamed

* more global namespace fix

* fixed libcc.so dependencies

* all templated to impl.h

* fix single def for helpers;
restore global namespaces;
restore fix for tokentransfer inputs check

* fix tokenv2balance evalcode

* first ver of Unspent CC Index;
SetCCUnspentsInMempool added, AddNormalInpustRemote mempool flag;
tokencreate use normals in mempool (temp)

* TestBlockValidity call surrounded by crit section

* fixed maxOutputs

* deb logging

* added TokenV2List with unspent cc index support

* added if-cc-active condition like in other places

* refactored critical section for TestBlockValidity

* changed cc index key (txid index added) and value;
revuint used for creationid;
template GetNonFungible calls fixed;

* lost in the prev commit

* old token logging refactored

* del extra logging

* deleted more trace logging

* fix mempool index keyType for cryptoconditions

* added opt ver IsSpentInMempool using spent index;
calls profiling

* added mempool cs around TestBlockValidity

* try LOCK2 for TestBlockValidity

* restored cs_main around TestBlockValidity; formatting (justification) in BitcoinMiner

* removed time profiling

* restored mempool index in AddNormalInputsRemote

* tx param changed to const in myAddToMempool

* added mempool.check and a loop to update mempool indexes in CheckBlock (instead of CCTxFix...)

* removed txhash and index from unspent cc index key,
fixed mempool address and spent index for cc txns type,
added unspent cc index for mempool
tokentransfer usemempool input

* restored txhash and index in the cc index key (needed to allow multiple cc tx for one creationid)

* added listccunspents rpc (to browse unspent cc index)
  • Loading branch information
dimxy committed Dec 23, 2021
1 parent 0269cfd commit 2c28024
Show file tree
Hide file tree
Showing 22 changed files with 2,180 additions and 954 deletions.
24 changes: 17 additions & 7 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -298,17 +298,24 @@ libbitcoin_server_a_SOURCES = \
cc/import.cpp \
cc/importgateway.cpp \
cc/CCassetsCore.cpp \
cc/old/CCassetsCore_v0.cpp \
cc/CCassetstx.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/oraclesV2.cpp \
cc/prices.cpp \
Expand All @@ -318,6 +325,9 @@ libbitcoin_server_a_SOURCES = \
cc/channelsV2.cpp \
cc/auction.cpp \
cc/betprotocol.cpp \
cc/pricesfeed.cpp \
cc/priceslibs/cjsonpointer.cpp \
cc/kogs.cpp \
chain.cpp \
checkpoints.cpp \
fs.cpp \
Expand Down Expand Up @@ -352,6 +362,10 @@ libbitcoin_server_a_SOURCES = \
rpc/net.cpp \
rpc/rawtransaction.cpp \
rpc/server.cpp \
rpc/tokensrpc.cpp \
rpc/pricesrpc.cpp \
rpc/marmararpc.cpp \
rpc/ccutilsrpc.cpp \
script/serverchecker.cpp \
script/sigcache.cpp \
timedata.cpp \
Expand Down Expand Up @@ -399,9 +413,6 @@ libbitcoin_wallet_a_SOURCES = \
transaction_builder.cpp \
wallet/rpcdisclosure.cpp \
wallet/rpcdump.cpp \
cc/CCtokens.cpp \
cc/CCassetsCore.cpp \
cc/CCassetstx.cpp \
cc/CCtx.cpp \
wallet/rpcwallet.cpp \
wallet/wallet.cpp \
Expand Down Expand Up @@ -521,7 +532,9 @@ 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) \
$(LIBZCASH_H)

Expand Down Expand Up @@ -554,10 +567,6 @@ if GLIBC_BACK_COMPAT
libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp
endif

if ENABLE_TESTS
libbitcoin_server_a_SOURCES += rpc/testtransactions.cpp
endif


# cli: zcash-cli
libbitcoin_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
Expand Down Expand Up @@ -787,6 +796,7 @@ clean-local:
-$(MAKE) -C secp256k1 clean
-$(MAKE) -C snark clean
-$(MAKE) -C univalue clean
-$(MAKE) -C cryptoconditions clean
rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
-rm -f config.h

Expand Down
45 changes: 42 additions & 3 deletions src/cc/CCinclude.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Details.
#include "../komodo_nSPV_defs.h"
#include "../komodo_cJSON.h"
#include "../init.h"
#include "../unspentccindex.h"
#include "rpc/server.h"

#define CC_BURNPUBKEY "02deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead" //!< 'dead' pubkey in hex for burning tokens (if tokens are sent to it, they become 'burned')
Expand Down Expand Up @@ -360,7 +361,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(CTransaction &tx, CValidationState *pstate = NULL, bool fSkipExpiry = false);
bool myAddtomempool(const CTransaction &tx, CValidationState *pstate = NULL, 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<CTransaction> &txs,uint8_t evalcode,uint8_t funcid);
Expand Down Expand Up @@ -769,6 +770,20 @@ int64_t CCduration(int32_t &numblocks,uint256 txid);
bool ExactAmounts(Eval* eval, const CTransaction &tx, uint64_t txfee);
bool CCOpretCheck(Eval* eval, const CTransaction &tx, bool no_burn, bool no_multi, bool last_vout);

/// decodes cc transaction vout basic data: evalcode, funcid, version, creationId
/// first tries to find cc data in vout's opdrop then in the last vout opreturn
/// cc data must follow the common format: evalcode funcid version creationId
/// if tx does not have evalcode cc vins the function treats the tx as the creation tx and sets creationId to tx.GetHash()
/// @param tx cc transaction
/// @param n vout number to check
/// @param[out] evalcode
/// @param[out] funcid
/// @param[out] version
/// @param[out] creationId uint256 value euther from cc data or tx id itself
/// @returns true if decoded okay
bool CCDecodeTxVout(const CTransaction &tx, int32_t n, uint8_t &evalcode, uint8_t &funcid, uint8_t &version, uint256 &creationId);


/// @private
uint256 CCOraclesReverseScan(char const *logcategory,uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid);
/// @private
Expand Down Expand Up @@ -835,7 +850,31 @@ UniValue FinalizeCCV2Tx(bool remote, uint64_t mask, struct CCcontract_info *cp,
/// @param[out] unspentOutputs vector of pairs of address key and amount
/// @param coinaddr address where unspent outputs are searched
/// @param CCflag if true the function searches for cc outputs, otherwise for normal outputs
void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr,bool CCflag = true);
void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs, char *coinaddr,bool CCflag = true);

/// SetCCunspentsWithMempool returns a vector of unspent outputs on an address, including outputs in mempool
/// outputs that spent in mempool are removed
/// @param[out] unspentOutputs vector of pairs of address key and amount
/// @param coinaddr address where unspent outputs are searched
/// @param CCflag if true the function searches for cc outputs, otherwise for normal outputs
void SetCCunspentsWithMempool(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs, char *coinaddr, bool ccflag = true);

/// SetCCunspents returns a vector of unspent outputs for a cc address and creationid of cc instance
/// @param[out] unspentOutputs vector of pairs of objects CAddressUnspentCCKey and CAddressUnspentCCValue
/// @param coinaddr cc address where unspent outputs are searched
/// @param creationid cc instance creationid for which outputs are searched
void SetCCunspentsCCIndex(std::vector<std::pair<CUnspentCCIndexKey, CUnspentCCIndexValue> > &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<std::pair<CUnspentCCIndexKey, CUnspentCCIndexValue> > &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, might be empty to return all txns on coinaddr
void AddCCunspentsCCIndexMempool(std::vector<std::pair<CUnspentCCIndexKey, CUnspentCCIndexValue> > &unspentOutputs, const char *coinaddr, uint256 creationId);

/// SetCCtxids returns a vector of all outputs on an address
/// @param[out] addressIndex vector of pairs of address index key and amount
Expand Down Expand Up @@ -894,7 +933,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);
int64_t AddNormalinputsRemote(CMutableTransaction &mtx, CPubKey mypk, int64_t 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
Expand Down
87 changes: 80 additions & 7 deletions src/cc/CCtokens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
tokens cc tx creation and validation code
*/

#include "CCtokens_impl.h"

thread_local uint32_t tokenValIndentSize = 0; // for debug logging

Expand Down Expand Up @@ -170,7 +171,7 @@ CAmount V1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, alwa

// get optional nft eval code:
vscript_t vopretNonfungible;
GetNonfungibleData(reftokenid, vopretNonfungible);
GetNonfungibleData<V1>(reftokenid, vopretNonfungible);
if (vopretNonfungible.size() > 0) {
// shift evalcodes so the first is NFT evalcode
evalCode2 = evalCode1;
Expand Down Expand Up @@ -324,7 +325,7 @@ CAmount V1::CheckTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, alwa
LOGSTREAM(cctokens_log, CCLOG_DEBUG2, stream << "IsTokensvout() vopretExtra=" << HexStr(vopretExtra) << std::endl);

// get non-fungible data
GetNonfungibleData(reftokenid, vopretNonfungible);
GetNonfungibleData<V1>(reftokenid, vopretNonfungible);
std::vector<CPubKey> voutPubkeys;
FilterOutTokensUnspendablePk(voutPubkeysInOpret, voutPubkeys); // cannot send tokens to token unspendable cc addr (only marker is allowed there)

Expand Down Expand Up @@ -578,8 +579,6 @@ CAmount V2::CheckTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_
}


#include "CCtokens_impl.h"

/*static CPubKey GetTokenOriginatorPubKey(CScript scriptPubKey) {
uint8_t funcId;
Expand Down Expand Up @@ -611,6 +610,10 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &

if (strcmp(ASSETCHAINS_SYMBOL, "ROGUE") == 0 && chainActive.Height() <= 12500)
return true;

// my test chains:
if (strcmp(ASSETCHAINS_SYMBOL, "TOK3") == 0 /*&& eval->GetCurrentHeight() < 100*/)
return true;

// check boundaries:
if (tx.vout.size() < 1)
Expand Down Expand Up @@ -709,9 +712,9 @@ bool Tokensv2Validate(struct CCcontract_info *cp, Eval* eval, const CTransaction

std::string errorStr;

if (CheckTokensV2CreateTx(cp, eval, tx))
if (CheckTokensV2CreateTx(cp, eval, tx)) //found create tx and it is valid
return true;
if (eval->state.IsInvalid())
if (eval->state.IsInvalid()) // create tx is invalid
return false;

// check 't' vouts (could have multiple tokenids)
Expand Down Expand Up @@ -761,7 +764,77 @@ CAmount GetTokenBalance(CPubKey pk, uint256 tokenid, bool usemempool)
return GetTokenBalance<V1>(pk, tokenid, usemempool);
}
UniValue TokenInfo(uint256 tokenid) { return TokenInfo<V1>(tokenid); }
UniValue TokenList() { return TokenList<V1>(); }

UniValue TokenList()
{
UniValue result(UniValue::VARR);
std::vector<uint256> txids;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;

struct CCcontract_info *cp, C;
cp = CCinit(&C, EVAL_TOKENS);

auto addTokenId = [&](uint256 txid) {
CTransaction vintx;
uint256 hashBlock;
std::vector<uint8_t> origpubkey;
std::string name, description;

if (myGetTransaction(txid, vintx, hashBlock) != 0) {
std::vector<vscript_t> 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() <<std::endl);
}
}
};

SetCCtxids(txids, cp->normaladdr, false, cp->evalcode, 0, zeroid, 'c'); // find by old normal addr marker
for (std::vector<uint256>::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);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) {
addTokenId(it->first.txhash);
}

return(result);
}

UniValue TokenV2List()
{
UniValue result(UniValue::VARR);
std::vector<std::pair<CUnspentCCIndexKey, CUnspentCCIndexValue> > unspentOutputs;

struct CCcontract_info *cp, C;
cp = CCinit(&C, EVAL_TOKENSV2);

auto addTokenId = [&](uint256 tokenid, const CScript &opreturn) {
std::vector<uint8_t> origpubkey;
std::string name, description;
std::vector<vscript_t> 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);
}
};

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<std::pair<CUnspentCCIndexKey, CUnspentCCIndexValue> >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) {
addTokenId(it->first.creationid, it->second.opreturn);
}

return(result);
}


bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, std::string &errorStr)
{
Expand Down
1 change: 1 addition & 0 deletions src/cc/CCtokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ bool IsTokenMarkerVout(CTxOut vout);
int64_t GetTokenBalance(CPubKey pk, uint256 tokenid, bool usemempool = false);
UniValue TokenInfo(uint256 tokenid);
UniValue TokenList();
UniValue TokenV2List();

///template <class V> UniValue TokenBeginTransferTx(CMutableTransaction &mtx, struct CCcontract_info *cp, const CPubKey &remotepk, CAmount txfee);
///template <class V> UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info *cp, const CPubKey &remotepk, uint256 tokenid, const char *tokenaddr, std::vector<CPubKey> destpubkeys, const std::pair<CC*, uint8_t*> &probecond, CAmount amount, bool useMempool);
Expand Down
Loading

0 comments on commit 2c28024

Please sign in to comment.