Add support for out of order blocks and tolerance for future stamped blocks

In order to speed up block propagation, it is possible for some blocks
to arrive out of order due to propagation delays combined with 2 or
more blocks mined very quickly.

Additionally futurestamping blocks allows a high hash rate miner to
produce blocks that would be valid after a passage of time.

Previously such blocks triggered an extreme response that banned the
peer that broadcast it. Since these are temporary issues, if the block
is still valid when it is within the allowed timestamp window, this
update will process it normally.
This commit is contained in:
jl777
2018-04-25 13:41:27 +03:00
parent dd20bebc5c
commit 63831f76e0
7 changed files with 625 additions and 652 deletions

View File

@@ -659,7 +659,7 @@ int32_t komodo_block2height(CBlock *block)
return(height); return(height);
} }
void komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block)
{ {
int32_t n; int32_t n;
if ( KOMODO_LOADINGBLOCKS == 0 ) if ( KOMODO_LOADINGBLOCKS == 0 )
@@ -675,8 +675,12 @@ void komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block)
//komodo_init(0); //komodo_init(0);
n = block->vtx[0].vout[0].scriptPubKey.size(); n = block->vtx[0].vout[0].scriptPubKey.size();
if ( n == 35 ) if ( n == 35 )
{
memcpy(pubkey33,ptr+1,33); memcpy(pubkey33,ptr+1,33);
return(1);
}
} }
return(0);
} }
int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex)
@@ -909,20 +913,20 @@ int32_t komodo_is_special(uint8_t pubkeys[66][33],int32_t mids[66],uint32_t bloc
} }
/*int32_t komodo_MoM(int32_t *notarized_heightp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip) /*int32_t komodo_MoM(int32_t *notarized_heightp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip)
{ {
int32_t depth,notarized_ht; uint256 MoM,kmdtxid; int32_t depth,notarized_ht; uint256 MoM,kmdtxid;
depth = komodo_MoMdata(&notarized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip); depth = komodo_MoMdata(&notarized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip);
memset(MoMp,0,sizeof(*MoMp)); memset(MoMp,0,sizeof(*MoMp));
memset(kmdtxidp,0,sizeof(*kmdtxidp)); memset(kmdtxidp,0,sizeof(*kmdtxidp));
*notarized_heightp = 0; *notarized_heightp = 0;
if ( depth > 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht ) if ( depth > 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht )
{ {
*MoMp = MoM; *MoMp = MoM;
*notarized_heightp = notarized_ht; *notarized_heightp = notarized_ht;
*kmdtxidp = kmdtxid; *kmdtxidp = kmdtxid;
} }
return(depth); return(depth);
}*/ }*/
int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash) int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
{ {
@@ -1031,3 +1035,313 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_
return(0); return(0);
} }
/*
komodo_checkPOW (fast) is called early in the process and should only refer to data immediately available. it is a filter to prevent bad blocks from going into the local DB. The more blocks we can filter out at this stage, the less junk in the local DB that will just get purged later on.
komodo_checkPOW (slow) is called right before connecting blocks so all prior blocks can be assumed to be there and all checks must pass
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
uint64_t komodo_commission(const CBlock *pblock)
{
int32_t i,j,n=0,txn_count; uint64_t commission,total = 0;
txn_count = pblock->vtx.size();
for (i=0; i<txn_count; i++)
{
n = pblock->vtx[i].vout.size();
for (j=0; j<n; j++)
{
//fprintf(stderr,"(%d %.8f).%d ",i,dstr(block.vtx[i].vout[j].nValue),j);
if ( i != 0 || j != 1 )
total += pblock->vtx[i].vout[j].nValue;
}
}
//fprintf(stderr,"txn.%d n.%d commission total %.8f -> %.8f\n",txn_count,n,dstr(total),dstr((total * ASSETCHAINS_COMMISSION) / COIN));
commission = ((total * ASSETCHAINS_COMMISSION) / COIN);
if ( commission < 10000 )
commission = 0;
return(commission);
}
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)
{
CBlockIndex *pindex; 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; uint64_t value,coinage,supply = ASSETCHAINS_SUPPLY + nHeight*ASSETCHAINS_REWARD/SATOSHIDEN;
txtime = komodo_txtime(&value,txid,vout,address);
if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 )
return(0);
if ( (minage= nHeight*3) > 6000 )
minage = 6000;
if ( blocktime < prevtime+57 )
blocktime = prevtime+57;
if ( blocktime > txtime+minage && (pindex= komodo_chainactive(nHeight>200?nHeight-200: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++)
{
diff = (iter + blocktime - txtime - minage);
if ( diff > 3600*24 )
break;
coinage = (value * diff) * ((diff >> 16) + 1);
hashval = arith_uint256(supply * 64) * (UintToArith256(hash) / arith_uint256(coinage+1));
if ( hashval <= bnTarget )
{
winner = 1;
if ( validateflag == 0 )
{
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;
}
}
//fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
if ( 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);
}
}
if ( nHeight < 2 )
return(blocktime);
return(blocktime * winner);
}
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;
*percPoSp = percPoS = 0;
if ( height < 3 )
return(target);
sum = arith_uint256(0);
ave = sum;
for (i=n=0; i<100; i++)
{
ht = height - 100 + i;
if ( (pindex= komodo_chainactive(ht)) != 0 )
{
bnTarget.SetCompact(pindex->nBits,&fNegative,&fOverflow);
bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT));
hashval = UintToArith256(pindex->GetBlockHash());
if ( hashval <= bnTarget ) // PoW is never as easy as PoS/64, some PoS will be counted as PoW
{
fprintf(stderr,"1");
sum += hashval;
n++;
}
else
{
percPoS++;
fprintf(stderr,"0");
}
if ( (i % 10) == 9 )
fprintf(stderr," %d, ",percPoS);
}
}
fprintf(stderr," -> %d%% percPoS ht.%d\n",percPoS,height);
*percPoSp = percPoS;
target = (target / arith_uint256(KOMODO_POWMINMULT));
if ( n > 0 )
{
ave = (sum / arith_uint256(n));
if ( ave > target )
ave = target;
} else return(target);
if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget
{
bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256((goalperc) * (goalperc));
/*if ( height > 1165 )
{
if ( height > 1180 )
{
if ( height > 1230 )
bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256((goalperc) * (goalperc));
else bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc);
}
else bnTarget = (ave * arith_uint256(goalperc * goalperc)) / arith_uint256(2 * (percPoS + goalperc) * (percPoS + goalperc));
} else bnTarget = (ave * arith_uint256(goalperc)) / arith_uint256(percPoS + goalperc);*/
if ( 1 )
{
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&ave)[i]);
fprintf(stderr," increase diff -> ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," floor diff ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&target)[i]);
fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
}
}
else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget
{
bnTarget = ((ave * arith_uint256(goalperc)) + (target * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc);
if ( 1 )
{
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&ave)[i]);
fprintf(stderr," decrease diff -> ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," floor diff ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&target)[i]);
fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
}
}
else bnTarget = ave; // recent ave is perfect
return(bnTarget);
}
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;
txn_count = pblock->vtx.size();
if ( txn_count > 1 )
{
if ( prevtime == 0 )
{
if ( (previndex= mapBlockIndex[pblock->hashPrevBlock]) != 0 )
prevtime = (uint32_t)previndex->nTime;
}
txid = pblock->vtx[txn_count-1].vin[0].prevout.hash;
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 ( 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));
} else isPoS = 1;
}
else if ( slowflag == 0 ) // maybe previous block is not seen yet, do the best approx
{
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);
}
return(isPoS);
}
int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
{
uint256 hash; arith_uint256 bnTarget,bhash; bool fNegative,fOverflow; uint8_t *script,pubkey33[33],pubkeys[64][33]; int32_t i,possible,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev;
if ( !CheckEquihashSolution(pblock, Params()) )
{
fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height);
return(-1);
}
hash = pblock->GetHash();
bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow);
bhash = UintToArith256(hash);
possible = komodo_block2pubkey33(pubkey33,pblock);
//fprintf(stderr,"height.%d slowflag.%d possible.%d cmp.%d\n",height,slowflag,possible,bhash > bnTarget);
if ( height == 0 )
{
if ( slowflag != 0 )
return(0);
if ( (pprev= mapBlockIndex[pblock->hashPrevBlock]) != 0 )
height = pprev->nHeight + 1;
if ( height == 0 )
return(0);
}
if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget )
{
failed = 1;
if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case
{
if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 )
{
for (i=0; i<n; i++)
if ( memcmp(pubkey33,pubkeys[i],33) == 0 )
{
notaryid = i;
break;
}
}
}
else if ( possible == 0 || ASSETCHAINS_SYMBOL[0] != 0 )
{
fprintf(stderr,"pow violation and no chance it is notary ht.%d %s\n",height,hash.ToString().c_str());
return(-1);
}
}
else 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!
return(-1);
else
{
if ( slowflag != 0 )
bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
else bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT)); // lower bound
if ( bhash > bnTarget )
{
for (i=31; i>=16; i--)
fprintf(stderr,"%02x",((uint8_t *)&bhash)[i]);
fprintf(stderr," > ");
for (i=31; i>=16; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," ht.%d PoW diff violation PoSperc.%d vs goalperc.%d\n",height,PoSperc,(int32_t)ASSETCHAINS_STAKED);
return(-1);
}
}
} else if ( is_PoSblock < 0 )
return(-1);
}
if ( failed == 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 )
{
checktoshis = komodo_commission(pblock);
if ( checktoshis > 10000 && pblock->vtx[0].vout.size() != 2 )
return(-1);
else if ( checktoshis != 0 )
{
script = (uint8_t *)pblock->vtx[0].vout[1].scriptPubKey.data();
if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 )
return(-1);
if ( pblock->vtx[0].vout[1].nValue != checktoshis )
{
fprintf(stderr,"checktoshis %.8f vs actual vout[1] %.8f\n",dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue));
return(-1);
}
}
}
//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed);
if ( failed != 0 && possible == 0 && notaryid < 0 )
return(-1);
else return(0);
}

View File

@@ -405,11 +405,11 @@ static int _paxorder(const void *a,const void *b)
uint64_t aval,bval; uint64_t aval,bval;
aval = pax_a->fiatoshis + pax_a->komodoshis + pax_a->height; aval = pax_a->fiatoshis + pax_a->komodoshis + pax_a->height;
bval = pax_b->fiatoshis + pax_b->komodoshis + pax_b->height; bval = pax_b->fiatoshis + pax_b->komodoshis + pax_b->height;
if ( bval > aval ) if ( bval > aval )
return(-1); return(-1);
else if ( bval < aval ) else if ( bval < aval )
return(1); return(1);
return(0); return(0);
#undef pax_a #undef pax_a
#undef pax_b #undef pax_b
} }
@@ -526,11 +526,11 @@ int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t to
continue; continue;
} }
/*printf("pax.%s marked.%d %.8f -> %.8f ready.%d validated.%d\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0); /*printf("pax.%s marked.%d %.8f -> %.8f ready.%d validated.%d\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0);
if ( pax->marked != 0 || (pax->type != 'D' && pax->type != 'A') || pax->ready == 0 ) if ( pax->marked != 0 || (pax->type != 'D' && pax->type != 'A') || pax->ready == 0 )
{ {
printf("reject 2\n"); printf("reject 2\n");
continue; continue;
}*/ }*/
if ( ASSETCHAINS_SYMBOL[0] != 0 && (strcmp(pax->symbol,symbol) != 0 || pax->validated == 0 || pax->ready == 0) ) if ( ASSETCHAINS_SYMBOL[0] != 0 && (strcmp(pax->symbol,symbol) != 0 || pax->validated == 0 || pax->ready == 0) )
{ {
if ( strcmp(pax->symbol,ASSETCHAINS_SYMBOL) == 0 ) if ( strcmp(pax->symbol,ASSETCHAINS_SYMBOL) == 0 )
@@ -551,7 +551,7 @@ int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t to
} }
} else continue; } else continue;
} }
//printf("redeem.%d? (%c) %p pax.%s marked.%d %.8f -> %.8f ready.%d validated.%d approved.%d\n",tokomodo,pax->type,pax,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0,pax->approved!=0); //printf("redeem.%d? (%c) %p pax.%s marked.%d %.8f -> %.8f ready.%d validated.%d approved.%d\n",tokomodo,pax->type,pax,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0,pax->approved!=0);
if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
printf("pax.%s marked.%d %.8f -> %.8f\n",ASSETCHAINS_SYMBOL,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); printf("pax.%s marked.%d %.8f -> %.8f\n",ASSETCHAINS_SYMBOL,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis));
@@ -650,153 +650,6 @@ int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max)
void komodo_passport_iteration(); void komodo_passport_iteration();
uint64_t komodo_commission(const CBlock &block)
{
int32_t i,j,n=0,txn_count; uint64_t total = 0;
txn_count = block.vtx.size();
for (i=0; i<txn_count; i++)
{
n = block.vtx[i].vout.size();
for (j=0; j<n; j++)
{
//fprintf(stderr,"(%d %.8f).%d ",i,dstr(block.vtx[i].vout[j].nValue),j);
if ( i != 0 || j != 1 )
{
total += block.vtx[i].vout[j].nValue;
}
}
}
//fprintf(stderr,"txn.%d n.%d commission total %.8f -> %.8f\n",txn_count,n,dstr(total),dstr((total * ASSETCHAINS_COMMISSION) / COIN));
return((total * ASSETCHAINS_COMMISSION) / COIN);
}
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)
{
CBlockIndex *pindex; 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; uint64_t value,coinage,supply = ASSETCHAINS_SUPPLY + nHeight*ASSETCHAINS_REWARD/SATOSHIDEN;
txtime = komodo_txtime(&value,txid,vout,address);
if ( value == 0 || txtime == 0 )
return(0);
if ( (minage= nHeight*3) > 6000 )
minage = 6000;
if ( blocktime > txtime+minage && (pindex= komodo_chainactive(nHeight>200?nHeight-200: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++)
{
diff = (iter + blocktime - txtime - minage);
if ( diff > 3600*24 )
break;
coinage = (value * diff) * ((diff >> 16) + 1);
hashval = arith_uint256(supply * 64) * (UintToArith256(hash) / arith_uint256(coinage+1));
if ( hashval <= bnTarget )
{
winner = 1;
if ( validateflag == 0 )
{
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;
}
}
//fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
if ( 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);
}
}
if ( nHeight < 2 )
return(blocktime);
return(blocktime * winner);
}
#define KOMODO_POWMINMULT 16
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;
*percPoSp = percPoS = 0;
sum = arith_uint256(0);
ave = sum;
for (i=n=0; i<100; i++)
{
ht = height - 100 + i;
if ( (pindex= komodo_chainactive(ht)) != 0 )
{
bnTarget.SetCompact(pindex->nBits,&fNegative,&fOverflow);
bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT));
hashval = UintToArith256(pindex->GetBlockHash());
if ( hashval <= bnTarget ) // PoW is never as easy as PoS/64, some PoS will be counted as PoW
{
sum += hashval;
n++;
} else percPoS++;
}
}
*percPoSp = percPoS;
target = (target / arith_uint256(KOMODO_POWMINMULT));
if ( n > 0 )
{
ave = (sum / arith_uint256(n));
if ( ave > target )
ave = target;
} else return(target);
if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget
{
bnTarget = (ave * arith_uint256(goalperc)) / arith_uint256(percPoS + goalperc);
if ( 1 )
{
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&ave)[i]);
fprintf(stderr," increase diff -> ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," floor diff ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&target)[i]);
fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
}
}
else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget
{
bnTarget = ((ave * arith_uint256(goalperc)) + (target * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc);
if ( 1 )
{
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&ave)[i]);
fprintf(stderr," decrease diff -> ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," floor diff ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&target)[i]);
fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
}
}
else bnTarget = ave; // recent ave is perfect
return(bnTarget);
}
int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime) // verify above block is valid pax pricing int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime) // verify above block is valid pax pricing
{ {
static uint256 array[64]; static int32_t numbanned,indallvouts; static uint256 array[64]; static int32_t numbanned,indallvouts;
@@ -854,7 +707,7 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim
{ {
if ( overflow != 0 || total > COIN/10 ) if ( overflow != 0 || total > COIN/10 )
{ {
//fprintf(stderr,">>>>>>>> <<<<<<<<<< ht.%d illegal nonz output %.8f n.%d\n",height,dstr(block.vtx[0].vout[1].nValue),n); fprintf(stderr,">>>>>>>> <<<<<<<<<< ht.%d illegal nonz output %.8f n.%d\n",height,dstr(block.vtx[0].vout[1].nValue),n);
if ( height >= activation ) if ( height >= activation )
return(-1); return(-1);
} }
@@ -867,377 +720,16 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim
} }
else else
{ {
if ( ASSETCHAINS_STAKED != 0 && height >= 2 )
{
arith_uint256 bnTarget,hashval; int32_t PoSperc; bool fNegative,fOverflow; CBlockIndex *previndex; uint32_t eligible,isPoS = 0;
bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
if ( txn_count > 1 )
{
if ( prevtime == 0 )
{
if ( (previndex= mapBlockIndex[block.hashPrevBlock]) != 0 )
prevtime = (uint32_t)previndex->nTime;
}
eligible = komodo_stake(1,bnTarget,height,block.vtx[txn_count-1].vin[0].prevout.hash,block.vtx[txn_count-1].vin[0].prevout.n,block.nTime,prevtime,(char *)"");
if ( eligible == 0 || eligible > block.nTime )
{
fprintf(stderr,"PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)block.nTime,(int32_t)(eligible - block.nTime));
} else isPoS = 1;
}
if ( isPoS == 0 && height > 100 )
{
if ( ASSETCHAINS_STAKED == 100 )
{
fprintf(stderr,"ht.%d 100%% PoS after height 100 rule violated for -ac_staking=100\n",height);
return(-1);
}
// check PoW
bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
hashval = UintToArith256(block.GetHash());
if ( hashval > bnTarget )
{
/*for (i=31; i>=0; i--)
fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
fprintf(stderr," > ");
for (i=31; i>=0; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," ht.%d PoW diff violation PoSperc.%d vs goalperc.%d\n",height,PoSperc,(int32_t)ASSETCHAINS_STAKED);*/
return(-1);
}
}
}
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && block.vtx[0].vout.size() > 1 )
{
script = (uint8_t *)block.vtx[0].vout[1].scriptPubKey.data();
if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 )
return(-1);
if ( (checktoshis = komodo_commission(block)) != 0 )
{
if ( block.vtx[0].vout[1].nValue != checktoshis )
{
fprintf(stderr,"checktoshis %.8f vs actual vout[1] %.8f\n",dstr(checktoshis),dstr(block.vtx[0].vout[1].nValue));
return(-1);
} else return(0);
}
}
if ( overflow != 0 || total > 0 ) if ( overflow != 0 || total > 0 )
return(-1); return(-1);
} }
return(0); return(0);
} }
/*
//fprintf(stderr,"ht.%d n.%d nValue %.8f (%d %d %d)\n",height,n,dstr(block.vtx[0].vout[1].nValue),KOMODO_PAX,komodo_isrealtime(&ht),KOMODO_PASSPORT_INITDONE);
offset += komodo_scriptitemlen(&opretlen,&script[offset]);
//printf("offset.%d opretlen.%d [%02x %02x %02x %02x]\n",offset,opretlen,script[0],script[1],script[2],script[3]);
if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
opcode = 'X';
if ( height >= 235300 )
return(-1);
strcpy(symbol,(char *)"KMD");
if ( komodo_isrealtime(&ht) == 0 || KOMODO_PASSPORT_INITDONE == 0 ) // init time already in DB
return(0);
}
else
{
strcpy(symbol,ASSETCHAINS_SYMBOL);
opcode = 'I';
if ( (baseid= komodo_baseid(symbol)) < 0 )
{
if ( block.vtx[0].vout.size() != 1 )
{
printf("%s has more than one coinbase?\n",symbol);
return(-1);
}
return(0);
}
while ( KOMODO_PASSPORT_INITDONE == 0 )
komodo_passport_iteration();
komodo_passport_iteration();
// grandfathering preexisting
if ( height < 777 )
return(0);
if ( baseid == USD ) // 6820 in balance calcs
{
if ( height <= 6821 || height <= 2000 || height == 2968 || height == 2960 || height == 2649 || height == 3275 || height == 3282 || height == 3328 || height == 3468 )
return(0);
}
else if ( baseid == EUR )
{
if ( height < 1200 || height == 1408 || height == 1111 || height == 1094 || height == 1092 || height == 1080 || height == 1053 || height == 1005 || height == 822 || height == 821 || height == 810 || height == 797 || height == 790 || height == 787 || height == 785 || height == 1313 || height == 1288 || height == 1263 || height == 1262 || height <= 211 || height == 210 || height == 188 || height == 185 || height == 182 || height == 181 || height == 171 || height == 170 || height == 169 || height == 168 || height == 167 || height == 166 || height == 165 || height == 164 || height == 163 || height == 162 )
return(0);
}
else if ( baseid == JPY )
{
if ( height == 1038 || height == 1039 || height == 1040 || height == 1041 || height == 1014 || height == 998 || height == 973 || height == 139 || height == 971 || height == 141 || height == 816 || height == 814 || height == 803 || height == 142 || height == 782 || height == 145 || height == 181 || height == 186 || height == 192 || height == 190 || height == 189 || height == 255 || height == 218 || height == 233 || height == 259 || height == 278 || height == 361 || height == 367 || height == 733 || height == 688 || height == 468 )
return(0);
}
else if ( baseid == GBP )
{
if ( height == 1025 || height == 1026 || height == 1027 || height == 1028 || height == 997 || height == 970 || height == 953 || height == 951 || height == 803 || height == 800 || height == 786 || height == 123 || height == 771 || height == 137 || height == 139 || height == 140 || height == 146 || height == 194 || height == 200 || height == 202 || height == 203 || height == 205 || height == 210 || height == 216 || height == 271 || height == 233 || height == 294 )
return(0);
}
else if ( baseid == AUD )
{
if ( height == 1012 || height == 1013 || height == 1014 || height == 985 || height == 958 || height == 936 || height == 933 || height == 790 || height == 788 || height == 778 || height == 124 || height == 777 || height == 122 || height == 140 || height == 142 || height == 143 || height == 186 || height == 196 || height == 198 || height == 201 || height == 210 || height == 192 )
return(0);
}
else if ( baseid == CAD )
{
if ( height < 1000 || height == 836 || height == 781 || height == 779 || height == 798 || height == 794 || height == 1181 || height == 1179 || height == 1159 || height == 1134 || height == 1132 || height == 121 || height == 970 || height == 119 || height == 299 || height == 302 || height == 303 || height == 306 || height == 308 || height == 355 || height == 362 || height == 367 || height == 363 || height == 364 || height == 380 || height == 373 || height == 390 || height == 437 || height == 777 )
return(0);
}
else if ( baseid == CHF )
{
if ( height == 987 || height == 988 || height == 989 || height == 960 || height == 931 || height == 914 || height == 122 || height == 912 || height == 141 || height == 780 || height == 145 || height == 777 || height == 151 || height == 775 || height == 765 || height == 195 || height == 764 || height == 737 || height == 194 || height == 193 || height == 198 || height == 207 || height == 216 || height == 227 || height == 256 || height == 260 || height == 276 || height == 289 || height == 292 || height == 349 )
return(0);
}
else if ( baseid == NZD )
{
if ( height < 1000 || height == 787 || height == 786 || height == 784 || height == 785 || height == 777 || height == 1113 || height == 1083 || height == 1067 || height == 265 || height == 1064 || height == 920 || height == 913 || height == 124 || height == 911 || height == 903 || height == 900 || height == 879 || height == 122 || height == 266 || height == 269 || height == 270 || height == 278 || height == 307 || height == 318 || height == 322 || height == 335 || height == 395 || height == 406 || height == 314 )
return(0);
}
else if ( baseid == CNY )
{
if ( height == 987 || height == 988 || height == 989 || height == 982 || height == 957 || height == 931 || height == 119 || height == 929 || height == 134 || height == 782 || height == 137 || height == 775 || height == 143 || height == 772 || height == 186 || height == 763 || height == 761 || height == 734 || height == 183 || height == 190 || height == 192 || height == 211 || height == 203 || height == 226 || height == 263 || height == 264 || height == 277 || height == 342 || height == 613 || height == 525 )
return(0);
}
else if ( baseid == RUB )
{
if ( height == 819 || height == 812 || height == 810 || height == 802 || height == 801 || height == 1074 || height == 1040 || height == 1014 || height == 163 || height == 1013 || height == 877 || height == 867 || height == 863 || height == 834 || height == 158 || height == 126 || height == 106 || height == 105 || height == 174 || height == 175 || height == 176 || height == 177 || height == 181 || height == 183 || height == 184 || height == 187 )
return(0);
}
else if ( baseid == MXN )
{
if ( height == 1079 || height == 1080 || height == 1081 || height == 1069 || height == 1048 || height == 1028 || height == 121 || height == 1027 || height == 146 || height == 894 || height == 891 || height == 148 || height == 882 || height == 879 || height == 151 || height == 856 || height == 158 || height == 822 || height == 197 || height == 203 || height == 207 || height == 209 || height == 213 || height == 217 || height == 218 || height == 226 || height == 283 || height == 302 || height == 319 || height == 318 || height == 569 )
return(0);
}
else if ( baseid == BRL )
{
if ( height == 1003 || height == 1004 || height == 1005 || height == 972 || height == 943 || height == 922 || height == 118 || height == 920 || height == 145 || height == 787 || height == 783 || height == 147 || height == 781 || height == 774 || height == 148 || height == 771 || height == 154 || height == 751 || height == 156 || height == 188 || height == 193 || height == 195 || height == 199 || height == 203 || height == 225 || height == 230 || height == 262 || height == 266 || height == 284 || height == 300 || height == 640 )
return(0);
}
else if ( baseid == INR )
{
if ( height == 998 || height == 999 || height == 1000 || height == 788 || height == 786 || height == 775 || height == 753 || height == 125 || height == 153 || height == 155 || height == 159 || height == 204 || height == 206 || height == 211 || height == 217 || height == 220 || height == 229 || height == 265 || height == 292 || height == 300 )
return(0);
}
else if ( baseid == PLN )
{
if ( height == 1029 || height == 1030 || height == 1031 || height == 1009 || height == 984 || height == 960 || height == 959 || height == 798 || height == 794 || height == 792 || height == 782 || height == 775 || height == 755 || height == 122 || height == 120 || height == 158 || height == 160 || height == 163 || height == 225 || height == 217 || height == 219 || height == 229 || height == 234 || height == 286 || height == 231 || height == 292 )
return(0);
}
else if ( baseid == HKD )
{
if ( height == 1013 || height == 1014 || height == 1015 || height == 1002 || height == 979 || height == 947 || height == 123 || height == 946 || height == 153 || height == 811 || height == 808 || height == 806 || height == 155 || height == 795 || height == 157 || height == 773 || height == 205 || height == 208 || height == 210 || height == 211 || height == 215 || height == 221 || height == 231 || height == 255 || height == 273 || height == 293 || height == 310 || height == 654 )
return(0);
}
else if ( baseid == TRY )
{
if ( height == 1022 || height == 1023 || height == 1051 || height == 991 || height == 974 || height == 949 || height == 141 || height == 948 || height == 783 || height == 153 || height == 781 || height == 779 || height == 776 || height == 768 || height == 765 || height == 121 || height == 142 || height == 144 || height == 143 || height == 149 || height == 204 || height == 210 || height == 216 || height == 229 || height == 280 || height == 145 )
return(0);
}
else if ( baseid == NOK )
{
if ( height == 987 || height == 988 || height == 989 || height == 962 || height == 911 || height == 907 || height == 125 || height == 765 || height == 150 || height == 762 || height == 760 || height == 753 || height == 152 || height == 751 || height == 151 || height == 154 || height == 160 || height == 195 || height == 203 || height == 207 || height == 211 || height == 220 || height == 236 || height == 253 || height == 278 || height == 283 )
return(0);
}
else if ( baseid == ZAR )
{
if ( height == 979 || height == 980 || height == 981 || height == 956 || height == 937 || height == 906 || height == 905 || height == 122 || height == 756 || height == 754 || height == 752 || height == 749 || height == 742 || height == 739 || height == 120 || height == 151 || height == 153 || height == 157 || height == 159 || height == 206 || height == 213 || height == 216 || height == 222 || height == 277 || height == 287 || height == 215 )
return(0);
}
else if ( baseid == SEK )
{
if ( height == 960 || height == 961 || height == 962 || height == 943 || height == 925 || height == 896 || height == 147 || height == 894 || height == 759 || height == 751 || height == 749 || height == 742 || height == 740 || height == 716 || height == 123 || height == 148 || height == 150 || height == 151 || height == 157 || height == 199 || height == 200 || height == 201 || height == 206 || height == 256 || height == 257 || height == 268 )
return(0);
}
else if ( baseid == CZK )
{
if ( height < 1000 || height == 1084 || height == 1085 || height == 1086 || height == 778 || height == 1079 || height == 1054 || height == 1032 || height == 121 || height == 1030 || height == 182 || height == 876 || height == 873 || height == 871 || height == 184 || height == 862 || height == 185 || height == 861 || height == 186 || height == 838 || height == 238 || height == 242 || height == 246 || height == 248 || height == 250 || height == 251 || height == 256 || height == 282 || height == 322 || height == 343 || height == 433 || height == 323 || height == 276 )
return(0);
}
else if ( baseid == HUF )
{
if ( height < 2200 || height == 1531 || height == 1528 || height == 1530 || height == 1451 || height == 1448 || height == 1442 || height == 1418 || height == 1407 || height == 1406 || height == 1392 || height == 1391 || height == 1387 || height == 1383 || height == 1335 || height == 1337 || height == 1338 || height == 1649 || height == 2378 || height == 2376 || height == 2371 || height == 1330 || height == 2326 || height == 1344 || height == 2305 || height == 2304 || height == 2171 || height == 2168 || height == 2166 || height == 2156 || height == 2135 || height == 1343 || height == 1342 || height == 1341 || height == 1340 || height == 1339 || height == 1336 || height == 1334 || height == 1333 || height == 1346 || height == 1400 || height == 1525 || height == 1509 )
return(0);
}
else if ( baseid == DKK )
{
if ( height == 1241 || height == 945 || height == 898 || height == 894 || height == 892 || height == 866 || height == 857 || height == 853 || height == 834 || height == 812 || height == 792 || height == 784 || height == 778 || height == 783 || height == 1214 || height == 1186 || height == 1158 || height == 126 || height == 1156 || height == 329 || height == 1021 || height == 1016 || height == 1014 || height == 333 || height == 1003 || height == 1002 || height == 978 || height == 332 || height == 337 || height == 381 || height == 390 || height == 386 || height == 401 || height == 389 || height == 396 || height == 428 || height == 473 || height == 490 || height == 493 )
return(0);
}
else if ( baseid == ILS )
{
if ( height == 1017 || height == 1018 || height == 1019 || height == 1010 || height == 985 || height == 954 || height == 120 || height == 952 || height == 143 || height == 819 || height == 817 || height == 808 || height == 145 || height == 786 || height == 155 || height == 753 || height == 151 || height == 149 || height == 199 || height == 193 || height == 201 || height == 209 || height == 284 || height == 305 || height == 676 || height == 702 || height == 406 )
return(0);
}
else if ( baseid == MYR )
{
if ( height == 1020 || height == 1021 || height == 1022 || height == 1015 || height == 984 || height == 950 || height == 949 || height == 823 || height == 820 || height == 818 || height == 812 || height == 809 || height == 126 || height == 789 || height == 144 || height == 746 || height == 146 || height == 147 || height == 148 || height == 150 || height == 205 || height == 210 || height == 215 || height == 219 || height == 222 || height == 290 || height == 242 || height == 312 )
return(0);
}
else if ( baseid == PHP )
{
if ( height == 859 || height == 817 || height == 812 || height == 811 || height == 792 || height == 779 || height == 778 || height == 781 || height == 1154 || height == 1114 || height == 1077 || height == 1076 || height == 931 || height == 927 || height == 925 || height == 918 || height == 891 || height == 127 || height == 125 || height == 272 || height == 275 || height == 276 || height == 278 || height == 328 || height == 330 || height == 335 || height == 344 || height == 315 )
return(0);
}
else if ( baseid == KRW )
{
if ( height == 1021 || height == 1022 || height == 1023 || height == 1010 || height == 950 || height == 916 || height == 138 || height == 914 || height == 140 || height == 785 || height == 782 || height == 781 || height == 142 || height == 775 || height == 148 || height == 772 || height == 751 || height == 147 || height == 146 || height == 159 || height == 175 || height == 181 || height == 184 || height == 186 || height == 188 || height == 196 || height == 209 || height == 238 )
return(0);
}
else if ( baseid == RON )
{
if ( height == 1008 || height == 1009 || height == 1010 || height == 1003 || height == 973 || height == 940 || height == 939 || height == 806 || height == 802 || height == 800 || height == 793 || height == 789 || height == 768 || height == 123 || height == 141 || height == 143 || height == 144 || height == 150 || height == 197 || height == 200 || height == 202 || height == 217 || height == 240 || height == 276 )
return(0);
}
else if ( baseid == SGD )
{
if ( height == 1016 || height == 1017 || height == 1018 || height == 1010 || height == 984 || height == 951 || height == 950 || height == 801 || height == 798 || height == 792 || height == 788 || height == 122 || height == 769 || height == 120 || height == 158 || height == 160 || height == 164 || height == 169 || height == 229 || height == 234 || height == 246 || height == 297 || height == 299 || height == 316 || height == 233 )
return(0);
}
else if ( baseid == THB )
{
if ( height == 977 || height == 978 || height == 968 || height == 933 || height == 898 || height == 897 || height == 788 || height == 786 || height == 779 || height == 777 || height == 757 || height == 119 || height == 140 || height == 142 || height == 146 || height == 152 || height == 196 || height == 200 || height == 214 || height == 260 || height == 263 )
return(0);
}
else if ( baseid == BGN )
{
if ( height == 1044 || height == 1045 || height == 1046 || height == 1030 || height == 995 || height == 960 || height == 959 || height == 830 || height == 822 || height == 819 || height == 810 || height == 809 || height == 781 || height == 124 || height == 122 || height == 189 || height == 193 || height == 200 || height == 194 || height == 250 || height == 256 || height == 260 || height == 280 )
return(0);
}
else if ( baseid == HRK )
{
if ( height == 1027 || height == 1028 || height == 1029 || height == 1022 || height == 999 || height == 969 || height == 967 || height == 832 || height == 829 || height == 827 || height == 817 || height == 792 || height == 754 || height == 125 || height == 123 || height == 184 || height == 186 || height == 187 || height == 227 || height == 230 || height == 235 || height == 240 || height == 242 || height == 261 || height == 336 )
return(0);
}
else if ( baseid == IDR )
{
if ( height == 836 || height == 1036 || height == 837 || height == 720 || height == 715 || height == 714 || height == 696 || height == 695 || height == 694 || height == 693 || height == 119 || height == 689 || height == 120 || height == 669 || height == 123 || height == 662 || height == 122 || height == 634 || height == 121 || height == 609 || height == 124 || height == 174 || height == 603 || height == 595 || height == 166 || height == 176 || height == 589 || height == 172 || height == 587 || height == 179 || height == 239 || height == 175 || height == 245 || height == 260 )
return(0);
}
}
if ( script[offset] == opcode && opretlen < block.vtx[0].vout[n-1].scriptPubKey.size() )
{
if ( (num= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,&script[offset],opretlen,opcode == 'X')) > 0 )
{
for (i=1; i<n-1; i++)
{
if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && (sp= komodo_stateptrget(ASSETCHAINS_SYMBOL)) != 0 && strcmp(CURRENCIES[baseids[i-1]],ASSETCHAINS_SYMBOL) == 0 )
{
int32_t rtflag = 0;
while ( (sp->RTmask & (1LL << 32)) == 0 )
{
if ( rtflag == 0 )
printf("[%s] skip checkdeposit.%s not RT %llx\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseids[i-1]],(long long)sp->RTmask);
sleep(60);
rtflag = 1;
//matched++;
//continue;
}
if ( rtflag != 0 )
printf("[%s] %s reached RT\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseids[i-1]]);
}
if ( (pax= komodo_paxfinds(txids[i-1],vouts[i-1])) != 0 ) // finds... make sure right one
{
pax->type = opcode;
if ( opcode == 'I' && (pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis) )
{
printf("checkdeposit.[%s.%d]: skip %s %.8f when avail %.8f deposited %.8f, issued %.8f withdrawn %.8f approved %.8f redeemed %.8f\n",ASSETCHAINS_SYMBOL,height,symbol,dstr(pax->fiatoshis),dstr(available),dstr(deposited),dstr(issued),dstr(withdrawn),dstr(approved),dstr(redeemed));
return(-1);
}
if ( pax->fiatoshis == block.vtx[0].vout[i].nValue )
{
matched++;
if ( pax->marked != 0 && height >= 80820 )
{
printf(">>>>>>>>>>> %c errs.%d i.%d match %.8f vs %.8f paxmarked.%d kht.%d ht.%d [%s].%d\n",opcode,errs,i,dstr(opcode == 'I' ? pax->fiatoshis : pax->komodoshis),dstr(block.vtx[0].vout[i].nValue),pax->marked,pax->height,pax->otherheight,ASSETCHAINS_SYMBOL,height);
}
else
{
}
if ( strcmp(ASSETCHAINS_SYMBOL,CURRENCIES[baseids[i-1]]) == 0 )
{
//check deposit validates AUD.1047 [3] 0.14585530 -> 0.01000000 (0.14585530 0.01000000 0.01000000)
char destaddr[64],coinaddr[64]; uint8_t pubkey33[33];
checktoshis = PAX_fiatdest(&seed,0,destaddr,pubkey33,coinaddr,pax->height,CURRENCIES[baseids[i-1]],pax->fiatoshis);
//checktoshis = komodo_paxprice(&seed,pax->height,CURRENCIES[baseids[i-1]],(char *)"KMD",(uint64_t)pax->komodoshis);
if ( komodo_paxcmp(CURRENCIES[baseids[i-1]],pax->height,pax->komodoshis,checktoshis,seed) < 0 )
{
printf("paxcmp FAIL when check deposit validates %s.%d [%d] %.8f -> %.8f (%.8f %.8f %.8f)\n",CURRENCIES[baseids[i-1]],height,i,dstr(srcvalues[i-1]),dstr(values[i-1]),dstr(pax->komodoshis),dstr(pax->fiatoshis),dstr(block.vtx[0].vout[i].nValue));
return(-1);
} //else printf("check deposit validates %s.%d [%d] %.8f -> %.8f (%.8f %.8f %.8f)\n",CURRENCIES[baseids[i-1]],height,i,dstr(srcvalues[i-1]),dstr(values[i-1]),dstr(pax->komodoshis),dstr(pax->fiatoshis),dstr(block.vtx[0].vout[i].nValue));
}
}
else if ( strcmp(ASSETCHAINS_SYMBOL,CURRENCIES[baseids[i-1]]) == 0 )
{
for (j=0; j<32; j++)
printf("%02x",((uint8_t *)&txids[i-1])[j]);
printf(" cant paxfind %c txid [%d]\n",opcode,height);
printf(">>>>>>>>>>> %c errs.%d i.%d match %.8f vs %.8f pax.%p [%s] ht.%d\n",opcode,errs,i,dstr(opcode == 'I' ? pax->fiatoshis : pax->komodoshis),dstr(block.vtx[0].vout[i].nValue),pax,ASSETCHAINS_SYMBOL,height);
return(-1);
}
}
else //if ( kmdheights[i-1] > 0 && otherheights[i-1] > 0 )
{
hash = block.GetHash();
for (j=0; j<n; j++)
printf("%.8f ",dstr(block.vtx[0].vout[j].nValue));
printf("vout values\n");
for (j=0; j<32; j++)
printf("%02x",((uint8_t *)&txids[i-1])[j]);
printf(" kht.%d ht.%d %.8f %.8f couldnt find vout.[%d of %d] ht.%d %s for [%s]\n",kmdheights[i-1],otherheights[i-1],dstr(values[i-1]),dstr(srcvalues[i]),i,n,height,ASSETCHAINS_SYMBOL,CURRENCIES[baseids[i-1]]);
if ( ASSETCHAINS_SYMBOL[0] != 0 || height >= activation )
return(-1);
}
}
if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
//if ( height > 0 && (height < chainActive.Tip()->nHeight || (height >= chainActive.Tip()->nHeight && komodo_isrealtime(&ht) != 0)) && matched != num )
//{
// printf("WOULD REJECT %s: ht.%d (%c) matched.%d vs num.%d tip.%d isRT.%d\n",symbol,height,opcode,matched,num,(int32_t)chainActive.Tip()->nHeight,komodo_isrealtime(&ht));
// can easily happen depending on order of loading
//if ( height > 200000 )
//{
// printf("REJECT: ht.%d (%c) matched.%d vs num.%d\n",height,opcode,matched,num);
// return(-1);
//}
//} // disabled 'X' path
}
else
{
if ( height > 0 && (height < chainActive.Tip()->nHeight || (height >= chainActive.Tip()->nHeight && komodo_isrealtime(&ht) != 0)) && matched != num )
{
printf("REJECT %s: ht.%d (%c) matched.%d vs num.%d tip.%d isRT.%d\n",symbol,height,opcode,matched,num,(int32_t)chainActive.Tip()->nHeight,komodo_isrealtime(&ht));
return(-1);
}
}
}
else
{
for (i=0; i<n; i++)
printf("%.8f ",dstr(block.vtx[0].vout[i].nValue));
printf("no opreturn entries to check ht.%d %s\n",height,ASSETCHAINS_SYMBOL);
if ( ASSETCHAINS_SYMBOL[0] != 0 || height >= activation )
return(-1);
}
//printf("opretlen.%d num.%d\n",opretlen,num);
}
else
{
for (i=0; i<opretlen&&i<100; i++)
printf("%02x",script[i]);
printf(" height.%d checkdeposit n.%d [%02x] [%c] %d opcode.%d len.%d ",height,n,script[0],script[offset],script[offset],opcode,opretlen);
printf("not proper vout with opreturn format %s ht.%d cmp.%d %d\n",ASSETCHAINS_SYMBOL,height,script[offset] == opcode,(int32_t)block.vtx[0].vout[n-1].scriptPubKey.size());
return(-1);
}
return(0);*/
} }
const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source) const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source)
{ {
uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,kvheight,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fee,fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,kvheight,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fee,fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff;
const char *typestr = "unknown"; const char *typestr = "unknown";
if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 && opretbuf[0] != 'K' ) if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 && opretbuf[0] != 'K' )
{ {
@@ -1649,11 +1141,11 @@ void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_
} }
printf("numR.%d numV.%d numN.%d count.%d\n",numR,numV,numN,count); printf("numR.%d numV.%d numN.%d count.%d\n",numR,numV,numN,count);
/*else if ( func == 'K' ) // KMD height: stop after 1st /*else if ( func == 'K' ) // KMD height: stop after 1st
else if ( func == 'T' ) // KMD height+timestamp: stop after 1st else if ( func == 'T' ) // KMD height+timestamp: stop after 1st
else if ( func == 'N' ) // notarization, scan backwards 1440+ blocks; else if ( func == 'N' ) // notarization, scan backwards 1440+ blocks;
else if ( func == 'V' ) // price feed: can stop after 1440+ else if ( func == 'V' ) // price feed: can stop after 1440+
else if ( func == 'R' ) // opreturn:*/ else if ( func == 'R' ) // opreturn:*/
} }
void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep)
@@ -1859,10 +1351,10 @@ void komodo_passport_iteration()
} }
} }
/*if ( KOMODO_PAX == 0 ) /*if ( KOMODO_PAX == 0 )
{ {
KOMODO_PASSPORT_INITDONE = 1; KOMODO_PASSPORT_INITDONE = 1;
return; return;
}*/ }*/
starttime = (uint32_t)time(NULL); starttime = (uint32_t)time(NULL);
if ( callcounter++ < 1 ) if ( callcounter++ < 1 )
limit = 10000; limit = 10000;
@@ -1972,7 +1464,7 @@ void komodo_passport_iteration()
if ( expired == 0 && KOMODO_PASSPORT_INITDONE == 0 ) if ( expired == 0 && KOMODO_PASSPORT_INITDONE == 0 )
{ {
KOMODO_PASSPORT_INITDONE = 1; KOMODO_PASSPORT_INITDONE = 1;
printf("done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,refid); printf("READY for RPC calls at %u! done PASSPORT %s refid.%d\n",(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid);
} }
} }

View File

@@ -55,7 +55,7 @@ CCriticalSection cs_main;
extern uint8_t NOTARY_PUBKEY33[33]; extern uint8_t NOTARY_PUBKEY33[33];
extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN; extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN;
int32_t KOMODO_NEWBLOCKS; int32_t KOMODO_NEWBLOCKS;
void komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block);
BlockMap mapBlockIndex; BlockMap mapBlockIndex;
CChain chainActive; CChain chainActive;
@@ -1603,7 +1603,7 @@ bool ReadBlockFromDisk(int32_t height,CBlock& block, const CDiskBlockPos& pos)
if (filein.IsNull()) if (filein.IsNull())
{ {
//fprintf(stderr,"readblockfromdisk err A\n"); //fprintf(stderr,"readblockfromdisk err A\n");
return false;//error("ReadBlockFromDisk: OpenBlockFile failed for %s", pos.ToString()); return error("ReadBlockFromDisk: OpenBlockFile failed for %s", pos.ToString());
} }
// Read block // Read block
@@ -2449,9 +2449,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = libzcash::ProofVerifier::Strict();
auto disabledVerifier = libzcash::ProofVerifier::Disabled(); auto disabledVerifier = libzcash::ProofVerifier::Disabled();
int32_t futureblock;
// Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in // Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in
if (!CheckBlock(pindex->nHeight,pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck)) if (!CheckBlock(&futureblock,pindex->nHeight,pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck) || futureblock != 0 )
{
//fprintf(stderr,"checkblock failure in connectblock futureblock.%d\n",futureblock);
return false; return false;
}
// verify that the view's current state corresponds to the previous block // verify that the view's current state corresponds to the previous block
uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash(); uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash();
@@ -2604,7 +2608,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && block.vtx[0].vout.size() > 1 ) if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && block.vtx[0].vout.size() > 1 )
{ {
uint64_t checktoshis; uint64_t checktoshis;
if ( (checktoshis = komodo_commission(block)) != 0 ) if ( (checktoshis= komodo_commission((const CBlock *)&block)) != 0 )
{ {
if ( block.vtx[0].vout.size() == 2 && block.vtx[0].vout[1].nValue == checktoshis ) if ( block.vtx[0].vout.size() == 2 && block.vtx[0].vout[1].nValue == checktoshis )
blockReward += checktoshis; blockReward += checktoshis;
@@ -3307,9 +3311,21 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
// Check for duplicate // Check for duplicate
uint256 hash = block.GetHash(); uint256 hash = block.GetHash();
BlockMap::iterator it = mapBlockIndex.find(hash); BlockMap::iterator it = mapBlockIndex.find(hash);
BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
if (it != mapBlockIndex.end()) if (it != mapBlockIndex.end())
return it->second; {
if ( it->second != 0 ) // vNodes.size() >= KOMODO_LIMITED_NETWORKSIZE, change behavior to allow komodo_ensure to work
{
// this is the strange case where somehow the hash is in the mapBlockIndex via as yet undetermined process, but the pindex for the hash is not there. Theoretically it is due to processing the block headers, but I have seen it get this case without having received it from the block headers or anywhere else... jl777
//fprintf(stderr,"addtoblockindex already there %p\n",it->second);
return it->second;
}
if ( miPrev != mapBlockIndex.end() && (*miPrev).second == 0 )
{
//fprintf(stderr,"edge case of both block and prevblock in the strange state\n");
return(0); // return here to avoid the state of pindex->nHeight not set and pprev NULL
}
}
// Construct new block index object // Construct new block index object
CBlockIndex* pindexNew = new CBlockIndex(block); CBlockIndex* pindexNew = new CBlockIndex(block);
assert(pindexNew); assert(pindexNew);
@@ -3319,11 +3335,11 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
pindexNew->nSequenceId = 0; pindexNew->nSequenceId = 0;
BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first); pindexNew->phashBlock = &((*mi).first);
BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
if (miPrev != mapBlockIndex.end()) if (miPrev != mapBlockIndex.end())
{ {
pindexNew->pprev = (*miPrev).second; if ( (pindexNew->pprev= (*miPrev).second) != 0 )
pindexNew->nHeight = pindexNew->pprev->nHeight + 1; pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
else fprintf(stderr,"unexpected null pprev %s\n",hash.ToString().c_str());
pindexNew->BuildSkip(); pindexNew->BuildSkip();
} }
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew); pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew);
@@ -3332,7 +3348,8 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
pindexBestHeader = pindexNew; pindexBestHeader = pindexNew;
setDirtyBlockIndex.insert(pindexNew); setDirtyBlockIndex.insert(pindexNew);
//fprintf(stderr,"added to block index %s %p\n",hash.ToString().c_str(),pindexNew);
mi->second = pindexNew;
return pindexNew; return pindexNew;
} }
@@ -3488,7 +3505,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
return true; return true;
} }
bool CheckBlockHeader(int32_t height,CBlockIndex *pindex, const CBlockHeader& blockhdr, CValidationState& state, bool fCheckPOW) bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex, const CBlockHeader& blockhdr, CValidationState& state, bool fCheckPOW)
{ {
// Check timestamp // Check timestamp
if ( 0 ) if ( 0 )
@@ -3506,25 +3523,44 @@ bool CheckBlockHeader(int32_t height,CBlockIndex *pindex, const CBlockHeader& bl
fprintf(stderr," <- chainTip\n"); fprintf(stderr," <- chainTip\n");
} }
} }
*futureblockp = 0;
if (blockhdr.GetBlockTime() > GetAdjustedTime() + 60) if (blockhdr.GetBlockTime() > GetAdjustedTime() + 60)
return state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),REJECT_INVALID, "time-too-new"); {
else if ( ASSETCHAINS_STAKED != 0 && pindex != 0 && pindex->pprev != 0 && pindex->nTime <= pindex->pprev->nTime ) CBlockIndex *tipindex;
//fprintf(stderr,"ht.%d future block %u vs time.%u + 60\n",height,(uint32_t)blockhdr.GetBlockTime(),(uint32_t)GetAdjustedTime());
if ( (tipindex= chainActive.Tip()) != 0 && tipindex->GetBlockHash() == blockhdr.hashPrevBlock && blockhdr.GetBlockTime() < GetAdjustedTime() + 60 + 5 )
{
//fprintf(stderr,"it is the next block, let's wait for %d seconds\n",GetAdjustedTime() + 60 - blockhdr.GetBlockTime());
while ( blockhdr.GetBlockTime() > GetAdjustedTime() + 60 )
sleep(1);
//fprintf(stderr,"now its valid\n");
}
else
{
if (blockhdr.GetBlockTime() < GetAdjustedTime() + 600)
*futureblockp = 1;
LogPrintf("CheckBlockHeader block from future %d error\n",blockhdr.GetBlockTime() - GetAdjustedTime());
return false; //state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),REJECT_INVALID, "time-too-new");
}
}
/*if (blockhdr.GetBlockTime() > GetAdjustedTime() + 60)
return state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),REJECT_INVALID, "time-too-new");
else*/
if ( ASSETCHAINS_STAKED != 0 && pindex != 0 && pindex->pprev != 0 && pindex->nTime <= pindex->pprev->nTime )
{ {
fprintf(stderr,"ht.%d %u vs ht.%d %u, is not monotonic\n",pindex->nHeight,pindex->nTime,pindex->pprev->nHeight,pindex->pprev->nTime); fprintf(stderr,"ht.%d %u vs ht.%d %u, is not monotonic\n",pindex->nHeight,pindex->nTime,pindex->pprev->nHeight,pindex->pprev->nTime);
return state.Invalid(error("CheckBlockHeader(): block timestamp needs to always increase"),REJECT_INVALID, "time-too-new"); return state.Invalid(error("CheckBlockHeader(): block timestamp needs to always increase"),REJECT_INVALID, "time-too-new");
} }
// Check block version // Check block version
if (height > 0 && blockhdr.nVersion < MIN_BLOCK_VERSION) if (height > 0 && blockhdr.nVersion < MIN_BLOCK_VERSION)
{
fprintf(stderr,"nVersion.%d vs min %d\n",blockhdr.nVersion,MIN_BLOCK_VERSION);
return state.DoS(100, error("CheckBlockHeader(): block version too low"),REJECT_INVALID, "version-too-low"); return state.DoS(100, error("CheckBlockHeader(): block version too low"),REJECT_INVALID, "version-too-low");
}
// Check Equihash solution is valid // Check Equihash solution is valid
/*if ( fCheckPOW && !CheckEquihashSolution(&blockhdr, Params()) ) /*if ( fCheckPOW && !CheckEquihashSolution(&blockhdr, Params()) )
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution");*/ return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution");
// Check proof of work matches claimed amount // Check proof of work matches claimed amount
/*komodo_index2pubkey33(pubkey33,pindex,height); /*komodo_index2pubkey33(pubkey33,pindex,height);
if ( fCheckPOW && !CheckProofOfWork(height,pubkey33,blockhdr.GetHash(), blockhdr.nBits, Params().GetConsensus(),blockhdr.nTime) ) if ( fCheckPOW && !CheckProofOfWork(height,pubkey33,blockhdr.GetHash(), blockhdr.nBits, Params().GetConsensus(),blockhdr.nTime) )
return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),REJECT_INVALID, "high-hash");*/ return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),REJECT_INVALID, "high-hash");*/
return true; return true;
@@ -3565,25 +3601,43 @@ int32_t komodo_reverify_blockcheck(CValidationState& state,int32_t height,CBlock
return(0); return(0);
} }
bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state,
libzcash::ProofVerifier& verifier, libzcash::ProofVerifier& verifier,
bool fCheckPOW, bool fCheckMerkleRoot) bool fCheckPOW, bool fCheckMerkleRoot)
{ {
uint8_t pubkey33[33]; uint8_t pubkey33[33]; uint256 hash;
// These are checks that are independent of context. // These are checks that are independent of context.
hash = block.GetHash();
// Check that the header is valid (particularly PoW). This is mostly // Check that the header is valid (particularly PoW). This is mostly redundant with the call in AcceptBlockHeader.
// redundant with the call in AcceptBlockHeader. if (!CheckBlockHeader(futureblockp,height,pindex,block,state,fCheckPOW))
if (!CheckBlockHeader(height,pindex,block,state,fCheckPOW))
{ {
//fprintf(stderr,"CheckBlockHeader error in CheckBlock fCheckPOW.%d\n",fCheckPOW); if ( *futureblockp == 0 )
return false; {
LogPrintf("CheckBlock header error\n");
return false;
}
} }
if ( fCheckPOW && !CheckEquihashSolution(&block, Params()) ) if ( fCheckPOW )
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution"); {
komodo_block2pubkey33(pubkey33,(CBlock *)&block); //if ( !CheckEquihashSolution(&block, Params()) )
if ( fCheckPOW && !CheckProofOfWork(height,pubkey33,block.GetHash(), block.nBits, Params().GetConsensus(),block.nTime) ) // return state.DoS(100, error("CheckBlock: Equihash solution invalid"),REJECT_INVALID, "invalid-solution");
return state.DoS(1, error("CheckBlock(): proof of work failed"),REJECT_INVALID, "high-hash"); komodo_block2pubkey33(pubkey33,(CBlock *)&block);
if ( !CheckProofOfWork(height,pubkey33,hash,block.nBits,Params().GetConsensus(),block.nTime) )
{
int32_t z; for (z=31; z>=0; z--)
fprintf(stderr,"%02x",((uint8_t *)&hash)[z]);
fprintf(stderr," failed hash ht.%d\n",height);
return state.DoS(50, error("CheckBlock: proof of work failed"),REJECT_INVALID, "high-hash");
}
if ( komodo_checkPOW(1,(CBlock *)&block,height) < 0 ) // checks Equihash
return state.DoS(100, error("CheckBlock: failed slow_checkPOW"),REJECT_INVALID, "failed-slow_checkPOW");
}
/*if ( fCheckPOW && !CheckEquihashSolution(&block, Params()) )
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution");
komodo_block2pubkey33(pubkey33,(CBlock *)&block);
if ( fCheckPOW && !CheckProofOfWork(height,pubkey33,block.GetHash(), block.nBits, Params().GetConsensus(),block.nTime) )
return state.DoS(1, error("CheckBlock(): proof of work failed"),REJECT_INVALID, "high-hash");*/
// Check the merkle root. // Check the merkle root.
if (fCheckMerkleRoot) { if (fCheckMerkleRoot) {
bool mutated; bool mutated;
@@ -3639,7 +3693,7 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat
{ {
static uint32_t counter; static uint32_t counter;
//if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 ) //if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 )
fprintf(stderr,"check deposit rejection\n"); fprintf(stderr,"check deposit rejection\n");
return(false); return(false);
} }
return true; return true;
@@ -3744,70 +3798,93 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
return true; return true;
} }
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex) bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex)
{ {
static uint256 zero;
const CChainParams& chainparams = Params(); const CChainParams& chainparams = Params();
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
// Check for duplicate // Check for duplicate
uint256 hash = block.GetHash(); uint256 hash = block.GetHash();
BlockMap::iterator miSelf = mapBlockIndex.find(hash); BlockMap::iterator miSelf = mapBlockIndex.find(hash);
CBlockIndex *pindex = NULL; CBlockIndex *pindex = NULL;
if (miSelf != mapBlockIndex.end()) { if (miSelf != mapBlockIndex.end())
{
// Block header is already known. // Block header is already known.
pindex = miSelf->second; if ( (pindex= miSelf->second) == 0 )
miSelf->second = pindex = AddToBlockIndex(block);
if (ppindex) if (ppindex)
*ppindex = pindex; *ppindex = pindex;
if ( pindex != 0 && pindex->nStatus & BLOCK_FAILED_MASK ) if ( pindex != 0 && pindex->nStatus & BLOCK_FAILED_MASK )
return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate"); return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate");
return true; return true;
} }
if (!CheckBlockHeader(futureblockp,*ppindex!=0?(*ppindex)->nHeight:0,*ppindex, block, state,0))
if (!CheckBlockHeader(*ppindex!=0?(*ppindex)->nHeight:0,*ppindex, block, state,0))
{ {
fprintf(stderr,"CheckBlockHeader failed\n"); if ( *futureblockp == 0 )
return false; {
LogPrintf("AcceptBlockHeader CheckBlockHeader error\n");
return false;
}
} }
// Get prev block index // Get prev block index
CBlockIndex* pindexPrev = NULL; CBlockIndex* pindexPrev = NULL;
if (hash != chainparams.GetConsensus().hashGenesisBlock) { if (hash != chainparams.GetConsensus().hashGenesisBlock)
{
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi == mapBlockIndex.end()) if (mi == mapBlockIndex.end())
{ {
return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk"); LogPrintf("AcceptBlockHeader hashPrevBlock %s not found\n",block.hashPrevBlock.ToString().c_str());
return(false);
//return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk");
} }
pindexPrev = (*mi).second; pindexPrev = (*mi).second;
if (pindexPrev == 0 || (pindexPrev->nStatus & BLOCK_FAILED_MASK) ) if (pindexPrev == 0 )
{
LogPrintf("AcceptBlockHeader hashPrevBlock %s no pindexPrev\n",block.hashPrevBlock.ToString().c_str());
return(false);
}
if ( (pindexPrev->nStatus & BLOCK_FAILED_MASK) )
return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
} }
if (!ContextualCheckBlockHeader(block, state, pindexPrev)) if (!ContextualCheckBlockHeader(block, state, pindexPrev))
{ {
fprintf(stderr,"ContextualCheckBlockHeader failed\n"); //fprintf(stderr,"AcceptBlockHeader ContextualCheckBlockHeader failed\n");
LogPrintf("AcceptBlockHeader ContextualCheckBlockHeader failed\n");
return false; return false;
} }
if (pindex == NULL) if (pindex == NULL)
{ {
if ( (pindex= AddToBlockIndex(block)) == 0 ) if ( (pindex= AddToBlockIndex(block)) != 0 )
fprintf(stderr,"couldnt add to block index\n"); {
miSelf = mapBlockIndex.find(hash);
if (miSelf != mapBlockIndex.end())
miSelf->second = pindex;
//fprintf(stderr,"AcceptBlockHeader couldnt add to block index\n");
}
} }
if (ppindex) if (ppindex)
*ppindex = pindex; *ppindex = pindex;
return true; return true;
} }
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp)
{ {
const CChainParams& chainparams = Params(); const CChainParams& chainparams = Params();
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
CBlockIndex *&pindex = *ppindex; CBlockIndex *&pindex = *ppindex;
if (!AcceptBlockHeader(block, state, &pindex)) if (!AcceptBlockHeader(futureblockp,block, state, &pindex))
{ {
//fprintf(stderr,"AcceptBlockHeader rejected\n"); if ( *futureblockp == 0 )
return false; {
LogPrintf("AcceptBlock AcceptBlockHeader error\n");
return false;
}
} }
if ( pindex == 0 ) if ( pindex == 0 )
{ {
//fprintf(stderr,"unexpected AcceptBlock error null pindex\n"); LogPrintf("AcceptBlock null pindex error\n");
return false; return false;
} }
//fprintf(stderr,"acceptblockheader passed\n"); //fprintf(stderr,"acceptblockheader passed\n");
@@ -3821,10 +3898,11 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
// blocks which are too close in height to the tip. Apply this test // blocks which are too close in height to the tip. Apply this test
// regardless of whether pruning is enabled; it should generally be safe to // regardless of whether pruning is enabled; it should generally be safe to
// not process unrequested blocks. // not process unrequested blocks.
bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP)); bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + BLOCK_DOWNLOAD_WINDOW)); //MIN_BLOCKS_TO_KEEP));
// TODO: deal better with return value and error conditions for duplicate // TODO: deal better with return value and error conditions for duplicate
// and unrequested blocks. // and unrequested blocks.
//fprintf(stderr,"Accept %s flags already.%d requested.%d morework.%d farahead.%d\n",pindex->GetBlockHash().ToString().c_str(),fAlreadyHave,fRequested,fHasMoreWork,fTooFarAhead);
if (fAlreadyHave) return true; if (fAlreadyHave) return true;
if (!fRequested) { // If we didn't ask for it: if (!fRequested) { // If we didn't ask for it:
if (pindex->nTx != 0) return true; // This is a previously-processed block that was pruned if (pindex->nTx != 0) return true; // This is a previously-processed block that was pruned
@@ -3834,18 +3912,20 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
// See method docstring for why this is always disabled // See method docstring for why this is always disabled
auto verifier = libzcash::ProofVerifier::Disabled(); auto verifier = libzcash::ProofVerifier::Disabled();
if ((!CheckBlock(pindex->nHeight,pindex,block, state, verifier,0)) || !ContextualCheckBlock(block, state, pindex->pprev)) if ((!CheckBlock(futureblockp,pindex->nHeight,pindex,block, state, verifier,0)) || !ContextualCheckBlock(block, state, pindex->pprev))
{ {
if (state.IsInvalid() && !state.CorruptionPossible()) { if ( *futureblockp == 0 )
pindex->nStatus |= BLOCK_FAILED_VALID; {
setDirtyBlockIndex.insert(pindex); if (state.IsInvalid() && !state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
}
LogPrintf("AcceptBlock CheckBlock or ContextualCheckBlock error\n");
return false;
} }
fprintf(stderr,"CheckBlock or ContextualCheckBlock failed\n");
return false;
} }
int nHeight = pindex->nHeight; int nHeight = pindex->nHeight;
// Write block to history file // Write block to history file
try { try {
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
@@ -3865,8 +3945,10 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
if (fCheckForPruning) if (fCheckForPruning)
FlushStateToDisk(state, FLUSH_STATE_NONE); // we just allocated more disk space for block files FlushStateToDisk(state, FLUSH_STATE_NONE); // we just allocated more disk space for block files
if ( *futureblockp == 0 )
return true; return true;
LogPrintf("AcceptBlock block from future error\n");
return false;
} }
static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams) static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams)
@@ -3883,21 +3965,105 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
void komodo_currentheight_set(int32_t height); void komodo_currentheight_set(int32_t height);
bool ProcessNewBlock(int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) CBlockIndex *komodo_ensure(CBlock *pblock,uint256 hash)
{
CBlockIndex *pindex;
BlockMap::iterator miSelf = mapBlockIndex.find(hash);
if ( miSelf != mapBlockIndex.end() )
{
if ( (pindex= miSelf->second) == 0 ) // create pindex so first Accept block doesnt fail
{
miSelf->second = AddToBlockIndex(*pblock);
//fprintf(stderr,"Block header %s is already known, but without pindex -> ensured %p\n",hash.ToString().c_str(),miSelf->second);
}
if ( hash != Params().GetConsensus().hashGenesisBlock )
{
miSelf = mapBlockIndex.find(pblock->hashPrevBlock);
if ( miSelf != mapBlockIndex.end() )
{
if ( miSelf->second == 0 )
{
miSelf->second = InsertBlockIndex(pblock->hashPrevBlock);
fprintf(stderr,"autocreate previndex %s\n",pblock->hashPrevBlock.ToString().c_str());
}
}
}
}
}
CBlockIndex *oldkomodo_ensure(CBlock *pblock,uint256 hash)
{
CBlockIndex *pindex=0,*previndex=0;
if ( (pindex= mapBlockIndex[hash]) == 0 )
{
pindex = new CBlockIndex();
if (!pindex)
throw runtime_error("komodo_ensure: new CBlockIndex failed");
BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindex)).first;
pindex->phashBlock = &((*mi).first);
}
BlockMap::iterator miSelf = mapBlockIndex.find(hash);
if ( miSelf == mapBlockIndex.end() )
{
LogPrintf("komodo_ensure unexpected missing hash %s\n",hash.ToString().c_str());
return(0);
}
if ( miSelf->second == 0 ) // create pindex so first Accept block doesnt fail
{
if ( pindex == 0 )
{
pindex = AddToBlockIndex(*pblock);
fprintf(stderr,"ensure call addtoblockindex, got %p\n",pindex);
}
if ( pindex != 0 )
{
miSelf->second = pindex;
LogPrintf("Block header %s is already known, but without pindex -> ensured %p\n",hash.ToString().c_str(),miSelf->second);
} else LogPrintf("komodo_ensure unexpected null pindex\n");
}
/*if ( hash != Params().GetConsensus().hashGenesisBlock )
{
miSelf = mapBlockIndex.find(pblock->hashPrevBlock);
if ( miSelf == mapBlockIndex.end() )
previndex = InsertBlockIndex(pblock->hashPrevBlock);
if ( (miSelf= mapBlockIndex.find(pblock->hashPrevBlock)) != mapBlockIndex.end() )
{
if ( miSelf->second == 0 ) // create pindex so first Accept block doesnt fail
{
if ( previndex == 0 )
previndex = InsertBlockIndex(pblock->hashPrevBlock);
if ( previndex != 0 )
{
miSelf->second = previndex;
LogPrintf("autocreate previndex %s\n",pblock->hashPrevBlock.ToString().c_str());
} else LogPrintf("komodo_ensure unexpected null previndex\n");
}
} else LogPrintf("komodo_ensure unexpected null miprev\n");
}
}*/
return(pindex);
}
bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp)
{ {
// Preliminary checks // Preliminary checks
bool checked; bool checked; uint256 hash; int32_t futureblock=0;
auto verifier = libzcash::ProofVerifier::Disabled(); auto verifier = libzcash::ProofVerifier::Disabled();
hash = pblock->GetHash();
//fprintf(stderr,"process newblock %s\n",hash.ToString().c_str());
if ( chainActive.Tip() != 0 ) if ( chainActive.Tip() != 0 )
komodo_currentheight_set(chainActive.Tip()->nHeight); komodo_currentheight_set(chainActive.Tip()->nHeight);
if ( ASSETCHAINS_SYMBOL[0] == 0 ) checked = CheckBlock(&futureblock,height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0);
checked = CheckBlock(height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0);
else checked = CheckBlock(height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0);
{ {
LOCK(cs_main); LOCK(cs_main);
bool fRequested = MarkBlockAsReceived(pblock->GetHash()); bool fRequested = MarkBlockAsReceived(hash);
fRequested |= fForceProcessing; fRequested |= fForceProcessing;
if (!checked) if ( checked != 0 && komodo_checkPOW(from_miner && ASSETCHAINS_STAKED == 0,pblock,height) < 0 )
{
checked = 0;
fprintf(stderr,"passed checkblock but failed checkPOW.%d\n",from_miner && ASSETCHAINS_STAKED == 0);
}
if (!checked && futureblock == 0)
{ {
if ( pfrom != 0 ) if ( pfrom != 0 )
{ {
@@ -3905,19 +4071,24 @@ bool ProcessNewBlock(int32_t height,CValidationState &state, CNode* pfrom, CBloc
} }
return error("%s: CheckBlock FAILED", __func__); return error("%s: CheckBlock FAILED", __func__);
} }
// Store to disk // Store to disk
CBlockIndex *pindex = NULL; CBlockIndex *pindex = NULL;
bool ret = AcceptBlock(*pblock, state, &pindex, fRequested, dbp); if ( 1 )
{
// without the komodo_ensure call, it is quite possible to get a non-error but null pindex returned from AcceptBlockHeader. In a 2 node network, it will be a long time before that block is reprocessed. Even though restarting makes it rescan, it seems much better to keep the nodes in sync
komodo_ensure(pblock,hash);
}
bool ret = AcceptBlock(&futureblock,*pblock, state, &pindex, fRequested, dbp);
if (pindex && pfrom) { if (pindex && pfrom) {
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
} }
CheckBlockIndex(); CheckBlockIndex();
if (!ret) if (!ret && futureblock == 0)
return error("%s: AcceptBlock FAILED", __func__); return error("%s: AcceptBlock FAILED", __func__);
//else fprintf(stderr,"added block %s %p\n",pindex->GetBlockHash().ToString().c_str(),pindex->pprev);
} }
if (!ActivateBestChain(state, pblock)) if (futureblock == 0 && !ActivateBestChain(state, pblock))
return error("%s: ActivateBestChain failed", __func__); return error("%s: ActivateBestChain failed", __func__);
return true; return true;
@@ -3934,30 +4105,31 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
indexDummy.nHeight = pindexPrev->nHeight + 1; indexDummy.nHeight = pindexPrev->nHeight + 1;
// JoinSplit proofs are verified in ConnectBlock // JoinSplit proofs are verified in ConnectBlock
auto verifier = libzcash::ProofVerifier::Disabled(); auto verifier = libzcash::ProofVerifier::Disabled();
// NOTE: CheckBlockHeader is called by CheckBlock // NOTE: CheckBlockHeader is called by CheckBlock
if (!ContextualCheckBlockHeader(block, state, pindexPrev)) if (!ContextualCheckBlockHeader(block, state, pindexPrev))
{ {
fprintf(stderr,"TestBlockValidity failure A\n"); //fprintf(stderr,"TestBlockValidity failure A checkPOW.%d\n",fCheckPOW);
return false; return false;
} }
if (!CheckBlock(indexDummy.nHeight,0,block, state, verifier, fCheckPOW, fCheckMerkleRoot)) int32_t futureblock;
if (!CheckBlock(&futureblock,indexDummy.nHeight,0,block, state, verifier, fCheckPOW, fCheckMerkleRoot))
{ {
//fprintf(stderr,"TestBlockValidity failure B\n"); //fprintf(stderr,"TestBlockValidity failure B checkPOW.%d\n",fCheckPOW);
return false; return false;
} }
if (!ContextualCheckBlock(block, state, pindexPrev)) if (!ContextualCheckBlock(block, state, pindexPrev))
{ {
fprintf(stderr,"TestBlockValidity failure C\n"); //fprintf(stderr,"TestBlockValidity failure C checkPOW.%d\n",fCheckPOW);
return false; return false;
} }
if (!ConnectBlock(block, state, &indexDummy, viewNew, true,fCheckPOW)) if (!ConnectBlock(block, state, &indexDummy, viewNew, true,fCheckPOW))
{ {
fprintf(stderr,"TestBlockValidity failure D\n"); //fprintf(stderr,"TestBlockValidity failure D checkPOW.%d\n",fCheckPOW);
return false; return false;
} }
assert(state.IsValid()); assert(state.IsValid());
if ( futureblock != 0 )
return(false);
return true; return true;
} }
@@ -4028,7 +4200,6 @@ void FindFilesToPrune(std::set<int>& setFilesToPrune)
if (chainActive.Tip()->nHeight <= Params().PruneAfterHeight()) { if (chainActive.Tip()->nHeight <= Params().PruneAfterHeight()) {
return; return;
} }
unsigned int nLastBlockWeCanPrune = chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP; unsigned int nLastBlockWeCanPrune = chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP;
uint64_t nCurrentUsage = CalculateCurrentUsage(); uint64_t nCurrentUsage = CalculateCurrentUsage();
// We don't check to prune until after we've allocated new space for files // We don't check to prune until after we've allocated new space for files
@@ -4106,7 +4277,7 @@ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
while ( fread(ignore,1,incr,file) == incr ) while ( fread(ignore,1,incr,file) == incr )
fprintf(stderr,"."); fprintf(stderr,".");
free(ignore); free(ignore);
fprintf(stderr,"blk.%d loaded %ld bytes set fpos.%ld loading.%d\n",(int)pos.nFile,(long)ftell(file),(long)fpos,KOMODO_LOADINGBLOCKS); //fprintf(stderr,"blk.%d loaded %ld bytes set fpos.%ld loading.%d\n",(int)pos.nFile,(long)ftell(file),(long)fpos,KOMODO_LOADINGBLOCKS);
} }
} }
fseek(file,fpos,SEEK_SET); fseek(file,fpos,SEEK_SET);
@@ -4350,7 +4521,8 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
if (!ReadBlockFromDisk(block, pindex)) if (!ReadBlockFromDisk(block, pindex))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 1: verify block validity // check level 1: verify block validity
if (nCheckLevel >= 1 && !CheckBlock(pindex->nHeight,pindex,block, state, verifier,0)) int32_t futureblock;
if (nCheckLevel >= 1 && !CheckBlock(&futureblock,pindex->nHeight,pindex,block, state, verifier,0))
return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 2: verify undo validity // check level 2: verify undo validity
if (nCheckLevel >= 2 && pindex) { if (nCheckLevel >= 2 && pindex) {
@@ -4685,7 +4857,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
// process in case the block isn't known yet // process in case the block isn't known yet
if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) { if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) {
CValidationState state; CValidationState state;
if (ProcessNewBlock(0,state, NULL, &block, true, dbp)) if (ProcessNewBlock(0,0,state, NULL, &block, true, dbp))
nLoaded++; nLoaded++;
if (state.IsError()) if (state.IsError())
break; break;
@@ -4707,7 +4879,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(),
head.ToString()); head.ToString());
CValidationState dummy; CValidationState dummy;
if (ProcessNewBlock(0,dummy, NULL, &block, true, &it->second)) if (ProcessNewBlock(0,0,dummy, NULL, &block, true, &it->second))
{ {
nLoaded++; nLoaded++;
queue.push_back(block.GetHash()); queue.push_back(block.GetHash());
@@ -5578,12 +5750,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
} }
pfrom->PushMessage("headers", vHeaders); pfrom->PushMessage("headers", vHeaders);
} }
/*else if ( NOTARY_PUBKEY33[0] != 0 )
{
static uint32_t counter;
if ( counter++ < 3 )
fprintf(stderr,"you can ignore redundant getheaders from peer.%d %d prev.%d\n",(int32_t)pfrom->id,(int32_t)(pindex ? pindex->nHeight : -1),pfrom->lasthdrsreq);
}*/
} }
@@ -5747,9 +5913,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
Misbehaving(pfrom->GetId(), 20); Misbehaving(pfrom->GetId(), 20);
return error("non-continuous headers sequence"); return error("non-continuous headers sequence");
} }
if (!AcceptBlockHeader(header, state, &pindexLast)) { int32_t futureblock;
if (!AcceptBlockHeader(&futureblock,header, state, &pindexLast)) {
int nDoS; int nDoS;
if (state.IsInvalid(nDoS)) if (state.IsInvalid(nDoS) && futureblock == 0)
{ {
if (nDoS > 0) if (nDoS > 0)
Misbehaving(pfrom->GetId(), nDoS/nDoS); Misbehaving(pfrom->GetId(), nDoS/nDoS);
@@ -5792,7 +5959,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Such an unrequested block may still be processed, subject to the // Such an unrequested block may still be processed, subject to the
// conditions in AcceptBlock(). // conditions in AcceptBlock().
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(); bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
ProcessNewBlock(0,state, pfrom, &block, forceProcessing, NULL); ProcessNewBlock(0,0,state, pfrom, &block, forceProcessing, NULL);
int nDoS; int nDoS;
if (state.IsInvalid(nDoS)) { if (state.IsInvalid(nDoS)) {
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),

View File

@@ -183,7 +183,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals);
* @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location.
* @return True if state.IsValid() * @return True if state.IsValid()
*/ */
bool ProcessNewBlock(int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp); bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp);
/** Check whether enough disk space is available for an incoming block */ /** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
/** Open a block file (blk?????.dat) */ /** Open a block file (blk?????.dat) */
@@ -450,8 +450,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false,bool fCheckPOW = false); bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false,bool fCheckPOW = false);
/** Context-independent validity checks */ /** Context-independent validity checks */
bool CheckBlockHeader(int32_t height,CBlockIndex *pindex,const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state,
libzcash::ProofVerifier& verifier, libzcash::ProofVerifier& verifier,
bool fCheckPOW = true, bool fCheckMerkleRoot = true); bool fCheckPOW = true, bool fCheckMerkleRoot = true);
@@ -469,8 +469,8 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
* - The only caller of AcceptBlock verifies JoinSplit proofs elsewhere. * - The only caller of AcceptBlock verifies JoinSplit proofs elsewhere.
* If dbp is non-NULL, the file is known to already reside on disk * If dbp is non-NULL, the file is known to already reside on disk
*/ */
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp); bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp);
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL);

View File

@@ -119,7 +119,7 @@ int32_t komodo_is_issuer();
int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *symbol,int32_t tokomodo); int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *symbol,int32_t tokomodo);
int32_t komodo_isrealtime(int32_t *kmdheightp); int32_t komodo_isrealtime(int32_t *kmdheightp);
int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag);
uint64_t komodo_commission(const CBlock &block); 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); 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);
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
@@ -454,7 +454,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
}*/ }*/
pblock->vtx[0] = txNew; pblock->vtx[0] = txNew;
if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission(pblocktemplate->block)) != 0 ) if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock *)&pblocktemplate->block)) != 0 )
{ {
int32_t i; uint8_t *ptr; int32_t i; uint8_t *ptr;
txNew.vout.resize(2); txNew.vout.resize(2);
@@ -487,8 +487,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
if ( ASSETCHAINS_SYMBOL[0] == 0 && NOTARY_PUBKEY33[0] != 0 && pblock->nTime < pindexPrev->nTime+60 ) if ( ASSETCHAINS_SYMBOL[0] == 0 && NOTARY_PUBKEY33[0] != 0 && pblock->nTime < pindexPrev->nTime+60 )
{ {
pblock->nTime = pindexPrev->nTime + 60; pblock->nTime = pindexPrev->nTime + 60;
fprintf(stderr,"block.nTime %u vs prev.%u, gettime.%u vs adjusted.%u\n",(uint32_t)pblock->nTime,(uint32_t)(pindexPrev->nTime + 60),(uint32_t)pblock->GetBlockTime(),(uint32_t)(GetAdjustedTime() + 60)); //fprintf(stderr,"block.nTime %u vs prev.%u, gettime.%u vs adjusted.%u\n",(uint32_t)pblock->nTime,(uint32_t)(pindexPrev->nTime + 60),(uint32_t)pblock->GetBlockTime(),(uint32_t)(GetAdjustedTime() + 60));
while ( pblock->GetBlockTime() > GetAdjustedTime() + 60 ) while ( pblock->GetBlockTime() > GetAdjustedTime() + 10 )
sleep(1); sleep(1);
} }
pblock->nSolution.clear(); pblock->nSolution.clear();
@@ -655,7 +655,7 @@ static bool ProcessBlockFound(CBlock* pblock)
// Process this block the same as if we had received it from another node // Process this block the same as if we had received it from another node
CValidationState state; CValidationState state;
if (!ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL))
return error("KomodoMiner: ProcessNewBlock, block not accepted"); return error("KomodoMiner: ProcessNewBlock, block not accepted");
TrackMinedBlock(pblock->GetHash()); TrackMinedBlock(pblock->GetHash());

View File

@@ -267,7 +267,7 @@ UniValue generate(const UniValue& params, bool fHelp)
} }
endloop: endloop:
CValidationState state; CValidationState state;
if (!ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL))
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight; ++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex()); blockHashes.push_back(pblock->GetHash().GetHex());
@@ -807,7 +807,7 @@ UniValue submitblock(const UniValue& params, bool fHelp)
CValidationState state; CValidationState state;
submitblock_StateCatcher sc(block.GetHash()); submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc); RegisterValidationInterface(&sc);
bool fAccepted = ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, &block, true, NULL); bool fAccepted = ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, &block, true, NULL);
UnregisterValidationInterface(&sc); UnregisterValidationInterface(&sc);
if (fBlockPresent) if (fBlockPresent)
{ {

View File

@@ -261,7 +261,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
*/ */
CValidationState state; CValidationState state;
BOOST_CHECK(ProcessNewBlock(state, NULL, pblock, true, NULL)); BOOST_CHECK(ProcessNewBlock(1,chainActive.Height()+1,state, NULL, pblock, true, NULL));
BOOST_CHECK_MESSAGE(state.IsValid(), state.GetRejectReason()); BOOST_CHECK_MESSAGE(state.IsValid(), state.GetRejectReason());
pblock->hashPrevBlock = pblock->GetHash(); pblock->hashPrevBlock = pblock->GetHash();