Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) { Object result; result.push_back(Pair("hash", block.GetHash().GetHex())); CMerkleTx txGen(block.vtx[0]); txGen.SetMerkleBranch(&block); result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain())); result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); result.push_back(Pair("headerhash", block.GetHeaderHash().GetHex())); result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); Array txs; BOOST_FOREACH(const CTransaction&tx, block.vtx) txs.push_back(tx.GetHash().GetHex()); result.push_back(Pair("tx", txs)); result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime())); result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce)); result.push_back(Pair("bits", HexBits(block.nBits))); result.push_back(Pair("difficulty", GetPrimeDifficulty(block.nBits))); result.push_back(Pair("transition", GetPrimeDifficulty(blockindex->nWorkTransition))); CBigNum bnPrimeChainOrigin = CBigNum(block.GetHeaderHash()) * block.bnPrimeChainMultiplier; result.push_back(Pair("primechain", GetPrimeChainName(blockindex->nPrimeChainType, blockindex->nPrimeChainLength).c_str())); result.push_back(Pair("primeorigin", bnPrimeChainOrigin.ToString().c_str())); if (blockindex->pprev) result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); if (blockindex->pnext) result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex())); return result; }
// pNut: list prime chain records within pnut network Value listprimerecords(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "listprimerecords <primechain length> [primechain type]\n" "Returns the list of record prime chains in pnut network.\n" "<primechain length> is integer like 10, 11, 12 etc.\n" "[primechain type] is optional type, among 1CC, 2CC and TWN"); int nPrimeChainLength = params[0].get_int(); unsigned int nPrimeChainType = 0; if (params.size() > 1) { std::string strPrimeChainType = params[1].get_str(); if (strPrimeChainType.compare("1CC") == 0) nPrimeChainType = PRIME_CHAIN_CUNNINGHAM1; else if (strPrimeChainType.compare("2CC") == 0) nPrimeChainType = PRIME_CHAIN_CUNNINGHAM2; else if (strPrimeChainType.compare("TWN") == 0) nPrimeChainType = PRIME_CHAIN_BI_TWIN; else throw runtime_error("Prime chain type must be 1CC, 2CC or TWN."); } Array ret; CBigNum bnPrimeRecord = 0; for (CBlockIndex* pindex = pindexGenesisBlock; pindex; pindex = pindex->pnext) { if (nPrimeChainLength != (int) TargetGetLength(pindex->nPrimeChainLength)) continue; // length not matching, next block if (nPrimeChainType && nPrimeChainType != pindex->nPrimeChainType) continue; // type not matching, next block CBlock block; block.ReadFromDisk(pindex); // read block CBigNum bnPrimeChainOrigin = CBigNum(block.GetHeaderHash()) * block.bnPrimeChainMultiplier; // compute prime chain origin if (bnPrimeChainOrigin > bnPrimeRecord) { bnPrimeRecord = bnPrimeChainOrigin; // new record in pnut Object entry; entry.push_back(Pair("time", DateTimeStrFormat("%Y-%m-%d %H:%M:%S UTC", pindex->GetBlockTime()).c_str())); entry.push_back(Pair("epoch", (boost::int64_t) pindex->GetBlockTime())); entry.push_back(Pair("height", pindex->nHeight)); entry.push_back(Pair("ismine", pwalletMain->IsMine(block.vtx[0]))); CTxDestination address; entry.push_back(Pair("mineraddress", (block.vtx[0].vout.size() > 1)? "multiple" : ExtractDestination(block.vtx[0].vout[0].scriptPubKey, address)? CBitcoinAddress(address).ToString().c_str() : "invalid")); entry.push_back(Pair("primedigit", (int) bnPrimeChainOrigin.ToString().length())); entry.push_back(Pair("primechain", GetPrimeChainName(pindex->nPrimeChainType, pindex->nPrimeChainLength).c_str())); entry.push_back(Pair("primeorigin", bnPrimeChainOrigin.ToString().c_str())); entry.push_back(Pair("primorialform", GetPrimeOriginPrimorialForm(bnPrimeChainOrigin).c_str())); ret.push_back(entry); } } return ret; }
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; }
// pNut: list top prime chain within pnut network Value listtopprimes(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "listtopprimes <primechain length> [primechain type]\n" "Returns the list of top prime chains in pnut network.\n" "<primechain length> is integer like 10, 11, 12 etc.\n" "[primechain type] is optional type, among 1CC, 2CC and TWN"); int nPrimeChainLength = params[0].get_int(); unsigned int nPrimeChainType = 0; if (params.size() > 1) { std::string strPrimeChainType = params[1].get_str(); if (strPrimeChainType.compare("1CC") == 0) nPrimeChainType = PRIME_CHAIN_CUNNINGHAM1; else if (strPrimeChainType.compare("2CC") == 0) nPrimeChainType = PRIME_CHAIN_CUNNINGHAM2; else if (strPrimeChainType.compare("TWN") == 0) nPrimeChainType = PRIME_CHAIN_BI_TWIN; else throw runtime_error("Prime chain type must be 1CC, 2CC or TWN."); } // Search for top prime chains unsigned int nRankingSize = 10; // ranking list size unsigned int nSortVectorSize = 64; // vector size for sort operation CBigNum bnPrimeQualify = 0; // minimum qualify value for ranking list vector<pair<CBigNum, uint256> > vSortedByOrigin; for (CBlockIndex* pindex = pindexGenesisBlock; pindex; pindex = pindex->pnext) { if (nPrimeChainLength != (int) TargetGetLength(pindex->nPrimeChainLength)) continue; // length not matching, next block if (nPrimeChainType && nPrimeChainType != pindex->nPrimeChainType) continue; // type not matching, next block CBlock block; block.ReadFromDisk(pindex); // read block CBigNum bnPrimeChainOrigin = CBigNum(block.GetHeaderHash()) * block.bnPrimeChainMultiplier; // compute prime chain origin if (bnPrimeChainOrigin > bnPrimeQualify) vSortedByOrigin.push_back(make_pair(bnPrimeChainOrigin, block.GetHash())); if (vSortedByOrigin.size() >= nSortVectorSize) { // Sort prime chain candidates sort(vSortedByOrigin.begin(), vSortedByOrigin.end()); reverse(vSortedByOrigin.begin(), vSortedByOrigin.end()); // Truncate candidate list while (vSortedByOrigin.size() > nRankingSize) vSortedByOrigin.pop_back(); // Update minimum qualify value for top prime chains bnPrimeQualify = vSortedByOrigin.back().first; } } // Final sort of prime chain candidates sort(vSortedByOrigin.begin(), vSortedByOrigin.end()); reverse(vSortedByOrigin.begin(), vSortedByOrigin.end()); // Truncate candidate list while (vSortedByOrigin.size() > nRankingSize) vSortedByOrigin.pop_back(); // Output top prime chains Array ret; BOOST_FOREACH(const PAIRTYPE(CBigNum, uint256)& item, vSortedByOrigin) { CBigNum bnPrimeChainOrigin = item.first; CBlockIndex* pindex = mapBlockIndex[item.second]; CBlock block; block.ReadFromDisk(pindex); // read block Object entry; entry.push_back(Pair("time", DateTimeStrFormat("%Y-%m-%d %H:%M:%S UTC", pindex->GetBlockTime()).c_str())); entry.push_back(Pair("epoch", (boost::int64_t) pindex->GetBlockTime())); entry.push_back(Pair("height", pindex->nHeight)); entry.push_back(Pair("ismine", pwalletMain->IsMine(block.vtx[0]))); CTxDestination address; entry.push_back(Pair("mineraddress", (block.vtx[0].vout.size() > 1)? "multiple" : ExtractDestination(block.vtx[0].vout[0].scriptPubKey, address)? CBitcoinAddress(address).ToString().c_str() : "invalid")); entry.push_back(Pair("primedigit", (int) bnPrimeChainOrigin.ToString().length())); entry.push_back(Pair("primechain", GetPrimeChainName(pindex->nPrimeChainType, pindex->nPrimeChainLength).c_str())); entry.push_back(Pair("primeorigin", bnPrimeChainOrigin.ToString().c_str())); entry.push_back(Pair("primorialform", GetPrimeOriginPrimorialForm(bnPrimeChainOrigin).c_str())); ret.push_back(entry); } return ret; }