@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
11
src/init.cpp
11
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));
|
||||
|
||||
@@ -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<string,UniValue> registers;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
24
src/main.cpp
24
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());
|
||||
|
||||
@@ -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<CBlockTemplate> 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();
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -239,7 +239,7 @@ class CTxOut
|
||||
public:
|
||||
CAmount nValue;
|
||||
CScript scriptPubKey;
|
||||
|
||||
uint64_t interest;
|
||||
CTxOut()
|
||||
{
|
||||
SetNull();
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -182,7 +182,7 @@ Value importaddress(const Array& params, bool fHelp)
|
||||
std::vector<unsigned char> 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()));
|
||||
|
||||
@@ -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; i<n; i++)
|
||||
// interest += komodo_interest(mapBlockIndex[wtx.hashBlock]->nHeight,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<CTxDestination, CAddressBookData>::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<COutput> 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;
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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<COutput>& 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<COutput>& 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<pair<CAmount, pair<const CWalletTx*,unsigned int> > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue,
|
||||
vector<char>& vfBest, CAmount& nBest, int iterations = 1000)
|
||||
static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue,vector<char>& vfBest, CAmount& nBest, int iterations = 1000)
|
||||
{
|
||||
vector<char> vfIncluded;
|
||||
|
||||
@@ -2253,12 +2293,13 @@ static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,uns
|
||||
}
|
||||
}
|
||||
|
||||
bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
|
||||
set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const
|
||||
bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,set<pair<const CWalletTx*,unsigned int> >& 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<CAmount, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
|
||||
coinLowestLarger.first = std::numeric_limits<CAmount>::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<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl* coinControl) const
|
||||
bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& 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<COutput> 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<pair<const CWalletTx*
|
||||
fNeedCoinbaseCoinsRet = (valueWithCoinbase >= 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<CRecipient>& 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<CRecipient>& 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<CRecipient>& 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;
|
||||
|
||||
|
||||
@@ -279,7 +279,7 @@ public:
|
||||
uint256 hashBlock;
|
||||
std::vector<uint256> 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<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl *coinControl = NULL) const;
|
||||
bool SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& 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<COutput>& 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<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const;
|
||||
bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet,uint64_t *interestp) const;
|
||||
|
||||
bool IsSpent(const uint256& hash, unsigned int n) const;
|
||||
bool IsSpent(const uint256& nullifier) const;
|
||||
|
||||
Reference in New Issue
Block a user