diff --git a/src/komodo.h b/src/komodo.h index aba93c9e4..63569e60d 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -476,7 +476,7 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp) { static uint256 zero; static FILE *signedfp; - int32_t opretlen,nid,k,len = 0; uint256 kmdtxid,desttxid; uint8_t crypto777[33]; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; + CBlockIndex *pindex; int32_t opretlen,nid,k,len = 0; uint256 kmdtxid,desttxid; uint8_t crypto777[33]; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) return(-1); if ( scriptlen == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) @@ -537,6 +537,11 @@ int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scr len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&kmdtxid); len += iguana_rwnum(0,&scriptbuf[len],sizeof(*notarizedheightp),(uint8_t *)notarizedheightp); len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid); + if ( notarized != 0 && IsInitialBlockDownload() == 0 && ((pindex= mapBlockIndex[kmdtxid]) == 0 || pindex->nHeight != *notarizedheightp) ) + { + fprintf(stderr,"%s possible FORK detected. notarized.%d %s not in this chain! last notarization %d -> rewindtarget.%d\n",ASSETCHAINS_SYMBOL,*notarizedheightp,kmdtxid.ToString().c_str(),sp->NOTARIZED_HEIGHT,sp->NOTARIZED_HEIGHT); + notarized = 0; + } if ( notarized != 0 && *notarizedheightp > sp->NOTARIZED_HEIGHT && *notarizedheightp < height && (height < sp->CURRENT_HEIGHT-1000 || komodo_verifynotarization(ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL,(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "BTC" : "KMD"),height,*notarizedheightp,kmdtxid,desttxid) == 0) ) { sp->NOTARIZED_HEIGHT = *notarizedheightp; diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index bc7ec2bd5..e9ddd4fc0 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -651,7 +651,7 @@ int32_t komodo_block2height(CBlock *block) } if ( height != height2 ) { - fprintf(stderr,"block2height height.%d vs height2.%d, match.%d mismatch.%d\n",height,height2,match,mismatch); + //fprintf(stderr,"block2height height.%d vs height2.%d, match.%d mismatch.%d\n",height,height2,match,mismatch); mismatch++; if ( height2 >= 0 ) height = height2; diff --git a/src/komodo_notary.h b/src/komodo_notary.h index e7ae7d738..0f9779129 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -202,7 +202,7 @@ uint32_t komodo_heightstamp(int32_t height); int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp) { - static uint8_t elected_pubkeys0[64][33],elected_pubkeys1[64][33],did0,did1; + static uint8_t elected_pubkeys0[64][33],elected_pubkeys1[64][33],did0,did1; static int32_t n0,n1; int32_t i,htind,n; uint64_t mask = 0; struct knotary_entry *kp,*tmp; if ( timestamp == 0 && ASSETCHAINS_SYMBOL[0] != 0 ) timestamp = komodo_heightstamp(height); @@ -214,29 +214,30 @@ int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestam { if ( did0 == 0 ) { - n = (int32_t)(sizeof(Notaries_elected0)/sizeof(*Notaries_elected0)); - for (i=0; i= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) diff --git a/src/main.cpp b/src/main.cpp index 48324ca42..cfd451f24 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2229,16 +2229,11 @@ static int64_t nTimeIndex = 0; static int64_t nTimeCallbacks = 0; static int64_t nTimeTotal = 0; -bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck) +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck,bool fCheckPOW) { const CChainParams& chainparams = Params(); //fprintf(stderr,"connectblock ht.%d\n",(int32_t)pindex->nHeight); AssertLockHeld(cs_main); -/*<<<<<<< HEA - // Check it again in case a previous version let a bad block in - bool fExpensiveChecks = (!fCheckpointsEnabled || pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints())); -======= -*/ bool fExpensiveChecks = true; if (fCheckpointsEnabled) { CBlockIndex *pindexLastCheckpoint = Checkpoints::GetLastCheckpoint(chainparams.Checkpoints()); @@ -2252,7 +2247,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin auto disabledVerifier = libzcash::ProofVerifier::Disabled(); // 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, !fJustCheck, !fJustCheck)) + if (!CheckBlock(pindex->nHeight,pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck)) return false; // verify that the view's current state corresponds to the previous block @@ -3214,8 +3209,8 @@ bool CheckBlockHeader(int32_t height,CBlockIndex *pindex, const CBlockHeader& bl // return state.DoS(100, error("CheckBlockHeader(): block version too low"),REJECT_INVALID, "version-too-low"); // Check Equihash solution is valid - if ( fCheckPOW && !CheckEquihashSolution(&blockhdr, Params()) ) - return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution"); + /*if ( fCheckPOW && !CheckEquihashSolution(&blockhdr, Params()) ) + return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution");*/ // Check proof of work matches claimed amount /*komodo_index2pubkey33(pubkey33,pindex,height); @@ -3235,7 +3230,12 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat // Check that the header is valid (particularly PoW). This is mostly // redundant with the call in AcceptBlockHeader. if (!CheckBlockHeader(height,pindex,block,state,fCheckPOW)) + { + fprintf(stderr,"CheckBlockHeader error in CheckBlock\n"); return false; + } + 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()) ) return state.DoS(50, error("CheckBlock(): proof of work failed"),REJECT_INVALID, "high-hash"); @@ -3407,43 +3407,12 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc *ppindex = pindex; if (pindex != 0 && pindex->nStatus & BLOCK_FAILED_MASK) return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate"); - if ( pindex != 0 && IsInitialBlockDownload() == 0 ) // jl777 - { - if (!CheckBlockHeader(pindex->nHeight,pindex, block, state)) - { - pindex->nStatus |= BLOCK_FAILED_MASK; - fprintf(stderr,"known block failing CheckBlockHeader %d\n",(int32_t)pindex->nHeight); - return false; - } - CBlockIndex* pindexPrev = NULL; - if (hash != chainparams.GetConsensus().hashGenesisBlock) - { - BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); - if (mi == mapBlockIndex.end()) - { - pindex->nStatus |= BLOCK_FAILED_MASK; - fprintf(stderr,"known block.%d failing to find prevblock\n",(int32_t)pindex->nHeight); - return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk"); - } - pindexPrev = (*mi).second; - if (pindexPrev == 0 || (pindexPrev->nStatus & BLOCK_FAILED_MASK) ) - { - pindex->nStatus |= BLOCK_FAILED_MASK; - fprintf(stderr,"known block.%d found invalid prevblock\n",(int32_t)pindex->nHeight); - return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); - } - } - if (!ContextualCheckBlockHeader(block, state, pindexPrev)) - { - pindex->nStatus |= BLOCK_FAILED_MASK; - //fprintf(stderr,"known block.%d failing ContextualCheckBlockHeader\n",(int32_t)pindex->nHeight); - return false; - } - } - return true; + if ( *ppindex == 0 ) + fprintf(stderr,"acceptblockheader returns null ptr\n"); + return true; } - if (!CheckBlockHeader(*ppindex!=0?(*ppindex)->nHeight:0,*ppindex, block, state)) + if (!CheckBlockHeader(*ppindex!=0?(*ppindex)->nHeight:0,*ppindex, block, state,0)) return false; // Get prev block index @@ -3459,7 +3428,10 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc if (!ContextualCheckBlockHeader(block, state, pindexPrev)) return false; if (pindex == NULL) - pindex = AddToBlockIndex(block); + { + if ( (pindex= AddToBlockIndex(block)) == 0 ) + fprintf(stderr,"addtoblockindex failed\n"); + } if (ppindex) *ppindex = pindex; return true; @@ -3501,7 +3473,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, // See method docstring for why this is always disabled auto verifier = libzcash::ProofVerifier::Disabled(); - if ((!CheckBlock(pindex->nHeight,pindex,block, state, verifier)) || !ContextualCheckBlock(block, state, pindex->pprev)) { + if ((!CheckBlock(pindex->nHeight,pindex,block, state, verifier,0)) || !ContextualCheckBlock(block, state, pindex->pprev)) { if (state.IsInvalid() && !state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; setDirtyBlockIndex.insert(pindex); @@ -3556,8 +3528,8 @@ bool ProcessNewBlock(int32_t height,CValidationState &state, CNode* pfrom, CBloc if ( chainActive.Tip() != 0 ) komodo_currentheight_set(chainActive.Tip()->nHeight); if ( ASSETCHAINS_SYMBOL[0] == 0 ) - checked = CheckBlock(height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier); - else checked = CheckBlock(height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier); + 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); bool fRequested = MarkBlockAsReceived(pblock->GetHash()); @@ -3605,7 +3577,7 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex } if (!CheckBlock(indexDummy.nHeight,0,block, state, verifier, fCheckPOW, fCheckMerkleRoot)) { - //fprintf(stderr,"TestBlockValidity failure B\n"); + fprintf(stderr,"TestBlockValidity failure B\n"); return false; } if (!ContextualCheckBlock(block, state, pindexPrev)) @@ -3613,7 +3585,7 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex fprintf(stderr,"TestBlockValidity failure C\n"); return false; } - if (!ConnectBlock(block, state, &indexDummy, viewNew, true)) + if (!ConnectBlock(block, state, &indexDummy, viewNew, true,fCheckPOW)) { fprintf(stderr,"TestBlockValidity failure D\n"); return false; @@ -3962,7 +3934,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth if (!ReadBlockFromDisk(block, pindex)) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 1: verify block validity - if (nCheckLevel >= 1 && !CheckBlock(pindex->nHeight,pindex,block, state, verifier)) + if (nCheckLevel >= 1 && !CheckBlock(pindex->nHeight,pindex,block, state, verifier,0)) return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 2: verify undo validity if (nCheckLevel >= 2 && pindex) { @@ -4001,7 +3973,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth CBlock block; if (!ReadBlockFromDisk(block, pindex)) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); - if (!ConnectBlock(block, state, pindex, coins)) + if (!ConnectBlock(block, state, pindex, coins,false,true)) return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } } diff --git a/src/main.h b/src/main.h index bcdd04a5e..e5b63bddf 100644 --- a/src/main.h +++ b/src/main.h @@ -410,7 +410,7 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex); bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL); /** Apply the effects of this block (with given index) on the UTXO set represented by coins */ -bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false,bool fCheckPOW = false); /** Context-independent validity checks */ bool CheckBlockHeader(int32_t height,CBlockIndex *pindex,const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); diff --git a/src/miner.cpp b/src/miner.cpp index 7c44915d2..2a0648238 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -861,6 +861,12 @@ void static BitcoinMiner() // fprintf(stderr," missed target\n"); return false; } + CValidationState tmpstate; + if ( !TestBlockValidity(tmpstate, *pblock, chainActive.Tip(), true, false)) + { + fprintf(stderr,"formerly valid mining block became invalid\n"); + return false; + } if ( /*ASSETCHAINS_SYMBOL[0] == 0 &&*/ Mining_start != 0 && time(NULL) < Mining_start+roundrobin_delay ) { //printf("Round robin diff sleep %d\n",(int32_t)(Mining_start+roundrobin_delay-time(NULL))); @@ -1002,12 +1008,6 @@ void static BitcoinMiner() // Changing pblock->nTime can change work required on testnet: hashTarget.SetCompact(pblock->nBits); } - /*CValidationState tmpstate; - if ( !TestBlockValidity(tmpstate, *pblock, pindexPrev, false, false)) - { - fprintf(stderr,"formerly valid mining block became invalid, likely due to tx expiration\n"); - break; - }*/ } } } diff --git a/zcutil/build.sh b/zcutil/build.sh index 2e3837f3a..f789c7a8d 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -88,5 +88,5 @@ PREFIX="$(pwd)/depends/$BUILD/" HOST="$HOST" BUILD="$BUILD" NO_RUST="$RUST_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh -CC="$CC" CXX="$CXX" ./configure --prefix="${PREFIX}" --host="$HOST" --build="$BUILD" "$RUST_ARG" "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" CXXFLAGS='-fwrapv -fno-strict-aliasing -Werror -g' +CC="$CC" CXX="$CXX" ./configure --prefix="${PREFIX}" --host="$HOST" --build="$BUILD" "$RUST_ARG" "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" CXXFLAGS='-fwrapv -fno-strict-aliasing -g' "$MAKE" "$@" V=1