Final: final parsing - scriptPubKey; toggles around checks for validity: # of CB's; nBits; PoW

This commit is contained in:
airk42 2018-01-02 17:07:49 -05:00
parent 19121b7e6f
commit 9d8b64ccfe
11 changed files with 209 additions and 65 deletions

View File

@ -495,7 +495,7 @@ std::string HelpMessage(HelpMessageMode mode)
#ifdef FORK_CB_INPUT
strUsage += HelpMessageGroup(_("Fork :"));
strUsage += HelpMessageOpt("-utxo-file=<file>", _("Specify input utxo file"));
#endif //FORK_CB_INPUT
#endif
#ifdef ENABLE_MINING
strUsage += HelpMessageGroup(_("Mining options:"));
@ -896,6 +896,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
#endif
}
#ifdef FORK_CB_INPUT
forkStartHeight = GetArg("-fork-startheight", FORK_BLOCK_HEIGHT_START);
forkHeightRange = GetArg("-fork-heightrange", FORK_BLOCK_HEIGHT_RANGE);
forkCBPerBlock = GetArg("-fork-cbperblock", FORK_COINBASE_PER_BLOCK);
#endif
// ********************************************************* Step 3: parameter-to-internal-flags
fDebug = !mapMultiArgs["-debug"].empty();

View File

@ -72,8 +72,10 @@ uint64_t nPruneTarget = 0;
bool fAlerts = DEFAULT_ALERTS;
#ifdef FORK_CB_INPUT
bool bForking = false;
#endif //FORK_CB_INPUT
int64_t forkStartHeight = FORK_BLOCK_HEIGHT_START;
int64_t forkHeightRange = FORK_BLOCK_HEIGHT_RANGE;
int64_t forkCBPerBlock = FORK_COINBASE_PER_BLOCK;
#endif
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
@ -1375,11 +1377,20 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString());
}
#ifdef FORK_CB_INPUT
if (!isForking()) {
#endif
// Check the header
if (!(CheckEquihashSolution(&block, Params()) &&
CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())))
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
#ifdef FORK_CB_INPUT
}
#endif
return true;
}
@ -1917,8 +1928,15 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
}
}
int nNonCBIdx = 0;
// restore inputs
if (i > 0) { // not coinbases
#ifdef FORK_CB_INPUT
if (isForking()){
nNonCBIdx = forkCBPerBlock;
}
#endif
if (i > nNonCBIdx) { // not coinbases
const CTxUndo &txundo = blockUndo.vtxundo[i-1];
if (txundo.vprevout.size() != tx.vin.size())
return error("DisconnectBlock(): transaction and undo data inconsistent");
@ -2192,12 +2210,18 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart;
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001);
#ifdef FORK_CB_INPUT
if (!isForking()){
#endif
CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus());
if (block.vtx[0].GetValueOut() > blockReward)
return state.DoS(100,
error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
block.vtx[0].GetValueOut(), blockReward),
REJECT_INVALID, "bad-cb-amount");
#ifdef FORK_CB_INPUT
}
#endif
if (!control.Wait())
return state.DoS(100, false);
@ -2979,11 +3003,19 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),
REJECT_INVALID, "invalid-solution");
#ifdef FORK_CB_INPUT
if (!isForking()) {
#endif
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus()))
return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),
REJECT_INVALID, "high-hash");
#ifdef FORK_CB_INPUT
}
#endif
// Check timestamp
if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
return state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),
@ -3034,21 +3066,21 @@ bool CheckBlock(const CBlock& block, CValidationState& state,
REJECT_INVALID, "bad-cb-missing");
#ifdef FORK_CB_INPUT
if (bForking) {
//This blocks might have up to FORK_COINBASE_PER_BLOCK coinbases
for (unsigned int i = FORK_COINBASE_PER_BLOCK; i < block.vtx.size(); i++)
if (isForking()) {
//This blocks might have up to fork pre-defined value coinbases
for (unsigned int i = forkCBPerBlock; i < block.vtx.size(); i++)
if (block.vtx[i].IsCoinBase())
return state.DoS(100, error("CheckBlock(): it is forking block - more than 1000 coinbase"),
REJECT_INVALID, "bad-cb-multiple");
} else {
#endif //FORK_CB_INPUT
#endif
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"),
REJECT_INVALID, "bad-cb-multiple");
#ifdef FORK_CB_INPUT
}
#endif //FORK_CB_INPUT
#endif
// Check transactions
BOOST_FOREACH(const CTransaction& tx, block.vtx)
if (!CheckTransaction(tx, state, verifier))
@ -3079,9 +3111,15 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
int nHeight = pindexPrev->nHeight+1;
// Check proof of work
#ifdef FORK_CB_INPUT
if (!isForking()) {
#endif
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
return state.DoS(100, error("%s: incorrect proof of work", __func__),
REJECT_INVALID, "bad-diffbits");
#ifdef FORK_CB_INPUT
}
#endif
// Check timestamp against prev
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
@ -3305,10 +3343,6 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
// NOTE: CheckBlockHeader is called by CheckBlock
if (!ContextualCheckBlockHeader(block, state, pindexPrev))
return false;
#ifdef FORK_CB_INPUT
bForking = (pindexPrev->nHeight + 1 >= FORK_BLOCK_HEIGHT_START /*&& nHeight < FORK_BLOCK_HEIGHT_END*/);
#endif //FORK_CB_INPUT
if (!CheckBlock(block, state, verifier, fCheckPOW, fCheckMerkleRoot))
return false;
@ -3496,7 +3530,12 @@ CBlockIndex * InsertBlockIndex(uint256 hash)
bool static LoadBlockIndexDB()
{
const CChainParams& chainparams = Params();
#ifdef FORK_CB_INPUT
if (!pblocktree->LoadBlockIndexGuts(forkStartHeight, forkStartHeight+forkHeightRange))
#else
if (!pblocktree->LoadBlockIndexGuts())
#endif
return false;
boost::this_thread::interruption_point();

View File

@ -533,9 +533,19 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
#ifdef FORK_CB_INPUT
#define FORK_BLOCK_HEIGHT_START 1000000 //current ZCL height is 200K-300K, this value here is placeholder, it will have to be changed to correct fork block height
// I don't belive it should be set via paramter or env variable
//#define FORK_BLOCK_HEIGHT_END FORK_BLOCK_HEIGHT_START + 65000
#define FORK_BLOCK_HEIGHT_RANGE 65000 //assumption
#define FORK_COINBASE_PER_BLOCK 1000
#endif //FORK_CB_INPUT
extern int64_t forkStartHeight;
extern int64_t forkHeightRange;
extern int64_t forkCBPerBlock;
inline bool isForking()
{
int nNextHeight = chainActive.Tip()->nHeight + 1;
return chainActive.Tip()? (nNextHeight >= forkStartHeight && nNextHeight < (forkStartHeight+forkHeightRange)): false;
}
#endif
#endif // BITCOIN_MAIN_H

View File

@ -42,7 +42,7 @@
#ifdef FORK_CB_INPUT
#include <fstream>
#endif //FORK_CB_INPUT
#endif
using namespace std;
@ -125,7 +125,7 @@ uint64_t bytes2uint64(char *array)
static_cast<uint64_t>(array[7]) << 56 & 0xff00000000000000;
return x;
}
CBlockTemplate* CreateNewForkBlock()
CBlockTemplate* CreateNewForkBlock(int& utxoFileCurPos)
{
std::string utxo_path = GetArg("-utxo-file","");
@ -164,47 +164,55 @@ CBlockTemplate* CreateNewForkBlock()
if (!if_utxo.is_open()) {
throw std::runtime_error("CreateNewForkBlock(): Cannot open UTXO file - " + utxo_path);
}
if_utxo.seekg(utxoFileCurPos, ios_base::beg);
LogPrintf("CreateNewForkBlock(): Reading UTXO file from %d\n", utxoFileCurPos);
while (if_utxo) {
while (if_utxo && nBlockTx < forkCBPerBlock) {
char term = 0;
char coin[8] = {};
if (!if_utxo.read(coin, 8)) {
LogPrintf("CreateNewBlock(): No more data (Amount)\n");
LogPrintf("CreateNewForkBlock(): No more data (Amount)\n");
break;
}
char pubkeysize[8] = {};
if (!if_utxo.read(pubkeysize, 8)) {
LogPrintf("CreateNewBlock(): Not more data (PubKeyScript size)\n");
LogPrintf("CreateNewForkBlock(): Not more data (PubKeyScript size)\n");
break;
}
int pbsize = bytes2uint64(pubkeysize);
LogPrintf("CreateNewBlock():PubKeyScript size = d\n", pbsize);
LogPrintf("CreateNewForkBlock():PubKeyScript size = %d\n", pbsize);
if (pbsize == 0) {
LogPrintf("CreateNewBlock(): Warning! PubKeyScript size = 0\n");
LogPrintf("CreateNewForkBlock(): Warning! PubKeyScript size = 0\n");
//but proceed
}
std::unique_ptr<char[]> pubKeyScript(new char[pbsize]);
if (!if_utxo.read(&pubKeyScript[0], pbsize)) {
LogPrintf("CreateNewBlock(): Not more data (PubKeyScript)\n");
LogPrintf("CreateNewForkBlock(): Not more data (PubKeyScript)\n");
break;
}
uint64_t amount = bytes2uint64(coin);
LogPrintf("CreateNewBlock(): txn %u has ammount %u\n", nBlockTx, amount);
LogPrintf("CreateNewForkBlock(): txn %u has ammount %u\n", nBlockTx, amount);
// Add coinbase tx's
CMutableTransaction txNew;
txNew.vin.resize(1);
txNew.vin[0].prevout.SetNull();
txNew.vout.resize(1);
txNew.vout[0].scriptPubKey = CScript(); //PUB KEY READ FROM FILE
unsigned char* pks = (unsigned char*)pubKeyScript.get();
txNew.vout[0].scriptPubKey = CScript(pks, pks+pbsize);
LogPrintf("CreateNewForkBlock(): ScriptPubKey: %s\n", txNew.vout[0].scriptPubKey.ToString());
txNew.vout[0].nValue = amount;
txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
@ -220,16 +228,16 @@ CBlockTemplate* CreateNewForkBlock()
if (!if_utxo.read(&term, 1)) {
LogPrintf("CreateNewBlock(): No more data (record separator)\n");
LogPrintf("CreateNewForkBlock(): No more data (record separator)\n");
break;
}
if (term != '\n') {
//This maybe not an error, but warning none the less
LogPrintf("CreateNewBlock(): Warning! No record separator ('0xA') was found\n");
LogPrintf("CreateNewForkBlock(): Warning! No record separator ('0xA') was found\n");
if_utxo.seekg(-1, ios_base::cur); //move one char back - if it is not a separator, maybe there is not separators at all
}
}
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
LogPrintf("CreateNewForkBlock(): total size %u\n", nBlockSize);
// Randomise nonce
arith_uint256 nonce = UintToArith256(GetRandHash());
@ -242,7 +250,12 @@ CBlockTemplate* CreateNewForkBlock()
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
pblock->hashReserved = uint256();
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); //TODO: SET LOW DIFFICATLY
pblock->nBits = 0x207fffff; // Difficulty = 1
//0x207fffff -> 0x 7fffff00 00000000 00000000 00000000 00000000 00000000 00000000 00000000
//alternativly
//0x1d00ffff -> 0x 00000000 ffff0000 00000000 00000000 00000000 00000000 00000000 00000000
// or
//0x1f07ffff -> 0x 007fffff 00000000 00000000 00000000 00000000 00000000 00000000 00000000
pblock->nSolution.clear();
pblocktemplate->vTxSigOps[0] = 0; //NO SigOps
@ -251,9 +264,11 @@ CBlockTemplate* CreateNewForkBlock()
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false))
throw std::runtime_error("CreateNewForkBlock(): TestBlockValidity failed");
utxoFileCurPos = if_utxo.tellg(); //-1, if end of data
return pblocktemplate.release();
}
#endif //FORK_CB_INPUT
#endif
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
{
@ -649,6 +664,10 @@ void static BitcoinMiner()
CReserveKey reservekey(pwallet);
#endif
#ifdef FORK_CB_INPUT
int forkFilePos = 0; //TODO: make it percistent
#endif
// Each thread has its own counter
unsigned int nExtraNonce = 0;
@ -692,48 +711,53 @@ void static BitcoinMiner()
CBlock *pblock = nullptr;
unsigned int nTransactionsUpdatedLast = 0;
#ifdef FORK_CB_INPUT
bool bForking = (pindexPrev->nHeight >= FORK_BLOCK_HEIGHT_START);
if (bForking) {
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewForkBlock());
if (!pblocktemplate.get()) {
LogPrintf("Error in BTCPrivate Miner: Cannot create Fork Block\n");
}
pblock = &pblocktemplate->block;
LogPrintf("Running BTCPrivate Miner with %u forking transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
} else {
#endif //FORK_CB_INPUT
//
// Create new block
//
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
unique_ptr<CBlockTemplate> pblocktemplate;
#ifdef FORK_CB_INPUT
bool bForking = isForking(); //(pindexPrev->nHeight >= forkStartHeight);
if (bForking) {
if (forkFilePos != -1) {
pblocktemplate.reset(CreateNewForkBlock(forkFilePos));
if (!pblocktemplate.get()) {
LogPrintf("Error in BTCPrivate Miner: Cannot create Fork Block\n");
}
pblock = &pblocktemplate->block;
LogPrintf("Running BTCPrivate Miner with %u forking transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
}
} else {
#endif
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
#ifdef ENABLE_WALLET
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
pblocktemplate.reset(CreateNewBlockWithKey(reservekey));
#else
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey());
pblocktemplate.reset(CreateNewBlockWithKey());
#endif
if (!pblocktemplate.get())
{
if (GetArg("-mineraddress", "").empty()) {
LogPrintf("Error in BTCPrivate Miner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
} else {
// Should never reach here, because -mineraddress validity is checked in init.cpp
LogPrintf("Error in BTCPrivate Miner: Invalid -mineraddress\n");
if (!pblocktemplate.get())
{
if (GetArg("-mineraddress", "").empty()) {
LogPrintf("Error in BTCPrivate Miner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
} else {
// Should never reach here, because -mineraddress validity is checked in init.cpp
LogPrintf("Error in BTCPrivate Miner: Invalid -mineraddress\n");
}
return;
}
return;
}
pblock = &pblocktemplate->block;
pblock = &pblocktemplate->block;
LogPrintf("Running BTCPrivate Miner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
LogPrintf("Running BTCPrivate Miner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
#ifdef FORK_CB_INPUT
} //else
#endif //FORK_CB_INPUT
#endif
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
@ -869,12 +893,12 @@ void static BitcoinMiner()
break;
#ifdef FORK_CB_INPUT
if (!bForking) {
#endif //FORK_CB_INPUT
#endif
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
break;
#ifdef FORK_CB_INPUT
}
#endif //FORK_CB_INPUT
#endif
if (pindexPrev != chainActive.Tip())
break;

View File

@ -55,6 +55,6 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams,
#ifdef FORK_CB_INPUT
CBlockTemplate* CreateNewForkBlock();
#endif //FORK_CB_INPUT
#endif
#endif // BITCOIN_MINER_H

View File

@ -13,6 +13,10 @@
#include <univalue.h>
#ifndef FORK_CB_INPUT
#define FORK_CB_INPUT
#endif
using namespace std;
class CRPCConvertParam
@ -112,6 +116,11 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "z_getoperationstatus", 0},
{ "z_getoperationresult", 0},
{ "z_importkey", 2 },
#ifdef FORK_CB_INPUT
{ "startfork", 0 },
{ "startforkat", 1 },
#endif
};
class CRPCConvertTable

View File

@ -157,6 +157,29 @@ UniValue getgenerate(const UniValue& params, bool fHelp)
return GetBoolArg("-gen", false);
}
#ifdef FORK_CB_INPUT
UniValue startfork(const UniValue& params, bool fHelp)
{
CBlockIndex* pindexPrev = chainActive.Tip();
forkStartHeight = pindexPrev->nHeight;
return NullUniValue;
}
UniValue startforkat(const UniValue& params, bool fHelp)
{
if (params.size() == 1) {
forkStartHeight = params[0].get_int();
} else {
throw runtime_error(
"startfork at chain height\n"
+ HelpExampleCli("startforkat", "100")
);
}
return NullUniValue;
}
#endif
UniValue generate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 1)

View File

@ -309,6 +309,11 @@ static const CRPCCommand vRPCCommands[] =
{ "generating", "generate", &generate, true },
#endif
#ifdef FORK_CB_INPUT
{ "generating", "startfork", &startfork, true },
{ "generating", "startforkat", &startforkat, true },
#endif
/* Raw transactions */
{ "rawtransactions", "createrawtransaction", &createrawtransaction, true },
{ "rawtransactions", "decoderawtransaction", &decoderawtransaction, true },

View File

@ -20,6 +20,10 @@
#include <univalue.h>
#ifndef FORK_CB_INPUT
#define FORK_CB_INPUT
#endif
class AsyncRPCQueue;
class CRPCCommand;
@ -192,6 +196,10 @@ extern UniValue importwallet(const UniValue& params, bool fHelp);
extern UniValue getgenerate(const UniValue& params, bool fHelp); // in rpcmining.cpp
extern UniValue setgenerate(const UniValue& params, bool fHelp);
extern UniValue generate(const UniValue& params, bool fHelp);
#ifdef FORK_CB_INPUT
extern UniValue startfork(const UniValue& params, bool fHelp);
extern UniValue startforkat(const UniValue& params, bool fHelp);
#endif
extern UniValue getlocalsolps(const UniValue& params, bool fHelp);
extern UniValue getnetworksolps(const UniValue& params, bool fHelp);
extern UniValue getnetworkhashps(const UniValue& params, bool fHelp);

View File

@ -272,7 +272,11 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
return true;
}
#ifdef FORK_CB_INPUT
bool CBlockTreeDB::LoadBlockIndexGuts(int64_t forkStart, int64_t forkStop)
#else
bool CBlockTreeDB::LoadBlockIndexGuts()
#endif
{
boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
@ -311,8 +315,14 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nStatus = diskindex.nStatus;
pindexNew->nTx = diskindex.nTx;
#ifdef FORK_CB_INPUT
if (pindexNew->nHeight < forkStart || pindexNew->nHeight >= forkStop) {
#endif
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());
#ifdef FORK_CB_INPUT
}
#endif
pcursor->Next();
} else {

View File

@ -67,7 +67,17 @@ public:
bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list);
bool WriteFlag(const std::string &name, bool fValue);
bool ReadFlag(const std::string &name, bool &fValue);
#ifndef FORK_CB_INPUT
#define FORK_CB_INPUT
#endif
#ifdef FORK_CB_INPUT
bool LoadBlockIndexGuts(int64_t forkStart, int64_t forkStop);
#else
bool LoadBlockIndexGuts();
#endif
};
#endif // BITCOIN_TXDB_H