This commit is contained in:
myriadcoin
2015-07-08 20:47:42 +02:00
parent e0eb59aa50
commit 92ebd5be96
15 changed files with 544 additions and 43 deletions
+3 -1
View File
@@ -85,7 +85,8 @@ BITCOIN_CORE_H = \
hashgroestl.h \
hashskein.h \
hashqubit.h \
stealthaddress.h
stealthaddress.h \
auxpow.h
JSON_H = \
json/json_spirit.h \
@@ -125,6 +126,7 @@ libbitcoin_server_a_SOURCES = \
rpcserver.cpp \
txdb.cpp \
txmempool.cpp \
auxpow.cpp \
$(JSON_H) \
$(BITCOIN_CORE_H)
+1
View File
@@ -6,6 +6,7 @@
#include "core.h"
#include "util.h"
#include "auxpow.h"
std::string COutPoint::ToString() const
{
+33 -1
View File
@@ -29,6 +29,8 @@ enum
// primary version
BLOCK_VERSION_DEFAULT = 2,
BLOCK_VERSION_AUXPOW = (1 << 8),
// algo
BLOCK_VERSION_ALGO = (7 << 9),
BLOCK_VERSION_SCRYPT = (1 << 9),
@@ -37,6 +39,13 @@ enum
BLOCK_VERSION_QUBIT = (4 << 9),
};
static const int BLOCK_VERSION_CHAIN_START = (1 << 16);
static const int BLOCK_VERSION_CHAIN_END = (1 << 30);
static const int AUXPOW_CHAIN_ID = 0x005A;
static const int AUXPOW_START_MAINNET = 9999999; //TODO change me
static const int AUXPOW_START_TESTNET = 1;
inline int GetAlgo(int nVersion)
{
switch (nVersion & BLOCK_VERSION_ALGO)
@@ -402,6 +411,16 @@ public:
)
};
class CAuxPow;
template <typename Stream>
int ReadWriteAuxPow(Stream& s, const boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionSerialize ser_action);
template <typename Stream>
int ReadWriteAuxPow(Stream& s, boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionUnserialize ser_action);
template <typename Stream>
int ReadWriteAuxPow(Stream& s, const boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionGetSerializeSize ser_action);
/** Nodes collect new transactions into a block, hash them into a hash tree,
* and scan through nonce values to make the block's hash satisfy proof-of-work
@@ -410,6 +429,7 @@ public:
* in the block is a special one that creates a new coin owned by the creator
* of the block.
*/
class CBlockHeader
{
public:
@@ -421,6 +441,7 @@ public:
unsigned int nTime;
unsigned int nBits;
unsigned int nNonce;
boost::shared_ptr<CAuxPow> auxpow;
CBlockHeader()
{
@@ -438,11 +459,12 @@ public:
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
nSerSize += ReadWriteAuxPow(s, auxpow, nType, nVersion, ser_action);
)
void SetNull()
{
nVersion = CBlockHeader::CURRENT_VERSION;
nVersion = CBlockHeader::CURRENT_VERSION | (AUXPOW_CHAIN_ID * BLOCK_VERSION_CHAIN_START);
hashPrevBlock = 0;
hashMerkleRoot = 0;
nTime = 0;
@@ -455,6 +477,13 @@ public:
return (nBits == 0);
}
int GetChainID() const
{
return nVersion / BLOCK_VERSION_CHAIN_START;
}
void SetAuxPow(CAuxPow* pow);
uint256 GetHash() const;
// Note: we use explicitly provided algo instead of the one returned by GetAlgo(), because this can be a block
@@ -486,6 +515,8 @@ public:
{
return (int64_t)nTime;
}
bool CheckProofOfWork(int nHeight) const;
};
@@ -531,6 +562,7 @@ public:
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
block.auxpow = auxpow;
return block;
}
+99 -4
View File
@@ -16,6 +16,7 @@
#include "txmempool.h"
#include "ui_interface.h"
#include "util.h"
#include "auxpow.h"
#include <sstream>
@@ -407,6 +408,33 @@ CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const {
CCoinsViewCache *pcoinsTip = NULL;
CBlockTreeDB *pblocktree = NULL;
// to enable merged mining:
// - set a block from which it will be enabled
// - set a unique chain ID
// each merged minable scrypt_1024_1_1_256 coin should have a different one
// (if two have the same ID, they can't be merge mined together)
int GetAuxPowStartBlock()
{
if (TestNet())
return AUXPOW_START_TESTNET;
else
return AUXPOW_START_MAINNET;
}
void CBlockHeader::SetAuxPow(CAuxPow* pow)
{
if (pow != NULL)
nVersion |= BLOCK_VERSION_AUXPOW;
else
nVersion &= ~BLOCK_VERSION_AUXPOW;
auxpow.reset(pow);
}
bool IsAuxPowVersion(int nVersion)
{
return (nVersion == BLOCK_VERSION_AUXPOW_WITH_AUX || nVersion == BLOCK_VERSION_AUXPOW_WITHOUT_AUX);
}
//////////////////////////////////////////////////////////////////////////////
//
// mapOrphanTransactions
@@ -1469,6 +1497,47 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits, int algo)
return true;
}
bool CBlockHeader::CheckProofOfWork(int nHeight) const
{
int algo = GetAlgo();
if ((nHeight >= GetAuxPowStartBlock()) && (algo == ALGO_SHA256D))
{
// Prevent same work from being submitted twice:
// - this block must have our chain ID
// - parent block must not have the same chain ID (see CAuxPow::Check)
// - index of this chain in chain merkle tree must be pre-determined (see CAuxPow::Check)
if (!TestNet() && nHeight != INT_MAX && GetChainID() != AUXPOW_CHAIN_ID)
return error("CheckProofOfWork() : block (chainID=%d) does not have our chain ID (chainID=%d)", GetChainID(),AUXPOW_CHAIN_ID);
if (auxpow.get() != NULL)
{
if (!auxpow->Check(GetHash(), GetChainID()))
return error("CheckProofOfWork() : AUX POW is not valid");
// Check proof of work matches claimed amount
if (!::CheckProofOfWork(auxpow->GetParentBlockHash(algo), nBits, algo))
return error("CheckProofOfWork() : AUX proof of work failed");
}
else
{
// Check proof of work matches claimed amount
if (!::CheckProofOfWork(GetPoWHash(algo), nBits, algo))
return error("CheckProofOfWork() : proof of work failed");
}
}
else
{
if (auxpow.get() != NULL)
{
return error("CheckProofOfWork() : AUX POW is not allowed at this block");
}
// Check if proof of work marches claimed amount
if (!::CheckProofOfWork(GetPoWHash(algo), nBits, algo))
return error("CheckProofOfWork() : proof of work failed");
}
return true;
}
// Return maximum amount of blocks that other nodes claim to have
int GetNumBlocksOfPeers()
{
@@ -1627,7 +1696,8 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state
}
if (!state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID;
pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex));
//pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex));
pblocktree->WriteBlockIndex(*pindex);
setBlockIndexValid.erase(pindex);
InvalidChainFound(pindex);
}
@@ -2033,8 +2103,9 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
pindex->nStatus = (pindex->nStatus & ~BLOCK_VALID_MASK) | BLOCK_VALID_SCRIPTS;
CDiskBlockIndex blockindex(pindex);
if (!pblocktree->WriteBlockIndex(blockindex))
//CDiskBlockIndex blockindex(pindex);
//if (!pblocktree->WriteBlockIndex(blockindex))
if (!pblocktree->WriteBlockIndex(*pindex))
return state.Abort(_("Failed to write block index"));
}
@@ -2305,6 +2376,27 @@ bool ActivateBestChain(CValidationState &state) {
return true;
}
CBlockHeader CBlockIndex::GetBlockHeader() const
{
CBlockHeader block;
if (nVersion & BLOCK_VERSION_AUXPOW) {
CDiskBlockIndex diskblockindex;
// auxpow is not in memory, load CDiskBlockHeader
// from database to get it
pblocktree->ReadDiskBlockIndex(*phashBlock, diskblockindex);
block.auxpow = diskblockindex.auxpow;
}
block.nVersion = nVersion;
if (pprev)
block.hashPrevBlock = pprev->GetBlockHash();
block.hashMerkleRoot = hashMerkleRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
return block;
}
bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos)
{
// Check for duplicate
@@ -2341,7 +2433,10 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
pindexNew->nStatus = BLOCK_VALID_TRANSACTIONS | BLOCK_HAVE_DATA;
setBlockIndexValid.insert(pindexNew);
if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)))
//if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)))
if (!pblocktree->WriteDiskBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(*pindexNew))
/* write both the immutible data (CDiskBlockIndex) and the mutable data (BlockIndex) */
//if (!pblocktree->WriteDiskBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(*pindexNew))
return state.Abort(_("Failed to write block index"));
// New best?
+43 -13
View File
@@ -67,6 +67,14 @@ static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 128;
/** Timeout in seconds before considering a block download peer unresponsive. */
static const unsigned int BLOCK_DOWNLOAD_TIMEOUT = 60;
/** AuxPow Block versions for sanity checks. */
/** bare AuxPoW block version which will be modulated further. */
static const int BLOCK_VERSION_AUXPOW_BARE = CBlockHeader::CURRENT_VERSION | (AUXPOW_CHAIN_ID * BLOCK_VERSION_CHAIN_START);
/** version when AuxPoW exists on the block */
static const int BLOCK_VERSION_AUXPOW_WITH_AUX = BLOCK_VERSION_AUXPOW_BARE | BLOCK_VERSION_AUXPOW;
/** version when no AuxPoW exists on the block */
static const int BLOCK_VERSION_AUXPOW_WITHOUT_AUX = BLOCK_VERSION_AUXPOW_BARE & ~BLOCK_VERSION_AUXPOW;
/** Stealth addresses */
static const int64_t BLOCK_STEALTH_START = 740000;
@@ -180,6 +188,12 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev);
/** Determine whether the block version is modulated with auxpow logic */
bool IsAuxPowVersion(int nVersion);
/** Get the block at which AuxPoW is enabled for this network */
int GetAuxPowStartBlock();
/** Create a new block index entry for a given block hash */
CBlockIndex * InsertBlockIndex(uint256 hash);
/** Verify a signature */
@@ -705,6 +719,8 @@ const int64_t nBlockTimeWarpPreventStart3 = 1048320; // block where time warp 3
* candidates to be the next block. A blockindex may have multiple pprev pointing
* to it, but at most one of them can be part of the currently active branch.
*/
class CDiskBlockIndex;
class CBlockIndex
{
public:
@@ -797,6 +813,22 @@ public:
nNonce = block.nNonce;
}
IMPLEMENT_SERIALIZE
(
/* mutable stuff goes here, immutable stuff
* has SERIALIZE functions in CDiskBlockIndex */
if (!(nType & SER_GETHASH))
READWRITE(VARINT(nVersion));
READWRITE(VARINT(nStatus));
if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO))
READWRITE(VARINT(nFile));
if (nStatus & BLOCK_HAVE_DATA)
READWRITE(VARINT(nDataPos));
if (nStatus & BLOCK_HAVE_UNDO)
READWRITE(VARINT(nUndoPos));
)
int GetAlgo() const { return ::GetAlgo(nVersion); }
CDiskBlockPos GetBlockPos() const {
@@ -817,18 +849,7 @@ public:
return ret;
}
CBlockHeader GetBlockHeader() const
{
CBlockHeader block;
block.nVersion = nVersion;
if (pprev)
block.hashPrevBlock = pprev->GetBlockHash();
block.hashMerkleRoot = hashMerkleRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
return block;
}
CBlockHeader GetBlockHeader() const;
uint256 GetBlockHash() const
{
@@ -1030,12 +1051,20 @@ class CDiskBlockIndex : public CBlockIndex
public:
uint256 hashPrev;
// if this is an aux work block
boost::shared_ptr<CAuxPow> auxpow;
CDiskBlockIndex() {
hashPrev = 0;
}
explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex) {
//CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex) {
// hashPrev = (pprev ? pprev->GetBlockHash() : 0);
//}
explicit CDiskBlockIndex(CBlockIndex* pindex, boost::shared_ptr<CAuxPow> auxpow) : CBlockIndex(*pindex) {
hashPrev = (pprev ? pprev->GetBlockHash() : 0);
this->auxpow = auxpow;
}
IMPLEMENT_SERIALIZE
@@ -1060,6 +1089,7 @@ public:
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
ReadWriteAuxPow(s, auxpow, nType, this->nVersion, ser_action);
)
uint256 GetBlockHash() const
+44 -23
View File
@@ -8,6 +8,7 @@
#include "core.h"
#include "main.h"
#include "net.h"
#include "auxpow.h"
#ifdef ENABLE_WALLET
#include "wallet.h"
#endif
@@ -134,7 +135,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, int algo)
error("CreateNewBlock: bad algo");
return NULL;
}
// Create coinbase tx
CTransaction txNew;
txNew.vin.resize(1);
@@ -487,19 +488,39 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
{
int algo = pblock->GetAlgo();
uint256 hashPoW = pblock->GetPoWHash(algo);
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
uint256 hash = pblock->GetHash();
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
if (hashPoW > hashTarget)
return false;
// LogPrintf("DEBUG| proof-of-work submitted \n algo: %s\nblock-PoWhash: %s\nblock-hash: %s\n ntarget: %s\n",
// algo,
// hashPoW.GetHex(),
// hash.GetHex(),
// hashTarget.GetHex());
CAuxPow *auxpow = pblock->auxpow.get();
if (auxpow != NULL) {
if (!auxpow->Check(pblock->GetHash(), pblock->GetChainID()))
return error("AUX POW is not valid");
if (auxpow->GetParentBlockHash(algo) > hashTarget)
return error("AUX POW parent hash %s is not under target %s", auxpow->GetParentBlockHash(algo).GetHex().c_str(), hashTarget.GetHex().c_str());
// print to log
LogPrintf("MyriadMiner: AUX proof-of-work found; our hash: %s ; parent hash: %s ; target: %s\n",
hash.GetHex().c_str(),
auxpow->GetParentBlockHash(algo).GetHex().c_str(),
hashTarget.GetHex().c_str());
}
else
{
if (hashPoW > hashTarget)
return false;
// print to log
LogPrintf("MyriadMiner: proof-of-work found; hashPoW: %s ; target: %s\n", hashPoW.GetHex().c_str(), hashTarget.GetHex().c_str());
}
uint256 hashBlock = pblock->GetHash();
//// debug print
LogPrintf("MyriadcoinMiner:\n");
LogPrintf("proof-of-work found \n block-hash: %s\n pow-hash: %s\ntarget: %s\n",
hashBlock.GetHex(),
hashPoW.GetHex(),
hashTarget.GetHex());
pblock->print();
LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
@@ -507,7 +528,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
{
LOCK(cs_main);
if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
return error("MyriadcoinMiner : generated block is stale");
return error("MyriadMiner : generated block is stale");
// Remove key from key pool
reservekey.KeepKey();
@@ -521,7 +542,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
// Process this block the same as if we had received it from another node
CValidationState state;
if (!ProcessBlock(state, NULL, pblock))
return error("MyriadcoinMiner : ProcessBlock, block not accepted");
return error("MyriadMiner : ProcessBlock, block not accepted");
}
return true;
@@ -529,7 +550,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
void static MinerWaitOnline()
{
if (Params().NetworkID() != CChainParams::REGTEST)
if (Params().NetworkID() != CChainParams::REGTEST)
{
// Busy-wait for the network to come online so we don't waste time mining
// on an obsolete chain. In regtest mode we expect to fly solo.
@@ -683,7 +704,7 @@ void static ScryptMiner(CWallet *pwallet)
while(true)
{
MinerWaitOnline();
//
// Create new block
//
@@ -695,7 +716,7 @@ void static ScryptMiner(CWallet *pwallet)
return;
CBlock *pblock = &pblocktemplate->block;
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
LogPrintf("Running scrypt miner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
@@ -801,7 +822,7 @@ void static ScryptMiner(CWallet *pwallet)
nBlockBits = ByteReverse(pblock->nBits);
hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
}
}
}
}
@@ -828,7 +849,7 @@ void static GenericMiner(CWallet *pwallet, int algo)
CBlock *pblock = &pblocktemplate->block;
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
LogPrintf("Running %s miner with %u transactions in block (%u bytes)\n",
LogPrintf("Running %s miner with %u transactions in block (%u bytes)\n",
GetAlgoName(algo).c_str(),
pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
@@ -853,7 +874,7 @@ void static GenericMiner(CWallet *pwallet, int algo)
break;
}
++pblock->nNonce;
// Meter hashes/sec
static int64_t nHashCounter;
if (nHPSTimerStart == 0)
@@ -904,7 +925,7 @@ void static GenericMiner(CWallet *pwallet, int algo)
// hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
}
}
}
}
}
void static ThreadBitcoinMiner(CWallet *pwallet)
@@ -912,8 +933,8 @@ void static ThreadBitcoinMiner(CWallet *pwallet)
LogPrintf("Myriadcoin miner started\n");
SetThreadPriority(THREAD_PRIORITY_LOWEST);
RenameThread("bitcoin-miner");
try
try
{
switch (miningAlgo)
{
+3
View File
@@ -7,6 +7,8 @@
#define BITCOIN_MINER_H
#include <stdint.h>
#include "auxpow.h"
#include "core.h"
class CBlock;
class CBlockIndex;
@@ -22,6 +24,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, int algo);
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int algo);
/** Modify the extranonce in a block */
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
void IncrementExtraNonceWithAux(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, std::vector<unsigned char>& vchAux);
/** Do mining precalculation */
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
/** Check mined block */
+1
View File
@@ -7,6 +7,7 @@
#include "main.h"
#include "sync.h"
#include "checkpoints.h"
#include "auxpow.h"
#include <stdint.h>
+287
View File
@@ -633,3 +633,290 @@ Value submitblock(const Array& params, bool fHelp)
return Value::null;
}
#ifdef ENABLE_WALLET
Value getworkaux(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1)
throw runtime_error(
"getworkaux <aux>\n"
"getworkaux '' <data>\n"
"getworkaux 'submit' <data>\n"
"getworkaux '' <data> <chain-index> <branch>*\n"
" get work with auxiliary data in coinbase, for multichain mining\n"
"<aux> is the merkle root of the auxiliary chain block hashes, concatenated with the aux chain merkle tree size and a nonce\n"
"<chain-index> is the aux chain index in the aux chain merkle tree\n"
"<branch> is the optional merkle branch of the aux chain\n"
"If <data> is not specified, returns formatted hash data to work on:\n"
" \"midstate\" : precomputed hash state after hashing the first half of the data\n"
" \"data\" : block data\n"
" \"hash1\" : formatted hash buffer for second hash\n"
" \"target\" : little endian hash target\n"
"If <data> is specified and 'submit', tries to solve the block for this (parent) chain and returns true if it was successful."
"If <data> is specified and empty first argument, returns the aux merkle root, with size and nonce."
"If <data> and <chain-index> are specified, creates an auxiliary proof of work for the chain specified and returns:\n"
" \"aux\" : merkle root of auxiliary chain block hashes\n"
" \"auxpow\" : aux proof of work to submit to aux chain\n"
);
if (vNodes.empty())
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Unitus is not connected!");
if (IsInitialBlockDownload())
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Unitus is downloading blocks...");
// We use height plus one because we're testing the next block
if ((chainActive.Tip()->nHeight+1) < GetAuxPowStartBlock()) {
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "getworkaux method is not available until switch-over block.");
}
static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
static vector<CBlockTemplate*> vNewBlockTemplate;
static CReserveKey reservekey(pwalletMain);
if (params.size() == 1)
{
static vector<unsigned char> vchAuxPrev;
vector<unsigned char> vchAux = ParseHex(params[0].get_str());
// Update block
static unsigned int nTransactionsUpdatedLast;
static CBlockIndex* pindexPrev;
static uint64_t nStart;
static CBlockTemplate* pblocktemplate;
if (pindexPrev != chainActive.Tip() ||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60))
{
if (pindexPrev != chainActive.Tip())
{
// Deallocate old blocks since they're obsolete now
mapNewBlock.clear();
BOOST_FOREACH(CBlockTemplate* pblocktemplate, vNewBlockTemplate)
delete pblocktemplate;
vNewBlockTemplate.clear();
}
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
pindexPrev = chainActive.Tip();
vchAuxPrev = vchAux;
nStart = GetTime();
// Create new block
pblocktemplate = CreateNewBlockWithKey(*pMiningKey, miningAlgo);
if (!pblocktemplate)
throw JSONRPCError(-7, "Out of memory");
vNewBlockTemplate.push_back(pblocktemplate);
}
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
// Update nTime
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
pblock->nNonce = 0;
// Update nExtraNonce
static unsigned int nExtraNonce = 0;
IncrementExtraNonceWithAux(pblock, pindexPrev, nExtraNonce, vchAux);
// Save
mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, nExtraNonce);
// Prebuild hash buffers
char pmidstate[32];
char pdata[128];
char phash1[64];
FormatHashBuffers(pblock, pmidstate, pdata, phash1);
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
Object result;
result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
return result;
}
else
{
if (params[0].get_str() != "submit" && params[0].get_str() != "")
throw JSONRPCError(-8, "<aux> must be the empty string or 'submit' if work is being submitted");
// Parse parameters
vector<unsigned char> vchData = ParseHex(params[1].get_str());
if (vchData.size() != 128)
throw JSONRPCError(-8, "Invalid parameter");
CBlock* pdata = (CBlock*)&vchData[0];
// Byte reverse
for (int i = 0; i < 128/4; i++)
((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
// Get saved block
if (!mapNewBlock.count(pdata->hashMerkleRoot))
return false;
CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
unsigned int nExtraNonce = mapNewBlock[pdata->hashMerkleRoot].second;
pblock->nTime = pdata->nTime;
pblock->nNonce = pdata->nNonce;
// Get the aux merkle root from the coinbase
CScript script = pblock->vtx[0].vin[0].scriptSig;
opcodetype opcode;
CScript::const_iterator pc = script.begin();
script.GetOp(pc, opcode);
script.GetOp(pc, opcode);
script.GetOp(pc, opcode);
if (opcode != OP_2)
throw runtime_error("invalid aux pow script");
vector<unsigned char> vchAux;
script.GetOp(pc, opcode, vchAux);
RemoveMergedMiningHeader(vchAux);
unsigned int nHeight = chainActive.Tip()->nHeight+1; // Height first in coinbase required for block.version=2
pblock->vtx[0].vin[0].scriptSig = MakeCoinbaseWithAux(nHeight, nExtraNonce, vchAux);
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
if (params.size() > 2)
{
// Requested aux proof of work
int nChainIndex = params[2].get_int();
CAuxPow pow(pblock->vtx[0]);
for (unsigned int i = 3 ; i < params.size() ; i++)
{
uint256 nHash;
nHash.SetHex(params[i].get_str());
pow.vChainMerkleBranch.push_back(nHash);
}
pow.SetMerkleBranch(pblock);
pow.nChainIndex = nChainIndex;
pow.parentBlockHeader = *pblock;
CDataStream ss(SER_GETHASH, PROTOCOL_VERSION);
ss << pow;
Object result;
result.push_back(Pair("auxpow", HexStr(ss.begin(), ss.end())));
return result;
}
else
{
if (params[0].get_str() == "submit")
{
return CheckWork(pblock, *pwalletMain, reservekey);
}
else
{
Object result;
result.push_back(Pair("aux", HexStr(vchAux.begin(), vchAux.end())));
result.push_back(Pair("hash", pblock->GetHash().GetHex()));
return result;
}
}
}
}
Value getauxblock(const Array& params, bool fHelp)
{
if (fHelp || (params.size() != 0 && params.size() != 2))
throw runtime_error(
"getauxblock [<hash> <auxpow>]\n"
" create a new block"
"If <hash>, <auxpow> is not specified, returns a new block hash.\n"
"If <hash>, <auxpow> is specified, tries to solve the block based on "
"the aux proof of work and returns true if it was successful.");
if (vNodes.empty())
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Unitus is not connected!");
if (IsInitialBlockDownload())
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Unitus is downloading blocks...");
// We use height plus one because we're testing the next block
if ((chainActive.Tip()->nHeight+1) < GetAuxPowStartBlock()) {
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "getauxblock method is not available until switch-over block.");
}
static map<uint256, CBlock*> mapNewBlock;
static vector<CBlockTemplate*> vNewBlockTemplate;
static CReserveKey reservekey(pwalletMain);
if (params.size() == 0)
{
// Update block
static unsigned int nTransactionsUpdatedLast;
static CBlockIndex* pindexPrev;
static uint64_t nStart;
static CBlock* pblock;
static CBlockTemplate* pblocktemplate;
if (pindexPrev != chainActive.Tip() ||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60))
{
if (pindexPrev != chainActive.Tip())
{
// Deallocate old blocks since they're obsolete now
mapNewBlock.clear();
BOOST_FOREACH(CBlockTemplate* pblocktemplate, vNewBlockTemplate)
delete pblocktemplate;
vNewBlockTemplate.clear();
}
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
pindexPrev = chainActive.Tip();
nStart = GetTime();
// Create new block with nonce = 0 and extraNonce = 1
pblocktemplate = CreateNewBlockWithKey(*pMiningKey, miningAlgo);
if (!pblocktemplate)
throw JSONRPCError(-7, "Out of memory");
pblock = &pblocktemplate->block;
// Update nTime
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
pblock->nNonce = 0;
// Update nExtraNonce
static unsigned int nExtraNonce = 0;
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
// Sets the version
pblock->SetAuxPow(new CAuxPow());
// Save
mapNewBlock[pblock->GetHash()] = pblock;
vNewBlockTemplate.push_back(pblocktemplate);
}
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
Object result;
result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
result.push_back(Pair("hash", pblock->GetHash().GetHex()));
result.push_back(Pair("chainid", pblock->GetChainID()));
return result;
}
else
{
uint256 hash;
hash.SetHex(params[0].get_str());
vector<unsigned char> vchAuxPow = ParseHex(params[1].get_str());
CDataStream ss(vchAuxPow, SER_GETHASH, PROTOCOL_VERSION);
CAuxPow* pow = new CAuxPow();
ss >> *pow;
if (!mapNewBlock.count(hash))
return ::error("getauxblock() : block not found");
CBlock* pblock = mapNewBlock[hash];
pblock->SetAuxPow(pow);
if (!CheckWork(pblock, *pwalletMain, reservekey))
{
return false;
}
else
{
return true;
}
}
}
#endif
+3
View File
@@ -325,6 +325,9 @@ static const CRPCCommand vRPCCommands[] =
{ "scanforalltxns", &scanforalltxns, false, false, true},
{ "scanforstealthtxns", &scanforstealthtxns, false, false, true},
{ "getworkaux", &getworkaux, true, false, true },
{ "getauxblock", &getauxblock, true, false, true }
#endif // ENABLE_WALLET
};
+3
View File
@@ -198,4 +198,7 @@ extern json_spirit::Value clearwallettransactions(const json_spirit::Array& para
extern json_spirit::Value scanforalltxns(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value scanforstealthtxns(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getworkaux(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getauxblock(const json_spirit::Array& params, bool fHelp);
#endif
+1
View File
@@ -10,6 +10,7 @@
#include "serialize.h"
#include "uint256.h"
#include "util.h"
#include "auxpow.h"
#include <vector>
+1
View File
@@ -9,6 +9,7 @@
#include "main.h"
#include "auxpow.h"
#include <cstdio>
+18
View File
@@ -7,6 +7,7 @@
#include "core.h"
#include "uint256.h"
#include "auxpow.h"
#include <stdint.h>
@@ -68,10 +69,27 @@ bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const u
CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}
/*
bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
{
return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
}
*/
bool CBlockTreeDB::WriteBlockIndex(const CBlockIndex& blockindex)
{
return Write(boost::tuples::make_tuple('b', blockindex.GetBlockHash(), 'b'), blockindex);
}
bool CBlockTreeDB::ReadDiskBlockIndex(const uint256 &blkid, CDiskBlockIndex &diskblockindex)
{
return Read(boost::tuples::make_tuple('b', blkid, 'a'), diskblockindex);
}
bool CBlockTreeDB::WriteDiskBlockIndex(const CDiskBlockIndex& diskblockindex)
{
return Write(boost::tuples::make_tuple('b', *diskblockindex.phashBlock, 'a'), diskblockindex);
}
bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
{
+4 -1
View File
@@ -51,7 +51,10 @@ private:
CBlockTreeDB(const CBlockTreeDB&);
void operator=(const CBlockTreeDB&);
public:
bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
// bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
bool WriteDiskBlockIndex(const CDiskBlockIndex& diskblockindex);
bool WriteBlockIndex(const CBlockIndex& blockindex);
bool ReadDiskBlockIndex(const uint256 &blkid, CDiskBlockIndex& diskblockindex);
bool WriteBestInvalidWork(const CBigNum& bnBestInvalidWork);
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo);
bool WriteBlockFileInfo(int nFile, const CBlockFileInfo &fileinfo);