diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 5f47ba352..1f7267701 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -144,7 +144,8 @@ bool AppInit(int argc, char* argv[]) fDaemon = GetBoolArg("-daemon", false); if (fDaemon) { - fprintf(stdout, "Komodo server starting\n"); + extern char ASSETCHAINS_SYMBOL[16]; + fprintf(stdout, "Komodo %s server starting\n",ASSETCHAINS_SYMBOL); // Daemonize pid_t pid = fork(); diff --git a/src/coins.cpp b/src/coins.cpp index dc3880a2a..ca8bf3b46 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -383,12 +383,12 @@ const CScript &CCoinsViewCache::GetSpendFor(const CTxIn& input) const return coins->vout[input.prevout.n].scriptPubKey; } -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +//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); extern char ASSETCHAINS_SYMBOL[16]; CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTransaction& tx,uint32_t tiptime) const { - uint32_t timestamp,minutes; int64_t interest; *interestp = 0; if ( tx.IsCoinBase() != 0 ) return 0; @@ -397,19 +397,20 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTr { value = GetOutputFor(tx.vin[i]).nValue; nResult += value; - interest = komodo_interest(nHeight,value,tx.nLockTime,tiptime); #ifdef KOMODO_ENABLE_INTEREST if ( ASSETCHAINS_SYMBOL[0] == 0 && nHeight >= 60000 ) { - if ( interest != 0 ) + if ( value >= 10*COIN ) { - printf("nResult %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)nResult/COIN,(double)interest/COIN,nHeight,tx.nLockTime,tiptime); - fprintf(stderr,"nResult %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)nResult/COIN,(double)interest/COIN,nHeight,tx.nLockTime,tiptime); + int64_t interest; int32_t txheight; uint32_t locktime; + interest = komodo_accrued_interest(&txheight,&locktime,tx.vin[i].prevout.hash,tx.vin[i].prevout.n,0,value); + //printf("nResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nResult/COIN,(double)value/COIN,(double)interest/COIN,txheight,locktime,tiptime); + //fprintf(stderr,"nResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nResult/COIN,(double)value/COIN,(double)interest/COIN,txheight,locktime,tiptime); + nResult += interest; + (*interestp) += interest; } - nResult += interest; } #endif - (*interestp) += interest; } nResult += tx.GetJoinSplitValueIn(); diff --git a/src/coins.h b/src/coins.h index 7d5bc8168..34e3a89d7 100644 --- a/src/coins.h +++ b/src/coins.h @@ -87,14 +87,14 @@ public: //! version of the CTransaction; accesses to this value should probably check for nHeight as well, //! as new tx version will probably only be introduced at certain heights int nVersion; - uint32_t nLockTime; + //uint32_t nLockTime; void FromTx(const CTransaction &tx, int nHeightIn) { fCoinBase = tx.IsCoinBase(); vout = tx.vout; nHeight = nHeightIn; nVersion = tx.nVersion; - nLockTime = tx.nLockTime; + //nLockTime = tx.nLockTime; ClearUnspendable(); } diff --git a/src/init.cpp b/src/init.cpp index fb2ae6aeb..cfd4f56dc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -455,7 +455,8 @@ std::string HelpMessage(HelpMessageMode mode) std::string LicenseInfo() { return FormatParagraph(strprintf(_("Copyright (C) 2009-%i The Bitcoin Core Developers"), COPYRIGHT_YEAR)) + "\n" + - FormatParagraph(strprintf(_("Copyright (C) 2015-%i The Zcash Developers"), COPYRIGHT_YEAR)) + "\n" + + FormatParagraph(strprintf(_("Copyright (C) 2015-%i The Zcash Developers"), COPYRIGHT_YEAR)) + "\n" + + FormatParagraph(strprintf(_("Copyright (C) 2015-%i jl777 and SuperNET developers"), COPYRIGHT_YEAR)) + "\n" + "\n" + FormatParagraph(_("This is experimental software.")) + "\n" + "\n" + @@ -929,7 +930,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Sanity check if (!InitSanityCheck()) - return InitError(_("Initialization sanity check failed. Zcash is shutting down.")); + return InitError(_("Initialization sanity check failed. Komodo is shutting down.")); std::string strDataDir = GetDataDir().string(); #ifdef ENABLE_WALLET @@ -945,9 +946,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) try { static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); if (!lock.try_lock()) - return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Zcash is probably already running."), strDataDir)); + return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Komodo is probably already running."), strDataDir)); } catch(const boost::interprocess::interprocess_exception& e) { - return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Zcash is probably already running.") + " %s.", strDataDir, e.what())); + return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Komodo is probably already running.") + " %s.", strDataDir, e.what())); } #ifndef WIN32 @@ -956,7 +957,7 @@ 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("Zcash version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); + LogPrintf("Komodo version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); #ifdef ENABLE_WALLET LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); diff --git a/src/komodo-tx.cpp b/src/komodo-tx.cpp index 32d504b18..d5e333093 100644 --- a/src/komodo-tx.cpp +++ b/src/komodo-tx.cpp @@ -29,6 +29,11 @@ using namespace std; #include "komodo_interest.h" +uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue) +{ + return(0); +} + static bool fCreateBlank; static map registers; diff --git a/src/komodo.h b/src/komodo.h index 34b249f3b..f308c893b 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -20,7 +20,7 @@ // 0. optimize assetchains RT loop // 1. error check fiat redeem amounts // 2. net balance limiter -// 3. verify: interest payment, ratification, reorgs +// 3. verify: reorgs // 4. automate notarization fee payouts // 5. automated distribution of test REVS snapshot diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index af86faa76..8979bae06 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -547,3 +547,38 @@ int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 has fprintf(stderr,"couldnt find notary_hash %s ht.%d\n",notarized_hash.ToString().c_str(),notarized_height); return(0); } + +uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n) +{ + LOCK(cs_main); + CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex; + if ( !GetTransaction(hash,tx,hashBlock,true) ) + return(0); + uint32_t locktime = 0; + if ( n < tx.vout.size() ) + { + if ( (pindex= mapBlockIndex[hashBlock]) != 0 && (tipindex= chainActive.Tip()) != 0 ) + { + *valuep = tx.vout[n].nValue; + *txheightp = pindex->nHeight; + *tiptimep = tipindex->nTime; + locktime = tx.nLockTime; + //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep); + } + } + 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) +{ + uint64_t value; uint32_t tiptime; + if ( (*locktimep= komodo_interest_args(txheightp,&tiptime,&value,hash,n)) != 0 ) + { + if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) ) + return(komodo_interest(*txheightp,value,*locktimep,tiptime)); + //fprintf(stderr,"nValue %llu lock.%u:%u nTime.%u -> %llu\n",(long long)coins.vout[n].nValue,coins.nLockTime,timestamp,pindex->nTime,(long long)interest); + else fprintf(stderr,"komodo_accrued_interest value mismatch %llu vs %llu or height mismatch %d vs %d\n",(long long)value,(long long)checkvalue,*txheightp,checkheight); + } + return(0); +} diff --git a/src/komodo_interest.h b/src/komodo_interest.h index 68ab2e2f3..b3b1e21f7 100644 --- a/src/komodo_interest.h +++ b/src/komodo_interest.h @@ -15,7 +15,7 @@ #define KOMODO_INTEREST ((uint64_t)(0.05 * COIN)) // 5% -uint64_t komodo_accrued_interest(int32_t height,int64_t paidinterest) +uint64_t komodo_earned_interest(int32_t height,int64_t paidinterest) { static uint64_t *interests; static int32_t maxheight; uint64_t total; int32_t ind,incr = 100000; @@ -50,25 +50,26 @@ uint64_t komodo_accrued_interest(int32_t height,int64_t paidinterest) uint64_t komodo_moneysupply(int32_t height) { - if ( height <= 1 ) + if ( height <= 1 || ASSETCHAINS_SYMBOL[0] == 0 ) return(0); - else return(COIN * 100000000 + (height-1) * 3 + komodo_accrued_interest(height,-1)); + else return(COIN * 100000000 + (height-1) * 3 + komodo_earned_interest(height,-1)); } uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) { int32_t minutes; uint64_t numerator,denominator,interest = 0; - if ( komodo_moneysupply(txheight) < MAX_MONEY && nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= COIN ) + if ( komodo_moneysupply(txheight) < MAX_MONEY && nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) { - if ( (minutes= (tiptime - nLockTime) / 60) > 60 ) + if ( (minutes= (tiptime - nLockTime) / 60) >= 60 ) { numerator = (nValue * KOMODO_INTEREST); denominator = (((uint64_t)365 * 24 * 60) / minutes); if ( denominator == 0 ) denominator = 1; // max KOMODO_INTEREST per transfer, do it at least annually! interest = (numerator / denominator) / COIN; - //fprintf(stderr,"komodo_interest %lld %.8f nLockTime.%u tiptime.%u minutes.%d interest %lld %.8f (%llu / %llu)\n",(long long)nValue,dstr(nValue),nLockTime,tiptime,minutes,(long long)interest,dstr(interest),(long long)numerator,(long long)denominator); + //fprintf(stderr,"komodo_interest %lld %.8f nLockTime.%u tiptime.%u minutes.%d interest %lld %.8f (%llu / %llu)\n",(long long)nValue,(double)nValue/COIN,nLockTime,tiptime,minutes,(long long)interest,(double)interest/COIN,(long long)numerator,(long long)denominator); } } return(interest); } + diff --git a/src/main.cpp b/src/main.cpp index dd1d52a92..be9d34e40 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1718,6 +1718,21 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c // Check for negative or overflow input values nValueIn += coins->vout[prevout.n].nValue; +#ifdef KOMODO_ENABLE_INTEREST + if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Tip() != 0 && chainActive.Tip()->nHeight >= 60000 ) + { + if ( coins->vout[prevout.n].nValue >= 10*COIN ) + { + int64_t interest; int32_t txheight; uint32_t locktime; + if ( (interest= komodo_accrued_interest(&txheight,&locktime,prevout.hash,prevout.n,0,coins->vout[prevout.n].nValue)) != 0 ) + { + //printf("checkResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nValueIn/COIN,(double)coins->vout[prevout.n].nValue/COIN,(double)interest/COIN,txheight,locktime,chainActive.Tip()->nTime); + //fprintf(stderr,"checkResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nValueIn/COIN,(double)coins->vout[prevout.n].nValue/COIN,(double)interest/COIN,txheight,locktime,chainActive.Tip()->nTime); + nValueIn += interest; + } + } + } +#endif if (!MoneyRange(coins->vout[prevout.n].nValue) || !MoneyRange(nValueIn)) return state.DoS(100, error("CheckInputs(): txin values out of range"), REJECT_INVALID, "bad-txns-inputvalues-outofrange"); @@ -1730,9 +1745,8 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c REJECT_INVALID, "bad-txns-inputvalues-outofrange"); if (nValueIn < tx.GetValueOut()) - return state.DoS(100, error("CheckInputs(): %s value in (%s) < value out (%s)", - tx.GetHash().ToString(), FormatMoney(nValueIn), FormatMoney(tx.GetValueOut())), - REJECT_INVALID, "bad-txns-in-belowout"); + return state.DoS(100, error("CheckInputs(): %s value in (%s) < value out (%s) diff %.8f", + tx.GetHash().ToString(), FormatMoney(nValueIn), FormatMoney(tx.GetValueOut()),((double)nValueIn - tx.GetValueOut())/COIN),REJECT_INVALID, "bad-txns-in-belowout"); // Tally transaction fees CAmount nTxFee = nValueIn - tx.GetValueOut(); @@ -1743,7 +1757,7 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c if (!MoneyRange(nFees)) return state.DoS(100, error("CheckInputs(): nFees out of range"), REJECT_INVALID, "bad-txns-fee-outofrange"); - +//fprintf(stderr,"nFees %.8f\n",(double)nFees/COIN); // The first loop above does all the inexpensive checks. // Only if ALL inputs pass do we perform expensive ECDSA signature checks. // Helps prevent CPU exhaustion attacks. @@ -2230,7 +2244,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return false; control.Add(vChecks); } - komodo_accrued_interest(pindex->nHeight,sum); + komodo_earned_interest(pindex->nHeight,sum); CTxUndo undoDummy; if (i > 0) { blockundo.vtxundo.push_back(CTxUndo()); diff --git a/src/miner.cpp b/src/miner.cpp index 928bad008..90fd460f6 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -479,7 +479,7 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese { LOCK(cs_main); if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash()) - return error("ZcashMiner: generated block is stale"); + return error("KomodoMiner: generated block is stale"); } // Remove key from key pool @@ -495,7 +495,7 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese // Process this block the same as if we had received it from another node CValidationState state; if (!ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) - return error("ZcashMiner: ProcessNewBlock, block not accepted"); + return error("KomodoMiner: ProcessNewBlock, block not accepted"); minedBlocks.increment(); @@ -506,9 +506,9 @@ int32_t komodo_baseid(char *origbase); void static BitcoinMiner(CWallet *pwallet) { - LogPrintf("ZcashMiner started\n"); + LogPrintf("KomodoMiner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); - RenameThread("zcash-miner"); + RenameThread("komodo-miner"); const CChainParams& chainparams = Params(); // Each thread has its own key and counter @@ -583,12 +583,12 @@ void static BitcoinMiner(CWallet *pwallet) unique_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); if (!pblocktemplate.get()) { - LogPrintf("Error in ZcashMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n"); + LogPrintf("Error in KomodoMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n"); return; } CBlock *pblock = &pblocktemplate->block; IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); - LogPrintf("Running ZcashMiner.%s with %u transactions in block (%u bytes)\n",solver.c_str(),pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION)); + LogPrintf("Running KomodoMiner.%s with %u transactions in block (%u bytes)\n",solver.c_str(),pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION)); // // Search // @@ -641,7 +641,7 @@ void static BitcoinMiner(CWallet *pwallet) } // Found a solution SetThreadPriority(THREAD_PRIORITY_NORMAL); - LogPrintf("ZcashMiner:\n"); + LogPrintf("KomodoMiner:\n"); LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); if (ProcessBlockFound(pblock, *pwallet, reservekey)) { // Ignore chain updates caused by us @@ -755,12 +755,12 @@ void static BitcoinMiner(CWallet *pwallet) } catch (const boost::thread_interrupted&) { - LogPrintf("ZcashMiner terminated\n"); + LogPrintf("KomodoMiner terminated\n"); throw; } catch (const std::runtime_error &e) { - LogPrintf("ZcashMiner runtime error: %s\n", e.what()); + LogPrintf("KomodoMiner runtime error: %s\n", e.what()); return; } c.disconnect(); diff --git a/src/pow.cpp b/src/pow.cpp index befb665bd..e9d092bb2 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -127,7 +127,7 @@ bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned in } if ( nonz == 0 ) return(true); // will come back via different path with pubkey set - if ( height > 60000 ) + //if ( height > 60000 ) { if ( notaryid >= 0 ) { @@ -142,7 +142,7 @@ bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned in } } } - else + /*else { if ( special > 0 ) // special notary id == (height % numnotaries) { @@ -151,12 +151,10 @@ bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned in bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); flag = 1; } - } + }*/ } if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) return error("CheckProofOfWork(): nBits below minimum work"); - if ( height > 70000 ) - bnTarget /= 64; // Check proof of work matches claimed amount if ( UintToArith256(hash) > bnTarget ) { diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 035f9af9e..3c02f2134 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -239,7 +239,7 @@ class CTxOut public: CAmount nValue; CScript scriptPubKey; - + uint64_t interest; CTxOut() { SetNull(); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 7373d51c9..ae9f41540 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -386,6 +386,7 @@ uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uin 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); char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); +uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n); Value notaries(const Array& params, bool fHelp) { @@ -504,6 +505,8 @@ Value paxprices(const Array& params, bool fHelp) return ret; } +uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue); + Value gettxout(const Array& params, bool fHelp) { if (fHelp || params.size() < 2 || params.size() > 3) @@ -574,15 +577,9 @@ Value gettxout(const Array& params, bool fHelp) ret.push_back(Pair("confirmations", 0)); else ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1)); ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue))); - - CBlockIndex *pblockindex = chainActive[coins.nHeight]; - uint64_t interest; uint32_t timestamp=0; - if ( pblockindex != 0 ) - timestamp = pblockindex->nTime; // this is approx, but cant figure out how to get tx here - interest = komodo_interest(coins.nHeight,coins.vout[n].nValue,timestamp,pindex->nTime); - //fprintf(stderr,"nValue %llu lock.%u:%u nTime.%u -> %llu\n",(long long)coins.vout[n].nValue,coins.nLockTime,timestamp,pindex->nTime,(long long)interest); - ret.push_back(Pair("interest", ValueFromAmount(interest))); - + uint64_t interest; int32_t txheight; uint32_t locktime; + if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue)) != 0 ) + ret.push_back(Pair("interest", ValueFromAmount(interest))); Object o; ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true); ret.push_back(Pair("scriptPubKey", o)); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 4642a52db..b2f8aa0b2 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -39,6 +39,8 @@ using namespace std; * * Or alternatively, create a specific query method for the information. **/ +uint64_t komodo_interestsum(); + Value getinfo(const Array& params, bool fHelp) { extern uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID; @@ -90,10 +92,13 @@ Value getinfo(const Array& params, bool fHelp) if (pwalletMain) { obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); + obj.push_back(Pair("interest", ValueFromAmount(komodo_interestsum()))); } #endif obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("timeoffset", GetTimeOffset())); + if ( chainActive.Tip() != 0 ) + obj.push_back(Pair("tiptime", (int)chainActive.Tip()->nTime)); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index c27f8213c..4b5cdae35 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -122,16 +122,18 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) entry.push_back(Pair("vin", vin)); Array vout; BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); - CBlockIndex *pindex = it->second; + CBlockIndex *tipindex,*pindex = it->second; uint64_t interest; for (unsigned int i = 0; i < tx.vout.size(); i++) { const CTxOut& txout = tx.vout[i]; Object out; out.push_back(Pair("value", ValueFromAmount(txout.nValue))); - if ( pindex != 0 && tx.nLockTime != 0 ) + if ( pindex != 0 && tx.nLockTime != 0 && (tipindex= chainActive.Tip()) != 0 ) { - interest = komodo_interest(pindex->nHeight,txout.nValue,tx.nLockTime,pindex->nTime); - //fprintf(stderr,"TxtoJSON interest %llu %.8f\n",(long long)interest,(double)interest/COIN); + extern char ASSETCHAINS_SYMBOL[16]; + interest = komodo_interest(pindex->nHeight,txout.nValue,tx.nLockTime,tipindex->nTime); + if ( strcmp("REVS",ASSETCHAINS_SYMBOL) == 0 ) + fprintf(stderr,"TxtoJSON interest %llu %.8f (%d %llu %u %u)\n",(long long)interest,(double)interest/COIN,(int32_t)pindex->nHeight,(long long)txout.nValue,(uint32_t)tx.nLockTime,(int32_t)tipindex->nTime); out.push_back(Pair("interest", ValueFromAmount(interest))); } out.push_back(Pair("n", (int64_t)i)); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 78a438d03..e8a9958ce 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -253,7 +253,7 @@ Value help(const Array& params, bool fHelp) Value stop(const Array& params, bool fHelp) { - // Accept the deprecated and ignored 'detach' boolean argument + // Accept the deprecated and ignored 'detach' boolean argument if (fHelp || params.size() > 1) throw runtime_error( "stop\n" @@ -638,7 +638,7 @@ void StartRPCThreads() "The username and password MUST NOT be the same.\n" "If the file does not exist, create it with owner-readable-only file permissions.\n" "It is also recommended to set alertnotify so you are notified of problems;\n" - "for example: alertnotify=echo %%s | mail -s \"Zcash Alert\" admin@foo.com\n"), + "for example: alertnotify=echo %%s | mail -s \"Komodo Alert\" admin@foo.com\n"), GetConfigFile().string(), EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32)), "", CClientUIInterface::MSG_ERROR | CClientUIInterface::SECURE); diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 2f674df0f..885dcf5b7 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -375,7 +375,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) std::string testKey = CZCSpendingKey(testSpendingKey).ToString(); // create test data using the random key - std::string format_str = "# Wallet dump created by Zcash v0.11.2.0.z8-9155cc6-dirty (2016-08-11 11:37:00 -0700)\n" + std::string format_str = "# Wallet dump created by Komodo v0.11.2.0.z8-9155cc6-dirty (2016-08-11 11:37:00 -0700)\n" "# * Created on 2016-08-12T21:55:36Z\n" "# * Best block at time of backup was 0 (0de0a3851fef2d433b9b4f51d4342bdd24c5ddd793eb8fba57189f07e9235d52),\n" "# mined on 2009-01-03T18:15:05Z\n" diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 789bd4537..9e8fc6e68 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -182,7 +182,7 @@ Value importaddress(const Array& params, bool fHelp) std::vector data(ParseHex(params[0].get_str())); script = CScript(data.begin(), data.end()); } else { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address or script"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Komodo address or script"); } string strLabel = ""; @@ -408,7 +408,7 @@ Value dumpprivkey(const Array& params, bool fHelp) string strAddress = params[0].get_str(); CBitcoinAddress address; if (!address.SetString(strAddress)) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Komodo address"); CKeyID keyID; if (!address.GetKeyID(keyID)) throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key"); @@ -483,7 +483,7 @@ Value dumpwallet_impl(const Array& params, bool fHelp, bool fDumpZKeys) std::sort(vKeyBirth.begin(), vKeyBirth.end()); // produce output - file << strprintf("# Wallet dump created by Zcash %s (%s)\n", CLIENT_BUILD, CLIENT_DATE); + file << strprintf("# Wallet dump created by Komodo %s (%s)\n", CLIENT_BUILD, CLIENT_DATE); file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime())); file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString()); file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime())); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 1e8e6c17d..1f2cb706b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -72,8 +72,12 @@ void EnsureWalletIsUnlocked() throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); } +uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue); +uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); + void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { + //int32_t i,n,txheight; uint32_t locktime; uint64_t interest = 0; int confirms = wtx.GetDepthInMainChain(); entry.push_back(Pair("confirmations", confirms)); if (wtx.IsCoinBase()) @@ -86,6 +90,11 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) } uint256 hash = wtx.GetHash(); entry.push_back(Pair("txid", hash.GetHex())); + //n = wtx.vout.size(); + //for (i=0; inHeight,wtx.vout[i].nValue,wtx.nLockTime,mapBlockIndex[wtx.hashBlock]->nTime); + //entry.push_back(Pair("interest", interest)); + Array conflicts; BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts()) conflicts.push_back(conflict.GetHex()); @@ -114,7 +123,7 @@ Value getnewaddress(const Array& params, bool fHelp) if (fHelp || params.size() > 1) throw runtime_error( "getnewaddress ( \"account\" )\n" - "\nReturns a new Zcash address for receiving payments.\n" + "\nReturns a new Komodo address for receiving payments.\n" "\nArguments:\n" "1. \"account\" (string, optional) DEPRECATED. If provided, it MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "\nResult:\n" @@ -191,7 +200,7 @@ Value getaccountaddress(const Array& params, bool fHelp) if (fHelp || params.size() != 1) throw runtime_error( "getaccountaddress \"account\"\n" - "\nDEPRECATED. Returns the current Zcash address for receiving payments to this account.\n" + "\nDEPRECATED. Returns the current Komodo address for receiving payments to this account.\n" "\nArguments:\n" "1. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "\nResult:\n" @@ -223,7 +232,7 @@ Value getrawchangeaddress(const Array& params, bool fHelp) if (fHelp || params.size() > 1) throw runtime_error( "getrawchangeaddress\n" - "\nReturns a new Zcash address, for receiving change.\n" + "\nReturns a new Komodo address, for receiving change.\n" "This is for use with raw transactions, NOT normal use.\n" "\nResult:\n" "\"address\" (string) The address\n" @@ -271,7 +280,7 @@ Value setaccount(const Array& params, bool fHelp) CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Komodo address"); string strAccount; if (params.size() > 1) @@ -318,7 +327,7 @@ Value getaccount(const Array& params, bool fHelp) CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Komodo address"); string strAccount; map::iterator mi = pwalletMain->mapAddressBook.find(address.Get()); @@ -443,7 +452,7 @@ Value sendtoaddress(const Array& params, bool fHelp) CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Komodo address"); // Amount CAmount nAmount = AmountFromValue(params[1]); @@ -683,7 +692,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) // Bitcoin address CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Komodo address"); CScript scriptPubKey = GetScriptForDestination(address.Get()); if (!IsMine(*pwalletMain,scriptPubKey)) return (double)0.0; @@ -995,7 +1004,7 @@ Value sendfrom(const Array& params, bool fHelp) string strAccount = AccountFromValue(params[0]); CBitcoinAddress address(params[1].get_str()); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Komodo address"); CAmount nAmount = AmountFromValue(params[2]); int nMinDepth = 1; if (params.size() > 3) @@ -1087,7 +1096,7 @@ Value sendmany(const Array& params, bool fHelp) { CBitcoinAddress address(s.name_); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+s.name_); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Komodo address: ")+s.name_); if (setAddress.count(address)) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_); @@ -1139,7 +1148,7 @@ Value addmultisigaddress(const Array& params, bool fHelp) { string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n" "\nAdd a nrequired-to-sign multisignature address to the wallet.\n" - "Each key is a Zcash address or hex-encoded public key.\n" + "Each key is a Komodo address or hex-encoded public key.\n" "If 'account' is specified (DEPRECATED), assign address to that account.\n" "\nArguments:\n" @@ -2134,7 +2143,7 @@ Value encryptwallet(const Array& params, bool fHelp) // slack space in .dat files; that is bad if the old data is // unencrypted private keys. So: StartShutdown(); - return "wallet encrypted; Zcash server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup."; + return "wallet encrypted; Komodo server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup."; } Value lockunspent(const Array& params, bool fHelp) @@ -2423,7 +2432,7 @@ Value listunspent(const Array& params, bool fHelp) BOOST_FOREACH(Value& input, inputs) { CBitcoinAddress address(input.get_str()); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+input.get_str()); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Komodo address: ")+input.get_str()); if (setAddress.count(address)) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str()); setAddress.insert(address); @@ -2473,11 +2482,11 @@ Value listunspent(const Array& params, bool fHelp) if ( out.tx->nLockTime != 0 ) { BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); - CBlockIndex *pindex = it->second; + CBlockIndex *tipindex,*pindex = it->second; uint64_t interest; - if ( pindex != 0 ) + if ( pindex != 0 && (tipindex= chainActive.Tip()) != 0 ) { - interest = komodo_interest(pindex->nHeight,nValue,out.tx->nLockTime,pindex->nTime); + interest = komodo_interest(pindex->nHeight,nValue,out.tx->nLockTime,tipindex->nTime); entry.push_back(Pair("interest",ValueFromAmount(interest))); } } @@ -2489,6 +2498,30 @@ Value listunspent(const Array& params, bool fHelp) return results; } +uint64_t komodo_interestsum() +{ + uint64_t interest,sum = 0; + vector vecOutputs; + assert(pwalletMain != NULL); + LOCK2(cs_main, pwalletMain->cs_wallet); + pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); + BOOST_FOREACH(const COutput& out,vecOutputs) + { + CAmount nValue = out.tx->vout[out.i].nValue; + if ( out.tx->nLockTime != 0 ) + { + BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); + CBlockIndex *tipindex,*pindex = it->second; + if ( pindex != 0 && (tipindex= chainActive.Tip()) != 0 ) + { + interest = komodo_interest(pindex->nHeight,nValue,out.tx->nLockTime,tipindex->nTime); + sum += interest; + } + } + } + return(sum); +} + Value zc_sample_joinsplit(const json_spirit::Array& params, bool fHelp) { if (fHelp) { @@ -3181,9 +3214,11 @@ Value z_gettotalbalance(const Array& params, bool fHelp) // so we use our own method to get balance of utxos. CAmount nBalance = getBalanceTaddr("", nMinDepth); CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth); - CAmount nTotalBalance = nBalance + nPrivateBalance; + uint64_t interest = komodo_interestsum(); + CAmount nTotalBalance = nBalance + nPrivateBalance + interest; Object result; result.push_back(Pair("transparent", FormatMoney(nBalance, false))); + result.push_back(Pair("interest", FormatMoney(interest, false))); result.push_back(Pair("private", FormatMoney(nPrivateBalance, false))); result.push_back(Pair("total", FormatMoney(nTotalBalance, false))); return result; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index a5bc52b8d..01482e08e 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -78,24 +78,24 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) empty_wallet(); // with an empty wallet we can't even pay one cent - BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet,0)); add_coin(1*CENT, 4); // add a new 1 cent coin // with a new 1 cent coin, we still can't find a mature 1 cent - BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet,0)); // but we can find a new 1 cent - BOOST_CHECK( wallet.SelectCoinsMinConf( 1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf( 1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); add_coin(2*CENT); // add a mature 2 cent coin // we can't make 3 cents of mature coins - BOOST_CHECK(!wallet.SelectCoinsMinConf( 3 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(!wallet.SelectCoinsMinConf( 3 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet,0)); // we can make 3 cents of new coins - BOOST_CHECK( wallet.SelectCoinsMinConf( 3 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf( 3 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 3 * CENT); add_coin(5*CENT); // add a mature 5 cent coin, @@ -105,33 +105,33 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // now we have new: 1+10=11 (of which 10 was self-sent), and mature: 2+5+20=27. total = 38 // we can't make 38 cents only if we disallow new coins: - BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet,0)); // we can't even make 37 cents if we don't allow new coins even if they're from us - BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, 6, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, 6, 6, vCoins, setCoinsRet, nValueRet,0)); // but we can make 37 cents if we accept new coins from ourself - BOOST_CHECK( wallet.SelectCoinsMinConf(37 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(37 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 37 * CENT); // and we can make 38 cents if we accept all new coins - BOOST_CHECK( wallet.SelectCoinsMinConf(38 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(38 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 38 * CENT); // try making 34 cents from 1,2,5,10,20 - we can't do it exactly - BOOST_CHECK( wallet.SelectCoinsMinConf(34 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(34 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_GT(nValueRet, 34 * CENT); // but should get more than 34 cents BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U); // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible) // when we try making 7 cents, the smaller coins (1,2,5) are enough. We should see just 2+5 - BOOST_CHECK( wallet.SelectCoinsMinConf( 7 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf( 7 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 7 * CENT); BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); // when we try making 8 cents, the smaller coins (1,2,5) are exactly enough. - BOOST_CHECK( wallet.SelectCoinsMinConf( 8 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf( 8 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK(nValueRet == 8 * CENT); BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U); // when we try making 9 cents, no subset of smaller coins is enough, and we get the next bigger coin (10) - BOOST_CHECK( wallet.SelectCoinsMinConf( 9 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf( 9 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 10 * CENT); BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U); @@ -145,30 +145,30 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) add_coin(30*CENT); // now we have 6+7+8+20+30 = 71 cents total // check that we have 71 and not 72 - BOOST_CHECK( wallet.SelectCoinsMinConf(71 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK(!wallet.SelectCoinsMinConf(72 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(71 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); + BOOST_CHECK(!wallet.SelectCoinsMinConf(72 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); // now try making 16 cents. the best smaller coins can do is 6+7+8 = 21; not as good at the next biggest coin, 20 - BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 20 * CENT); // we should get 20 in one coin BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U); add_coin( 5*CENT); // now we have 5+6+7+8+20+30 = 75 cents total // now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, better than the next biggest coin, 20 - BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 3 coins BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U); add_coin( 18*CENT); // now we have 5+6+7+8+18+20+30 // and now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, the same as the next biggest coin, 18 - BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 1 coin BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U); // because in the event of a tie, the biggest coin wins // now try making 11 cents. we should get 5+6 - BOOST_CHECK( wallet.SelectCoinsMinConf(11 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(11 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 11 * CENT); BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); @@ -177,11 +177,11 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) add_coin( 2*COIN); add_coin( 3*COIN); add_coin( 4*COIN); // now we have 5+6+7+8+18+20+30+100+200+300+400 = 1094 cents - BOOST_CHECK( wallet.SelectCoinsMinConf(95 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(95 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 1 * COIN); // we should get 1 BTC in 1 coin BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U); - BOOST_CHECK( wallet.SelectCoinsMinConf(195 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(195 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 2 * COIN); // we should get 2 BTC in 1 coin BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U); @@ -195,14 +195,14 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 = 1.5 cents // we'll get sub-cent change whatever happens, so can expect 1.0 exactly - BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // but if we add a bigger coin, making it possible to avoid sub-cent change, things change: add_coin(1111*CENT); // try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + 1111 = 1112.5 cents - BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount // if we add more sub-cent coins: @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) add_coin(0.7*CENT); // and try again to make 1.0 cents, we can still make 1.0 cents - BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount // run the 'mtgox' test (see http://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf) @@ -219,7 +219,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) for (int i = 0; i < 20; i++) add_coin(50000 * COIN); - BOOST_CHECK( wallet.SelectCoinsMinConf(500000 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(500000 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 500000 * COIN); // we should get the exact amount BOOST_CHECK_EQUAL(setCoinsRet.size(), 10U); // in ten coins @@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) add_coin(0.6 * CENT); add_coin(0.7 * CENT); add_coin(1111 * CENT); - BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 1111 * CENT); // we get the bigger coin BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U); @@ -242,7 +242,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) add_coin(0.6 * CENT); add_coin(0.8 * CENT); add_coin(1111 * CENT); - BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); // in two coins 0.4+0.6 @@ -253,12 +253,12 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) add_coin(1 * COIN); // trying to make 1.0001 from these three coins - BOOST_CHECK( wallet.SelectCoinsMinConf(1.0001 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(1.0001 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 1.0105 * COIN); // we should get all coins BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U); // but if we try to make 0.999, we should take the bigger of the two small coins to avoid sub-cent change - BOOST_CHECK( wallet.SelectCoinsMinConf(0.999 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK( wallet.SelectCoinsMinConf(0.999 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet,0)); BOOST_CHECK_EQUAL(nValueRet, 1.01 * COIN); // we should get 1 + 0.01 BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); @@ -270,8 +270,8 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // picking 50 from 100 coins doesn't depend on the shuffle, // but does depend on randomness in the stochastic approximation code - BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet , nValueRet)); - BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet2, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet , nValueRet,0)); + BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet2, nValueRet,0)); BOOST_CHECK(!equal_sets(setCoinsRet, setCoinsRet2)); int fails = 0; @@ -279,8 +279,8 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) { // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time // run the test RANDOM_REPEATS times and only complain if all of them fail - BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet , nValueRet)); - BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet2, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet , nValueRet,0)); + BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet2, nValueRet,0)); if (equal_sets(setCoinsRet, setCoinsRet2)) fails++; } @@ -296,8 +296,8 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) { // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time // run the test RANDOM_REPEATS times and only complain if all of them fail - BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet , nValueRet)); - BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet2, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet , nValueRet,0)); + BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet2, nValueRet,0)); if (equal_sets(setCoinsRet, setCoinsRet2)) fails++; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5c8ce5a9f..d37b2793f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2169,8 +2169,11 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const /** * populate vCoins with vector of available COutputs. */ +uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); + void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase) const { + uint64_t interest,*ptr; vCoins.clear(); { @@ -2196,19 +2199,56 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const if (nDepth < 0) continue; - for (unsigned int i = 0; i < pcoin->vout.size(); i++) { + for (unsigned int i = 0; i < pcoin->vout.size(); i++) + { isminetype mine = IsMine(pcoin->vout[i]); if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO && !IsLockedCoin((*it).first, i) && (pcoin->vout[i].nValue > 0 || fIncludeZeroValue) && (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) - vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO)); + { +#ifdef KOMODO_ENABLE_INTEREST + extern char ASSETCHAINS_SYMBOL[16]; + if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Tip() != 0 && chainActive.Tip()->nHeight >= 60000 ) + { + if ( pcoin->vout[i].nValue >= 10*COIN ) + { + interest = komodo_interest(chainActive.Tip()->nHeight+1,pcoin->vout[i].nValue,pcoin->nLockTime,chainActive.Tip()->nTime); + if ( interest != 0 ) + { + //printf("wallet nValueRet %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,chainActive.Tip()->nHeight+1,pcoin->nLockTime,chainActive.Tip()->nTime); + //fprintf(stderr,"wallet nValueRet %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,chainActive.Tip()->nHeight+1,pcoin->nLockTime,chainActive.Tip()->nTime); + //ptr = (uint64_t *)&pcoin->vout[i].nValue; + //(*ptr) += interest; + ptr = (uint64_t *)&pcoin->vout[i].interest; + (*ptr) = interest; + //pcoin->vout[i].nValue += interest; + } + else + { + ptr = (uint64_t *)&pcoin->vout[i].interest; + (*ptr) = 0; + } + } + else + { + ptr = (uint64_t *)&pcoin->vout[i].interest; + (*ptr) = 0; + } + } + else + { + ptr = (uint64_t *)&pcoin->vout[i].interest; + (*ptr) = 0; + } +#endif + vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO)); + } } } } } -static void ApproximateBestSubset(vector > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue, - vector& vfBest, CAmount& nBest, int iterations = 1000) +static void ApproximateBestSubset(vector > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue,vector& vfBest, CAmount& nBest, int iterations = 1000) { vector vfIncluded; @@ -2253,12 +2293,13 @@ static void ApproximateBestSubset(vector vCoins, - set >& setCoinsRet, CAmount& nValueRet) const +bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector vCoins,set >& setCoinsRet, CAmount& nValueRet, uint64_t *interestp) const { + uint64_t interests[512],lowest_interest = 0; int32_t count = 0; setCoinsRet.clear(); + memset(interests,0,sizeof(interests)); nValueRet = 0; - + *interestp = 0; // List of values less than target pair > coinLowestLarger; coinLowestLarger.first = std::numeric_limits::max(); @@ -2287,16 +2328,23 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(coin.second); nValueRet += coin.first; + *interestp += pcoin->vout[i].interest; return true; } else if (n < nTargetValue + CENT) { vValue.push_back(coin); nTotalLower += n; + if ( count < sizeof(interests)/sizeof(*interests) ) + { + //fprintf(stderr,"count.%d %.8f\n",count,(double)pcoin->vout[i].interest/COIN); + interests[count++] = pcoin->vout[i].interest; + } } else if (n < coinLowestLarger.first) { coinLowestLarger = coin; + lowest_interest = pcoin->vout[i].interest; } } @@ -2306,6 +2354,8 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(vValue[i].second); nValueRet += vValue[i].first; + if ( i < count ) + *interestp += interests[i]; } return true; } @@ -2316,6 +2366,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int return false; setCoinsRet.insert(coinLowestLarger.second); nValueRet += coinLowestLarger.first; + *interestp += lowest_interest; return true; } @@ -2335,6 +2386,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(coinLowestLarger.second); nValueRet += coinLowestLarger.first; + *interestp += lowest_interest; } else { for (unsigned int i = 0; i < vValue.size(); i++) @@ -2342,6 +2394,8 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(vValue[i].second); nValueRet += vValue[i].first; + if ( i < count ) + *interestp += interests[i]; } LogPrint("selectcoins", "SelectCoins() best subset: "); @@ -2354,11 +2408,13 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int return true; } -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); - -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,uint64_t *interestp) const { // Output parameter fOnlyCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos. + uint64_t tmp; + if ( interestp == 0 ) + interestp = &tmp; + *interestp = 0; vector vCoinsNoCoinbase, vCoinsWithCoinbase; AvailableCoins(vCoinsNoCoinbase, true, coinControl, false, false); AvailableCoins(vCoinsWithCoinbase, true, coinControl, false, true); @@ -2388,44 +2444,30 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set= nTargetValue); } } - - // coin control -> return all selected outputs (we want all selected to go into the transaction for sure) + // coin control -> return all selected outputs (we want all to go into the transaction for sure) + *interestp = 0; if (coinControl && coinControl->HasSelected()) { - extern char ASSETCHAINS_SYMBOL[16]; - uint64_t interest; BOOST_FOREACH(const COutput& out, vCoins) { if(!out.fSpendable) continue; nValueRet += out.tx->vout[out.i].nValue; - interest = komodo_interest(chainActive.Tip()->nHeight+1,out.tx->vout[out.i].nValue,out.tx->nLockTime,chainActive.Tip()->nTime); -#ifdef KOMODO_ENABLE_INTEREST - if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Tip()->nHeight+1 >= 60000 ) - { - if ( interest != 0 ) - { - printf("nValueRet %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)nValueRet/COIN,(double)interest/COIN,chainActive.Tip()->nHeight+1,out.tx->nLockTime,chainActive.Tip()->nTime); - fprintf(stderr,"nValueRet %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)nValueRet/COIN,(double)interest/COIN,chainActive.Tip()->nHeight+1,out.tx->nLockTime,chainActive.Tip()->nTime); - } - nValueRet += interest; - } -#endif + *interestp += out.tx->vout[out.i].interest; setCoinsRet.insert(make_pair(out.tx, out.i)); } return (nValueRet >= nTargetValue); } - - return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) || - SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) || - (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet))); +//fprintf(stderr,"nValueRet %8f vs target %.8f\n",(double)nValueRet/COIN,(double)nTargetValue/COIN); + return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet,interestp) || + SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet,interestp) || + (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet,interestp))); } bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl) { - CAmount nValue = 0; - unsigned int nSubtractFeeFromAmount = 0; + uint64_t interest2,interest = 0; CAmount nValue = 0; unsigned int nSubtractFeeFromAmount = 0; BOOST_FOREACH (const CRecipient& recipient, vecSend) { if (nValue < 0 || recipient.nAmount < 0) @@ -2530,7 +2572,8 @@ bool CWallet::CreateTransaction(const vector& vecSend, CAmount nValueIn = 0; bool fOnlyCoinbaseCoins = false; bool fNeedCoinbaseCoins = false; - if (!SelectCoins(nTotalValue, setCoins, nValueIn, fOnlyCoinbaseCoins, fNeedCoinbaseCoins, coinControl)) + interest = interest2 = 0; + if (!SelectCoins(nTotalValue, setCoins, nValueIn, fOnlyCoinbaseCoins, fNeedCoinbaseCoins, coinControl,&interest)) { if (fOnlyCoinbaseCoins && Params().GetConsensus().fCoinbaseMustBeProtected) { strFailReason = _("Coinbase funds can only be sent to a zaddr"); @@ -2548,13 +2591,16 @@ bool CWallet::CreateTransaction(const vector& vecSend, //reflecting an assumption the user would accept a bit more delay for //a chance at a free transaction. //But mempool inputs might still be in the mempool, so their age stays 0 + //fprintf(stderr,"nCredit %.8f interest %.8f\n",(double)nCredit/COIN,(double)pcoin.first->vout[pcoin.second].interest/COIN); + interest2 += pcoin.first->vout[pcoin.second].interest; int age = pcoin.first->GetDepthInMainChain(); if (age != 0) age += 1; dPriority += (double)nCredit * age; } - - CAmount nChange = nValueIn - nValue; + //fprintf(stderr,"interest sum %.8f, interest2 %.8f\n",(double)interest/COIN,(double)interest2/COIN); + CAmount nChange = (nValueIn - nValue + interest); +//fprintf(stderr,"wallet change %.8f (%.8f - %.8f) interest %.8f total %.8f\n",(double)nChange/COIN,(double)nValueIn/COIN,(double)nValue/COIN,(double)interest/COIN,(double)nTotalValue/COIN); if (nSubtractFeeFromAmount == 0) nChange -= nFeeRet; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 404edf4b7..8dee91cf7 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -279,7 +279,7 @@ public: uint256 hashBlock; std::vector vMerkleBranch; int nIndex; - + // memory only mutable bool fMerkleVerified; @@ -575,7 +575,7 @@ public: 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,uint64_t *interestp = NULL) const; CWalletDB *pwalletdbEncryption; @@ -791,7 +791,7 @@ public: 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; - bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector vCoins, std::set >& setCoinsRet, CAmount& nValueRet) const; + bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector vCoins, std::set >& setCoinsRet, CAmount& nValueRet,uint64_t *interestp) const; bool IsSpent(const uint256& hash, unsigned int n) const; bool IsSpent(const uint256& nullifier) const;