// Copyright (c) 2016-2024 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
/******************************************************************************
 * 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.            *
 *                                                                            *
 ******************************************************************************/
#ifndef CC_INCLUDE_H
#define CC_INCLUDE_H


#include <cc/eval.h>
#include <script/cc.h>
#include <script/script.h>
#include "../script/standard.h"
#include "../base58.h"
#include "../key.h"
#include "../core_io.h"
#include "../script/sign.h"
#include "../wallet/wallet.h"
#include <univalue.h>
#include <exception>
#include "../hush_defs.h"
#include "../utlist.h"
#include "../uthash.h"
#include "merkleblock.h"
#include "../hush_nSPV_defs.h"
#include "../hush_cJSON.h"
#include "../init.h"
#include "rpc/server.h"

/// \cond INTERNAL
#define CC_MAXVINS 1024
// NOTE: CryptoConditions (CC) contracts are inherited from the Komodo/Hush lineage and are
// largely vestigial on DragonX (ac_private=1 fully-shielded chain). This user-facing message
// still describes the legacy prerequisites for using CC contracts (nspv_login in superlite
// mode, or launching dragonxd with a valid -pubkey=).
#define CC_REQUIREMENTS_MSG (HUSH_NSPV_SUPERLITE?"to use CC contracts you need to nspv_login first\n":"to use CC contracts, you need to launch dragonxd with valid -pubkey= for an address in your wallet\n")

#define SMALLVAL 0.000000000000001
#define SATOSHIDEN ((uint64_t)100000000L)
#define dstr(x) ((double)(x) / SATOSHIDEN)
#define CCDISABLEALL memset(ASSETCHAINS_CCDISABLES,1,sizeof(ASSETCHAINS_CCDISABLES))

/// \cond INTERNAL
struct CC_utxo
{
    uint256 txid;
    int64_t nValue;
    int32_t vout;
};
/// \endcond


/// CC (CryptoConditions) contract info structure that contains data used for signing and validation of cc contract transactions.
/// NOTE: the CC framework (historically called "Antara modules" in the Komodo/Hush lineage) is largely vestigial on DragonX.
struct CCcontract_info
{
    uint8_t evalcode;  //!< cc contract eval code, set by CCinit function
    uint8_t additionalTokensEvalcode2;  //!< additional eval code for spending from three-eval-code vouts with EVAL_TOKENS, evalcode, additionalTokensEvalcode2 
                                        //!< or vouts with two evalcodes: EVAL_TOKENS, additionalTokensEvalcode2. 
                                        //!< Set by AddTokenCCInputs function

    char unspendableCCaddr[64]; //!< global contract cryptocondition address, set by CCinit function
    char CChexstr[72];          //!< global contract pubkey in hex, set by CCinit function
    char normaladdr[64];        //!< global contract normal address, set by CCinit function
    uint8_t CCpriv[32];         //!< global contract private key, set by CCinit function

    /// vars for spending from 1of2 cc.
    /// NOTE: the value of 'evalcode' member variable will be used for constructing 1of2 cryptocondition
    char coins1of2addr[64];     //!< address of 1of2 cryptocondition, set by CCaddr1of2set function
    CPubKey coins1of2pk[2];     //!< two pubkeys of 1of2 cryptocondition, set by CCaddr1of2set function
    uint8_t coins1of2priv[32];  //!< privkey for the one of two pubkeys of 1of2 cryptocondition, set by CCaddr1of2set function

    /// vars for spending from 1of2 token cc.
    /// NOTE: the value of 'evalcode' member variable will be used for constructing 1of2 token cryptocondition
    char tokens1of2addr[64];    //!< address of 1of2 token cryptocondition set by CCaddrTokens1of2set function
    CPubKey tokens1of2pk[2];    //!< two pubkeys of 1of2 token cryptocondition set by CCaddrTokens1of2set function
    uint8_t tokens1of2priv[32]; //!< privkey for the one of two pubkeys of 1of2 token cryptocondition set by CCaddrTokens1of2set function

    /// vars for spending from two additional global CC addresses of other contracts with their own eval codes
    uint8_t unspendableEvalcode2;   //!< other contract eval code, set by CCaddr2set function
    uint8_t unspendableEvalcode3;   //!< yet another other contract eval code, set by CCaddr3set function
    char    unspendableaddr2[64];   //!< other contract global cc address, set by CCaddr2set function
    char    unspendableaddr3[64];   //!< yet another contract global cc address, set by CCaddr3set function
    uint8_t unspendablepriv2[32];   //!< other contract private key for the global cc address, set by CCaddr2set function
    uint8_t unspendablepriv3[32];   //!< yet another contract private key for the global cc address, set by CCaddr3set function
    CPubKey unspendablepk2;         //!< other contract global public key, set by CCaddr2set function
    CPubKey unspendablepk3;         //!< yet another contract global public key, set by CCaddr3set function

    /// cc contract transaction validation callback that enforces the contract consensus rules
    /// @param cp CCcontract_info structure with initialzed with CCinit
    /// @param eval object of Eval type, used to report validation error like eval->Invalid("some error");
    /// @param tx transaction object to validate
    /// @param nIn not used at this time
    bool(*validate)(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn);

    /// checks if the value of evalcode in cp object is present in the scriptSig parameter, 
    /// that is, the vin for this scriptSig will be validated by the cc contract defined by the eval code in this CCcontract_info object
    /// @param scriptSig scriptSig to check\n
    /// Example:
    /// \code
    /// bool ccFound = false;
    /// for(int i = 0; i < tx.vin.size(); i ++)
    ///     if (cp->ismyvin(tx.vin[i].scriptSig)) {
    ///         ccFound = true;
    ///         break;
    ///     }
    /// \endcode
    bool (*ismyvin)(CScript const& scriptSig);	

    /// @private
    uint8_t didinit;
};

/// init CCcontract_info structure with global pubkey, privkey and address for the contract identified by the passed evalcode.\n
/// Members of the cp object that are filled with this function:\n
/// cp->unspendableCCaddr\n
/// cp->normaladdr\n
/// cp->CChexstr\n
/// cp->CCpriv\n
/// cp->validate\n
/// cp->ismyvin\n
/// @param cp the address of CCcontract_info structure which will be filled with the global keys and address
/// @param evalcode eval code for the module
/// @returns pointer to the passed CCcontract_info structure, it must not be freed
struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode);

typedef std::vector<uint8_t> vscript_t;
extern struct NSPV_CCmtxinfo NSPV_U;  //!< global variable with info about mtx object and used utxo

#ifdef ENABLE_WALLET
extern CWallet* pwalletMain;  //!< global wallet object pointer to access wallet functionality
#endif
//extern CCoinsViewCache *pcoinsTip;

/// @private seems old-style
bool GetAddressUnspent(uint160 addressHash, int type,std::vector<std::pair<CAddressUnspentKey,CAddressUnspentValue> > &unspentOutputs);

/// CCgetspenttxid finds the txid of the transaction which spends a transaction output. The function does this without loading transactions from the chain, by using spent index
/// @param[out] spenttxid transaction id of the spending transaction
/// @param[out] vini order number of input of the spending transaction
/// @param[out] height block height where spending transaction is located
/// @param txid id of the transaction for which spending tx is searched
/// @param vout output number of the transaction for which spending transaction is searched
/// @returns 0 if spending tx is found or -1 if not
int32_t CCgetspenttxid(uint256 &spenttxid,int32_t &vini,int32_t &height,uint256 txid,int32_t vout);

/// @private
UniValue CClib(struct CCcontract_info *cp,char *method,char *jsonstr);

static const uint256 zeroid;  //!< null uint256 constant

/// \cond INTERNAL
static uint256 ignoretxid;
static int32_t ignorevin;
/// \endcond

/// myGetTransaction is non-locking version of GetTransaction
/// @param hash hash of transaction to get (txid)
/// @param[out] txOut returned transaction object
/// @param[out] hashBlock hash of the block where the tx resides
bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock);

/// NSPV_myGetTransaction is called in NSPV mode
/// @param hash hash of transaction to get (txid)
/// @param[out] txOut returned transaction object
/// @param[out] hashBlock hash of the block where the tx resides
/// @param[out] txheight height of the block where the tx resides
/// @param[out] currentheight current chain height
bool NSPV_myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, int32_t &txheight, int32_t &currentheight);

/// decodes char array in hex encoding to byte array
int32_t decode_hex(uint8_t *bytes, int32_t n, char *hex);

/// checks if char string has hex symbols
/// @returns no zero if string has only hex symbols
int32_t is_hexstr(char *str,int32_t n);

/// CCgettxout returns the amount of an utxo. The function does this without loading the utxo transaction from the chain, by using coin cache
/// @param txid transaction id of the utxo
/// @param vout utxo transaction vout order number 
/// @param mempoolflag if true the function checks the mempool to
/// @param lockflag if true the function locks the mempool while accesses it
/// @returns utxo value or -1 if utxo not found
int64_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag,int32_t lockflag);

/// \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 mytxid_inmempool(uint256 txid);
int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout);
/// \endcond

/// \cond INTERNAL
int32_t dragon_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp);
int32_t dragon_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp);
/// \endcond

CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys);

/// CCaddress_balance returns amount of outputs on an address
/// @param coinaddr address to search outputs on
/// @param CCflag if non-zero then address is a cryptocondition address, if false - normal address
int64_t CCaddress_balance(char *coinaddr,int32_t CCflag);

/// Creates a bitcoin address from a transaction id. This address can never be spent
/// @param[out] txidaddr returned address created from txid value 
/// @param txid transaction id
/// @return the public key for the created address 
CPubKey CCtxidaddr(char *txidaddr,uint256 txid);

/// Creates a custom bitcoin address from a transaction id. This address can never be spent
/// @param[out] txidaddr returned address created from txid value 
/// @param txid transaction id
/// @param taddr custom address prefix
/// @param prefix custom pubkey prefix
/// @param prefix2 custom script prefix
/// @return public key for the created address 
CPubKey CCCustomtxidaddr(char *txidaddr,uint256 txid,uint8_t taddr,uint8_t prefix,uint8_t prefix2);

/// 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
/// @param pk pubkey for whose token inputs to add
/// @param tokenid id of token which inputs to add
/// @param total amount to add (if total==0 no inputs are added and all available amount is returned)
/// @param maxinputs maximum number of inputs to add. If 0 then CC_MAXVINS define is used
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs);

/// An overload that also returns NFT data in vopretNonfungible parameter
/// the rest parameters are the same as in the first AddTokenCCInputs overload
/// @see AddTokenCCInputs
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs, vscript_t &vopretNonfungible);

/// 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
int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid);

/// Decodes transaction object into hex encoding
/// @param tx transaction object
/// @param[out] strHexTx transaction in hex encoding
/// returns true if success
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);

/// @private
int32_t payments_parsehexdata(std::vector<uint8_t> &hexdata,cJSON *item,int32_t len);

/// @private
int64_t AddCClibtxfee(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk);

/// 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);

/// @private
bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector<CPubKey> &vinPubkeys);

// CCcustom

/// Returns global pubkey for the evalcode and sets private key for the global pubkey
/// @param cp CCcontract_info structure initialized for a evalcode
/// @param[out] unspendablepriv if not null then in this parameter private key is returned. Must have at least 32 byte size
/// @returns global contract pubkey.\n
/// Example: 
/// \code
/// struct CCcontract_info *cp, C;
/// uint8_t ccAssetsPriv[32]
/// cp = CCinit(&C, EVAL_ASSETS);
/// CPubKey ccAssetsPk = GetUnspendable(cp, ccAssetsPriv);
/// \endcode
/// Now ccAssetsPk has the 'Assets' CC module global pubkey and ccAssetsPriv has its publicly available private key
CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv);

// CCutils

/// finds normal address for private key
/// @param[out] coinaddr returned normal address, must be array of char with length 64
/// @param[out] buf33 array of length not less than 33 uint8_t, returned public key from private key
/// @param priv32 private key
/// @returns true if the address found successfully
bool priv2addr(char *coinaddr, uint8_t buf33[33], uint8_t priv32[32]);

/// converts public key as array of uint8_t to CPubKey object
/// @param buf33 public key as array of uint8_t
/// @returns created CPubKey object
CPubKey buf2pk(uint8_t *buf33);

/// \cond INTERNAL
void endiancpy(uint8_t *dest,uint8_t *src,int32_t len);
uint256 DiceHashEntropy(uint256 &entropy,uint256 _txidpriv,int32_t entropyvout,int32_t usevout);
/// \endcond

/// MakeCC1vout creates a transaction output with a cryptocondition that allows to spend it by one key. The returned output should be added to a transaction vout array.
/// @param evalcode cryptocondition eval code (transactions with this eval code in cc inputs will be forwarded to the contract associated with this eval code)
/// @param nValue value of the output in satoshi
/// @param pk pubkey to spend the cc
/// @param vData pointer to vector of vectors of unsigned char data to be added to the created vout for application needs
/// @returns vout object
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk, std::vector<std::vector<unsigned char>>* vData = NULL);

/// MakeCC1of2vout creates creates a transaction output with a 1of2 cryptocondition that allows to spend it by either of two keys. The returned output should be added to a transaction vout array.
/// @param evalcode cryptocondition eval code (transactions with this eval code in cc inputs will be forwarded to the contract associated with this eval code)
/// @param nValue value of the output in satoshi
/// @param pk one of two pubkeys to spend the cc
/// @param pk2 second of two pubkeys to spend the cc
/// @param vData pointer to vector of vectors of unsigned char data to be added to the created vout for application needs
/// @returns vout object
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2, std::vector<std::vector<unsigned char>>* vData = NULL);

/// @private
int32_t has_opret(const CTransaction &tx, uint8_t evalcode);
/// @private
bool getCCopret(const CScript &scriptPubKey, CScript &opret);
/// @private
bool makeCCopret(CScript &opret, std::vector<std::vector<unsigned char>> &vData);

/// IsCCInput checks if scriptSig object contains a cryptocondition 
/// @param scriptSig scriptSig object with a cryptocondition
/// @returns true if the scriptSig object contains a cryptocondition
bool IsCCInput(CScript const& scriptSig);

/// CheckTxFee checks if queried transaction fee value is not less than the actual transaction fee of a real transaction
/// @param tx transaction object which actual txfee to check
/// @param txfee transaction fee to check
/// @param height the height of the block where the transaction resides
/// @param blocktime not used (block time of the block where the transaction resides)
/// @param[out] actualtxfee the returned actual transaction fee
/// @returns true if txfee >= actual transaction fee
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime,int64_t &actualtxfee);

/// \cond INTERNAL
int32_t unstringbits(char *buf,uint64_t bits);
uint64_t stringbits(char *str);
uint256 revuint256(uint256 txid);
char *uint256_str(char *dest,uint256 txid);
char *pubkey33_str(char *dest,uint8_t *pubkey33);
/// \endcond

/// converts public key as array of uint8_t to normal address
/// @param[out] destaddr char array with the returned normal address, should have 64 chars 
/// @param pubkey33 public key as array of uint8_t
/// @returns true if the normal address is obtained successfully
bool pubkey2addr(char *destaddr, uint8_t *pubkey33);

/// converts public key as vector of uint8_t to CPubKey object
/// @param vpubkey public key as vector of uint8_t
/// @returns created CPubKey object
CPubKey pubkey2pk(std::vector<uint8_t> vpubkey);

/// CCfullsupply returns token initial supply
/// @param tokenid id of token (id of token creation tx)
int64_t CCfullsupply(uint256 tokenid);


/// Returns bitcoin address for the scriptPubKey parameter
/// @param[out] destaddr the returned address of the scriptPubKey, the buffer should have size of at least 64 chars
/// @param scriptPubKey scriptPubKey object
/// @returns true if success
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey);

/// Returns my pubkey, that is set by the -pubkey dragonxd parameter
/// @returns public key as byte array
std::vector<uint8_t> Mypubkey();

/// @private
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids);

/// @private
CPubKey check_signing_pubkey(CScript scriptSig);

/// SignTx signs a transaction in normal vin scriptSig
/// @param mtx transaction object of CMutableTransaction type
/// @param vini order number of transaction input to sign (starting from 0)
/// @param utxovalue amount of utxo spent by the input to sign (this amount will be added to the signature hash)
/// @param scriptPubKey scriptPubKey of the utxo spent by the input to sign
bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey);

extern std::vector<CPubKey> NULL_pubkeys; //!< constant value for use in functions where such value might be passed @see FinalizeCCTx

/// overload old-style FinalizeCCTx for compatibility
/// @param skipmask parameter is not used
/// @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
/// @param txfee transaction fee
/// @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<CPubKey> 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 CC 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.
/// By using -addressindex=1 of the dragonxd daemon, it allows tracking of all the CC addresses.
///
/// For signing the vins the function builds several default probe scriptPubKeys and checks them against the referred previous transactions (vintx) vouts.
/// For cryptocondition vins the function creates a basic set of probe cryptconditions with mypk and module global pubkey, both for coins and tokens cases.
/// For signing 1of2 cryptocondition it is needed to use CCaddr1of2set function to set both pubkeys in cp object before calling FinalizeCCtx.
/// 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 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
/// @param txfee transaction fee
/// @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<CPubKey> pubkeys = NULL_pubkeys);

/// SetCCunspents returns a vector of unspent outputs on an address 
/// @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);

/// SetCCtxids returns a vector of all 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<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr,bool CCflag = true);

/// overloaded SetCCtxids returns 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
/// @param evalcode evalcode of cc module for which outputs will be filtered
/// @param filtertxid txid for which outputs will be filtered
/// @param func funcid for which outputs will be filtered
void SetCCtxids(std::vector<uint256> &txids,char *coinaddr,bool ccflag, uint8_t evalcode, uint256 filtertxid, uint8_t func);

/// In NSPV mode adds normal (not cc) inputs to the transaction object vin array for the specified total amount using available utxos on mypk's TX_PUBKEY address
/// @param mtx mutable transaction object
/// @param mypk pubkey to make TX_PUBKEY address from
/// @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
/// @param[out] ptr pointer to NSPV_CCmtxinfo structure with the info about the added utxo
/// @returns amount of added normal inputs or amount of all normal inputs in the wallet
int64_t NSPV_AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs,struct NSPV_CCmtxinfo *ptr);

/// AddNormalinputs wrapper for calling either AddNormalinputsLocal or AddNormalinputsRemote 
/// @param mtx mutable transaction object
/// @param mypk not used
/// @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
/// @param remote true if running in remote nspv mode (default false)
/// @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);

/// 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
/// @param mypk not used
/// @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);

/// 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 dragonxd.
/// @param mtx mutable transaction object
/// @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);

/// 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
/// @param mypk pubkey on which utxo's are searched
/// @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);

/// 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
/// @param utxotxid transaction id of the utxo
/// @param utxovout the utxo transaction vout order number (starting form 0)
/// @param CCflag if true the function searches for cc output, otherwise for normal output
/// @returns utxo value or 0 if utxo not found
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);

/// @private
bool NSPV_SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey,uint32_t nTime);

/*! \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 */

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 */

#define JSON_HEXTX "hex"
#define JSON_SIGDATA "SigData"

/// @private add sig data for signing partially signed tx to UniValue object
void AddSigData2UniValue(UniValue &result, int32_t vini, UniValue& ccjson, std::string sscriptpubkey, int64_t amount);


#endif
