Merge pull request #771 from jl777/dev

Dev
This commit is contained in:
jl777
2018-07-16 00:14:00 -11:00
committed by GitHub
37 changed files with 771 additions and 769 deletions

View File

@@ -1,3 +1,4 @@
Copyright (c) 2016-2018 The Komodo developers
Copyright (c) 2016-2017 The Zcash developers
Copyright (c) 2009-2017 The Bitcoin Core developers

View File

@@ -13,7 +13,7 @@ It downloads and stores the entire history of Komodo transactions; depending on
- Support: [https://support.komodoplatform.com/support/home](https://support.komodoplatform.com/support/home)
- Knowledgebase & How-to: [https://komodoplatform.atlassian.net/wiki/spaces/KPSD/pages](https://komodoplatform.atlassian.net/wiki/spaces/KPSD/pages)
- API references: [http://docs.supernet.org/](http://docs.supernet.org/) #Not up to date.
- Whitepaper: [Komodo Whitepaper](https://komodoplatform.com/wp-content/uploads/2018/03/2018-03-12-Komodo-White-Paper-Full.pdf)
- Whitepaper: [Komodo Whitepaper](https://komodoplatform.com/wp-content/uploads/2018/06/Komodo-Whitepaper-June-3.pdf)
- Komodo Platform public material: [Komodo Platform public material](https://docs.google.com/document/d/1AbhWrtagu4vYdkl-vsWz-HSNyNvK-W-ZasHCqe7CZy0)
## List of Komodo Platform Technologies

View File

@@ -45,7 +45,6 @@ BITCOIN_TESTS =\
test/arith_uint256_tests.cpp \
test/bignum.h \
test/addrman_tests.cpp \
test/alert_tests.cpp \
test/allocator_tests.cpp \
test/base32_tests.cpp \
test/base58_tests.cpp \

View File

@@ -11,6 +11,7 @@ using namespace std;
* CChain implementation
*/
void CChain::SetTip(CBlockIndex *pindex) {
lastTip = pindex;
if (pindex == NULL) {
vChain.clear();
return;

View File

@@ -121,7 +121,7 @@ public:
//! height of the entry in the chain. The genesis block has height 0
int nHeight;
int64_t newcoins,zfunds;
//! Which # file this block is stored in (blk?????.dat)
int nFile;
@@ -181,6 +181,7 @@ public:
void SetNull()
{
phashBlock = NULL;
newcoins = zfunds = 0;
pprev = NULL;
pskip = NULL;
nHeight = 0;
@@ -321,6 +322,7 @@ public:
//! Efficiently find an ancestor of this block.
CBlockIndex* GetAncestor(int height);
const CBlockIndex* GetAncestor(int height) const;
};
/** Used to marshal pointers into hashes for db storage. */
@@ -414,6 +416,7 @@ public:
class CChain {
private:
std::vector<CBlockIndex*> vChain;
CBlockIndex *lastTip;
public:
/** Returns the index entry for the genesis block of this chain, or NULL if none. */
@@ -425,6 +428,11 @@ public:
CBlockIndex *Tip() const {
return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL;
}
/** Returns the last tip of the chain, or NULL if none. */
CBlockIndex *LastTip() const {
return vChain.size() > 0 ? lastTip : NULL;
}
/** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */
CBlockIndex *operator[](int nHeight) const {

View File

@@ -466,7 +466,7 @@ bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
const COutPoint &prevout = tx.vin[i].prevout;
const CCoins* coins = AccessCoins(prevout.hash);
if (!coins || !coins->IsAvailable(prevout.n)) {
fprintf(stderr,"HaveInputs missing input %s/v%d\n",prevout.hash.ToString().c_str(),prevout.n);
//fprintf(stderr,"HaveInputs missing input %s/v%d\n",prevout.hash.ToString().c_str(),prevout.n);
return false;
}
}

View File

@@ -6,11 +6,11 @@
#define ZCASH_DEPRECATION_H
// Deprecation policy:
// * Shut down 16 weeks' worth of blocks after the estimated release block height.
// * A warning is shown during the 2 weeks' worth of blocks prior to shut down.
static const int APPROX_RELEASE_HEIGHT = 800000;
// * Shut down WEEKS_UNTIL_DEPRECATION weeks' worth of blocks after the estimated release block height.
// * A warning is shown during the DEPRECATION_WARN_LIMIT worth of blocks prior to shut down.
static const int WEEKS_UNTIL_DEPRECATION = 52;
static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24);
static const int DEPRECATION_HEIGHT = 1400000;
static const int APPROX_RELEASE_HEIGHT = DEPRECATION_HEIGHT - (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 60);
// Number of blocks before deprecation to warn users
static const int DEPRECATION_WARN_LIMIT = 60 * 24 * 60; // 2 months

View File

@@ -1756,11 +1756,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
StartNode(threadGroup, scheduler);
// Monitor the chain, and alert if we get blocks much quicker or slower than expected
int64_t nPowTargetSpacing = Params().GetConsensus().nPowTargetSpacing;
CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload,
boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing);
scheduler.scheduleEvery(f, nPowTargetSpacing);
#ifdef ENABLE_MINING
// Generate coins in the background

View File

@@ -823,7 +823,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
komodo_event_rewind(sp,symbol,pindex->nHeight);
komodo_stateupdate(pindex->nHeight,0,0,0,zero,0,0,0,0,-pindex->nHeight,pindex->nTime,0,0,0,0,zero,0);
}
komodo_currentheight_set(chainActive.Tip()->nHeight);
komodo_currentheight_set(chainActive.LastTip()->nHeight);
if ( pindex != 0 )
{
height = pindex->nHeight;
@@ -907,7 +907,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
#else
memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len);
#endif
notaryid = komodo_voutupdate(&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,&notarizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.Tip()->GetBlockTime());
notaryid = komodo_voutupdate(&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,&notarizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime());
if ( 0 && i > 0 )
{
for (k=0; k<len; k++)

View File

@@ -567,7 +567,7 @@ uint32_t komodo_txtime(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
#endif
hashBlock, true))
{
fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
//fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
return(0);
}
//fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
@@ -580,6 +580,56 @@ uint32_t komodo_txtime(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
return(tx.nLockTime);
}
uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
{
CTxDestination address; CBlockIndex *pindex; CTransaction tx; uint256 hashBlock; uint32_t txtime = 0;
*valuep = 0;
if (!GetTransaction(hash, tx,
#ifndef KOMODO_ZCASH
Params().GetConsensus(),
#endif
hashBlock, true))
{
//fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
return(0);
}
if ( (pindex= mapBlockIndex[hashBlock]) != 0 )
txtime = pindex->nTime;
else txtime = tx.nLockTime;
//fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
if ( n < tx.vout.size() )
{
*valuep = tx.vout[n].nValue;
if (ExtractDestination(tx.vout[n].scriptPubKey, address))
strcpy(destaddr,CBitcoinAddress(address).ToString().c_str());
}
return(txtime);
}
int32_t komodo_isPoS(CBlock *pblock)
{
int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid;
if ( ASSETCHAINS_STAKED != 0 )
{
if ( (n= pblock->vtx.size()) > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1 )
{
txid = pblock->vtx[n-1].vin[0].prevout.hash;
vout = pblock->vtx[n-1].vin[0].prevout.n;
txtime = komodo_txtime(&value,txid,vout,destaddr);
if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) )
{
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[n-1].vout[0].nValue == value )
{
//fprintf(stderr,"is PoS block!\n");
return(1);
}
}
}
}
return(0);
}
void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
{
char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp;
@@ -701,8 +751,8 @@ int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex)
uint32_t komodo_chainactive_timestamp()
{
if ( chainActive.Tip() != 0 )
return((uint32_t)chainActive.Tip()->GetBlockTime());
if ( chainActive.LastTip() != 0 )
return((uint32_t)chainActive.LastTip()->GetBlockTime());
else return(0);
}
@@ -710,11 +760,11 @@ CBlockIndex *komodo_chainactive(int32_t height)
{
if ( chainActive.Tip() != 0 )
{
if ( height <= chainActive.Tip()->nHeight )
if ( height <= chainActive.LastTip()->nHeight )
return(chainActive[height]);
// else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.Tip()->nHeight);
// else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.LastTip()->nHeight);
}
//fprintf(stderr,"komodo_chainactive null chainActive.Tip() height %d\n",height);
//fprintf(stderr,"komodo_chainactive null chainActive.LastTip() height %d\n",height);
return(0);
}
@@ -944,7 +994,7 @@ int32_t komodo_MoM(int32_t *notarized_heightp,uint256 *MoMp,uint256 *kmdtxidp,in
int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
{
int32_t notarized_height,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; CBlockIndex *notary,*pindex;
if ( (pindex= chainActive.Tip()) == 0 )
if ( (pindex= chainActive.LastTip()) == 0 )
return(-1);
notarized_height = komodo_notarizeddata(pindex->nHeight,&notarized_hash,&notarized_desttxid);
*notarized_heightp = notarized_height;
@@ -986,7 +1036,7 @@ uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_
*valuep = tx.vout[n].nValue;
*txheightp = pindex->nHeight;
*txheighttimep = pindex->nTime;
if ( *tiptimep == 0 && (tipindex= chainActive.Tip()) != 0 )
if ( *tiptimep == 0 && (tipindex= chainActive.LastTip()) != 0 )
*tiptimep = (uint32_t)tipindex->nTime;
locktime = tx.nLockTime;
//fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep);
@@ -1019,18 +1069,18 @@ int32_t komodo_isrealtime(int32_t *kmdheightp)
if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 )
*kmdheightp = sp->CURRENT_HEIGHT;
else *kmdheightp = 0;
if ( (pindex= chainActive.Tip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() )
if ( (pindex= chainActive.LastTip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() )
return(1);
else return(0);
}
int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag)
{
if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 )
if ( KOMODO_REWIND == 0 && (ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED != 0) && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 )
{
if ( txheight > 246748 )
if ( txheight > 246748 || ASSETCHAINS_STAKED != 0 )
{
if ( txheight < 247205 )
if ( txheight < 247205 && ASSETCHAINS_STAKED == 0 )
cmptime -= 16000;
if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME )
{
@@ -1054,9 +1104,8 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_
commission must be in coinbase.vout[1] and must be >= 10000 sats
PoS stake must be without txfee and in the last tx in the block at vout[0]
PoW mining on PoS chain must solve a harder diff that adjusts, but never less than KOMODO_POWMINMULT
*/
#define KOMODO_POWMINMULT 16
//#define KOMODO_POWMINMULT 16
uint64_t komodo_commission(const CBlock *pblock)
{
@@ -1086,76 +1135,152 @@ uint32_t komodo_segid32(char *coinaddr)
return(addrhash.uints[0]);
}
uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr)
int8_t komodo_segid(int32_t height)
{
CBlockIndex *pindex; bool fNegative,fOverflow; uint8_t hashbuf[128]; char address[64]; bits256 addrhash; arith_uint256 hashval; uint256 hash,pasthash; int64_t diff=0; int32_t segid,minage,i,iter=0; uint32_t txtime,winner = 0; arith_uint256 bnMaxPoSdiff; uint64_t value,coinage,supply = ASSETCHAINS_SUPPLY + nHeight*ASSETCHAINS_REWARD/SATOSHIDEN;
txtime = komodo_txtime(&value,txid,vout,address);
if ( blocktime < prevtime+57 )
blocktime = prevtime+57;
if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 )
CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout; uint256 txid; int8_t segid = -1;
if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 )
{
fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime);
return(0);
}
bnMaxPoSdiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
bnMaxPoSdiff = (bnMaxPoSdiff / arith_uint256(4));
if ( bnTarget < bnMaxPoSdiff )
bnTarget = bnMaxPoSdiff;
if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
minage = 6000;
pindex = 0;
if ( (pindex= komodo_chainactive(nHeight>50?nHeight-50:1)) != 0 )
{
vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address));
segid = ((nHeight + addrhash.uints[0]) & 0x3f);
pasthash = pindex->GetBlockHash();
memcpy(hashbuf,&pasthash,sizeof(pasthash));
memcpy(&hashbuf[sizeof(pasthash)],&addrhash,sizeof(addrhash));
vcalc_sha256(0,(uint8_t *)&hash,hashbuf,(int32_t)sizeof(uint256)*2);
//fprintf(stderr,"(%s) vs. (%s) %s %.8f txtime.%u\n",address,destaddr,hash.ToString().c_str(),dstr(value),txtime);
for (iter=0; iter<3600; iter++)
if ( komodo_blockload(block,pindex) == 0 )
{
diff = (iter + blocktime - txtime - minage);
if ( iter > 0 )
diff += iter + segid*2;
//if ( diff > 3600*24 )
// break;
if ( blocktime+iter+segid*2 < txtime+minage )
continue;
coinage = (value * diff) * ((diff >> 16) + 1);
hashval = arith_uint256(supply * 64) * (UintToArith256(hash) / arith_uint256(coinage+1));
if ( hashval <= bnTarget )
txn_count = block.vtx.size();
if ( txn_count > 1 && block.vtx[txn_count-1].vin.size() == 1 && block.vtx[txn_count-1].vout.size() == 1 )
{
winner = 1;
if ( validateflag == 0 )
txid = block.vtx[txn_count-1].vin[0].prevout.hash;
vout = block.vtx[txn_count-1].vin[0].prevout.n;
txtime = komodo_txtime(&value,txid,vout,destaddr);
if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
{
blocktime += iter;
blocktime += segid * 2;
}
break;
}
if ( validateflag != 0 )
{
/*for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
fprintf(stderr," vs target ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d gap.%d %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,(int32_t)(blocktime - prevtime),dstr(value),(int32_t)diff);*/
break;
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
if ( strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value )
{
segid = komodo_segid32(voutaddr) & 0x3f;
}
} else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height);
}
}
//fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
if ( 0 )
}
return(segid);
}
int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n)
{
static uint8_t prevhashbuf[100]; static int32_t prevheight;
int32_t i;
if ( height == prevheight && n == 100 )
memcpy(hashbuf,prevhashbuf,100);
else
{
memset(hashbuf,0xff,n);
for (i=0; i<n; i++)
{
for (i=31; i>=24; i--)
hashbuf[i] = (uint8_t)komodo_segid(height+i);
//fprintf(stderr,"%02x ",hashbuf[i]);
}
if ( n == 100 )
{
memcpy(prevhashbuf,hashbuf,100);
prevheight = height;
//fprintf(stderr,"prevsegids.%d\n",height+n);
}
}
}
uint32_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout)
{
bits256 addrhash;
vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address));
memcpy(&hashbuf[100],&addrhash,sizeof(addrhash));
memcpy(&hashbuf[100+sizeof(addrhash)],&txid,sizeof(txid));
memcpy(&hashbuf[100+sizeof(addrhash)+sizeof(txid)],&vout,sizeof(vout));
vcalc_sha256(0,(uint8_t *)hashp,hashbuf,100 + (int32_t)sizeof(uint256)*2 + sizeof(vout));
return(addrhash.uints[0]);
}
uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr)
{
bool fNegative,fOverflow; uint8_t hashbuf[256]; char address[64]; bits256 addrhash; arith_uint256 hashval,mindiff,ratio,coinage256; uint256 hash,pasthash; int32_t diff=0,segid,minage,i,iter=0; uint32_t txtime,winner = 0 ; uint64_t value,coinage;
txtime = komodo_txtime2(&value,txid,vout,address);
if ( validateflag == 0 )
{
//fprintf(stderr,"blocktime.%u -> ",blocktime);
if ( blocktime < prevtime+3 )
blocktime = prevtime+3;
if ( blocktime < GetAdjustedTime()-60 )
blocktime = GetAdjustedTime()+30;
//fprintf(stderr,"blocktime.%u txtime.%u\n",blocktime,txtime);
}
if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 )
{
//fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime);
return(0);
}
if ( value < SATOSHIDEN )
return(0);
value /= SATOSHIDEN;
mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
ratio = (mindiff / bnTarget);
if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
minage = 6000;
vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address));
segid = ((nHeight + addrhash.uints[0]) & 0x3f);
komodo_segids(hashbuf,nHeight-101,100);
memcpy(&hashbuf[100],&addrhash,sizeof(addrhash));
memcpy(&hashbuf[100+sizeof(addrhash)],&txid,sizeof(txid));
memcpy(&hashbuf[100+sizeof(addrhash)+sizeof(txid)],&vout,sizeof(vout));
vcalc_sha256(0,(uint8_t *)&hash,hashbuf,100 + (int32_t)sizeof(uint256)*2 + sizeof(vout));
for (iter=0; iter<180; iter++)
{
if ( blocktime+iter+segid*2 < txtime+minage )
continue;
diff = (iter + blocktime - txtime - minage);
if ( diff < 0 )
diff = 60;
else if ( diff > 3600*24*30 )
{
//printf("diff.%d (iter.%d blocktime.%u txtime.%u minage.%d)\n",(int32_t)diff,iter,blocktime,txtime,(int32_t)minage);
diff = 3600*24*30;
}
if ( iter > 0 )
diff += segid*2;
coinage = (value * diff);
if ( nHeight >= 2500 && blocktime+iter+segid*2 > prevtime+180 )
coinage *= ((blocktime+iter+segid*2) - (prevtime+60));
coinage256 = arith_uint256(coinage+1);
hashval = ratio * (UintToArith256(hash) / coinage256);
if ( nHeight >= 900 && nHeight < 916 )
hashval = (hashval / coinage256);
if ( hashval <= bnTarget )
{
winner = 1;
if ( validateflag == 0 )
{
//fprintf(stderr,"winner blocktime.%u iter.%d segid.%d\n",blocktime,iter,segid);
blocktime += iter;
blocktime += segid * 2;
}
break;
}
if ( validateflag != 0 )
{
/*for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
fprintf(stderr," vs ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,dstr(value),(int32_t)diff);
fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff);*/
break;
}
} //else fprintf(stderr,"skip PoS scan: diff %d blocktime %u > %u txtime+minage %u pindex.%p\n",(int32_t)(blocktime - (txtime+minage)),blocktime,txtime,minage,pindex);
}
//fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
if ( 0 && validateflag != 0 )
{
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
fprintf(stderr," vs ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d ht.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff,nHeight);
}
if ( nHeight < 10 )
return(blocktime);
return(blocktime * winner);
@@ -1163,18 +1288,36 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh
arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc)
{
CBlockIndex *pindex; arith_uint256 bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,ht,percPoS,diff,val;
CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,m,ht,percPoS,diff,val;
*percPoSp = percPoS = 0;
if ( height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) )
return(target);
sum = arith_uint256(0);
ave = sum;
for (i=n=0; i<100; i++)
easydiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
for (i=n=m=0; i<100; i++)
{
ht = height - 100 + i;
if ( ht <= 1 )
continue;
if ( (pindex= komodo_chainactive(ht)) != 0 )
{
if ( komodo_segid(ht) >= 0 )
{
n++;
percPoS++;
if ( ASSETCHAINS_STAKED < 100 )
fprintf(stderr,"0");
}
else
{
if ( ASSETCHAINS_STAKED < 100 )
fprintf(stderr,"1");
sum += UintToArith256(pindex->GetBlockHash());
m++;
}
}
/*if ( (pindex= komodo_chainactive(ht)) != 0 )
{
bnTarget.SetCompact(pindex->nBits,&fNegative,&fOverflow);
bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT));
@@ -1188,26 +1331,27 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he
}
else
{
n++;
percPoS++;
if ( ASSETCHAINS_STAKED < 100 )
fprintf(stderr,"0");
}
if ( ASSETCHAINS_STAKED < 100 && (i % 10) == 9 )
fprintf(stderr," %d, ",percPoS);
}
}*/
if ( ASSETCHAINS_STAKED < 100 && (i % 10) == 9 )
fprintf(stderr," %d, ",percPoS);
}
if ( n < 100 )
if ( m+n < 100 )
percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100;
if ( ASSETCHAINS_STAKED < 100 )
fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height);
*percPoSp = percPoS;
target = (target / arith_uint256(KOMODO_POWMINMULT));
if ( n > 0 )
//target = (target / arith_uint256(KOMODO_POWMINMULT));
if ( m > 0 )
{
ave = (sum / arith_uint256(n));
ave = (sum / arith_uint256(m));
if ( ave > target )
ave = target;
} else return(target);
} else ave = easydiff; //else return(target);
if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget
{
bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc);
@@ -1226,7 +1370,15 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he
}
else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget
{
bnTarget = ((ave * arith_uint256(goalperc)) + (target * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc);
bnTarget = (ave * arith_uint256(percPoS * percPoS * percPoS)) / arith_uint256(goalperc * goalperc);
if ( bnTarget > easydiff )
bnTarget = easydiff;
else if ( bnTarget < ave ) // overflow
{
bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc);
if ( bnTarget < ave )
bnTarget = ave;
}
if ( 1 )
{
for (i=31; i>=24; i--)
@@ -1246,9 +1398,11 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he
int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget)
{
CBlockIndex *previndex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,txn_count,eligible,isPoS = 0; uint64_t value; CTxDestination voutaddress;
CBlockIndex *previndex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,txn_count,eligible=0,isPoS = 0; uint64_t value; CTxDestination voutaddress;
if ( ASSETCHAINS_STAKED == 100 && height <= 10 )
return(1);
txn_count = pblock->vtx.size();
if ( txn_count > 1 )
if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 )
{
if ( prevtime == 0 )
{
@@ -1259,24 +1413,29 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
vout = pblock->vtx[txn_count-1].vin[0].prevout.n;
if ( prevtime != 0 )
{
eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime,(char *)"");
if ( komodo_isPoS(pblock) != 0 )
eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)"");
if ( eligible == 0 || eligible > pblock->nTime )
{
fprintf(stderr,"komodo_is_PoSblock PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)pblock->nTime,(int32_t)(eligible - pblock->nTime));
if ( ASSETCHAINS_STAKED < 100 )
fprintf(stderr,"komodo_is_PoSblock PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)pblock->nTime,(int32_t)(eligible - pblock->nTime));
} else isPoS = 1;
}
else if ( slowflag == 0 ) // maybe previous block is not seen yet, do the best approx
if ( slowflag == 0 ) // maybe previous block is not seen yet, do the best approx
{
txtime = komodo_txtime(&value,txid,vout,destaddr);
if ( komodo_isPoS(pblock) != 0 )
isPoS = 1;
/*txtime = komodo_txtime(&value,txid,vout,destaddr);
if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
{
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[txn_count-1].vout[0].nValue == value )
isPoS = 1; // close enough for a pre-filter
else fprintf(stderr,"komodo_is_PoSblock ht.%d (%s) != (%s) or %.8f != %.8f\n",height,destaddr,voutaddr,dstr(value),dstr(pblock->vtx[txn_count-1].vout[0].nValue));
} else fprintf(stderr,"komodo_is_PoSblock ht.%d couldnt extract voutaddress\n",height);
} else return(-1);
//else fprintf(stderr,"komodo_is_PoSblock ht.%d (%s) != (%s) or %.8f != %.8f\n",height,destaddr,voutaddr,dstr(value),dstr(pblock->vtx[txn_count-1].vout[0].nValue));
} else fprintf(stderr,"komodo_is_PoSblock ht.%d couldnt extract voutaddress\n",height);*/
} //else return(-1);
}
//fprintf(stderr,"slow.%d ht.%d isPoS.%d\n",slowflag,height,isPoS);
return(isPoS);
}
@@ -1344,23 +1503,24 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
}
else if ( possible == 0 || ASSETCHAINS_SYMBOL[0] != 0 )
{
if (KOMODO_TEST_ASSETCHAIN_SKIP_POW) return(0);
fprintf(stderr,"pow violation and no chance it is notary ht.%d %s\n",height,hash.ToString().c_str());
return(-1);
if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW )
return(0);
if ( ASSETCHAINS_STAKED == 0 ) // komodo_is_PoSblock will check bnTarget
return(-1);
}
}
else if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW
if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW
{
if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget)) == 0 )
{
if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed!
if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64
return(-1);
else
{
if ( slowflag == 0 ) // need all past 100 blocks to calculate PoW target
return(0);
if ( slowflag != 0 )
bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
else if ( height > 100 )
bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT)); // lower bound
if ( bhash > bnTarget )
{
for (i=31; i>=16; i--)
@@ -1395,3 +1555,79 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
else return(0);
}
int64_t komodo_newcoins(int64_t *zfundsp,int32_t nHeight,CBlock *pblock)
{
CTxDestination address; int32_t i,j,m,n,vout; uint8_t *script; uint256 txid,hashBlock; int64_t zfunds=0,vinsum=0,voutsum=0;
n = pblock->vtx.size();
for (i=0; i<n; i++)
{
CTransaction vintx,&tx = pblock->vtx[i];
zfunds += (tx.GetJoinSplitValueOut() - tx.GetJoinSplitValueIn());
if ( (m= tx.vin.size()) > 0 )
{
for (j=0; j<m; j++)
{
if ( i == 0 )
continue;
txid = tx.vin[j].prevout.hash;
vout = tx.vin[j].prevout.n;
if ( !GetTransaction(txid,vintx,hashBlock, false) || vout >= vintx.vout.size() )
{
fprintf(stderr,"ERROR: %s/v%d cant find\n",txid.ToString().c_str(),vout);
return(0);
}
vinsum += vintx.vout[vout].nValue;
}
}
if ( (m= tx.vout.size()) > 0 )
{
for (j=0; j<m-1; j++)
{
if ( ExtractDestination(tx.vout[j].scriptPubKey,address) != 0 && strcmp("RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY",CBitcoinAddress(address).ToString().c_str()) != 0 )
voutsum += tx.vout[j].nValue;
else printf("skip %.8f -> %s\n",dstr(tx.vout[j].nValue),CBitcoinAddress(address).ToString().c_str());
}
script = (uint8_t *)tx.vout[j].scriptPubKey.data();
if ( script == 0 || script[0] != 0x6a )
{
if ( ExtractDestination(tx.vout[j].scriptPubKey,address) != 0 && strcmp("RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY",CBitcoinAddress(address).ToString().c_str()) != 0 )
voutsum += tx.vout[j].nValue;
}
}
}
*zfundsp = zfunds;
if ( ASSETCHAINS_SYMBOL[0] == 0 && (voutsum-vinsum) == 100003*SATOSHIDEN ) // 15 times
return(3 * SATOSHIDEN);
//if ( voutsum-vinsum+zfunds > 100000*SATOSHIDEN || voutsum-vinsum+zfunds < 0 )
//. fprintf(stderr,"ht.%d vins %.8f, vouts %.8f -> %.8f zfunds %.8f\n",nHeight,dstr(vinsum),dstr(voutsum),dstr(voutsum)-dstr(vinsum),dstr(zfunds));
return(voutsum - vinsum);
}
int64_t komodo_coinsupply(int64_t *zfundsp,int32_t height)
{
CBlockIndex *pindex; CBlock block; int64_t zfunds=0,supply = 0;
//fprintf(stderr,"coinsupply %d\n",height);
*zfundsp = 0;
if ( (pindex= komodo_chainactive(height)) != 0 )
{
while ( pindex != 0 && pindex->nHeight > 0 )
{
if ( pindex->newcoins == 0 && pindex->zfunds == 0 )
{
if ( komodo_blockload(block,pindex) == 0 )
pindex->newcoins = komodo_newcoins(&pindex->zfunds,pindex->nHeight,&block);
else
{
fprintf(stderr,"error loading block.%d\n",pindex->nHeight);
return(0);
}
}
supply += pindex->newcoins;
zfunds += pindex->zfunds;
//printf("start ht.%d new %.8f -> supply %.8f zfunds %.8f -> %.8f\n",pindex->nHeight,dstr(pindex->newcoins),dstr(supply),dstr(pindex->zfunds),dstr(zfunds));
pindex = pindex->pprev;
}
}
*zfundsp = zfunds;
return(supply);
}

View File

@@ -1490,7 +1490,7 @@ void komodo_passport_iteration()
komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime");
if ( (fp= fopen(fname,"wb")) != 0 )
{
buf[0] = (uint32_t)chainActive.Tip()->nHeight;
buf[0] = (uint32_t)chainActive.LastTip()->nHeight;
buf[1] = (uint32_t)komodo_longestchain();
if ( buf[0] != 0 && buf[0] == buf[1] )
{

View File

@@ -52,7 +52,7 @@ uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC
char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096];
uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC;
uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT;
uint32_t ASSETCHAINS_MAGIC = 2387029918;
uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE;
uint64_t ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10;

View File

@@ -648,7 +648,7 @@ void jumblr_iteration()
free(retstr);
}
}
height = (int32_t)chainActive.Tip()->nHeight;
height = (int32_t)chainActive.LastTip()->nHeight;
if ( time(NULL) < lasttime+40 )
return;
lasttime = (uint32_t)time(NULL);

View File

@@ -637,13 +637,13 @@ uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint
uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume)
{
int32_t i,nonz=0; int64_t diff; uint64_t price,seed,sum = 0;
if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Tip() != 0 && height > chainActive.Tip()->nHeight )
if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && height > chainActive.LastTip()->nHeight )
{
if ( height < 100000000 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("komodo_paxprice height.%d vs tip.%d\n",height,chainActive.Tip()->nHeight);
printf("komodo_paxprice height.%d vs tip.%d\n",height,chainActive.LastTip()->nHeight);
}
return(0);
}

View File

@@ -1539,6 +1539,7 @@ void komodo_args(char *argv0)
}
}
}
KOMODO_STOPAT = GetArg("-stopat",0);
ASSETCHAINS_CC = GetArg("-ac_cc",0);
ASSETCHAINS_PUBLIC = GetArg("-ac_public",0);
ASSETCHAINS_PRIVATE = GetArg("-ac_private",0);

View File

@@ -1104,7 +1104,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
if ( ASSETCHAINS_PRIVATE != 0 )
{
fprintf(stderr,"private chain nValue %.8f iscoinbase.%d\n",(double)txout.nValue/COIN,iscoinbase);
if ( txout.nValue > 0 && iscoinbase == 0 )
if ( (txout.nValue > 0 && iscoinbase == 0) || tx.GetJoinSplitValueOut() > 0 )
return state.DoS(100, error("CheckTransaction(): this is a private chain, no public allowed"),REJECT_INVALID, "bad-txns-acprivacy-chain");
}
nValueOut += txout.nValue;
@@ -1269,7 +1269,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
}
auto verifier = libzcash::ProofVerifier::Strict();
if ( komodo_validate_interest(tx,chainActive.Tip()->nHeight+1,chainActive.Tip()->GetMedianTimePast() + 777,0) < 0 )
if ( komodo_validate_interest(tx,chainActive.LastTip()->nHeight+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 )
{
//fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n");
return error("AcceptToMemoryPool: komodo_validate_interest failed");
@@ -1311,7 +1311,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
uint256 hash = tx.GetHash();
if (pool.exists(hash))
{
fprintf(stderr,"already in mempool\n");
//fprintf(stderr,"already in mempool\n");
return state.Invalid(false, REJECT_DUPLICATE, "already in mempool");
}
@@ -1399,7 +1399,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Bring the best block into scope
view.GetBestBlock();
nValueIn = view.GetValueIn(chainActive.Tip()->nHeight,&interest,tx,chainActive.Tip()->nTime);
nValueIn = view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime);
if ( 0 && interest != 0 )
fprintf(stderr,"add interest %.8f\n",(double)interest/COIN);
// we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
@@ -1891,7 +1891,7 @@ void CheckForkWarningConditions()
if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 288)
pindexBestForkTip = NULL;
if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (GetBlockProof(*chainActive.Tip()) * 6)))
if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.LastTip()->nChainWork + (GetBlockProof(*chainActive.LastTip()) * 6)))
{
if (!fLargeWorkForkFound && pindexBestForkBase)
{
@@ -1926,7 +1926,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
AssertLockHeld(cs_main);
// If we are on a fork that is sufficiently large, set a warning flag
CBlockIndex* pfork = pindexNewForkTip;
CBlockIndex* plonger = chainActive.Tip();
CBlockIndex* plonger = chainActive.LastTip();
while (pfork && pfork != plonger)
{
while (plonger && plonger->nHeight > pfork->nHeight)
@@ -1983,7 +1983,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight,
log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S",
pindexNew->GetBlockTime()));
CBlockIndex *tip = chainActive.Tip();
CBlockIndex *tip = chainActive.LastTip();
assert (tip);
LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", __func__,
tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainWork.getdouble())/log(2.0),
@@ -2111,14 +2111,14 @@ namespace Consensus {
// Check for negative or overflow input values
nValueIn += coins->vout[prevout.n].nValue;
#ifdef KOMODO_ENABLE_INTEREST
if ( ASSETCHAINS_SYMBOL[0] == 0 && nSpendHeight > 60000 )//chainActive.Tip() != 0 && chainActive.Tip()->nHeight >= 60000 )
if ( ASSETCHAINS_SYMBOL[0] == 0 && nSpendHeight > 60000 )//chainActive.LastTip() != 0 && chainActive.LastTip()->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,(int32_t)nSpendHeight-1)) != 0 )
{
//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);
//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.LastTip()->nTime);
nValueIn += interest;
}
}
@@ -2691,7 +2691,8 @@ static int64_t nTimeTotal = 0;
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck,bool fCheckPOW)
{
const CChainParams& chainparams = Params();
if ( KOMODO_STOPAT != 0 && pindex->nHeight > KOMODO_STOPAT )
return(false);
//fprintf(stderr,"connectblock ht.%d\n",(int32_t)pindex->nHeight);
AssertLockHeld(cs_main);
bool fExpensiveChecks = true;
@@ -2867,7 +2868,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (!tx.IsCoinBase())
{
nFees += view.GetValueIn(chainActive.Tip()->nHeight,&interest,tx,chainActive.Tip()->nTime) - tx.GetValueOut();
nFees += view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime) - tx.GetValueOut();
sum += interest;
std::vector<CScriptCheck> vChecks;
@@ -3194,10 +3195,19 @@ void static UpdateTip(CBlockIndex *pindexNew) {
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
KOMODO_NEWBLOCKS++;
double progress;
if ( ASSETCHAINS_SYMBOL[0] == 0 ) {
progress = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip());
} else {
int32_t longestchain = komodo_longestchain();
progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0;
}
LogPrintf("%s: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__,
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
chainActive.LastTip()->GetBlockHash().ToString(), chainActive.Height(),
log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.LastTip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.LastTip()->GetBlockTime()), progress,
pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
cvBlockChange.notify_all();
@@ -3252,13 +3262,17 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
return false;
if (!fBare) {
if (!fBare)
{
// Resurrect mempool transactions from the disconnected block.
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
//BOOST_FOREACH(const CTransaction &tx, block.vtx) {
for (int i = 0; i < block.vtx.size(); i++)
{
CTransaction &tx = block.vtx[i];
// ignore validation errors in resurrected transactions
list<CTransaction> removed;
CValidationState stateDummy;
if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && komodo_isPoS((CBlock *)&block) != 0) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
mempool.remove(tx, removed, true);
}
if (anchorBeforeDisconnect != anchorAfterDisconnect) {
@@ -3275,11 +3289,23 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
assert(pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), newTree));
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
SyncWithWallets(tx, NULL);
}
//BOOST_FOREACH(const CTransaction &tx, block.vtx) {
// SyncWithWallets(tx, NULL);
//}
// Update cached incremental witnesses
//fprintf(stderr,"chaintip false\n");
for (int i = 0; i < block.vtx.size(); i++)
{
CTransaction &tx = block.vtx[i];
if ( (i == (block.vtx.size() - 1)) && komodo_isPoS((CBlock *)&block) != 0 )
{
EraseFromWallets(tx.GetHash());
}
else
{
SyncWithWallets(tx, NULL);
}
}
GetMainSignals().ChainTip(pindexDelete, &block, newTree, false);
return true;
}
@@ -3429,7 +3455,7 @@ static void PruneBlockIndexCandidates() {
// Note that we can't delete the current block itself, as we may need to return to it later in case a
// reorganization to a better block fails.
std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin();
while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.Tip())) {
while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.LastTip())) {
setBlockIndexCandidates.erase(it++);
}
// Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates.
@@ -3481,8 +3507,8 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
if ( KOMODO_REWIND != 0 )
{
CBlockIndex *tipindex;
fprintf(stderr,">>>>>>>>>>> rewind start ht.%d -> KOMODO_REWIND.%d\n",chainActive.Tip()->nHeight,KOMODO_REWIND);
while ( KOMODO_REWIND > 0 && (tipindex= chainActive.Tip()) != 0 && tipindex->nHeight > KOMODO_REWIND )
fprintf(stderr,">>>>>>>>>>> rewind start ht.%d -> KOMODO_REWIND.%d\n",chainActive.LastTip()->nHeight,KOMODO_REWIND);
while ( KOMODO_REWIND > 0 && (tipindex= chainActive.LastTip()) != 0 && tipindex->nHeight > KOMODO_REWIND )
{
fBlocksDisconnected = true;
fprintf(stderr,"%d ",(int32_t)tipindex->nHeight);
@@ -3896,9 +3922,9 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,
for (i=31; i>=0; i--)
fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
fprintf(stderr," <- CheckBlockHeader\n");
if ( chainActive.Tip() != 0 )
if ( chainActive.LastTip() != 0 )
{
hash = chainActive.Tip()->GetBlockHash();
hash = chainActive.LastTip()->GetBlockHash();
for (i=31; i>=0; i--)
fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
fprintf(stderr," <- chainTip\n");
@@ -4077,8 +4103,13 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
// Don't accept any forks from the main chain prior to last checkpoint
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints());
int32_t notarized_height;
if ( nHeight == 1 && chainActive.Tip() != 0 && chainActive.Tip()->nHeight > 1 )
return(false);
if ( nHeight == 1 && chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight > 1 )
{
CBlockIndex *heightblock = chainActive[nHeight];
if ( heightblock != 0 && heightblock->GetBlockHash() == hash )
return true;
return state.DoS(1, error("%s: trying to change height 1 forbidden", __func__));
}
if ( nHeight != 0 )
{
if ( pcheckpoint != 0 && nHeight < pcheckpoint->nHeight )
@@ -4409,8 +4440,8 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo
auto verifier = libzcash::ProofVerifier::Disabled();
hash = pblock->GetHash();
if ( chainActive.Tip() != 0 )
komodo_currentheight_set(chainActive.Tip()->nHeight);
if ( chainActive.LastTip() != 0 )
komodo_currentheight_set(chainActive.LastTip()->nHeight);
checked = CheckBlock(&futureblock,height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0);
{
LOCK(cs_main);
@@ -4828,11 +4859,21 @@ bool static LoadBlockIndexDB()
it->second->hashAnchorEnd = pcoinsTip->GetBestAnchor();
PruneBlockIndexCandidates();
double progress;
if ( ASSETCHAINS_SYMBOL[0] == 0 ) {
progress = Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.Tip());
} else {
int32_t longestchain = komodo_longestchain();
// TODO: komodo_longestchain does not have the data it needs at the time LoadBlockIndexDB
// runs, which makes it return 0, so we guess 50% for now
progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 0.5;
}
LogPrintf("%s: hashBestChain=%s height=%d date=%s progress=%f\n", __func__,
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(),
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.Tip()));
chainActive.LastTip()->GetBlockHash().ToString(), chainActive.Height(),
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.LastTip()->GetBlockTime()),
progress);
EnforceNodeDeprecation(chainActive.Height(), true);

View File

@@ -211,7 +211,7 @@ int printStats(bool mining)
{
LOCK2(cs_main, cs_vNodes);
height = chainActive.Height();
tipmediantime = chainActive.Tip()->GetMedianTimePast();
tipmediantime = chainActive.LastTip()->GetMedianTimePast();
connections = vNodes.size();
netsolps = GetNetworkHashPS(120, -1);
}

View File

@@ -117,11 +117,7 @@ uint32_t Mining_start,Mining_height;
int32_t My_notaryid = -1;
int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp);
int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize);
//uint64_t komodo_paxtotal();
int32_t komodo_baseid(char *origbase);
//int32_t komodo_is_issuer();
//int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *symbol,int32_t tokomodo);
//int32_t komodo_isrealtime(int32_t *kmdheightp);
int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag);
uint64_t komodo_commission(const CBlock *block);
int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig);
@@ -140,29 +136,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount)
return NULL;
}
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
/*if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) >= 0 && chainActive.Tip()->nHeight >= ASSETCHAINS_MINHEIGHT )
{
isrealtime = komodo_isrealtime(&kmdheight);
deposits = komodo_paxtotal();
while ( KOMODO_ON_DEMAND == 0 && deposits == 0 && (int32_t)mempool.GetTotalTxSize() == 0 )
{
deposits = komodo_paxtotal();
if ( KOMODO_PASSPORT_INITDONE == 0 || KOMODO_INITDONE == 0 || (komodo_baseid(ASSETCHAINS_SYMBOL) >= 0 && (isrealtime= komodo_isrealtime(&kmdheight)) == 0) )
{
//fprintf(stderr,"INITDONE.%d RT.%d deposits %.8f ht.%d\n",KOMODO_INITDONE,isrealtime,(double)deposits/COIN,kmdheight);
}
else if ( komodo_isrealtime(&kmdheight) != 0 && (deposits != 0 || (int32_t)mempool.GetTotalTxSize() > 0) )
{
fprintf(stderr,"start CreateNewBlock %s initdone.%d deposit %.8f mempool.%d RT.%u KOMODO_ON_DEMAND.%d\n",ASSETCHAINS_SYMBOL,KOMODO_INITDONE,(double)komodo_paxtotal()/COIN,(int32_t)mempool.GetTotalTxSize(),isrealtime,KOMODO_ON_DEMAND);
break;
}
sleep(10);
}
KOMODO_ON_DEMAND = 0;
if ( 0 && deposits != 0 )
printf("miner KOMODO_DEPOSIT %llu pblock->nHeight %d mempool.GetTotalTxSize(%d)\n",(long long)komodo_paxtotal(),(int32_t)chainActive.Tip()->nHeight,(int32_t)mempool.GetTotalTxSize());
}*/
// -regtest only: allow overriding block.nVersion with
// -regtest only: allow overriding block.nVersion with
// -blockversion=N to test forking scenarios
if (Params().MineBlocksOnDemand())
pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
@@ -192,7 +166,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount)
{
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
CBlockIndex* pindexPrev = chainActive.LastTip();
const int nHeight = pindexPrev->nHeight + 1;
uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, chainparams.GetConsensus());
pblock->nTime = GetAdjustedTime();
@@ -360,7 +334,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount)
//fprintf(stderr,"dont have inputs\n");
continue;
}
CAmount nTxFees = view.GetValueIn(chainActive.Tip()->nHeight,&interest,tx,chainActive.Tip()->nTime)-tx.GetValueOut();
CAmount nTxFees = view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime)-tx.GetValueOut();
nTxSigOps += GetP2SHSigOpCount(tx, view);
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
@@ -422,17 +396,18 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount)
{
uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid,revtxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr;
CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1);
sleep(1);
if ( (siglen= komodo_staked(txStaked,pblock->nBits,&blocktime,&txtime,&utxotxid,&utxovout,&utxovalue,utxosig)) > 0 )
{
CAmount txfees = 0;
if ( (int32_t)chainActive.Tip()->nHeight+1 > 100 && GetAdjustedTime() < blocktime-13 )
return(0);
//if ( (int32_t)chainActive.LastTip()->nHeight+1 > 100 && GetAdjustedTime() < blocktime-157 )
// return(0);
pblock->vtx.push_back(txStaked);
pblocktemplate->vTxFees.push_back(txfees);
pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked));
nFees += txfees;
pblock->nTime = blocktime;
printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.Tip()->nHeight+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13)));
//printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->nHeight+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13)));
} else return(0); //fprintf(stderr,"no utxos eligible for staking\n");
}
@@ -517,7 +492,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount)
return(0);
}
}
else
else if ( ASSETCHAINS_STAKED == 0 )
{
CValidationState state;
if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false))
@@ -665,19 +640,19 @@ static bool ProcessBlockFound(CBlock* pblock)
#endif // ENABLE_WALLET
{
LogPrintf("%s\n", pblock->ToString());
LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.Tip()->nHeight+1);
LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.LastTip()->nHeight+1);
// Found a solution
{
LOCK(cs_main);
if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
if (pblock->hashPrevBlock != chainActive.LastTip()->GetBlockHash())
{
uint256 hash; int32_t i;
hash = pblock->hashPrevBlock;
for (i=31; i>=0; i--)
fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
fprintf(stderr," <- prev (stale)\n");
hash = chainActive.Tip()->GetBlockHash();
hash = chainActive.LastTip()->GetBlockHash();
for (i=31; i>=0; i--)
fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
fprintf(stderr," <- chainTip (stale)\n");
@@ -705,7 +680,7 @@ static bool ProcessBlockFound(CBlock* pblock)
// Process this block the same as if we had received it from another node
CValidationState state;
if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL))
if (!ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, pblock, true, NULL))
return error("KomodoMiner: ProcessNewBlock, block not accepted");
TrackMinedBlock(pblock->GetHash());
@@ -743,13 +718,13 @@ void static BitcoinMiner()
unsigned int n = chainparams.EquihashN();
unsigned int k = chainparams.EquihashK();
uint8_t *script; uint64_t total,checktoshis; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1;
while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->nHeight != 235300 &&
while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.LastTip()->nHeight != 235300 &&
{
sleep(1);
if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
break;
}
komodo_chosennotary(&notaryid,chainActive.Tip()->nHeight,NOTARY_PUBKEY33,(uint32_t)chainActive.Tip()->GetBlockTime());
komodo_chosennotary(&notaryid,chainActive.LastTip()->nHeight,NOTARY_PUBKEY33,(uint32_t)chainActive.LastTip()->GetBlockTime());
if ( notaryid != My_notaryid )
My_notaryid = notaryid;
std::string solver;
@@ -775,9 +750,9 @@ void static BitcoinMiner()
fprintf(stderr,"try %s Mining with %s\n",ASSETCHAINS_SYMBOL,solver.c_str());
while (true)
{
if (chainparams.MiningRequiresPeers()) //chainActive.Tip()->nHeight != 235300 &&
if (chainparams.MiningRequiresPeers()) //chainActive.LastTip()->nHeight != 235300 &&
{
//if ( ASSETCHAINS_SEED != 0 && chainActive.Tip()->nHeight < 100 )
//if ( ASSETCHAINS_SEED != 0 && chainActive.LastTip()->nHeight < 100 )
// break;
// Busy-wait for the network to come online so we don't waste time mining
// on an obsolete chain. In regtest mode we expect to fly solo.
@@ -801,7 +776,7 @@ void static BitcoinMiner()
// Create new block
//
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
CBlockIndex* pindexPrev = chainActive.Tip();
CBlockIndex* pindexPrev = chainActive.LastTip();
if ( Mining_height != pindexPrev->nHeight+1 )
{
Mining_height = pindexPrev->nHeight+1;
@@ -810,7 +785,7 @@ void static BitcoinMiner()
if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_STAKED == 0 )
{
//fprintf(stderr,"%s create new block ht.%d\n",ASSETCHAINS_SYMBOL,Mining_height);
sleep(3);
//sleep(3);
}
#ifdef ENABLE_WALLET
CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey,pindexPrev->nHeight+1,gpucount);
@@ -856,9 +831,10 @@ void static BitcoinMiner()
//
// Search
//
uint8_t pubkeys[66][33]; uint32_t blocktimes[66]; int mids[256],nonzpkeys,i,j,externalflag; uint32_t savebits; int64_t nStart = GetTime();
uint8_t pubkeys[66][33]; arith_uint256 bnMaxPoSdiff; uint32_t blocktimes[66]; int mids[256],nonzpkeys,i,j,externalflag; uint32_t savebits; int64_t nStart = GetTime();
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
savebits = pblock->nBits;
HASHTarget = arith_uint256().SetCompact(pblock->nBits);
HASHTarget = arith_uint256().SetCompact(savebits);
roundrobin_delay = ROUNDROBIN_DELAY;
if ( ASSETCHAINS_SYMBOL[0] == 0 && notaryid >= 0 )
{
@@ -911,15 +887,11 @@ void static BitcoinMiner()
} //else fprintf(stderr,"duplicate at j.%d\n",j);
} else Mining_start = 0;
} else Mining_start = 0;
if ( ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0 )
if ( ASSETCHAINS_STAKED != 0 )
{
int32_t percPoS,z;
/*if ( Mining_height <= 100 )
{
sleep(60);
continue;
}*/
int32_t percPoS,z; bool fNegative,fOverflow;
HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
if ( ASSETCHAINS_STAKED < 100 )
{
for (z=31; z>=0; z--)
@@ -979,14 +951,18 @@ void static BitcoinMiner()
fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]);
fprintf(stderr," POW\n");*/
if ( h > hashTarget )
return false;
if ( B.nTime > GetAdjustedTime() )
{
fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime()));
//if ( ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0 )
// sleep(1);
return false;
}
if ( IS_KOMODO_NOTARY != 0 && B.nTime > GetAdjustedTime() )
{
//fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime()));
while ( GetAdjustedTime() < B.nTime-2 )
{
sleep(1);
if ( chainActive.Tip()->nHeight >= Mining_height )
if ( chainActive.LastTip()->nHeight >= Mining_height )
{
fprintf(stderr,"new block arrived\n");
return(false);
@@ -1004,15 +980,19 @@ void static BitcoinMiner()
}
else
{
while ( GetAdjustedTime() < B.nTime )
while ( B.nTime-57 > GetAdjustedTime() )
{
sleep(1);
if ( chainActive.LastTip()->nHeight >= Mining_height )
return(false);
}
uint256 tmp = B.GetHash();
int32_t z; for (z=31; z>=0; z--)
fprintf(stderr,"%02x",((uint8_t *)&tmp)[z]);
fprintf(stderr," mined block %d!\n",Mining_height);
fprintf(stderr," mined %s block %d!\n",ASSETCHAINS_SYMBOL,Mining_height);
}
CValidationState state;
if ( !TestBlockValidity(state,B, chainActive.Tip(), true, false))
if ( !TestBlockValidity(state,B, chainActive.LastTip(), true, false))
{
h = UintToArith256(B.GetHash());
for (z=31; z>=0; z--)
@@ -1132,7 +1112,7 @@ void static BitcoinMiner()
fprintf(stderr,"timeout, break\n");
break;
}
if ( pindexPrev != chainActive.Tip() )
if ( pindexPrev != chainActive.LastTip() )
{
if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
fprintf(stderr,"Tip advanced, break\n");

View File

@@ -190,6 +190,11 @@ bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash,unsigned int
}
if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
return error("CheckProofOfWork(): nBits below minimum work");
if ( ASSETCHAINS_STAKED != 0 )
{
arith_uint256 bnMaxPoSdiff;
bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
}
// Check proof of work matches claimed amount
if ( UintToArith256(hash) > bnTarget )
{

View File

@@ -232,11 +232,26 @@ CAmount CTransaction::GetJoinSplitValueIn() const
{
// NB: vpub_new "gives" money to the value pool just as inputs do
nValue += it->vpub_new;
if (!MoneyRange(it->vpub_new) || !MoneyRange(nValue))
throw std::runtime_error("CTransaction::GetJoinSplitValueIn(): value out of range");
}
return nValue;
}
CAmount CTransaction::GetJoinSplitValueOut() const
{
CAmount nValue = 0;
for (std::vector<JSDescription>::const_iterator it(vjoinsplit.begin()); it != vjoinsplit.end(); ++it)
{
// NB: vpub_new "gives" money to the value pool just as inputs do
nValue += it->vpub_old;
if (!MoneyRange(it->vpub_old) || !MoneyRange(nValue))
throw std::runtime_error("CTransaction::GetJoinSplitValueOut(): value out of range");
}
return nValue;
}

View File

@@ -445,6 +445,8 @@ public:
// Return sum of JoinSplit vpub_new
CAmount GetJoinSplitValueIn() const;
// Return sum of JoinSplit vpub_old
CAmount GetJoinSplitValueOut() const;
// Compute priority, given priority of inputs and (optionally) tx size
double ComputePriority(double dPriorityInputs, unsigned int nTxSize=0) const;

View File

@@ -530,7 +530,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
// serialize data
// use exact same output as mentioned in Bip64
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs;
ssGetUTXOResponse << chainActive.Height() << chainActive.LastTip()->GetBlockHash() << bitmap << outs;
string ssGetUTXOResponseString = ssGetUTXOResponse.str();
req->WriteHeader("Content-Type", "application/octet-stream");
@@ -540,7 +540,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
case RF_HEX: {
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs;
ssGetUTXOResponse << chainActive.Height() << chainActive.LastTip()->GetBlockHash() << bitmap << outs;
string strHex = HexStr(ssGetUTXOResponse.begin(), ssGetUTXOResponse.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
@@ -554,7 +554,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
// pack in some essentials
// use more or less the same output as mentioned in Bip64
objGetUTXOResponse.push_back(Pair("chainHeight", chainActive.Height()));
objGetUTXOResponse.push_back(Pair("chaintipHash", chainActive.Tip()->GetBlockHash().GetHex()));
objGetUTXOResponse.push_back(Pair("chaintipHash", chainActive.LastTip()->GetBlockHash().GetHex()));
objGetUTXOResponse.push_back(Pair("bitmap", bitmapStringRepresentation));
UniValue utxos(UniValue::VARR);

View File

@@ -38,10 +38,10 @@ double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficul
// minimum difficulty = 1.0.
if (blockindex == NULL)
{
if (chainActive.Tip() == NULL)
if (chainActive.LastTip() == NULL)
return 1.0;
else
blockindex = chainActive.Tip();
blockindex = chainActive.LastTip();
}
uint32_t bits;
@@ -326,7 +326,7 @@ UniValue getbestblockhash(const UniValue& params, bool fHelp)
);
LOCK(cs_main);
return chainActive.Tip()->GetBlockHash().GetHex();
return chainActive.LastTip()->GetBlockHash().GetHex();
}
UniValue getdifficulty(const UniValue& params, bool fHelp)
@@ -803,13 +803,13 @@ UniValue kvsearch(const UniValue& params, bool fHelp)
if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 )
{
ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
ret.push_back(Pair("currentheight", (int64_t)chainActive.Tip()->nHeight));
ret.push_back(Pair("currentheight", (int64_t)chainActive.LastTip()->nHeight));
ret.push_back(Pair("key",params[0].get_str()));
ret.push_back(Pair("keylen",keylen));
if ( keylen < sizeof(key) )
{
memcpy(key,params[0].get_str().c_str(),keylen);
if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.Tip()->nHeight,&flags,&height,value,key,keylen)) >= 0 )
if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&flags,&height,value,key,keylen)) >= 0 )
{
std::string val; char *valuestr;
val.resize(valuesize);
@@ -837,7 +837,7 @@ UniValue minerids(const UniValue& params, bool fHelp)
LOCK(cs_main);
int32_t height = atoi(params[0].get_str().c_str());
if ( height <= 0 )
height = chainActive.Tip()->nHeight;
height = chainActive.LastTip()->nHeight;
else
{
CBlockIndex *pblockindex = chainActive[height];
@@ -899,8 +899,8 @@ UniValue notaries(const UniValue& params, bool fHelp)
else timestamp = (uint32_t)time(NULL);
if ( height < 0 )
{
height = chainActive.Tip()->nHeight;
timestamp = chainActive.Tip()->GetBlockTime();
height = chainActive.LastTip()->nHeight;
timestamp = chainActive.LastTip()->GetBlockTime();
}
else if ( params.size() < 2 )
{
@@ -988,7 +988,7 @@ UniValue paxprice(const UniValue& params, bool fHelp)
std::string rel = params[1].get_str();
int32_t height;
if ( params.size() == 2 )
height = chainActive.Tip()->nHeight;
height = chainActive.LastTip()->nHeight;
else height = atoi(params[2].get_str().c_str());
//if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 )
basevolume = 100000;
@@ -1280,10 +1280,10 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("chain", Params().NetworkIDString()));
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()));
obj.push_back(Pair("bestblockhash", chainActive.LastTip()->GetBlockHash().GetHex()));
obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty()));
obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.LastTip())));
obj.push_back(Pair("chainwork", chainActive.LastTip()->nChainWork.GetHex()));
obj.push_back(Pair("pruned", fPruneMode));
ZCIncrementalMerkleTree tree;
@@ -1294,7 +1294,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("commitments", tree.size()));
#endif
CBlockIndex* tip = chainActive.Tip();
CBlockIndex* tip = chainActive.LastTip();
UniValue valuePools(UniValue::VARR);
valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none));
obj.push_back(Pair("valuePools", valuePools));
@@ -1319,7 +1319,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
if (fPruneMode)
{
CBlockIndex *block = chainActive.Tip();
CBlockIndex *block = chainActive.LastTip();
while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
block = block->pprev;
@@ -1394,7 +1394,7 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
}
// Always report the currently active tip.
setTips.insert(chainActive.Tip());
setTips.insert(chainActive.LastTip());
/* Construct the output array. */
UniValue res(UniValue::VARR); const CBlockIndex *forked;

View File

@@ -39,7 +39,7 @@ using namespace std;
* If 'height' is nonnegative, compute the estimate at the time when a given block was found.
*/
int64_t GetNetworkHashPS(int lookup, int height) {
CBlockIndex *pb = chainActive.Tip();
CBlockIndex *pb = chainActive.LastTip();
if (height >= 0 && height < chainActive.Height())
pb = chainActive[height];
@@ -224,7 +224,7 @@ UniValue generate(const UniValue& params, bool fHelp)
CBlock *pblock = &pblocktemplate->block;
{
LOCK(cs_main);
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
IncrementExtraNonce(pblock, chainActive.LastTip(), nExtraNonce);
}
// Hash state
@@ -268,7 +268,7 @@ UniValue generate(const UniValue& params, bool fHelp)
}
endloop:
CValidationState state;
if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL))
if (!ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, pblock, true, NULL))
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
@@ -550,7 +550,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
return "duplicate-inconclusive";
}
CBlockIndex* const pindexPrev = chainActive.Tip();
CBlockIndex* const pindexPrev = chainActive.LastTip();
// TestBlockValidity only supports blocks built on the current Tip
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
return "inconclusive-not-best-prevblk";
@@ -589,7 +589,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
else
{
// NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
hashWatchedChain = chainActive.Tip()->GetBlockHash();
hashWatchedChain = chainActive.LastTip()->GetBlockHash();
nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
}
@@ -599,7 +599,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
boost::unique_lock<boost::mutex> lock(csBestBlock);
while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
while (chainActive.LastTip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
{
if (!cvBlockChange.timed_wait(lock, checktxtime))
{
@@ -621,7 +621,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
static CBlockIndex* pindexPrev;
static int64_t nStart;
static CBlockTemplate* pblocktemplate;
if (pindexPrev != chainActive.Tip() ||
if (pindexPrev != chainActive.LastTip() ||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
{
// Clear pindexPrev so future calls make a new block, despite any failures from here on
@@ -629,7 +629,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
// Store the pindexBest used before CreateNewBlockWithKey, to avoid races
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
CBlockIndex* pindexPrevNew = chainActive.Tip();
CBlockIndex* pindexPrevNew = chainActive.LastTip();
nStart = GetTime();
// Create new block
@@ -640,7 +640,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
}
#ifdef ENABLE_WALLET
CReserveKey reservekey(pwalletMain);
pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.Tip()->nHeight+1,KOMODO_MAXGPUCOUNT);
pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->nHeight+1,KOMODO_MAXGPUCOUNT);
#else
pblocktemplate = CreateNewBlockWithKey();
#endif
@@ -693,7 +693,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
// Correct this if GetBlockTemplate changes the order
// entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue));
//}
CAmount nReward = GetBlockSubsidy(chainActive.Tip()->nHeight+1, Params().GetConsensus());
CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->nHeight+1, Params().GetConsensus());
entry.push_back(Pair("coinbasevalue", nReward));
entry.push_back(Pair("required", true));
txCoinbase = entry;
@@ -726,7 +726,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
result.push_back(Pair("coinbaseaux", aux));
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
}
result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
result.push_back(Pair("target", hashTarget.GetHex()));
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("mutable", aMutable));
@@ -809,7 +809,7 @@ UniValue submitblock(const UniValue& params, bool fHelp)
CValidationState state;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
bool fAccepted = ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, &block, true, NULL);
bool fAccepted = ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, &block, true, NULL);
UnregisterValidationInterface(&sc);
if (fBlockPresent)
{

View File

@@ -53,6 +53,7 @@ extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE;
extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN;
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
uint32_t komodo_segid32(char *coinaddr);
int64_t komodo_coinsupply(int64_t *zfundsp,int32_t height);
int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp);
#define KOMODO_VERSION "0.1.1"
extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
@@ -132,8 +133,8 @@ UniValue getinfo(const UniValue& params, bool fHelp)
//fprintf(stderr,"after longestchain %u\n",(uint32_t)time(NULL));
obj.push_back(Pair("longestchain", longestchain));
obj.push_back(Pair("timeoffset", GetTimeOffset()));
if ( chainActive.Tip() != 0 )
obj.push_back(Pair("tiptime", (int)chainActive.Tip()->nTime));
if ( chainActive.LastTip() != 0 )
obj.push_back(Pair("tiptime", (int)chainActive.LastTip()->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()));
@@ -151,7 +152,7 @@ UniValue getinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("errors", GetWarnings("statusbar")));
{
char pubkeystr[65]; int32_t notaryid;
if ( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.Tip()->nHeight,komodo_chainactive_timestamp())) >= 0 )
if ( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.LastTip()->nHeight,komodo_chainactive_timestamp())) >= 0 )
{
obj.push_back(Pair("notaryid", notaryid));
obj.push_back(Pair("pubkey", pubkeystr));
@@ -226,6 +227,26 @@ public:
};
#endif
UniValue coinsupply(const UniValue& params, bool fHelp)
{
int32_t height = 0; int64_t zfunds,supply = 0; UniValue result(UniValue::VOBJ);
if (fHelp || params.size() > 1)
throw runtime_error("coinsupply <height>\n");
if ( params.size() == 0 )
height = chainActive.Height();
else height = atoi(params[0].get_str());
if ( (supply= komodo_coinsupply(&zfunds,height)) > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("coin", ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL));
result.push_back(Pair("height", (int)height));
result.push_back(Pair("supply", ValueFromAmount(supply)));
result.push_back(Pair("zfunds", ValueFromAmount(zfunds)));
result.push_back(Pair("total", ValueFromAmount(zfunds + supply)));
} else result.push_back(Pair("error", "couldnt calculate supply"));
return(result);
}
UniValue jumblr_deposit(const UniValue& params, bool fHelp)
{
int32_t retval; UniValue result(UniValue::VOBJ);
@@ -805,7 +826,7 @@ UniValue getaddressutxos(const UniValue& params, bool fHelp)
result.push_back(Pair("utxos", utxos));
LOCK(cs_main);
result.push_back(Pair("hash", chainActive.Tip()->GetBlockHash().GetHex()));
result.push_back(Pair("hash", chainActive.LastTip()->GetBlockHash().GetHex()));
result.push_back(Pair("height", (int)chainActive.Height()));
return result;
} else {

View File

@@ -179,7 +179,7 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue&
const CTxOut& txout = tx.vout[i];
UniValue out(UniValue::VOBJ);
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
if ( pindex != 0 && tx.nLockTime >= 500000000 && (tipindex= chainActive.Tip()) != 0 )
if ( pindex != 0 && tx.nLockTime >= 500000000 && (tipindex= chainActive.LastTip()) != 0 )
{
int64_t interest; int32_t txheight; uint32_t locktime;
interest = komodo_accrued_interest(&txheight,&locktime,tx.GetHash(),i,0,txout.nValue,(int32_t)tipindex->nHeight);

View File

@@ -280,6 +280,7 @@ static const CRPCCommand vRPCCommands[] =
{ "network", "clearbanned", &clearbanned, true },
/* Block chain and UTXO */
{ "blockchain", "coinsupply", &coinsupply, true },
{ "blockchain", "getblockchaininfo", &getblockchaininfo, true },
{ "blockchain", "getbestblockhash", &getbestblockhash, true },
{ "blockchain", "getblockcount", &getblockcount, true },

View File

@@ -207,6 +207,7 @@ extern UniValue getblocktemplate(const UniValue& params, bool fHelp);
extern UniValue submitblock(const UniValue& params, bool fHelp);
extern UniValue estimatefee(const UniValue& params, bool fHelp);
extern UniValue estimatepriority(const UniValue& params, bool fHelp);
extern UniValue coinsupply(const UniValue& params, bool fHelp);
extern UniValue getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp
//extern UniValue getnewaddress64(const UniValue& params, bool fHelp); // in rpcwallet.cpp

View File

@@ -1,447 +0,0 @@
// Copyright (c) 2013 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
// Unit tests for alert system
//
#include "alert.h"
#include "chain.h"
#include "chainparams.h"
#include "clientversion.h"
#include "data/alertTests.raw.h"
#include "main.h"
#include "rpcprotocol.h"
#include "rpcserver.h"
#include "serialize.h"
#include "streams.h"
#include "util.h"
#include "utilstrencodings.h"
#include "test/test_bitcoin.h"
#include <fstream>
#include <boost/filesystem/operations.hpp>
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
#include "key.h"
#include "alertkeys.h"
#include <iostream>
/*
* If the alert key pairs have changed, the test suite will fail as the
* test data is now invalid. To create valid test data, signed with a
* new alert private key, follow these steps:
*
* 1. Copy your private key into alertkeys.h. Don't commit this file!
* See sendalert.cpp for more info.
*
* 2. Set the GENERATE_ALERTS_FLAG to true.
*
* 3. Build and run:
* test_bitcoin -t Generate_Alert_Test_Data
*
* 4. Test data is saved in your current directory as alertTests.raw.NEW
* Copy this file to: src/test/data/alertTests.raw
*
* For debugging purposes, terminal output can be copied into:
* src/test/data/alertTests.raw.h
*
* 5. Clean up...
* - Set GENERATE_ALERTS_FLAG back to false.
* - Remove your private key from alertkeys.h
*
* 6. Build and verify the new test data:
* test_bitcoin -t Alert_tests
*
*/
#define GENERATE_ALERTS_FLAG false
#if GENERATE_ALERTS_FLAG
// NOTE:
// A function SignAndSave() was used by Bitcoin Core to create alert test data
// but it has not been made publicly available. So instead, we have adapted
// some publicly available code which achieves the intended result:
// https://gist.github.com/lukem512/9b272bd35e2cdefbf386
// Code to output a C-style array of values
template<typename T>
std::string HexStrArray(const T itbegin, const T itend, int lineLength)
{
std::string rv;
static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
rv.reserve((itend-itbegin)*3);
int i = 0;
for(T it = itbegin; it < itend; ++it)
{
unsigned char val = (unsigned char)(*it);
if(it != itbegin)
{
if (i % lineLength == 0)
rv.push_back('\n');
else
rv.push_back(' ');
}
rv.push_back('0');
rv.push_back('x');
rv.push_back(hexmap[val>>4]);
rv.push_back(hexmap[val&15]);
rv.push_back(',');
i++;
}
return rv;
}
template<typename T>
inline std::string HexStrArray(const T& vch, int lineLength)
{
return HexStrArray(vch.begin(), vch.end(), lineLength);
}
// Sign CAlert with alert private key
bool SignAlert(CAlert &alert)
{
// serialize alert data
CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION);
sMsg << *(CUnsignedAlert*)&alert;
alert.vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end());
// sign alert
std::vector<unsigned char> vchTmp(ParseHex(pszPrivKey));
CPrivKey vchPrivKey(vchTmp.begin(), vchTmp.end());
CKey key;
if (!key.SetPrivKey(vchPrivKey, false))
{
printf("key.SetPrivKey failed\n");
return false;
}
if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig))
{
printf("SignAlert() : key.Sign failed\n");
return false;
}
return true;
}
// Sign a CAlert and serialize it
bool SignAndSerialize(CAlert &alert, CDataStream &buffer)
{
// Sign
if(!SignAlert(alert))
{
printf("SignAndSerialize() : could not sign alert\n");
return false;
}
// ...and save!
buffer << alert;
return true;
}
void GenerateAlertTests()
{
CDataStream sBuffer(SER_DISK, CLIENT_VERSION);
CAlert alert;
alert.nRelayUntil = 60;
alert.nExpiration = 24 * 60 * 60;
alert.nID = 1;
alert.nCancel = 0; // cancels previous messages up to this ID number
alert.nMinVer = 0; // These versions are protocol versions
alert.nMaxVer = 999001;
alert.nPriority = 1;
alert.strComment = "Alert comment";
alert.strStatusBar = "Alert 1";
// Replace SignAndSave with SignAndSerialize
SignAndSerialize(alert, sBuffer);
// More tests go here ...
alert.setSubVer.insert(std::string("/MagicBean:0.1.0/"));
alert.strStatusBar = "Alert 1 for MagicBean 0.1.0";
SignAndSerialize(alert, sBuffer);
alert.setSubVer.insert(std::string("/MagicBean:0.2.0/"));
alert.strStatusBar = "Alert 1 for MagicBean 0.1.0, 0.2.0";
SignAndSerialize(alert, sBuffer);
alert.setSubVer.clear();
++alert.nID;
alert.nCancel = 1;
alert.nPriority = 100;
alert.strStatusBar = "Alert 2, cancels 1";
SignAndSerialize(alert, sBuffer);
alert.nExpiration += 60;
++alert.nID;
SignAndSerialize(alert, sBuffer);
++alert.nID;
alert.nPriority = 5000;
alert.strStatusBar = "Alert 3, disables RPC";
alert.strRPCError = "RPC disabled";
SignAndSerialize(alert, sBuffer);
++alert.nID;
alert.nPriority = 5000;
alert.strStatusBar = "Alert 4, re-enables RPC";
alert.strRPCError = "";
SignAndSerialize(alert, sBuffer);
++alert.nID;
alert.nMinVer = 11;
alert.nMaxVer = 22;
alert.nPriority = 100;
SignAndSerialize(alert, sBuffer);
++alert.nID;
alert.strStatusBar = "Alert 2 for MagicBean 0.1.0";
alert.setSubVer.insert(std::string("/MagicBean:0.1.0/"));
SignAndSerialize(alert, sBuffer);
++alert.nID;
alert.nMinVer = 0;
alert.nMaxVer = 999999;
alert.strStatusBar = "Evil Alert'; /bin/ls; echo '";
alert.setSubVer.clear();
bool b = SignAndSerialize(alert, sBuffer);
if (b) {
// Print the hex array, which will become the contents of alertTest.raw.h
std::vector<unsigned char> vch = std::vector<unsigned char>(sBuffer.begin(), sBuffer.end());
printf("%s\n", HexStrArray(vch, 8).c_str());
// Write the data to alertTests.raw.NEW, to be copied to src/test/data/alertTests.raw
std::ofstream outfile("alertTests.raw.NEW", std::ios::out | std::ios::binary);
outfile.write((const char*)&vch[0], vch.size());
outfile.close();
}
}
struct GenerateAlertTestsFixture : public TestingSetup {
GenerateAlertTestsFixture() {}
~GenerateAlertTestsFixture() {}
};
BOOST_FIXTURE_TEST_SUITE(Generate_Alert_Test_Data, GenerateAlertTestsFixture);
BOOST_AUTO_TEST_CASE(GenerateTheAlertTests)
{
GenerateAlertTests();
}
BOOST_AUTO_TEST_SUITE_END()
#else
struct ReadAlerts : public TestingSetup
{
ReadAlerts()
{
std::vector<unsigned char> vch(alert_tests::alertTests, alert_tests::alertTests + sizeof(alert_tests::alertTests));
CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
try {
while (!stream.eof())
{
CAlert alert;
stream >> alert;
alerts.push_back(alert);
}
}
catch (const std::exception&) { }
}
~ReadAlerts() { }
static std::vector<std::string> read_lines(boost::filesystem::path filepath)
{
std::vector<std::string> result;
std::ifstream f(filepath.string().c_str());
std::string line;
while (std::getline(f,line))
result.push_back(line);
return result;
}
std::vector<CAlert> alerts;
};
BOOST_FIXTURE_TEST_SUITE(Alert_tests, ReadAlerts)
BOOST_AUTO_TEST_CASE(AlertApplies)
{
SetMockTime(11);
const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
BOOST_FOREACH(const CAlert& alert, alerts)
{
BOOST_CHECK(alert.CheckSignature(alertKey));
}
BOOST_CHECK(alerts.size() >= 3);
// Matches:
BOOST_CHECK(alerts[0].AppliesTo(1, ""));
BOOST_CHECK(alerts[0].AppliesTo(999001, ""));
BOOST_CHECK(alerts[0].AppliesTo(1, "/MagicBean:11.11.11/"));
BOOST_CHECK(alerts[1].AppliesTo(1, "/MagicBean:0.1.0/"));
BOOST_CHECK(alerts[1].AppliesTo(999001, "/MagicBean:0.1.0/"));
BOOST_CHECK(alerts[2].AppliesTo(1, "/MagicBean:0.1.0/"));
BOOST_CHECK(alerts[2].AppliesTo(1, "/MagicBean:0.2.0/"));
// Don't match:
BOOST_CHECK(!alerts[0].AppliesTo(-1, ""));
BOOST_CHECK(!alerts[0].AppliesTo(999002, ""));
BOOST_CHECK(!alerts[1].AppliesTo(1, ""));
BOOST_CHECK(!alerts[1].AppliesTo(1, "MagicBean:0.1.0"));
BOOST_CHECK(!alerts[1].AppliesTo(1, "/MagicBean:0.1.0"));
BOOST_CHECK(!alerts[1].AppliesTo(1, "MagicBean:0.1.0/"));
BOOST_CHECK(!alerts[1].AppliesTo(-1, "/MagicBean:0.1.0/"));
BOOST_CHECK(!alerts[1].AppliesTo(999002, "/MagicBean:0.1.0/"));
BOOST_CHECK(!alerts[1].AppliesTo(1, "/MagicBean:0.2.0/"));
BOOST_CHECK(!alerts[2].AppliesTo(1, "/MagicBean:0.3.0/"));
SetMockTime(0);
}
BOOST_AUTO_TEST_CASE(AlertNotify)
{
SetMockTime(11);
const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
boost::filesystem::path temp = GetTempPath() /
boost::filesystem::unique_path("alertnotify-%%%%.txt");
mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string();
BOOST_FOREACH(CAlert alert, alerts)
alert.ProcessAlert(alertKey, false);
std::vector<std::string> r = read_lines(temp);
BOOST_CHECK_EQUAL(r.size(), 6u);
// Windows built-in echo semantics are different than posixy shells. Quotes and
// whitespace are printed literally.
#ifndef _WIN32
BOOST_CHECK_EQUAL(r[0], "Alert 1");
BOOST_CHECK_EQUAL(r[1], "Alert 2, cancels 1");
BOOST_CHECK_EQUAL(r[2], "Alert 2, cancels 1");
BOOST_CHECK_EQUAL(r[3], "Alert 3, disables RPC");
BOOST_CHECK_EQUAL(r[4], "Alert 4, reenables RPC"); // dashes should be removed
BOOST_CHECK_EQUAL(r[5], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed
#else
BOOST_CHECK_EQUAL(r[0], "'Alert 1' ");
BOOST_CHECK_EQUAL(r[1], "'Alert 2, cancels 1' ");
BOOST_CHECK_EQUAL(r[2], "'Alert 2, cancels 1' ");
BOOST_CHECK_EQUAL(r[3], "'Alert 3, disables RPC' ");
BOOST_CHECK_EQUAL(r[4], "'Alert 4, reenables RPC' "); // dashes should be removed
BOOST_CHECK_EQUAL(r[5], "'Evil Alert; /bin/ls; echo ' ");
#endif
boost::filesystem::remove(temp);
SetMockTime(0);
mapAlerts.clear();
}
BOOST_AUTO_TEST_CASE(AlertDisablesRPC)
{
SetMockTime(11);
const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
// Command should work before alerts
BOOST_CHECK_EQUAL(GetWarnings("rpc"), "");
// First alert should disable RPC
alerts[5].ProcessAlert(alertKey, false);
BOOST_CHECK_EQUAL(alerts[5].strRPCError, "RPC disabled");
BOOST_CHECK_EQUAL(GetWarnings("rpc"), "RPC disabled");
// Second alert should re-enable RPC
alerts[6].ProcessAlert(alertKey, false);
BOOST_CHECK_EQUAL(alerts[6].strRPCError, "");
BOOST_CHECK_EQUAL(GetWarnings("rpc"), "");
SetMockTime(0);
mapAlerts.clear();
}
static bool falseFunc() { return false; }
BOOST_AUTO_TEST_CASE(PartitionAlert)
{
// Test PartitionCheck
CCriticalSection csDummy;
CBlockIndex indexDummy[400];
CChainParams& params = Params(CBaseChainParams::MAIN);
int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing;
// Generate fake blockchain timestamps relative to
// an arbitrary time:
int64_t now = 1427379054;
SetMockTime(now);
for (int i = 0; i < 400; i++)
{
indexDummy[i].phashBlock = NULL;
if (i == 0) indexDummy[i].pprev = NULL;
else indexDummy[i].pprev = &indexDummy[i-1];
indexDummy[i].nHeight = i;
indexDummy[i].nTime = now - (400-i)*nPowTargetSpacing;
// Other members don't matter, the partition check code doesn't
// use them
}
// Test 1: chain with blocks every nPowTargetSpacing seconds,
// as normal, no worries:
PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing);
BOOST_CHECK(strMiscWarning.empty());
// Test 2: go 3.5 hours without a block, expect a warning:
now += 3*60*60+30*60;
SetMockTime(now);
PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing);
BOOST_CHECK(!strMiscWarning.empty());
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
strMiscWarning = "";
// Test 3: test the "partition alerts only go off once per day"
// code:
now += 60*10;
SetMockTime(now);
PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing);
BOOST_CHECK(strMiscWarning.empty());
// Test 4: get 2.5 times as many blocks as expected:
now += 60*60*24; // Pretend it is a day later
SetMockTime(now);
int64_t quickSpacing = nPowTargetSpacing*2/5;
for (int i = 0; i < 400; i++) // Tweak chain timestamps:
indexDummy[i].nTime = now - (400-i)*quickSpacing;
PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing);
BOOST_CHECK(!strMiscWarning.empty());
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
strMiscWarning = "";
SetMockTime(0);
}
BOOST_AUTO_TEST_SUITE_END()
#endif

View File

@@ -400,9 +400,9 @@ bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &addr
int64_t CBlockTreeDB::Snapshot()
{
char chType; int64_t total = -1; std::string address;
char chType; int64_t total = 0; std::string address;
boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
pcursor->SeekToFirst();
pcursor->SeekToLast();
fprintf(stderr,"pcursor iterate\n");
while (pcursor->Valid())
{
@@ -428,7 +428,6 @@ int64_t CBlockTreeDB::Snapshot()
total = (int64_t)nValue;
else total += (int64_t)nValue;
//addressIndex.push_back(make_pair(indexKey, nValue));
pcursor->Next();
} catch (const std::exception& e) {
return error("failed to get address index value");
}
@@ -436,6 +435,7 @@ int64_t CBlockTreeDB::Snapshot()
} catch (const std::exception& e) {
break;
}
pcursor->Prev();
}
return(total);
}

View File

@@ -437,7 +437,7 @@ void CTxMemPool::removeExpired(unsigned int nBlockHeight)
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++)
{
const CTransaction& tx = it->GetTx();
tipindex = chainActive.Tip();
tipindex = chainActive.LastTip();
if (IsExpiredTx(tx, nBlockHeight) || (ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(tx,tipindex->nHeight+1,tipindex->GetMedianTimePast() + 777,0)) < 0)
{
transactionsToRemove.push_back(tx);

View File

@@ -51,3 +51,7 @@ void UnregisterAllValidationInterfaces() {
void SyncWithWallets(const CTransaction &tx, const CBlock *pblock) {
g_signals.SyncTransaction(tx, pblock);
}
void EraseFromWallets(const uint256 &hash) {
g_signals.EraseTransaction(hash);
}

View File

@@ -28,6 +28,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn);
void UnregisterAllValidationInterfaces();
/** Push an updated transaction to all registered wallets */
void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL);
void EraseFromWallets(const uint256 &hash);
class CValidationInterface {
protected:

View File

@@ -278,7 +278,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys
if (!file.is_open())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
int64_t nTimeBegin = chainActive.Tip()->GetBlockTime();
int64_t nTimeBegin = chainActive.LastTip()->GetBlockTime();
bool fGood = true;
@@ -364,7 +364,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys
file.close();
pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI
CBlockIndex *pindex = chainActive.Tip();
CBlockIndex *pindex = chainActive.LastTip();
while (pindex && pindex->pprev && pindex->GetBlockTime() > nTimeBegin - 7200)
pindex = pindex->pprev;
@@ -509,8 +509,8 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys)
// produce output
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()));
file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.LastTip()->GetBlockHash().ToString());
file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.LastTip()->GetBlockTime()));
file << "\n";
for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
const CKeyID &keyid = it->second;

View File

@@ -574,7 +574,7 @@ UniValue kvupdate(const UniValue& params, bool fHelp)
valuesize = (int32_t)strlen(params[1].get_str().c_str());
}
memcpy(keyvalue,key,keylen);
if ( (refvaluesize= komodo_kvsearch(&refpubkey,chainActive.Tip()->nHeight,&tmpflags,&height,&keyvalue[keylen],key,keylen)) >= 0 )
if ( (refvaluesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&tmpflags,&height,&keyvalue[keylen],key,keylen)) >= 0 )
{
if ( (tmpflags & KOMODO_KVPROTECTED) != 0 )
{
@@ -599,7 +599,7 @@ UniValue kvupdate(const UniValue& params, bool fHelp)
// printf("%02x",((uint8_t *)&sig)[i]);
//printf(" sig for keylen.%d + valuesize.%d\n",keylen,refvaluesize);
ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
height = chainActive.Tip()->nHeight;
height = chainActive.LastTip()->nHeight;
if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 )
ret.push_back(Pair("owner",refpubkey.GetHex()));
ret.push_back(Pair("height", (int64_t)height));
@@ -671,7 +671,7 @@ UniValue paxdeposit(const UniValue& params, bool fHelp)
int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN;
std::string base = params[2].get_str();
std::string dest;
height = chainActive.Tip()->nHeight;
height = chainActive.LastTip()->nHeight;
if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,(char *)base.c_str()) != 0 || available < fiatoshis )
{
fprintf(stderr,"available %llu vs fiatoshis %llu\n",(long long)available,(long long)fiatoshis);
@@ -1075,8 +1075,6 @@ UniValue getunconfirmedbalance(const UniValue &params, bool fHelp)
UniValue movecmd(const UniValue& params, bool fHelp)
{
if ( ASSETCHAINS_PRIVATE != 0 )
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
@@ -1100,6 +1098,8 @@ UniValue movecmd(const UniValue& params, bool fHelp)
"\nAs a json rpc call\n"
+ HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
);
if ( ASSETCHAINS_PRIVATE != 0 )
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
LOCK2(cs_main, pwalletMain->cs_wallet);
@@ -1150,8 +1150,6 @@ UniValue movecmd(const UniValue& params, bool fHelp)
UniValue sendfrom(const UniValue& params, bool fHelp)
{
if ( ASSETCHAINS_PRIVATE != 0 )
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
@@ -1181,6 +1179,8 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
"\nAs a json rpc call\n"
+ HelpExampleRpc("sendfrom", "\"tabby\", \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.01, 6, \"donation\", \"seans outpost\"")
);
if ( ASSETCHAINS_PRIVATE != 0 )
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
LOCK2(cs_main, pwalletMain->cs_wallet);
@@ -1217,8 +1217,6 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
UniValue sendmany(const UniValue& params, bool fHelp)
{
if ( ASSETCHAINS_PRIVATE != 0 )
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
@@ -1257,6 +1255,8 @@ UniValue sendmany(const UniValue& params, bool fHelp)
"\nAs a json rpc call\n"
+ HelpExampleRpc("sendmany", "\"\", \"{\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.01,\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.02}\", 6, \"testing\"")
);
if ( ASSETCHAINS_PRIVATE != 0 )
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
LOCK2(cs_main, pwalletMain->cs_wallet);
@@ -2713,13 +2713,13 @@ UniValue listunspent(const UniValue& params, bool fHelp)
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
CBlockIndex *tipindex,*pindex = it->second;
uint64_t interest; uint32_t locktime; int32_t txheight;
if ( pindex != 0 && (tipindex= chainActive.Tip()) != 0 )
if ( pindex != 0 && (tipindex= chainActive.LastTip()) != 0 )
{
interest = komodo_accrued_interest(&txheight,&locktime,out.tx->GetHash(),out.i,0,nValue,(int32_t)tipindex->nHeight);
//interest = komodo_interest(txheight,nValue,out.tx->nLockTime,tipindex->nTime);
entry.push_back(Pair("interest",ValueFromAmount(interest)));
}
//fprintf(stderr,"nValue %.8f pindex.%p tipindex.%p locktime.%u txheight.%d pindexht.%d\n",(double)nValue/COIN,pindex,chainActive.Tip(),locktime,txheight,pindex->nHeight);
//fprintf(stderr,"nValue %.8f pindex.%p tipindex.%p locktime.%u txheight.%d pindexht.%d\n",(double)nValue/COIN,pindex,chainActive.LastTip(),locktime,txheight,pindex->nHeight);
}
entry.push_back(Pair("confirmations",out.nDepth));
entry.push_back(Pair("spendable", out.fSpendable));
@@ -2746,7 +2746,7 @@ uint64_t komodo_interestsum()
{
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
CBlockIndex *tipindex,*pindex = it->second;
if ( pindex != 0 && (tipindex= chainActive.Tip()) != 0 )
if ( pindex != 0 && (tipindex= chainActive.LastTip()) != 0 )
{
interest = komodo_accrued_interest(&txheight,&locktime,out.tx->GetHash(),out.i,0,nValue,(int32_t)tipindex->nHeight);
//interest = komodo_interest(pindex->nHeight,nValue,out.tx->nLockTime,tipindex->nTime);
@@ -4513,6 +4513,8 @@ UniValue z_listoperationids(const UniValue& params, bool fHelp)
int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex);
extern std::string NOTARY_PUBKEY;
uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 hash,int32_t n,uint32_t blocktime,uint32_t prevtime,char *destaddr);
int8_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout);
int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n);
int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33)
{
@@ -4590,10 +4592,96 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33)
return(siglen);
}
struct komodo_staking
{
char address[64];
uint256 txid;
arith_uint256 hashval;
uint64_t nValue;
uint32_t segid32,txtime;
int32_t vout;
CScript scriptPubKey;
};
struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk)
{
uint256 hash; uint32_t segid32; struct komodo_staking *kp;
segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout);
if ( *numkp >= *maxkp )
{
*maxkp += 1000;
array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp));
}
kp = &array[(*numkp)++];
memset(kp,0,sizeof(*kp));
strcpy(kp->address,address);
kp->txid = txid;
kp->vout = vout;
kp->hashval = UintToArith256(hash);
kp->txtime = txtime;
kp->segid32 = segid32;
kp->nValue = nValue;
kp->scriptPubKey = pk;
return(array);
}
arith_uint256 _komodo_eligible(struct komodo_staking *kp,arith_uint256 ratio,uint32_t blocktime,int32_t iter,int32_t minage,int32_t segid,int32_t nHeight,uint32_t prevtime)
{
int32_t diff; uint64_t coinage; arith_uint256 coinage256,hashval;
diff = (iter + blocktime - kp->txtime - minage);
if ( diff < 0 )
diff = 60;
else if ( diff > 3600*24*30 )
diff = 3600*24*30;
if ( iter > 0 )
diff += segid*2;
coinage = ((uint64_t)kp->nValue/COIN * diff);
if ( nHeight >= 2500 && blocktime+iter+segid*2 > prevtime+180 )
coinage *= ((blocktime+iter+segid*2) - (prevtime+60));
coinage256 = arith_uint256(coinage+1);
hashval = ratio * (kp->hashval / coinage256);
if ( nHeight >= 900 && nHeight < 916 )
hashval = (hashval / coinage256);
return(hashval);
}
uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komodo_staking *kp,int32_t nHeight,uint32_t blocktime,uint32_t prevtime,int32_t minage,uint8_t *hashbuf)
{
int32_t maxiters = 180; uint256 hash;
int32_t segid,iter,diff; uint64_t coinage; arith_uint256 hashval,coinage256;
komodo_stakehash(&hash,kp->address,hashbuf,kp->txid,kp->vout);
kp->hashval = UintToArith256(hash);
segid = ((nHeight + kp->segid32) & 0x3f);
hashval = _komodo_eligible(kp,ratio,blocktime,maxiters,minage,segid,nHeight,prevtime);
//for (int i=32; i>=0; i--)
// fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
//fprintf(stderr," b.%u minage.%d segid.%d ht.%d prev.%u\n",blocktime,minage,segid,nHeight,prevtime);
if ( hashval <= bnTarget )
{
for (iter=0; iter<maxiters; iter++)
{
if ( blocktime+iter+segid*2 < kp->txtime+minage )
continue;
hashval = _komodo_eligible(kp,ratio,blocktime,iter,minage,segid,nHeight,prevtime);
if ( hashval <= bnTarget )
{
//fprintf(stderr,"winner %.8f blocktime.%u iter.%d segid.%d\n",(double)kp->nValue/COIN,blocktime,iter,segid);
blocktime += iter;
blocktime += segid * 2;
return(blocktime);
}
}
}
return(0);
}
int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig)
{
set<CBitcoinAddress> setAddress; int32_t i,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector<COutput> vecOutputs; uint32_t eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 bnTarget; bool fNegative,fOverflow;
static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime;
set<CBitcoinAddress> setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector<COutput> vecOutputs; uint32_t besttime,eligible,eligible2,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock;
bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
ratio = (mindiff / bnTarget);
assert(pwalletMain != NULL);
LOCK2(cs_main, pwalletMain->cs_wallet);
*utxovaluep = 0;
@@ -4601,60 +4689,108 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
memset(utxovoutp,0,sizeof(*utxovoutp));
memset(utxosig,0,72);
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
BOOST_FOREACH(const COutput& out, vecOutputs)
if ( (tipindex= chainActive.Tip()) == 0 )
return(0);
nHeight = tipindex->nHeight + 1;
if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
minage = 6000;
komodo_segids(hashbuf,nHeight-101,100);
if ( *blocktimep > tipindex->nTime+60 )
*blocktimep = tipindex->nTime+60;
//fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight);
if ( time(NULL) > lasttime+600 )
{
if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth )
if ( array != 0 )
{
fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth);
free(array);
array = 0;
maxkp = numkp = 0;
lasttime = 0;
}
BOOST_FOREACH(const COutput& out, vecOutputs)
{
if ( (tipindex= chainActive.Tip()) == 0 || tipindex->nHeight+1 > nHeight )
{
fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter);
return(0);
}
counter++;
if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth )
{
//fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth);
continue;
}
CAmount nValue = out.tx->vout[out.i].nValue;
if ( nValue < COIN || !out.fSpendable )
continue;
const CScript& pk = out.tx->vout[out.i].scriptPubKey;
if ( ExtractDestination(pk,address) != 0 )
{
if ( IsMine(*pwalletMain,address) == 0 )
continue;
if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && (pindex= mapBlockIndex[hashBlock]) != 0 )
{
array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk);
}
}
}
lasttime = (uint32_t)time(NULL);
//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp);
}
for (i=winners=0; i<numkp; i++)
{
if ( (tipindex= chainActive.Tip()) == 0 || tipindex->nHeight+1 > nHeight )
{
fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter);
return(0);
}
kp = &array[i];
if ( (eligible2= komodo_eligible(bnTarget,ratio,kp,nHeight,*blocktimep,(uint32_t)tipindex->nTime+27,minage,hashbuf)) == 0 )
continue;
}
if ( setAddress.size() )
eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address);
//fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible);
if ( eligible > 0 )
{
CTxDestination address;
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
besttime = m = 0;
if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) )
{
fprintf(stderr,"komodo_staked ExtractDestination error\n");
while ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) )
{
besttime = eligible;
eligible--;
if ( eligible < (uint32_t)tipindex->nTime-63 )
break;
m++;
//fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
}
}
else
{
fprintf(stderr,"ht.%d error validating winning blocktime %u -> %.8f eligible.%u test prior\n",nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
continue;
}
if (!setAddress.count(address))
eligible = besttime;
winners++;
//fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible);
if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) )
{
fprintf(stderr,"komodo_staked setAddress.count error\n");
continue;
earliest = eligible;
best_scriptPubKey = kp->scriptPubKey; //out.tx->vout[out.i].scriptPubKey;
*utxovaluep = (uint64_t)kp->nValue;
//decode_hex((uint8_t *)utxotxidp,32,(char *)out.tx->GetHash().GetHex().c_str());
decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str());
*utxovoutp = kp->vout;
*txtimep = kp->txtime;//(uint32_t)out.tx->nLockTime;
fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners);
}
}
CAmount nValue = out.tx->vout[out.i].nValue;
const CScript& pk = out.tx->vout[out.i].scriptPubKey;
//entry.push_back(Pair("generated", out.tx->IsCoinBase()));
CTxDestination address;
if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
{
//entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
//if (pwalletMain->mapAddressBook.count(address))
// entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
}
//BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
CBlockIndex *tipindex;
if ( (tipindex= chainActive.Tip()) != 0 )
{
eligible = komodo_stake(0,bnTarget,(uint32_t)tipindex->nHeight+1,out.tx->GetHash(),out.i,0,(uint32_t)tipindex->nTime,(char *)CBitcoinAddress(address).ToString().c_str());
if ( eligible > 0 )
{
if ( eligible != komodo_stake(1,bnTarget,(uint32_t)tipindex->nHeight+1,out.tx->GetHash(),out.i,eligible,(uint32_t)tipindex->nTime,(char *)CBitcoinAddress(address).ToString().c_str()) )
{
//fprintf(stderr,"tip.%d validation of winning blocktime failed %u -> eligible.%u\n",(uint32_t)tipindex->nHeight,*blocktimep,eligible);
}
else if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || nValue < *utxovaluep)) )
{
earliest = eligible;
best_scriptPubKey = out.tx->vout[out.i].scriptPubKey;
*utxovaluep = (uint64_t)nValue;
decode_hex((uint8_t *)utxotxidp,32,(char *)out.tx->GetHash().GetHex().c_str());
*utxovoutp = out.i;
*txtimep = (uint32_t)out.tx->nLockTime;
//fprintf(stderr,"earliest.%u [%d] (%s) nValue %.8f locktime.%u\n",earliest,(int32_t)(earliest- *blocktimep),CBitcoinAddress(address).ToString().c_str(),(double)nValue/COIN,*txtimep);
}
} //else fprintf(stderr,"utxo not eligible\n");
} //else fprintf(stderr,"no tipindex\n");
} //else fprintf(stderr,"utxo not eligible\n");
} //else fprintf(stderr,"no tipindex\n");
if ( numkp < 10000 && array != 0 )
{
free(array);
array = 0;
maxkp = numkp = 0;
lasttime = 0;
}
if ( earliest != 0 )
{
@@ -4686,7 +4822,8 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
//fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
*blocktimep = earliest;
}
} else fprintf(stderr,"no earliest utxo for staking\n");
} //else fprintf(stderr,"no earliest utxo for staking\n");
//fprintf(stderr,"end scan of utxo for staking t.%u counter.%d numkp.%d winners.%d\n",(uint32_t)time(NULL),counter,numkp,winners);
return(siglen);
}

View File

@@ -1819,7 +1819,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
double dProgressStart = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false);
double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip(), false);
double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip(), false);
while (pindex)
{
if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0)
@@ -2112,7 +2112,7 @@ std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime)
// Don't rebroadcast if newer than nTime:
if (wtx.nTimeReceived > nTime)
continue;
if ( ASSETCHAINS_SYMBOL[0] == 0 )
//if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
if ( wtx.nLockTime >= LOCKTIME_THRESHOLD && wtx.nLockTime < now-KOMODO_MAXMEMPOOLTIME )
{
@@ -2299,20 +2299,20 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
if ( KOMODO_EXCHANGEWALLET == 0 )
{
uint32_t locktime; int32_t txheight; CBlockIndex *tipindex;
if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Tip() != 0 && chainActive.Tip()->nHeight >= 60000 )
if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight >= 60000 )
{
if ( pcoin->vout[i].nValue >= 10*COIN )
{
if ( (tipindex= chainActive.Tip()) != 0 )
if ( (tipindex= chainActive.LastTip()) != 0 )
{
komodo_accrued_interest(&txheight,&locktime,wtxid,i,0,pcoin->vout[i].nValue,(int32_t)tipindex->nHeight);
interest = komodo_interestnew(txheight,pcoin->vout[i].nValue,locktime,tipindex->nTime);
} else interest = 0;
//interest = komodo_interestnew(chainActive.Tip()->nHeight+1,pcoin->vout[i].nValue,pcoin->nLockTime,chainActive.Tip()->nTime);
//interest = komodo_interestnew(chainActive.LastTip()->nHeight+1,pcoin->vout[i].nValue,pcoin->nLockTime,chainActive.LastTip()->nTime);
if ( interest != 0 )
{
//printf("wallet nValueRet %.8f += interest %.8f ht.%d lock.%u/%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,txheight,locktime,pcoin->nLockTime,tipindex->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);
//fprintf(stderr,"wallet nValueRet %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,chainActive.LastTip()->nHeight+1,pcoin->nLockTime,chainActive.LastTip()->nTime);
//ptr = (uint64_t *)&pcoin->vout[i].nValue;
//(*ptr) += interest;
ptr = (uint64_t *)&pcoin->vout[i].interest;
@@ -2687,7 +2687,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
int nextBlockHeight = chainActive.Height() + 1;
CMutableTransaction txNew = CreateNewContextualCMutableTransaction(
Params().GetConsensus(), nextBlockHeight);
txNew.nLockTime = (uint32_t)chainActive.Tip()->nTime + 1; // set to a time close to now
txNew.nLockTime = (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now
// Activates after Overwinter network upgrade
// Set nExpiryHeight to expiryDelta (default 20) blocks past current block height

View File

@@ -995,9 +995,9 @@ public:
bool UpdateNullifierNoteMap();
void UpdateNullifierNoteMapWithTx(const CWalletTx& wtx);
bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb);
void EraseFromWallet(const uint256 &hash);
void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
void EraseFromWallet(const uint256 &hash);
void WitnessNoteCommitment(
std::vector<uint256> commitments,
std::vector<boost::optional<ZCIncrementalWitness>>& witnesses,