123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827 |
- // ECOin - Copyright (c) - 2014/2022 - GPLv3 - epsylon@riseup.net (https://03c8.net)
- #include "txdb.h"
- #include "miner.h"
- #include "kernel.h"
- #include <iostream>
- using namespace std;
- string strMintWarning;
- extern unsigned int nMinerSleep;
- int static FormatHashBlocks(void* pbuffer, unsigned int len)
- {
- unsigned char* pdata = (unsigned char*)pbuffer;
- unsigned int blocks = 1 + ((len + 8) / 64);
- unsigned char* pend = pdata + 64 * blocks;
- memset(pdata + len, 0, 64 * blocks - len);
- pdata[len] = 0x80;
- unsigned int bits = len * 8;
- pend[-1] = (bits >> 0) & 0xff;
- pend[-2] = (bits >> 8) & 0xff;
- pend[-3] = (bits >> 16) & 0xff;
- pend[-4] = (bits >> 24) & 0xff;
- return blocks;
- }
- static const unsigned int pSHA256InitState[8] =
- {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
- void SHA256Transform(void* pstate, void* pinput, const void* pinit)
- {
- SHA256_CTX ctx;
- unsigned char data[64];
- SHA256_Init(&ctx);
- for (int i = 0; i < 16; i++)
- ((uint32_t*)data)[i] = ByteReverse(((uint32_t*)pinput)[i]);
- for (int i = 0; i < 8; i++)
- ctx.h[i] = ((uint32_t*)pinit)[i];
- SHA256_Update(&ctx, data, sizeof(data));
- for (int i = 0; i < 8; i++)
- ((uint32_t*)pstate)[i] = ctx.h[i];
- }
- class COrphan
- {
- public:
- CTransaction* ptx;
- set<uint256> setDependsOn;
- double dPriority;
- double dFeePerKb;
- COrphan(CTransaction* ptxIn)
- {
- ptx = ptxIn;
- dPriority = dFeePerKb = 0;
- }
- void print() const
- {
- printf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n",
- ptx->GetHash().ToString().substr(0,10).c_str(), dPriority, dFeePerKb);
- BOOST_FOREACH(uint256 hash, setDependsOn)
- printf(" setDependsOn %s\n", hash.ToString().substr(0,10).c_str());
- }
- };
- uint64 nLastBlockTx = 0;
- uint64 nLastBlockSize = 0;
- int64 nLastCoinStakeSearchInterval = 0;
- typedef boost::tuple<double, double, CTransaction*> TxPriority;
- class TxPriorityCompare
- {
- bool byFee;
- public:
- TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
- bool operator()(const TxPriority& a, const TxPriority& b)
- {
- if (byFee)
- {
- if (a.get<1>() == b.get<1>())
- return a.get<0>() < b.get<0>();
- return a.get<1>() < b.get<1>();
- }
- else
- {
- if (a.get<0>() == b.get<0>())
- return a.get<1>() < b.get<1>();
- return a.get<0>() < b.get<0>();
- }
- }
- };
- typedef boost::tuple<bool, CEcoinAddress> ProofOfTx;
- ProofOfTx ProofOfTxSearch(unsigned int nBlockHeight, CReserveKey pubKey)
- {
- bool fMatch = false;
- CEcoinAddress addrMiner;
- CBlock block;
- CBlockIndex* pblockindex = FindBlockByHeight(nBlockHeight);
- uint256 hashLastBlock = pblockindex->GetBlockHash();
- pblockindex = mapBlockIndex[hashLastBlock];
- block.ReadFromDisk(pblockindex, true);
- CMerkleTx txGen(block.vtx[0]);
- txGen.SetMerkleBranch(&block);
- if (!fMatch && nBlockHeight+1 > 57000 && block.vtx.size() <= 20)
- {
- BOOST_FOREACH (const CTransaction& tx, block.vtx)
- {
- if (tx.vout.size() <= 3)
- {
- for (unsigned int i = 0; i < tx.vout.size(); i++)
- {
- const CTxOut& txout = tx.vout[i];
- if (txout.nValue / 1000000.00 > 1)
- {
- txnouttype type;
- vector<CTxDestination> vAddresses;
- int nRequired;
- ExtractDestinations(txout.scriptPubKey, type, vAddresses, nRequired);
- BOOST_FOREACH(const CTxDestination& addr, vAddresses)
- {
- const char* pszAddress = CEcoinAddress(addr).ToString().c_str();
- CScript addrHex = CScript() << vector<unsigned char>((const unsigned char*)pszAddress, (const unsigned char*)pszAddress + strlen(pszAddress));
- string strSearch = SearchTermV2(addrHex.ToString().c_str());
- if (fAddrMiner(hashLastBlock.GetHex().c_str(), strSearch.c_str()))
- {
- addrMiner = CEcoinAddress(addr);
- fMatch = true;
- }
- else
- {
- fMatch = false;
- CKeyID keyID = pubKey.GetReservedKey().GetID();
- addrMiner.Set(keyID);
- }
- }
- }
- }
- }
- else
- {
- unsigned int iv = 0;
- if (tx.vout.size() > 10)
- iv = 10;
- else
- iv = tx.vout.size();
- for (unsigned int i = 0; i < iv; i++)
- {
- const CTxOut& txout = tx.vout[i];
- if (txout.nValue / 1000000.00 > 1)
- {
- txnouttype type;
- vector<CTxDestination> vAddresses;
- int nRequired;
- ExtractDestinations(txout.scriptPubKey, type, vAddresses, nRequired);
- BOOST_FOREACH(const CTxDestination& addr, vAddresses)
- {
- const char* pszAddress = CEcoinAddress(addr).ToString().c_str();
- CScript addrHex = CScript() << vector<unsigned char>((const unsigned char*)pszAddress, (const unsigned char*)pszAddress + strlen(pszAddress));
- string strSearch = SearchTerm(addrHex.ToString().c_str());
- if (fAddrMiner(hashLastBlock.GetHex().c_str(), strSearch.c_str()))
- {
- addrMiner = CEcoinAddress(addr);
- fMatch = true;
- }
- else
- {
- fMatch = false;
- CKeyID keyID = pubKey.GetReservedKey().GetID();
- addrMiner.Set(keyID);
- }
- }
- }
- }
- }
- }
- }
- else if (!fMatch && nBlockHeight+1 > 57000 && block.vtx.size() > 20)
- {
- CKeyID keyID = pubKey.GetReservedKey().GetID();
- addrMiner.Set(keyID);
- return boost::make_tuple(false, addrMiner);
- }
- else if (!fMatch && nBlockHeight+1 > 22000 && nBlockHeight+1 <= 57000 && block.vtx.size() < 11)
- {
- BOOST_FOREACH (const CTransaction& tx, block.vtx)
- {
- if (tx.vout.size() < 11)
- {
- for (unsigned int i = 0; i < tx.vout.size(); i++)
- {
- const CTxOut& txout = tx.vout[i];
- if (txout.nValue / 1000000.00 > 500)
- {
- txnouttype type;
- vector<CTxDestination> vAddresses;
- int nRequired;
- ExtractDestinations(txout.scriptPubKey, type, vAddresses, nRequired);
- BOOST_FOREACH(const CTxDestination& addr, vAddresses)
- {
- const char* pszAddress = CEcoinAddress(addr).ToString().c_str();
- CScript addrHex = CScript() << vector<unsigned char>((const unsigned char*)pszAddress, (const unsigned char*)pszAddress + strlen(pszAddress));
- string strSearch = SearchTerm(addrHex.ToString().c_str());
- if (fAddrMiner(hashLastBlock.GetHex().c_str(), strSearch.c_str()))
- {
- addrMiner = CEcoinAddress(addr);
- fMatch = true;
- }
- else
- {
- fMatch = false;
- CKeyID keyID = pubKey.GetReservedKey().GetID();
- addrMiner.Set(keyID);
- }
- }
- }
- }
- }
- else
- {
- for (unsigned int i = 0; i < 5; i++)
- {
- const CTxOut& txout = tx.vout[i];
- if (txout.nValue / 1000000.00 > 500)
- {
- txnouttype type;
- vector<CTxDestination> vAddresses;
- int nRequired;
- ExtractDestinations(txout.scriptPubKey, type, vAddresses, nRequired);
- BOOST_FOREACH(const CTxDestination& addr, vAddresses)
- {
- const char* pszAddress = CEcoinAddress(addr).ToString().c_str();
- CScript addrHex = CScript() << vector<unsigned char>((const unsigned char*)pszAddress, (const unsigned char*)pszAddress + strlen(pszAddress));
- string strSearch = SearchTerm(addrHex.ToString().c_str());
- if (fAddrMiner(hashLastBlock.GetHex().c_str(), strSearch.c_str()))
- {
- addrMiner = CEcoinAddress(addr);
- fMatch = true;
- }
- else
- {
- fMatch = false;
- CKeyID keyID = pubKey.GetReservedKey().GetID();
- addrMiner.Set(keyID);
- }
- }
- }
- }
- }
- }
- }
- else if (!fMatch && nBlockHeight+1 > 22000 && nBlockHeight+1 <= 57000 && block.vtx.size() > 10)
- {
- CKeyID keyID = pubKey.GetReservedKey().GetID();
- addrMiner.Set(keyID);
- return boost::make_tuple(false, addrMiner);
- }
- else if (nBlockHeight+1 > 12400 && nBlockHeight+1 < 22001 && block.vtx.size() > 5)
- {
- CKeyID keyID = pubKey.GetReservedKey().GetID();
- addrMiner.Set(keyID);
- return boost::make_tuple(false, addrMiner);
- }
- else if (!fMatch && nBlockHeight+1 > 12400 && nBlockHeight+1 < 22001 && block.vtx.size() < 6)
- {
- BOOST_FOREACH (const CTransaction& tx, block.vtx)
- {
- for (unsigned int i = 0; i < tx.vout.size(); i++)
- {
- const CTxOut& txout = tx.vout[i];
- if (txout.nValue / 1000000.00 > 500)
- {
- txnouttype type;
- vector<CTxDestination> vAddresses;
- int nRequired;
- ExtractDestinations(txout.scriptPubKey, type, vAddresses, nRequired);
- BOOST_FOREACH(const CTxDestination& addr, vAddresses)
- {
- const char* pszAddress = CEcoinAddress(addr).ToString().c_str();
- CScript addrHex = CScript() << vector<unsigned char>((const unsigned char*)pszAddress, (const unsigned char*)pszAddress + strlen(pszAddress));
- string strSearch = SearchTerm(addrHex.ToString().c_str());
- if (fAddrMiner(hashLastBlock.GetHex().c_str(), strSearch.c_str()))
- {
- addrMiner = CEcoinAddress(addr);
- fMatch = true;
- }
- else
- {
- fMatch = false;
- CKeyID keyID = pubKey.GetReservedKey().GetID();
- addrMiner.Set(keyID);
- }
- }
- }
- }
- }
- }
- else if (!fMatch && nBlockHeight > 0 && nBlockHeight+1 <= 12400)
- {
- BOOST_FOREACH (const CTransaction& tx, block.vtx)
- {
- for (unsigned int i = 0; i < tx.vout.size(); i++)
- {
- const CTxOut& txout = tx.vout[i];
- if (txout.nValue / 1000000.00 > 500)
- {
- txnouttype type;
- vector<CTxDestination> vAddresses;
- int nRequired;
- ExtractDestinations(txout.scriptPubKey, type, vAddresses, nRequired);
- BOOST_FOREACH(const CTxDestination& addr, vAddresses)
- {
- const char* pszAddress = CEcoinAddress(addr).ToString().c_str();
- CScript addrHex = CScript() << vector<unsigned char>((const unsigned char*)pszAddress, (const unsigned char*)pszAddress + strlen(pszAddress));
- string strSearch = SearchTerm(addrHex.ToString().c_str());
- if (fAddrMiner(hashLastBlock.GetHex().c_str(), strSearch.c_str()))
- {
- addrMiner = CEcoinAddress(addr);
- fMatch = true;
- }
- else
- {
- fMatch = false;
- CKeyID keyID = pubKey.GetReservedKey().GetID();
- addrMiner.Set(keyID);
- }
- }
- }
- }
- }
- }
- return boost::make_tuple(fMatch, addrMiner);
- }
- // CreateNewBlock: create new block (without proof-of-work/proof-of-stake)
- CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake)
- {
- bool fMatch = false;
- CBlockIndex* pindexPrev = pindexBest;
- CEcoinAddress addrMiner;
- CReserveKey reservekey(pwallet);
- // Create new block
- auto_ptr<CBlock> pblock(new CBlock());
- if (!pblock.get())
- return NULL;
- unsigned int nBlockHeight = pindexPrev->nHeight;
- ProofOfTx hashAddr = ProofOfTxSearch(nBlockHeight, reservekey);
- fMatch = hashAddr.get<0>();
- // Create coinbase tx
- CTransaction txNew;
- txNew.vin.resize(1);
- txNew.vin[0].prevout.SetNull();
- if (!fProofOfStake && !fMatch)
- {
- txNew.vout.resize(1);
- txNew.vout[0].scriptPubKey.SetDestination(reservekey.GetReservedKey().GetID());
- }
- else if (!fProofOfStake && fMatch)
- {
- txNew.vout.resize(2);
- txNew.vout[0].scriptPubKey.SetDestination(reservekey.GetReservedKey().GetID());
- addrMiner = hashAddr.get<1>();
- CScript txPubKey;
- CTxDestination txDestination = addrMiner.Get();
- txPubKey.SetDestination(txDestination);
- txNew.vout[1].scriptPubKey = txPubKey;
- }
- else if (fProofOfStake)
- {
- txNew.vout.resize(1);
- txNew.vout[0].SetEmpty();
- }
- pblock->vtx.push_back(txNew);
- unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2);
- nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
- unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000);
- nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
- unsigned int nBlockMinSize = GetArg("-blockminsize", 0);
- nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
- int64 nMinTxFee = MIN_TX_FEE;
- if (mapArgs.count("-mintxfee"))
- ParseMoney(mapArgs["-mintxfee"], nMinTxFee);
- pblock->nBits = GetNextTargetRequired(pindexPrev, fProofOfStake);
- int64 nFees = 0;
- {
- LOCK2(cs_main, mempool.cs);
- CBlockIndex* pindexPrev = pindexBest;
- CTxDB txdb("r");
- // Priority order to process transactions
- list<COrphan> vOrphan; // list memory doesn't move
- map<uint256, vector<COrphan*> > mapDependers;
- // This vector will be sorted into a priority queue:
- vector<TxPriority> vecPriority;
- vecPriority.reserve(mempool.mapTx.size());
- for (map<uint256, CTransaction>::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi)
- {
- CTransaction& tx = (*mi).second;
- if (tx.IsCoinBase() || tx.IsCoinStake() || !tx.IsFinal())
- continue;
- COrphan* porphan = NULL;
- double dPriority = 0;
- int64 nTotalIn = 0;
- bool fMissingInputs = false;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
- {
- // Read prev transaction
- CTransaction txPrev;
- CTxIndex txindex;
- if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex))
- {
- // This should never happen; all transactions in the memory
- // pool should connect to either transactions in the chain
- // or other transactions in the memory pool.
- if (!mempool.mapTx.count(txin.prevout.hash))
- {
- printf("ERROR: mempool transaction missing input\n");
- if (fDebug) assert("mempool transaction missing input" == 0);
- fMissingInputs = true;
- if (porphan)
- vOrphan.pop_back();
- break;
- }
- // Has to wait for dependencies
- if (!porphan)
- {
- // Use list for automatic deletion
- vOrphan.push_back(COrphan(&tx));
- porphan = &vOrphan.back();
- }
- mapDependers[txin.prevout.hash].push_back(porphan);
- porphan->setDependsOn.insert(txin.prevout.hash);
- nTotalIn += mempool.mapTx[txin.prevout.hash].vout[txin.prevout.n].nValue;
- continue;
- }
- int64 nValueIn = txPrev.vout[txin.prevout.n].nValue;
- nTotalIn += nValueIn;
- int nConf = txindex.GetDepthInMainChain();
- dPriority += (double)nValueIn * nConf;
- }
- if (fMissingInputs) continue;
- unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
- dPriority /= nTxSize;
- double dFeePerKb = double(nTotalIn-tx.GetValueOut()) / (double(nTxSize)/1000.0);
- if (porphan)
- {
- porphan->dPriority = dPriority;
- porphan->dFeePerKb = dFeePerKb;
- }
- else
- vecPriority.push_back(TxPriority(dPriority, dFeePerKb, &(*mi).second));
- }
- // Collect transactions into block
- map<uint256, CTxIndex> mapTestPool;
- uint64 nBlockSize = 1000;
- uint64 nBlockTx = 0;
- int nBlockSigOps = 100;
- bool fSortedByFee = (nBlockPrioritySize <= 0);
- TxPriorityCompare comparer(fSortedByFee);
- std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
- while (!vecPriority.empty())
- {
- // Take highest priority transaction off the priority queue:
- double dPriority = vecPriority.front().get<0>();
- double dFeePerKb = vecPriority.front().get<1>();
- CTransaction& tx = *(vecPriority.front().get<2>());
- std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
- vecPriority.pop_back();
- // Size limits
- unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
- if (nBlockSize + nTxSize >= nBlockMaxSize)
- continue;
- // Legacy limits on sigOps:
- unsigned int nTxSigOps = tx.GetLegacySigOpCount();
- if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
- continue;
- // Timestamp limit
- if (tx.nTime > GetAdjustedTime() || (fProofOfStake && tx.nTime > pblock->vtx[0].nTime))
- continue;
- // Simplify transaction fee - allow free = false
- int64 nMinFee = tx.GetMinFee(nBlockSize, false, GMF_BLOCK);
- // Skip free transactions if we're past the minimum block size:
- if (fSortedByFee && (dFeePerKb < nMinTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
- continue;
- if (!fSortedByFee &&
- ((nBlockSize + nTxSize >= nBlockPrioritySize) || (dPriority < COIN * 144 / 250)))
- {
- fSortedByFee = true;
- comparer = TxPriorityCompare(fSortedByFee);
- std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
- }
- map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
- MapPrevTx mapInputs;
- bool fInvalid;
- if (!tx.FetchInputs(txdb, mapTestPoolTmp, false, true, mapInputs, fInvalid))
- continue;
- int64 nTxFees = tx.GetValueIn(mapInputs)-tx.GetValueOut();
- if (nTxFees < nMinFee)
- continue;
- nTxSigOps += tx.GetP2SHSigOpCount(mapInputs);
- if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
- continue;
- if (!tx.ConnectInputs(txdb, mapInputs, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, false, true))
- continue;
- mapTestPoolTmp[tx.GetHash()] = CTxIndex(CDiskTxPos(1,1,1), tx.vout.size());
- swap(mapTestPool, mapTestPoolTmp);
- pblock->vtx.push_back(tx);
- nBlockSize += nTxSize;
- ++nBlockTx;
- nBlockSigOps += nTxSigOps;
- nFees += nTxFees;
- if (fDebug && GetBoolArg("-printpriority"))
- {
- printf("priority %.1f feeperkb %.1f txid %s\n",
- dPriority, dFeePerKb, tx.GetHash().ToString().c_str());
- }
- uint256 hash = tx.GetHash();
- if (mapDependers.count(hash))
- {
- BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
- {
- if (!porphan->setDependsOn.empty())
- {
- porphan->setDependsOn.erase(hash);
- if (porphan->setDependsOn.empty())
- {
- vecPriority.push_back(TxPriority(porphan->dPriority, porphan->dFeePerKb, porphan->ptx));
- std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
- }
- }
- }
- }
- }
- nLastBlockTx = nBlockTx;
- nLastBlockSize = nBlockSize;
- if (fDebug && GetBoolArg("-printpriority"))
- printf("CreateNewBlock(): total size %" PRI64u"\n", nBlockSize);
- if (!fProofOfStake && nBlockHeight+1 <= 57000)
- {
- if (!fMatch)
- pblock->vtx[0].vout[0].nValue = GetProofOfWorkReward(pindexPrev->nHeight+1, pindexPrev->GetBlockHash());
- else
- {
- pblock->vtx[0].vout[0].nValue = (GetProofOfWorkReward(pindexPrev->nHeight+1, pindexPrev->GetBlockHash())/2);
- pblock->vtx[0].vout[1].nValue = (GetProofOfWorkReward(pindexPrev->nHeight+1, pindexPrev->GetBlockHash())/2);
- }
- }
- else if (!fProofOfStake && nBlockHeight+1 > 57000)
- {
- if (!fMatch)
- pblock->vtx[0].vout[0].nValue = GetProofOfWorkReward(pindexPrev->nHeight+1, pindexPrev->GetBlockHash());
- else
- {
- pblock->vtx[0].vout[0].nValue = (GetProofOfWorkReward(pindexPrev->nHeight+1, pindexPrev->GetBlockHash())*0.95);
- pblock->vtx[0].vout[1].nValue = (GetProofOfWorkReward(pindexPrev->nHeight+1, pindexPrev->GetBlockHash())*0.05);
- }
- }
- pblock->hashPrevBlock = pindexPrev->GetBlockHash();
- pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, pblock->GetMaxTransactionTime());
- pblock->nTime = max(pblock->GetBlockTime(), PastDrift(pindexPrev->GetBlockTime()));
- if (!fProofOfStake)
- pblock->UpdateTime(pindexPrev);
- pblock->nNonce = 0;
- }
- return pblock.release();
- }
- void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
- {
- static uint256 hashPrevBlock;
- if (hashPrevBlock != pblock->hashPrevBlock)
- {
- nExtraNonce = 0;
- hashPrevBlock = pblock->hashPrevBlock;
- }
- ++nExtraNonce;
- unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
- pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CBigNum(nExtraNonce)) + COINBASE_FLAGS;
- assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100);
- pblock->hashMerkleRoot = pblock->BuildMerkleTree();
- }
- void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1)
- {
- struct
- {
- struct unnamed2
- {
- int nVersion;
- uint256 hashPrevBlock;
- uint256 hashMerkleRoot;
- unsigned int nTime;
- unsigned int nBits;
- unsigned int nNonce;
- }
- block;
- unsigned char pchPadding0[64];
- uint256 hash1;
- unsigned char pchPadding1[64];
- }
- tmp;
- memset(&tmp, 0, sizeof(tmp));
- tmp.block.nVersion = pblock->nVersion;
- tmp.block.hashPrevBlock = pblock->hashPrevBlock;
- tmp.block.hashMerkleRoot = pblock->hashMerkleRoot;
- tmp.block.nTime = pblock->nTime;
- tmp.block.nBits = pblock->nBits;
- tmp.block.nNonce = pblock->nNonce;
- FormatHashBlocks(&tmp.block, sizeof(tmp.block));
- FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
- // Byte swap all the input buffer
- for (unsigned int i = 0; i < sizeof(tmp)/4; i++)
- ((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);
- // Precalc the first half of the first hash, which stays constant
- SHA256Transform(pmidstate, &tmp.block, pSHA256InitState);
- memcpy(pdata, &tmp.block, 128);
- memcpy(phash1, &tmp.hash1, 64);
- }
- bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
- {
- uint256 hashBlock = pblock->GetHash();
- uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
- if(!pblock->IsProofOfWork())
- return error("CheckWork() : %s is not a proof-of-work block", hashBlock.GetHex().c_str());
- if (hashBlock > hashTarget)
- return error("CheckWork() : proof-of-work not meeting target");
- printf("CheckWork() : new proof-of-work block found \n hash: %s \ntarget: %s\n", hashBlock.GetHex().c_str(), hashTarget.GetHex().c_str());
- pblock->print();
- printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
- {
- LOCK(cs_main);
- if (pblock->hashPrevBlock != hashBestChain)
- return error("CheckWork() : generated block is stale");
- reservekey.KeepKey();
- {
- LOCK(wallet.cs_wallet);
- wallet.mapRequestCount[hashBlock] = 0;
- }
- if (!ProcessBlock(NULL, pblock))
- return error("CheckWork() : ProcessBlock, block not accepted");
- }
- return true;
- }
- bool CheckStake(CBlock* pblock, CWallet& wallet)
- {
- uint256 proofHash = 0, hashTarget = 0;
- uint256 hashBlock = pblock->GetHash();
- if(!pblock->IsProofOfStake())
- return error("CheckStake() : %s is not a proof-of-stake block", hashBlock.GetHex().c_str());
- // verify hash target and signature of coinstake tx
- if (!CheckProofOfStake(pblock->vtx[1], pblock->nBits, proofHash, hashTarget))
- return error("CheckStake() : proof-of-stake checking failed");
- printf("CheckStake() : new proof-of-stake block found \n hash: %s \nproofhash: %s \ntarget: %s\n", hashBlock.GetHex().c_str(), proofHash.GetHex().c_str(), hashTarget.GetHex().c_str());
- pblock->print();
- printf("out %s\n", FormatMoney(pblock->vtx[1].GetValueOut()).c_str());
- {
- LOCK(cs_main);
- if (pblock->hashPrevBlock != hashBestChain)
- return error("CheckStake() : generated block is stale");
- {
- LOCK(wallet.cs_wallet);
- wallet.mapRequestCount[hashBlock] = 0;
- }
- if (!ProcessBlock(NULL, pblock))
- return error("CheckStake() : ProcessBlock, block not accepted");
- }
- return true;
- }
- void StakeMiner(CWallet *pwallet)
- {
- SetThreadPriority(THREAD_PRIORITY_LOWEST);
- // Make this thread recognisable as the mining thread
- RenameThread("ecoin-miner");
- // Each thread has its own counter
- unsigned int nExtraNonce = 0;
- while (true)
- {
- if (fShutdown)
- return;
- while (pwallet->IsLocked())
- {
- //strMintWarning = strMintMessage;
- Sleep(1000);
- if (fShutdown)
- return;
- }
- while (vNodes.empty() || IsInitialBlockDownload())
- {
- Sleep(1000);
- if (fShutdown)
- return;
- }
- CBlockIndex* pindexPrev = pindexBest;
- auto_ptr<CBlock> pblock(CreateNewBlock(pwallet, true));
- if (!pblock.get())
- return;
- IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce);
- // Trying to sign a block
- if (pblock->SignBlock(*pwallet))
- {
- strMintWarning = _("Stake generation: new block found!");
- SetThreadPriority(THREAD_PRIORITY_NORMAL);
- CheckStake(pblock.get(), *pwallet);
- SetThreadPriority(THREAD_PRIORITY_LOWEST);
- Sleep(500);
- }
- else
- Sleep(nMinerSleep);
- continue;
- }
- }
|