// // Create a new block with just given transactions, coinbase paying to // scriptPubKey, and try to add it to the current chain. // CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey) { const CChainParams& chainparams = Params(); CBlockTemplate *pblocktemplate = CreateNewBlock(chainparams, scriptPubKey); CBlock& block = pblocktemplate->block; // Replace mempool-selected txns with just coinbase plus passed-in txns: block.vtx.resize(1); BOOST_FOREACH(const CMutableTransaction& tx, txns) block.vtx.push_back(tx); // IncrementExtraNonce creates a valid coinbase and merkleRoot unsigned int extraNonce = 0; IncrementExtraNonce(&block, chainActive.Tip(), extraNonce); while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; ProcessNewBlock(chainparams, &block, true, NULL, NULL); CBlock result = block; delete pblocktemplate; return result; }
// // Create a new block with just given transactions, coinbase paying to // scriptPubKey, and try to add it to the current chain. // CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey) { const CChainParams& chainparams = Params(); std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); CBlock& block = pblocktemplate->block; // Replace mempool-selected txns with just coinbase plus passed-in txns: block.vtx.resize(1); for (const CMutableTransaction& tx : txns) block.vtx.push_back(MakeTransactionRef(tx)); // IncrementExtraNonce creates a valid coinbase and merkleRoot unsigned int extraNonce = 0; IncrementExtraNonce(&block, chainActive.Tip(), extraNonce); while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block); ProcessNewBlock(chainparams, shared_pblock, true, nullptr); CBlock result = block; return result; }
int PrimeWorker::HandleRequest(zmq_pollitem_t *item) { proto::Request& req = mRequest; zmsg_t* msg = ReceiveRequest(req, item->socket); if(!msg) return 0; //req.PrintDebugString(); proto::Request::Type rtype = req.type(); proto::Reply::ErrType etype = proto::Reply::NONE; proto::Reply& rep = mReply; rep.Clear(); rep.set_type(rtype); rep.set_reqid(req.reqid()); if(!proto::Request::Type_IsValid(rtype)){ printf("ERROR: !proto::Request::Type_IsValid.\n"); rtype = proto::Request::NONE; etype = proto::Reply::INVALID; } while(etype == proto::Reply::NONE) { int vstatus = CheckVersion(req.version()); if(vstatus <= 0){ rep.set_errstr("Your miner version is no longer supported. Please upgrade."); etype = proto::Reply::VERSION; break; } if(rtype == proto::Request::CONNECT){ rep.mutable_sinfo()->CopyFrom(mServerInfo); if(vstatus == 1){ etype = proto::Reply::VERSION; rep.set_errstr("Your miner version will no longer be supported in the near future. Please upgrade."); } }else if(rtype == proto::Request::GETWORK){ if(!mCurrBlock.has_height()){ etype = proto::Reply::HEIGHT; break; } if(req.height() != mCurrHeight){ etype = proto::Reply::HEIGHT; break; } CBlock *pblock = &mBlockTemplate->block; IncrementExtraNonce(pblock, mIndexPrev, mExtraNonce); pblock->nTime = std::max(pblock->nTime, (unsigned int)GetAdjustedTime()); mNonceMap[pblock->hashMerkleRoot] = mExtraNonce; proto::Work* work = rep.mutable_work(); work->set_height(mCurrHeight); work->set_merkle(pblock->hashMerkleRoot.GetHex()); work->set_time(pblock->nTime); work->set_bits(pblock->nBits); }else if(rtype == proto::Request::SHARE){ if(!mCurrBlock.has_height()){ etype = proto::Reply::STALE; break; } if(!req.has_share()){ printf("ERROR: !req.has_share().\n"); etype = proto::Reply::INVALID; break; } const proto::Share& share = req.share(); if(share.height() != mCurrHeight){ etype = proto::Reply::STALE; break; } if(share.length() < mCurrBlock.minshare()){ printf("ERROR: share.length too short.\n"); etype = proto::Reply::INVALID; break; } uint256 merkleRoot; merkleRoot.SetHex(share.merkle()); unsigned extraNonce = mNonceMap[merkleRoot]; if(!extraNonce){ etype = proto::Reply::STALE; break; } unsigned nCandidateType = share.chaintype(); if(nCandidateType > 2){ printf("ERROR: share.chaintype invalid.\n"); etype = proto::Reply::INVALID; break; } CBlock *pblock = &mBlockTemplate->block; extraNonce--; IncrementExtraNonce(pblock, mIndexPrev, extraNonce); pblock->nTime = share.time(); pblock->nBits = share.bits(); pblock->nNonce = share.nonce(); uint256 headerHash = pblock->GetHeaderHash(); { uint256 headerHashClient; headerHashClient.SetHex(share.hash()); if(headerHashClient != headerHash){ printf("ERROR: headerHashClient != headerHash.\n"); etype = proto::Reply::INVALID; break; } } pblock->bnPrimeChainMultiplier.SetHex(share.multi()); uint256 blockhash = pblock->GetHash(); if(!mShares.insert(blockhash).second){ etype = proto::Reply::DUPLICATE; break; } CBigNum bnChainOrigin = CBigNum(headerHash) * pblock->bnPrimeChainMultiplier; unsigned int nChainLength = 0; bool isblock = ProbablePrimeChainTestForMiner(bnChainOrigin, pblock->nBits, nCandidateType+1, nChainLength); nChainLength = TargetGetLength(nChainLength); if(nChainLength >= mCurrBlock.minshare()){ if(isblock) isblock = CheckWork(pblock, *mWallet, mReserveKey); if(share.length() != nChainLength){ printf("ERROR: share.length() != nChainLength.\n"); etype = proto::Reply::INVALID; } mData.Clear(); proto::Share* mshare = mData.mutable_share(); mshare->CopyFrom(share); mshare->set_blockhash(blockhash.GetHex()); mshare->set_length(nChainLength); mshare->set_isblock(isblock); if(isblock){ mshare->set_genvalue(pblock->vtx[0].vout[0].nValue); } SendData(mData, mBackend); CBitcoinAddress address(share.addr()); if(!address.IsValid()){ printf("ERROR: invalid address for share: %s\n", share.addr().c_str()); etype = proto::Reply::INVALID; std::string errstr = "Your payment address '"; errstr.append(share.addr()); errstr.append("' is INVALID!!!"); rep.set_errstr(errstr); break; } }else{ printf("ERROR: share.length too short after test: %d/%d\n", nChainLength, share.length()); etype = proto::Reply::INVALID; break; } }else if(rtype == proto::Request::STATS){ if(!req.has_stats()){ printf("ERROR: !req.has_stats().\n"); etype = proto::Reply::INVALID; break; } const proto::ClientStats& stats = req.stats(); std::pair<std::string,uint64> key = std::make_pair(stats.addr(), stats.clientid() * stats.instanceid()); std::map<std::pair<std::string,uint64>, proto::Data>::iterator iter = mStats.find(key); if(iter != mStats.end()){ proto::ClientStats* s = mStats[key].mutable_clientstats(); s->set_version(std::min(s->version(), stats.version())); s->set_cpd(s->cpd() + stats.cpd()); s->set_errors(s->errors() + stats.errors()); s->set_temp(std::max(s->temp(), stats.temp())); s->set_latency(std::max(s->latency(), stats.latency())); s->set_ngpus(s->ngpus() + stats.ngpus()); /*if(s->name() != stats.name()){ s->mutable_name()->append("+"); s->mutable_name()->append(stats.name()); }*/ }else if(mStats.size() < 100000){ mStats[key].mutable_clientstats()->CopyFrom(stats); } } break; } if(req.height() < mCurrHeight){ rep.mutable_block()->CopyFrom(mCurrBlock); } mReqStats[std::make_pair(rtype,etype)]++; rep.set_error(etype); SendReply(rep, &msg, item->socket); zmsg_destroy(&msg); return 0; }