mirror of
https://github.com/jwinterm/myriadcoin.git
synced 2026-10-18 05:51:27 +02:00
auxpow
This commit is contained in:
+3
-1
@@ -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)
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "core.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "auxpow.h"
|
||||
|
||||
std::string COutPoint::ToString() const
|
||||
{
|
||||
|
||||
+33
-1
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "main.h"
|
||||
#include "sync.h"
|
||||
#include "checkpoints.h"
|
||||
#include "auxpow.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
#include "auxpow.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
|
||||
#include "main.h"
|
||||
#include "auxpow.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user