|
|
@ -1600,7 +1600,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock |
|
|
|
|
|
|
|
if (pindexSlow) { |
|
|
|
CBlock block; |
|
|
|
if (ReadBlockFromDisk(block, pindexSlow)) { |
|
|
|
if (ReadBlockFromDisk(block, pindexSlow,1)) { |
|
|
|
BOOST_FOREACH(const CTransaction &tx, block.vtx) { |
|
|
|
if (tx.GetHash() == hash) { |
|
|
|
txOut = tx; |
|
|
@ -1655,7 +1655,7 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::M |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
bool ReadBlockFromDisk(int32_t height,CBlock& block, const CDiskBlockPos& pos) |
|
|
|
bool ReadBlockFromDisk(int32_t height,CBlock& block, const CDiskBlockPos& pos,bool checkPOW) |
|
|
|
{ |
|
|
|
uint8_t pubkey33[33]; |
|
|
|
block.SetNull(); |
|
|
@ -1677,23 +1677,26 @@ bool ReadBlockFromDisk(int32_t height,CBlock& block, const CDiskBlockPos& pos) |
|
|
|
return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString()); |
|
|
|
} |
|
|
|
// Check the header
|
|
|
|
komodo_block2pubkey33(pubkey33,(CBlock *)&block); |
|
|
|
if (!(CheckEquihashSolution(&block, Params()) && CheckProofOfWork(height,pubkey33,block.GetHash(), block.nBits, Params().GetConsensus(),block.nTime))) |
|
|
|
if ( checkPOW != 0 ) |
|
|
|
{ |
|
|
|
int32_t i; for (i=0; i<33; i++) |
|
|
|
fprintf(stderr,"%02x",pubkey33[i]); |
|
|
|
fprintf(stderr," warning unexpected diff at ht.%d\n",height); |
|
|
|
|
|
|
|
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); |
|
|
|
komodo_block2pubkey33(pubkey33,(CBlock *)&block); |
|
|
|
if (!(CheckEquihashSolution(&block, Params()) && CheckProofOfWork(height,pubkey33,block.GetHash(), block.nBits, Params().GetConsensus(),block.nTime))) |
|
|
|
{ |
|
|
|
int32_t i; for (i=0; i<33; i++) |
|
|
|
fprintf(stderr,"%02x",pubkey33[i]); |
|
|
|
fprintf(stderr," warning unexpected diff at ht.%d\n",height); |
|
|
|
|
|
|
|
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex) |
|
|
|
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW) |
|
|
|
{ |
|
|
|
if ( pindex == 0 ) |
|
|
|
return false; |
|
|
|
if (!ReadBlockFromDisk(pindex->nHeight,block, pindex->GetBlockPos())) |
|
|
|
if (!ReadBlockFromDisk(pindex->nHeight,block, pindex->GetBlockPos(),checkPOW)) |
|
|
|
return false; |
|
|
|
if (block.GetHash() != pindex->GetBlockHash()) |
|
|
|
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", |
|
|
@ -3080,7 +3083,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { |
|
|
|
assert(pindexDelete); |
|
|
|
// Read block from disk.
|
|
|
|
CBlock block; |
|
|
|
if (!ReadBlockFromDisk(block, pindexDelete)) |
|
|
|
if (!ReadBlockFromDisk(block, pindexDelete,1)) |
|
|
|
return AbortNode(state, "Failed to read block"); |
|
|
|
// Apply the block atomically to the chain state.
|
|
|
|
uint256 anchorBeforeDisconnect = pcoinsTip->GetBestAnchor(); |
|
|
@ -3147,7 +3150,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * |
|
|
|
int64_t nTime1 = GetTimeMicros(); |
|
|
|
CBlock block; |
|
|
|
if (!pblock) { |
|
|
|
if (!ReadBlockFromDisk(block, pindexNew)) |
|
|
|
if (!ReadBlockFromDisk(block, pindexNew,1)) |
|
|
|
return AbortNode(state, "Failed to read block"); |
|
|
|
pblock = █ |
|
|
|
} |
|
|
@ -3750,7 +3753,7 @@ bool CheckBlockHeader(int32_t height,CBlockIndex *pindex, const CBlockHeader& bl |
|
|
|
{ |
|
|
|
if ( !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);
|
|
|
|
if ( fCheckPOW && !CheckProofOfWork(height,pubkey33,blockhdr.GetHash(), blockhdr.nBits, Params().GetConsensus(),blockhdr.nTime) ) |
|
|
@ -3760,6 +3763,38 @@ bool CheckBlockHeader(int32_t height,CBlockIndex *pindex, const CBlockHeader& bl |
|
|
|
|
|
|
|
int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime); |
|
|
|
|
|
|
|
int32_t komodo_fast_checkPOW(CBlock *pblock,int32_t height) |
|
|
|
{ |
|
|
|
arith_uint256 bnTarget; bool fNegative,fOverflow; uint8_t pubkey33[33],pubkeys[64][33]; int32_t i,n,failed = 0,notaryid = -1; |
|
|
|
if ( !CheckEquihashSolution(pblock, Params()) ) |
|
|
|
{ |
|
|
|
fprintf(stderr,"komodo_fast_checkPOW ht.%d CheckEquihashSolution failed\n",height); |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
bnTarget.SetCompact(nBits, &fNegative, &fOverflow); |
|
|
|
if ( UintToArith256(hash) > bnTarget ) |
|
|
|
{ |
|
|
|
failed = 1; |
|
|
|
if ( ASSETCHAINS_SYMBOL[0] == 0 ) |
|
|
|
{ |
|
|
|
komodo_block2pubkey33(pubkey33,pblock); |
|
|
|
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; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
fprintf(stderr,"komodo_fast_checkPOW ht.%d notaryid.%d failed.%d\n",height,notaryid,failed); |
|
|
|
if ( failed != 0 && notaryid < 0 ) |
|
|
|
return(-1); |
|
|
|
else return(0); |
|
|
|
} |
|
|
|
|
|
|
|
bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, |
|
|
|
libzcash::ProofVerifier& verifier, |
|
|
|
bool fCheckPOW, bool fCheckMerkleRoot) |
|
|
@ -3775,23 +3810,23 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat |
|
|
|
return false; |
|
|
|
} |
|
|
|
if ( fCheckPOW && !CheckEquihashSolution(&block, Params()) ) |
|
|
|
return state.DoS(100, error("CheckBlock(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution"); |
|
|
|
return state.DoS(100, error("CheckBlock: 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"); |
|
|
|
return state.DoS(1, error("CheckBlock: proof of work failed"),REJECT_INVALID, "high-hash"); |
|
|
|
// Check the merkle root.
|
|
|
|
if (fCheckMerkleRoot) { |
|
|
|
bool mutated; |
|
|
|
uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated); |
|
|
|
if (block.hashMerkleRoot != hashMerkleRoot2) |
|
|
|
return state.DoS(100, error("CheckBlock(): hashMerkleRoot mismatch"), |
|
|
|
return state.DoS(100, error("CheckBlock: hashMerkleRoot mismatch"), |
|
|
|
REJECT_INVALID, "bad-txnmrklroot", true); |
|
|
|
|
|
|
|
// Check for merkle tree malleability (CVE-2012-2459): repeating sequences
|
|
|
|
// of transactions in a block without affecting the merkle root of a block,
|
|
|
|
// while still invalidating it.
|
|
|
|
if (mutated) |
|
|
|
return state.DoS(100, error("CheckBlock(): duplicate transaction"), |
|
|
|
return state.DoS(100, error("CheckBlock: duplicate transaction"), |
|
|
|
REJECT_INVALID, "bad-txns-duplicate", true); |
|
|
|
} |
|
|
|
|
|
|
@ -3801,16 +3836,16 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat |
|
|
|
|
|
|
|
// Size limits
|
|
|
|
if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) |
|
|
|
return state.DoS(100, error("CheckBlock(): size limits failed"), |
|
|
|
return state.DoS(100, error("CheckBlock: size limits failed"), |
|
|
|
REJECT_INVALID, "bad-blk-length"); |
|
|
|
|
|
|
|
// First transaction must be coinbase, the rest must not be
|
|
|
|
if (block.vtx.empty() || !block.vtx[0].IsCoinBase()) |
|
|
|
return state.DoS(100, error("CheckBlock(): first tx is not coinbase"), |
|
|
|
return state.DoS(100, error("CheckBlock: first tx is not coinbase"), |
|
|
|
REJECT_INVALID, "bad-cb-missing"); |
|
|
|
for (unsigned int i = 1; i < block.vtx.size(); i++) |
|
|
|
if (block.vtx[i].IsCoinBase()) |
|
|
|
return state.DoS(100, error("CheckBlock(): more than one coinbase"), |
|
|
|
return state.DoS(100, error("CheckBlock: more than one coinbase"), |
|
|
|
REJECT_INVALID, "bad-cb-multiple"); |
|
|
|
|
|
|
|
// Check transactions
|
|
|
@ -3819,7 +3854,7 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat |
|
|
|
if ( komodo_validate_interest(tx,height == 0 ? komodo_block2height((CBlock *)&block) : height,block.nTime,1) < 0 ) |
|
|
|
return error("CheckBlock: komodo_validate_interest failed"); |
|
|
|
if (!CheckTransaction(tx, state, verifier)) |
|
|
|
return error("CheckBlock(): CheckTransaction failed"); |
|
|
|
return error("CheckBlock: CheckTransaction failed"); |
|
|
|
} |
|
|
|
unsigned int nSigOps = 0; |
|
|
|
BOOST_FOREACH(const CTransaction& tx, block.vtx) |
|
|
@ -3827,7 +3862,7 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat |
|
|
|
nSigOps += GetLegacySigOpCount(tx); |
|
|
|
} |
|
|
|
if (nSigOps > MAX_BLOCK_SIGOPS) |
|
|
|
return state.DoS(100, error("CheckBlock(): out-of-bounds SigOpCount"), |
|
|
|
return state.DoS(100, error("CheckBlock: out-of-bounds SigOpCount"), |
|
|
|
REJECT_INVALID, "bad-blk-sigops", true); |
|
|
|
if ( komodo_check_deposit(height,block,(pindex==0||pindex->pprev==0)?0:pindex->pprev->nTime) < 0 ) |
|
|
|
{ |
|
|
@ -4003,7 +4038,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, |
|
|
|
} |
|
|
|
if ( pindex == 0 ) |
|
|
|
{ |
|
|
|
fprintf(stderr,"unexpected AcceptBlock error null pindex\n"); |
|
|
|
//fprintf(stderr,"unexpected AcceptBlock error null pindex\n");
|
|
|
|
return false; |
|
|
|
} |
|
|
|
//fprintf(stderr,"acceptblockheader passed\n");
|
|
|
@ -4091,6 +4126,8 @@ bool ProcessNewBlock(int32_t height,CValidationState &state, CNode* pfrom, CBloc |
|
|
|
LOCK(cs_main); |
|
|
|
bool fRequested = MarkBlockAsReceived(pblock->GetHash()); |
|
|
|
fRequested |= fForceProcessing; |
|
|
|
if ( checked != 0 && komodo_fast_checkPOW(pblock,height) < 0 ) |
|
|
|
checked = 0; |
|
|
|
if (!checked) |
|
|
|
{ |
|
|
|
if ( pfrom != 0 ) |
|
|
@ -4552,7 +4589,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth |
|
|
|
break; |
|
|
|
CBlock block; |
|
|
|
// check level 0: read from disk
|
|
|
|
if (!ReadBlockFromDisk(block, pindex)) |
|
|
|
if (!ReadBlockFromDisk(block, pindex,0)) |
|
|
|
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,0)) |
|
|
@ -4592,7 +4629,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth |
|
|
|
uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)))); |
|
|
|
pindex = chainActive.Next(pindex); |
|
|
|
CBlock block; |
|
|
|
if (!ReadBlockFromDisk(block, pindex)) |
|
|
|
if (!ReadBlockFromDisk(block, pindex,0)) |
|
|
|
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); |
|
|
|
if (!ConnectBlock(block, state, pindex, coins,false, true)) |
|
|
|
return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); |
|
|
@ -4851,7 +4888,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) |
|
|
|
int nLoaded = 0; |
|
|
|
try { |
|
|
|
// This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
|
|
|
|
CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION); |
|
|
|
//CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION);
|
|
|
|
CBufferedFile blkdat(fileIn, 256*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION); |
|
|
|
uint64_t nRewind = blkdat.GetPos(); |
|
|
|
while (!blkdat.eof()) { |
|
|
|
boost::this_thread::interruption_point(); |
|
|
@ -4917,7 +4955,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) |
|
|
|
std::pair<std::multimap<uint256, CDiskBlockPos>::iterator, std::multimap<uint256, CDiskBlockPos>::iterator> range = mapBlocksUnknownParent.equal_range(head); |
|
|
|
while (range.first != range.second) { |
|
|
|
std::multimap<uint256, CDiskBlockPos>::iterator it = range.first; |
|
|
|
if (ReadBlockFromDisk(mapBlockIndex[hash]!=0?mapBlockIndex[hash]->nHeight:0,block, it->second)) |
|
|
|
if (ReadBlockFromDisk(mapBlockIndex[hash]!=0?mapBlockIndex[hash]->nHeight:0,block, it->second,1)) |
|
|
|
{ |
|
|
|
LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), |
|
|
|
head.ToString()); |
|
|
@ -5276,7 +5314,7 @@ void static ProcessGetData(CNode* pfrom) |
|
|
|
{ |
|
|
|
// Send block from disk
|
|
|
|
CBlock block; |
|
|
|
if (!ReadBlockFromDisk(block, (*mi).second)) |
|
|
|
if (!ReadBlockFromDisk(block, (*mi).second,1)) |
|
|
|
{ |
|
|
|
assert(!"cannot load block from disk"); |
|
|
|
} |
|
|
|