Browse Source

Merge pull request #20 from jl777/dev

update dev
pull/4/head
ca333 6 years ago
committed by GitHub
parent
commit
d3c94f437a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 36
      src/komodo_bitcoind.h
  2. 1
      src/komodo_defs.h
  3. 85
      src/main.cpp
  4. 24
      src/miner.cpp
  5. 2
      src/wallet/rpcwallet.cpp

36
src/komodo_bitcoind.h

@ -658,7 +658,7 @@ int32_t komodo_block2height(CBlock *block)
return(height);
}
void komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block)
int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block)
{
int32_t n;
if ( KOMODO_LOADINGBLOCKS == 0 )
@ -674,8 +674,12 @@ void komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block)
//komodo_init(0);
n = block->vtx[0].vout[0].scriptPubKey.size();
if ( n == 35 )
{
memcpy(pubkey33,ptr+1,33);
return(1);
}
}
return(0);
}
int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex)
@ -1045,7 +1049,7 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_
}
/*
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
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
@ -1166,6 +1170,8 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he
percPoS++;
fprintf(stderr,"0");
}
if ( (i % 10) == 9 )
fprintf(stderr," %d, ",percPoS);
}
}
fprintf(stderr," -> %d%% percPoS ht.%d\n",percPoS,height);
@ -1261,28 +1267,29 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
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,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev;
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();
if ( height == 0 )
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 && slowflag != 0 ) // we need to assume all prior height is in the block index
{
if ( (pprev= mapBlockIndex[pblock->hashPrevBlock]) != 0 )
height = pprev->nHeight + 1;
fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d zeroheight\n",slowflag,height);
fprintf(stderr,"komodo_checkPOW slowflag.%d zeroheight -> calcht.%d \n",slowflag,height);
//if ( height == 0 )
return(0);
return(-1);
}
bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow);
bhash = UintToArith256(hash);
komodo_block2pubkey33(pubkey33,pblock);
if ( bhash > bnTarget )
{
failed = 1;
if ( ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case
if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case
{
if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 )
{
@ -1294,6 +1301,11 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
}
}
}
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
{
@ -1337,8 +1349,8 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
}
}
}
fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d notaryid.%d failed.%d\n",slowflag,height,notaryid,failed);
if ( failed != 0 && notaryid < 0 )
//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);
}

1
src/komodo_defs.h

@ -5,5 +5,6 @@
#define KOMODO_ELECTION_GAP 2000
#define ROUNDROBIN_DELAY 61
#define KOMODO_ASSETCHAIN_MAXLEN 65
#define KOMODO_LIMITED_NETWORKSIZE 4
#endif

85
src/main.cpp

@ -55,7 +55,7 @@ CCriticalSection cs_main;
extern uint8_t NOTARY_PUBKEY33[33];
extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN;
int32_t KOMODO_NEWBLOCKS;
void komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block);
int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block);
BlockMap mapBlockIndex;
CChain chainActive;
@ -3541,9 +3541,22 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
// Check for duplicate
uint256 hash = block.GetHash();
BlockMap::iterator it = mapBlockIndex.find(hash);
BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
if (it != mapBlockIndex.end())
return it->second;
{
//if ( ASSETCHAINS_STAKED == 0 || it->second != 0 ) // change behavior to allow komodo_ensure to work
if ( vNodes.size() >= KOMODO_LIMITED_NETWORKSIZE || it->second != 0 ) // 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
CBlockIndex* pindexNew = new CBlockIndex(block);
assert(pindexNew);
@ -3553,11 +3566,11 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
pindexNew->nSequenceId = 0;
BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
if (miPrev != mapBlockIndex.end())
{
pindexNew->pprev = (*miPrev).second;
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
if ( (pindexNew->pprev= (*miPrev).second) != 0 )
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
else fprintf(stderr,"unexpected null pprev %s\n",hash.ToString().c_str());
pindexNew->BuildSkip();
}
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew);
@ -3566,7 +3579,7 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
pindexBestHeader = pindexNew;
setDirtyBlockIndex.insert(pindexNew);
//fprintf(stderr,"added to block index %s %p\n",hash.ToString().c_str(),pindexNew);
return pindexNew;
}
@ -3742,7 +3755,7 @@ bool CheckBlockHeader(int32_t height,CBlockIndex *pindex, const CBlockHeader& bl
}
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 )
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);
return state.Invalid(error("CheckBlockHeader(): block timestamp needs to always increase"),REJECT_INVALID, "time-too-new");
@ -3779,7 +3792,7 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat
// redundant with the call in AcceptBlockHeader.
if (!CheckBlockHeader(height,pindex,block,state,fCheckPOW))
{
fprintf(stderr,"checkblockheader error PoW.%d\n",fCheckPOW);
//fprintf(stderr,"checkblockheader error PoW.%d\n",fCheckPOW);
return false;
}
if ( fCheckPOW )
@ -3851,7 +3864,7 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat
{
//static uint32_t counter;
//if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 )
fprintf(stderr,"check deposit rejection\n");
// fprintf(stderr,"check deposit rejection\n");
return(false);
}
return true;
@ -3963,7 +3976,7 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
// Check for duplicate
uint256 hash = block.GetHash();
BlockMap::iterator miSelf = mapBlockIndex.find(hash);
CBlockIndex *tipindex,*pindex = NULL;
CBlockIndex *pindex = NULL;
if (miSelf != mapBlockIndex.end())
{
// Block header is already known.
@ -3972,11 +3985,13 @@ 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 )
// fprintf(stderr,"accepthdr %s already known but no pindex\n",hash.ToString().c_str());
return true;
}
if (!CheckBlockHeader(*ppindex!=0?(*ppindex)->nHeight:0,*ppindex, block, state,0))
{
fprintf(stderr,"CheckBlockHeader failed\n");
//fprintf(stderr,"CheckBlockHeader failed\n");
return false;
}
// Get prev block index
@ -4016,12 +4031,12 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
CBlockIndex *&pindex = *ppindex;
if (!AcceptBlockHeader(block, state, &pindex))
{
fprintf(stderr,"AcceptBlockHeader rejected\n");
//fprintf(stderr,"AcceptBlockHeader rejected\n");
return false;
}
if ( pindex == 0 )
{
//fprintf(stderr,"unexpected AcceptBlock error null pindex\n");
fprintf(stderr,"AcceptBlock error null pindex\n");
return false;
}
//fprintf(stderr,"acceptblockheader passed\n");
@ -4039,6 +4054,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
// TODO: deal better with return value and error conditions for duplicate
// 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 (!fRequested) { // If we didn't ask for it:
if (pindex->nTx != 0) return true; // This is a previously-processed block that was pruned
@ -4054,7 +4070,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
}
fprintf(stderr,"CheckBlock or ContextualCheckBlock failed\n");
//fprintf(stderr,"CheckBlock or ContextualCheckBlock failed\n");
return false;
}
@ -4097,17 +4113,33 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
void komodo_currentheight_set(int32_t height);
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);
}
}
}
bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp)
{
// Preliminary checks
bool checked;
bool checked; uint256 hash;
auto verifier = libzcash::ProofVerifier::Disabled();
hash = pblock->GetHash();
//fprintf(stderr,"process newblock %s\n",hash.ToString().c_str());
if ( chainActive.Tip() != 0 )
komodo_currentheight_set(chainActive.Tip()->nHeight);
checked = CheckBlock(height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0);
{
LOCK(cs_main);
bool fRequested = MarkBlockAsReceived(pblock->GetHash());
bool fRequested = MarkBlockAsReceived(hash);
fRequested |= fForceProcessing;
if ( checked != 0 && komodo_checkPOW(from_miner && ASSETCHAINS_STAKED == 0,pblock,height) < 0 )
{
@ -4122,9 +4154,13 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo
}
return error("%s: CheckBlock FAILED", __func__);
}
// Store to disk
CBlockIndex *pindex = NULL;
if ( vNodes.size() < KOMODO_LIMITED_NETWORKSIZE ) //ASSETCHAINS_STAKED != 0 )//
{
// 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(*pblock, state, &pindex, fRequested, dbp);
if (pindex && pfrom) {
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
@ -4132,6 +4168,7 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo
CheckBlockIndex();
if (!ret)
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))
@ -4154,22 +4191,22 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
// NOTE: CheckBlockHeader is called by CheckBlock
if (!ContextualCheckBlockHeader(block, state, pindexPrev))
{
fprintf(stderr,"TestBlockValidity failure A checkPOW.%d\n",fCheckPOW);
//fprintf(stderr,"TestBlockValidity failure A checkPOW.%d\n",fCheckPOW);
return false;
}
if (!CheckBlock(indexDummy.nHeight,0,block, state, verifier, fCheckPOW, fCheckMerkleRoot))
{
fprintf(stderr,"TestBlockValidity failure B checkPOW.%d\n",fCheckPOW);
//fprintf(stderr,"TestBlockValidity failure B checkPOW.%d\n",fCheckPOW);
return false;
}
if (!ContextualCheckBlock(block, state, pindexPrev))
{
fprintf(stderr,"TestBlockValidity failure C checkPOW.%d\n",fCheckPOW);
//fprintf(stderr,"TestBlockValidity failure C checkPOW.%d\n",fCheckPOW);
return false;
}
if (!ConnectBlock(block, state, &indexDummy, viewNew, true,fCheckPOW))
{
fprintf(stderr,"TestBlockValidity failure D checkPOW.%d\n",fCheckPOW);
//fprintf(stderr,"TestBlockValidity failure D checkPOW.%d\n",fCheckPOW);
return false;
}
assert(state.IsValid());
@ -4350,7 +4387,8 @@ CBlockIndex * InsertBlockIndex(uint256 hash)
throw runtime_error("LoadBlockIndex(): new CBlockIndex failed");
mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
//fprintf(stderr,"inserted to block index %s\n",hash.ToString().c_str());
return pindexNew;
}
@ -5975,6 +6013,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
Misbehaving(pfrom->GetId(), 20);
return error("non-continuous headers sequence");
}
//fprintf(stderr,"headers msg nCount.%d\n",(int32_t)nCount);
if (!AcceptBlockHeader(header, state, &pindexLast)) {
int nDoS;
if (state.IsInvalid(nDoS))

24
src/miner.cpp

@ -392,7 +392,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
{
uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid,revtxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr;
CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1);
blocktime += 2;
//if ( blocktime > pindexPrev->GetMedianTimePast()+60 )
// blocktime = pindexPrev->GetMedianTimePast() + 60;
if ( (siglen= komodo_staked(txStaked,pblock->nBits,&blocktime,&txtime,&utxotxid,&utxovout,&utxovalue,utxosig)) > 0 )
{
CAmount txfees = 0;
@ -401,9 +402,9 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked));
nFees += txfees;
pblock->nTime = blocktime;
if ( GetAdjustedTime() < pblock->nTime )
if ( GetAdjustedTime() < pblock->nTime )//|| pblock->GetBlockTime() > GetAdjustedTime() + 60)
{
printf("need to wait %d seconds to submit: ",(int32_t)(pblock->nTime - GetAdjustedTime()));
fprintf(stderr,"need to wait %d seconds to mine:\n",(int32_t)(pblock->nTime - GetAdjustedTime()));
while ( GetAdjustedTime()+30 < pblock->nTime )
{
sleep(30);
@ -412,8 +413,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
fprintf(stderr,"finished waiting\n");
//sleep(pblock->nTime - GetAdjustedTime());
}
} else fprintf(stderr,"no utxos eligible for staking\n");
} else return(0); //fprintf(stderr,"no utxos eligible for staking\n");
}
// Create coinbase tx
@ -635,19 +635,24 @@ static bool ProcessBlockFound(CBlock* pblock)
return error("KomodoMiner: ProcessNewBlock, block not accepted");
TrackMinedBlock(pblock->GetHash());
if ( ASSETCHAINS_STAKED != 0 )
if ( vNodes.size() < KOMODO_LIMITED_NETWORKSIZE*2 )
{
fprintf(stderr,"broadcast new block t.%u\n",(uint32_t)time(NULL));
int32_t n = 1;
//fprintf(stderr,"broadcast new block t.%u\n",(uint32_t)time(NULL));
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
if ( pnode->hSocket == INVALID_SOCKET )
continue;
pnode->PushMessage("block", *pblock);
if ( (rand() % n) == 0 )
{
pnode->PushMessage("block", *pblock);
n++;
}
}
}
fprintf(stderr,"finished broadcast new block t.%u\n",(uint32_t)time(NULL));
//fprintf(stderr,"finished broadcast new block t.%u\n",(uint32_t)time(NULL));
}
return true;
}
@ -765,6 +770,7 @@ void static BitcoinMiner()
static uint32_t counter;
if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 )
fprintf(stderr,"created illegal block, retry\n");
sleep(3);
continue;
}
unique_ptr<CBlockTemplate> pblocktemplate(ptr);

2
src/wallet/rpcwallet.cpp

@ -4558,7 +4558,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
for (i=0; i<siglen; i++)
utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
//fprintf(stderr," siglen.%d\n",siglen);
fprintf(stderr,"best %u from %u, gap %d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep));
fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
*blocktimep = earliest;
}
}

Loading…
Cancel
Save