diff --git a/src/komodo.h b/src/komodo.h index b97e4d205..d88b53c2a 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -266,7 +266,10 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long memset(&MoM,0,sizeof(MoM)); MoMdepth = 0; } + sp->PPNOTARIZED_HEIGHT = sp->PNOTARIZED_HEIGHT; + sp->PNOTARIZED_HEIGHT = sp->NOTARIZED_HEIGHT; komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); + printf("komodo_parsestatefiledata: [%s] NOTARIZED.%d PNOTARIZED_HEIGHT.%d PPNOTARIZED_HEIGHT.%d\n",ASSETCHAINS_SYMBOL,sp->NOTARIZED_HEIGHT,sp->PNOTARIZED_HEIGHT,sp->PPNOTARIZED_HEIGHT); } else if ( func == 'U' ) // deprecated { @@ -697,7 +700,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar komodo_rwccdata((char *)"KMD",1,&ccdata,0); // If we are checking a reorged notarisation tx we need to return true. So the coinbase can be recreated, otherwise notaries are not paid, - // if a notarisation TX is reorged before the next notarization happens! + // if a notarisation TX is reorged before the next notarization happens! if ( fJustCheck && matched != 0 && *notarizedheightp == sp->NOTARIZED_HEIGHT && sp->NOTARIZED_DESTTXID == desttxid && sp->NOTARIZED_HASH == srchash) return(-2); @@ -705,7 +708,8 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar { if ( fJustCheck ) return(-2); - sp->prevNOTARIZED_HEIGHT = sp->NOTARIZED_HEIGHT; + sp->PPNOTARIZED_HEIGHT = sp->PNOTARIZED_HEIGHT; + sp->PNOTARIZED_HEIGHT = sp->NOTARIZED_HEIGHT; sp->NOTARIZED_HEIGHT = *notarizedheightp; sp->NOTARIZED_HASH = srchash; sp->NOTARIZED_DESTTXID = desttxid; @@ -716,7 +720,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar } komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->MoM,sp->MoMdepth); if ( ASSETCHAINS_SYMBOL[0] != 0 ) - printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,*notarizedheightp,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth); + printf("[%s] ht.%d NUM_NPOINTS.%d NOTARIZED.%d PNOTARIZED_HEIGHT.%d PPNOTARIZED_HEIGHT.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,sp->NUM_NPOINTS,sp->NOTARIZED_HEIGHT,sp->PNOTARIZED_HEIGHT,sp->PPNOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth); if ( ASSETCHAINS_SYMBOL[0] == 0 ) { @@ -742,7 +746,8 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen-len+4+3+(scriptbuf[1] == 0x4d),j,zero,0); } } - } + } else if ( fJustCheck ) + return (-3); // if the notarisation is only invalid because its out of order it cannot be mined in a block with a valid one! } else if ( opretlen != 149 && height > 600000 && matched != 0 ) printf("%s validated.%d notarized.%d %llx reject ht.%d NOTARIZED.%d prev.%d %s.%s DESTTXID.%s len.%d opretlen.%d\n",ccdata.symbol,validated,notarized,(long long)signedmask,height,*notarizedheightp,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),desttxid.ToString().c_str(),len,opretlen); } @@ -958,7 +963,7 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) { memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); notaryid = komodo_voutupdate(fJustCheck,&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime()); - if ( fJustCheck && notaryid == -2 ) + if ( fJustCheck && (notaryid == -2 || notaryid == -3) ) { // We see a valid notarisation here, save its location. notarisations.push_back(i); @@ -1025,7 +1030,7 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) { if (notarisations.size() == 0) return(0); - if ( notarisations.size() == 1 && notarisations[0] == 1 ) + if ( notarisations.size() >= 1 && notarisations[0] == 1 ) return(1); else return(-1); diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index caa2c4460..e3e99d7c4 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1776,35 +1776,39 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) return(isPOS); } -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp,int32_t *prevNotarizedHt); +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp,int32_t *prevNotarizedHt,int32_t *ppNotarizedHt); -uint64_t komodo_notarypayamount(int32_t height, int64_t notarycount) +uint64_t komodo_notarypayamount(int64_t notarycount) { if ( notarycount == 0 ) { fprintf(stderr, "komodo_notarypayamount failed num notaries is 0!\n"); return(0); } - // fetch notarised height - int32_t notarizedht,prevMoMheight,prevnotarizedht; uint256 notarizedhash,txid; + // fetch notarised height, the previous, and the one before that. + int32_t notarizedht,prevMoMheight,prevnotarizedht,pprevnotarizedht; uint256 notarizedhash,txid; uint64_t AmountToPay=0,ret=0; - notarizedht = komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid,&prevnotarizedht); - // if this is the current checkpoint we will use the previous height. - // incase of reorgs, we still need to create the notary payment. - if ( height == notarizedht ) + notarizedht = komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid,&prevnotarizedht,&pprevnotarizedht); + //fprintf(stderr, "notarizedht.%d prevnotarizedht.%d pprevnotarizedht.%d \n",notarizedht,prevnotarizedht,pprevnotarizedht); + + // We cannot pay out if 3 notarisation's have not yet happened! + if ( pprevnotarizedht == 0 ) { - notarizedht = prevnotarizedht; - fprintf(stderr, "using the current checkpoint, calculating based on previous notarized height!\n"); + fprintf(stderr, "need 3 notarizations to happen before notaries can be paid.\n"); + return(0); } - // how many block since last notarisation. - int32_t n = height - notarizedht; + if ( prevnotarizedht == pprevnotarizedht ) + return(0); // cant happen, sanity check. + + // use the previous height and the height before that to guarentee that the notarzations used to calculate these values, + // are them selves actually notarised and cannot be reorged. + int32_t n = prevnotarizedht - pprevnotarizedht; + fprintf(stderr, "blocks since last notarization: %i\n",n); // multiply the amount possible to be used for each block by the amount of blocks passed // to get the total posible to be paid for this notarisation. AmountToPay = ASSETCHAINS_NOTARY_PAY*n; - //fprintf(stderr, "AmountToPay.%lu\n",AmountToPay); ret = AmountToPay / notarycount; - fprintf(stderr, "payment per notary.%lu\n",ret); return(ret); } @@ -1846,7 +1850,7 @@ uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &Notar return(0); numSN = numStakedNotaries(staked_pubkeys,staked_era); - // Check the notarisation is valid and get the notarized height to calcualte the payment. + // Check the notarisation is valid. int32_t notarizedheight = komodo_getnotarizedheight(timestamp, height, script, len); if ( notarizedheight == 0 ) return(0); @@ -1854,8 +1858,10 @@ uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &Notar // resize coinbase vouts to number of notary nodes +1 for coinbase itself. txNew.vout.resize(NotarisationNotaries.size()+1); - // Calcualte the amount to pay. - AmountToPay = komodo_notarypayamount(notarizedheight,NotarisationNotaries.size()); + // Calcualte the amount to pay. If 0, means not enough notarizations to calcuate amount. + AmountToPay = komodo_notarypayamount(NotarisationNotaries.size()); + if ( AmountToPay == 0 ) + return(0); // loop over notarisation vins and add transaction to coinbase. // Commented prints here can be used to verify manually the pubkeys match. @@ -1932,7 +1938,7 @@ uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height) fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen); return(0); } - } + } else return(0); // if notarypay fails, because the notarisation is not valid, exit now as txNew was not created. // This should never happen, as the notarisation is checked before this function is called. diff --git a/src/komodo_notary.h b/src/komodo_notary.h index dcd99bea1..88a079348 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -452,14 +452,15 @@ int32_t komodo_prevMoMheight() return(0); } -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp,int32_t *prevNotarizedHt) +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp,int32_t *prevNotarizedHt,int32_t *ppNotarizedHt) { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) { *hashp = sp->NOTARIZED_HASH; *txidp = sp->NOTARIZED_DESTTXID; - *prevNotarizedHt = sp->prevNOTARIZED_HEIGHT; + *prevNotarizedHt = sp->PNOTARIZED_HEIGHT; + *ppNotarizedHt = sp->PPNOTARIZED_HEIGHT; *prevMoMheightp = komodo_prevMoMheight(); return(sp->NOTARIZED_HEIGHT); } diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 2f8ba0850..b7a0ddd24 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -119,7 +119,7 @@ struct komodo_ccdata struct komodo_state { uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID,MoM; - int32_t SAVEDHEIGHT,CURRENT_HEIGHT,NOTARIZED_HEIGHT,prevNOTARIZED_HEIGHT,MoMdepth; + int32_t SAVEDHEIGHT,CURRENT_HEIGHT,NOTARIZED_HEIGHT,PNOTARIZED_HEIGHT,PPNOTARIZED_HEIGHT,MoMdepth; uint32_t SAVEDTIMESTAMP; uint64_t deposited,issued,withdrawn,approved,redeemed,shorted; struct notarized_checkpoint *NPOINTS; int32_t NUM_NPOINTS,last_NPOINTSi; diff --git a/src/main.cpp b/src/main.cpp index 054313a21..283e8ee38 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3284,14 +3284,16 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Do this here before the block is moved to the main block files. if ( ASSETCHAINS_NOTARY_PAY != 0 && pindex->GetHeight() > 10 ) { - // do a full block scan to get notarisation position and to enforce 1 notarisation is in block only. + // do a full block scan to get notarisation position and to enforce a valid notarization is in position 1. // if notarisation in the block, must be position 1 and the coinbase must pay notaries. int notarisationTx = komodo_connectblock(true,pindex,*(CBlock *)&block); - // -1 means that more than 1 notarisation is in a block, or the notarisation is not in order. + // -1 means that the valid notarization isnt in position 1. if ( notarisationTx == -1 ) return state.DoS(100, error("ConnectBlock(): Notarisation is not in TX position 1! Invalid Block!"), REJECT_INVALID, "bad-notarization-position"); - // 1 means this block contains a valid notarisation + // 1 means this block contains a valid notarisation and its in position 1. + // its no longer possible for any attempted notarization to be in a block with a valid one! + // if notaries create a notarisation even if its not in this chain it will need to be mined inside its own block! if ( notarisationTx == 1 ) { // Check if the notaries have been paid. @@ -3906,8 +3908,8 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { return AbortNode(state, "Failed to read block"); //if ( ASSETCHAINS_SYMBOL[0] != 0 || pindexDelete->GetHeight() > 1400000 ) { - int32_t prevMoMheight,prevnotarizedht; uint256 notarizedhash,txid; - komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid,&prevnotarizedht); + int32_t prevMoMheight,prevnotarizedht,prevNotarizedHt; uint256 notarizedhash,txid; + komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid,&prevnotarizedht,&prevNotarizedHt); if ( block.GetHash() == notarizedhash ) { fprintf(stderr,"DisconnectTip trying to disconnect notarized block at ht.%d\n",(int32_t)pindexDelete->GetHeight()); @@ -4241,8 +4243,8 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo assert(MAX_REORG_LENGTH > 0);//, "We must be able to reorg some distance"); if (reorgLength > MAX_REORG_LENGTH) { - int32_t notarizedht,prevnotarizedht,prevMoMheight; uint256 notarizedhash,txid; - notarizedht = komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid,&prevnotarizedht); + int32_t notarizedht,prevnotarizedht,prevNotarizedHt,prevMoMheight; uint256 notarizedhash,txid; + notarizedht = komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid,&prevnotarizedht,&prevNotarizedHt); if ( pindexFork->GetHeight() < notarizedht ) { fprintf(stderr,"pindexFork->GetHeight().%d is < notarizedht %d, so ignore it\n",(int32_t)pindexFork->GetHeight(),notarizedht); @@ -5593,8 +5595,8 @@ uint64_t CalculateCurrentUsage() /* Prune a block file (modify associated database entries)*/ bool PruneOneBlockFile(bool tempfile, const int fileNumber) { - uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,prevnotarized_height; - notarized_height = komodo_notarized_height(&prevMoMheight,¬arized_hash,¬arized_desttxid,&prevnotarized_height); + uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,prevnotarized_height,prevNotarizedHt; + notarized_height = komodo_notarized_height(&prevMoMheight,¬arized_hash,¬arized_desttxid,&prevnotarized_height,&prevNotarizedHt); //fprintf(stderr, "pruneblockfile.%i\n",fileNumber); sleep(15); for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); ++it) { diff --git a/src/miner.cpp b/src/miner.cpp index a0934ce96..36ef947d3 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -432,6 +432,12 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 fprintf(stderr, "Notarisation %s set to maximum priority replacing notarization %s\n",hash.ToString().c_str(), Tx.GetHash().ToString().c_str()); } } + else if ( fNotarisationBlock == true ) + { + // Any attempted notarization needs to be in its own block! + // If we find a valid one and place it in position 1, an invalid one must wait until the next block to be mined. + continue; + } } } } @@ -723,12 +729,10 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 int32_t scriptlen = (int32_t)pblock->vtx[1].vout[1].scriptPubKey.size(); if ( script[0] == OP_RETURN ) { - fprintf(stderr, ">>>>>MINER NotarisationNotaries.%li\n",NotarisationNotaries.size()); uint64_t totalsats = komodo_notarypay(txNew, NotarisationNotaries, pblock->nTime, nHeight, script, scriptlen); if ( totalsats == 0 ) { fprintf(stderr, "Could not create notary payment, trying again.\n"); - // invalidnotarisation = pblock->vtx[1].GetHash().ToString(); if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) { LEAVE_CRITICAL_SECTION(cs_main); diff --git a/src/notaries_staked.cpp b/src/notaries_staked.cpp index 422d0da18..868956f8a 100644 --- a/src/notaries_staked.cpp +++ b/src/notaries_staked.cpp @@ -17,14 +17,14 @@ int8_t is_STAKED(const char *chain_name) return(0); if (doneinit == 1 && ASSETCHAINS_SYMBOL[0] != 0) return(STAKED); - if ( (strcmp(chain_name, "LABS") == 0) || (strcmp(chain_name, "LABST2") == 0) ) + if ( (strcmp(chain_name, "LABS") == 0) ) STAKED = 1; // These chains are allowed coin emissions. else if ( (strncmp(chain_name, "LABS", 4) == 0) ) STAKED = 2; // These chains have no coin emission, block subsidy is always 0, and comission is 0. Notary pay is allowed. else if ( (strcmp(chain_name, "CFEK") == 0) || (strncmp(chain_name, "CFEK", 4) == 0) ) STAKED = 3; // These chains have no speical rules at all. else if ( (strcmp(chain_name, "TEST") == 0) || (strncmp(chain_name, "TEST", 4) == 0) ) - STAKED = 4; // These chains are for testing consensus to create a chain etc. Not meant ot be actually used for anything important. + STAKED = 4; // These chains are for testing consensus to create a chain etc. Not meant to be actually used for anything important. else if ( (strcmp(chain_name, "THIS_CHAIN_IS_BANNED") == 0) ) STAKED = 255; // Any chain added to this group is banned, no notarisations are valid, as a consensus rule. Can be used to remove a chain from cluster if needed. doneinit = 1; diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index bda9da062..15386d42a 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -63,7 +63,7 @@ int32_t Jumblr_depositaddradd(char *depositaddr); int32_t Jumblr_secretaddradd(char *secretaddr); uint64_t komodo_interestsum(); int32_t komodo_longestchain(); -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp,int32_t *prevNotarizedHt); +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp,int32_t *prevNotarizedHt,int32_t *ppNotarizedHt); bool komodo_txnotarizedconfirmed(uint256 txid); uint32_t komodo_chainactive_timestamp(); int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); @@ -164,7 +164,7 @@ UniValue getnotarysendmany(const UniValue& params, bool fHelp) UniValue getinfo(const UniValue& params, bool fHelp) { - uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,prevnotarized_height,longestchain,kmdnotarized_height,txid_height; + uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,prevnotarized_height,prevNotarizedHt,longestchain,kmdnotarized_height,txid_height; if (fHelp || params.size() != 0) throw runtime_error( "getinfo\n" @@ -200,7 +200,7 @@ UniValue getinfo(const UniValue& params, bool fHelp) proxyType proxy; GetProxy(NET_IPV4, proxy); - notarized_height = komodo_notarized_height(&prevMoMheight,¬arized_hash,¬arized_desttxid,&prevnotarized_height); + notarized_height = komodo_notarized_height(&prevMoMheight,¬arized_hash,¬arized_desttxid,&prevnotarized_height,&prevNotarizedHt); //fprintf(stderr,"after notarized_height %u\n",(uint32_t)time(NULL)); UniValue obj(UniValue::VOBJ);