Enable RPC commands for mining aux proof of work blocks.
This commit is contained in:
parent
8808f237aa
commit
5da72d7da8
|
@ -399,13 +399,6 @@ public:
|
|||
return nVersion / BLOCK_VERSION_CHAIN_START;
|
||||
}
|
||||
|
||||
uint256 GetPoWHash() const
|
||||
{
|
||||
uint256 thash;
|
||||
scrypt_1024_1_1_256(BEGIN(nVersion), BEGIN(thash));
|
||||
return thash;
|
||||
}
|
||||
|
||||
void SetAuxPow(CAuxPow* pow);
|
||||
|
||||
void SetNull()
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "main.h"
|
||||
#include "net.h"
|
||||
#include "scrypt.h"
|
||||
#include "auxpow.h"
|
||||
#ifdef ENABLE_WALLET
|
||||
#include "wallet.h"
|
||||
#endif
|
||||
|
@ -472,12 +473,31 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
|
|||
uint256 hash = pblock->GetPoWHash();
|
||||
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
|
||||
|
||||
if (hash > hashTarget)
|
||||
return false;
|
||||
CAuxPow *auxpow = pblock->auxpow.get();
|
||||
|
||||
//// debug print
|
||||
LogPrintf("DogecoinMiner:\n");
|
||||
LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
|
||||
if (auxpow != NULL) {
|
||||
if (!auxpow->Check(pblock->GetHash(), pblock->GetChainID()))
|
||||
return error("AUX POW is not valid");
|
||||
|
||||
if (auxpow->GetParentBlockHash() > hashTarget)
|
||||
return error("AUX POW parent hash %s is not under target %s", auxpow->GetParentBlockHash().GetHex().c_str(), hashTarget.GetHex().c_str());
|
||||
//// debug print
|
||||
printf("DogecoinMiner:\n");
|
||||
printf("AUX proof-of-work found \n our hash: %s \n parent hash: %s \n target: %s\n",
|
||||
hash.GetHex().c_str(),
|
||||
auxpow->GetParentBlockHash().GetHex().c_str(),
|
||||
hashTarget.GetHex().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hash > hashTarget)
|
||||
return false;
|
||||
|
||||
//// debug print
|
||||
printf("DogecoinMiner:\n");
|
||||
printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
|
||||
}
|
||||
|
||||
pblock->print();
|
||||
LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define BITCOIN_MINER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
class CBlock;
|
||||
class CBlockIndex;
|
||||
|
@ -14,6 +15,7 @@ struct CBlockTemplate;
|
|||
class CReserveKey;
|
||||
class CScript;
|
||||
class CWallet;
|
||||
class CAuxPow;
|
||||
|
||||
/** Run the miner threads */
|
||||
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads);
|
||||
|
@ -22,6 +24,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
|
|||
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
|
||||
/** 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>
|
||||
|
||||
|
@ -15,6 +16,9 @@
|
|||
using namespace json_spirit;
|
||||
using namespace std;
|
||||
|
||||
// from rpcraw.cpp
|
||||
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
|
||||
|
||||
void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
|
||||
|
||||
double GetDifficulty(const CBlockIndex* blockindex)
|
||||
|
@ -60,6 +64,38 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
|||
result.push_back(Pair("height", blockindex->nHeight));
|
||||
result.push_back(Pair("version", block.nVersion));
|
||||
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
|
||||
if (block.nVersion & BLOCK_VERSION_AUXPOW) {
|
||||
// this block includes auxpow
|
||||
Object auxpow;
|
||||
auxpow.push_back(Pair("size", (int)::GetSerializeSize(*block.auxpow, SER_NETWORK, PROTOCOL_VERSION)));
|
||||
|
||||
Object coinbasetx;
|
||||
TxToJSON(*block.auxpow, 0, coinbasetx);
|
||||
auxpow.push_back(Pair("coinbasetx", Value(coinbasetx)));
|
||||
|
||||
Array coinbaseMerkle;
|
||||
BOOST_FOREACH(const uint256 &hash, block.auxpow->vMerkleBranch)
|
||||
coinbaseMerkle.push_back(hash.GetHex());
|
||||
auxpow.push_back(Pair("coinbaseMerkleBranch", coinbaseMerkle));
|
||||
auxpow.push_back(Pair("coinbaseIndex", block.auxpow->nIndex));
|
||||
|
||||
Array chainMerkle;
|
||||
BOOST_FOREACH(const uint256 &hash, block.auxpow->vChainMerkleBranch)
|
||||
chainMerkle.push_back(hash.GetHex());
|
||||
auxpow.push_back(Pair("chainMerkleBranch", chainMerkle));
|
||||
auxpow.push_back(Pair("chainIndex", (boost::uint64_t)block.auxpow->nChainIndex));
|
||||
|
||||
Object parent_block;
|
||||
parent_block.push_back(Pair("hash", block.auxpow->parentBlockHeader.GetHash().GetHex()));
|
||||
parent_block.push_back(Pair("version", (boost::uint64_t)block.auxpow->parentBlockHeader.nVersion));
|
||||
parent_block.push_back(Pair("previousblockhash", block.auxpow->parentBlockHeader.hashPrevBlock.GetHex()));
|
||||
parent_block.push_back(Pair("merkleroot", block.auxpow->parentBlockHeader.hashMerkleRoot.GetHex()));
|
||||
parent_block.push_back(Pair("time", (boost::int64_t)block.auxpow->parentBlockHeader.nTime));
|
||||
parent_block.push_back(Pair("bits", HexBits(block.auxpow->parentBlockHeader.nBits)));
|
||||
parent_block.push_back(Pair("nonce", (boost::uint64_t)block.auxpow->parentBlockHeader.nNonce));
|
||||
auxpow.push_back(Pair("parent_block", Value(parent_block)));
|
||||
result.push_back(Pair("auxpow", Value(auxpow)));
|
||||
}
|
||||
Array txs;
|
||||
BOOST_FOREACH(const CTransaction&tx, block.vtx)
|
||||
txs.push_back(tx.GetHash().GetHex());
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "rpcserver.h"
|
||||
#include "chainparams.h"
|
||||
#include "auxpow.h"
|
||||
#include "init.h"
|
||||
#include "net.h"
|
||||
#include "main.h"
|
||||
|
@ -629,3 +630,278 @@ 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(-9, "Dogecoin is not connected!");
|
||||
|
||||
if (IsInitialBlockDownload())
|
||||
throw JSONRPCError(-10, "Dogecoin is downloading blocks...");
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
pblock->vtx[0].vin[0].scriptSig = MakeCoinbaseWithAux(pblock->nBits, 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(-9, "Dogecoin is not connected!");
|
||||
|
||||
if (IsInitialBlockDownload())
|
||||
throw JSONRPCError(-10, "Dogecoin is downloading blocks...");
|
||||
|
||||
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);
|
||||
if (!pblocktemplate)
|
||||
throw JSONRPCError(-7, "Out of memory");
|
||||
|
||||
pblock = &pblocktemplate->block;
|
||||
// Update nTime
|
||||
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||
pblock->nNonce = 0;
|
||||
|
||||
// Push OP_2 just in case we want versioning later
|
||||
pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(1) << OP_2;
|
||||
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||
|
||||
// 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
|
||||
|
|
|
@ -317,6 +317,9 @@ static const CRPCCommand vRPCCommands[] =
|
|||
{ "gethashespersec", &gethashespersec, true, false, false },
|
||||
{ "getwork", &getwork, true, false, true },
|
||||
{ "setgenerate", &setgenerate, true, true, false },
|
||||
{ "getwork", &getwork, true, false, true },
|
||||
{ "getworkaux", &getworkaux, true, false, true },
|
||||
{ "getauxblock", &getauxblock, true, false, true }
|
||||
#endif // ENABLE_WALLET
|
||||
};
|
||||
|
||||
|
|
|
@ -134,6 +134,9 @@ extern json_spirit::Value getwork(const json_spirit::Array& params, bool fHelp);
|
|||
extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value submitblock(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);
|
||||
|
||||
extern json_spirit::Value getnewaddress(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp
|
||||
extern json_spirit::Value getaccountaddress(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getrawchangeaddress(const json_spirit::Array& params, bool fHelp);
|
||||
|
|
Loading…
Reference in a new issue