Skip to content
3 changes: 3 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ bool AppInit2(int argc, char* argv[])
" -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port> (default: 8332)\n") +
" -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address\n") +
" -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)\n") +
#ifndef __WXMSW__
" -coinbaser=<cmd> \t " + _("Execute <cmd> to calculate coinbase payees\n") +
#endif
" -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)\n") +
" -rescan \t " + _("Rescan the block chain for missing wallet transactions\n");

Expand Down
168 changes: 162 additions & 6 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include "net.h"
#include "init.h"
#include "cryptopp/sha.h"

#include <limits.h>

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>

Expand Down Expand Up @@ -2652,6 +2655,117 @@ class COrphan
};


#ifndef __WXMSW__
int DoCoinbaser_I(CBlock* pblock, uint64 nTotal, FILE* file)
{
int nCount;
if (fscanf(file, "%d\n", &nCount) != 1)
{
printf("DoCoinbaser(): failed to fscanf count\n");
return -2;
}
pblock->vtx[0].vout.resize(nCount + 1);
uint64 nDistributed = 0;
for (int i = 1; i <= nCount; ++i)
{
uint64 nValue;
if (fscanf(file, "%" PRI64u "\n", &nValue) != 1)
{
printf("DoCoinbaser(): failed to fscanf amount for transaction #%d\n", i);
return -(0x1000 | i);
}
pblock->vtx[0].vout[i].nValue = nValue;
nDistributed += nValue;
char strAddr[35];
if (fscanf(file, "%34s\n", strAddr) != 1)
{
printf("DoCoinbaser(): failed to fscanf address for transaction #%d\n", i);
return -(0x2000 | i);
}
CBitcoinAddress address;
if (!address.SetString(strAddr))
{
printf("DoCoinbaser(): invalid bitcoin address for transaction #%d\n", i);
return -(0x3000 | i);
}
pblock->vtx[0].vout[i].scriptPubKey.SetBitcoinAddress(address);
}
if (nTotal < nDistributed)
{
printf("DoCoinbaser(): attempt to distribute %" PRI64u "/%" PRI64u "\n", nDistributed, nTotal);
return -3;
}
uint64 nMine = nTotal - nDistributed;
printf("DoCoinbaser(): total distributed: %" PRI64u "/%" PRI64u " = %" PRI64u " for me\n", nDistributed, nTotal, nMine);
pblock->vtx[0].vout[0].nValue = nMine;
return 0;
}

int DoCoinbaser(CBlock* pblock, uint64 nTotal)
{
string strCmd = mapArgs["-coinbaser"];
FILE* file = NULL;
if (!strCmd.compare(0, 4, "tcp:"))
{
CAddress addrCoinbaser(strCmd.substr(4), true, 0);
SOCKET hSocket;
if (!ConnectSocket(addrCoinbaser, hSocket))
{
perror("DoCoinbaser(): failed to connect");
return -3;
}
file = fdopen(hSocket, "r+");
if (file)
fprintf(file, "total: %" PRI64u "\n\n", nTotal);
}
else
{

try
{
char strTotal[11];
int nTotalLen = snprintf(strTotal, 11, "%" PRI64u, nTotal);
if (nTotalLen < 1 || nTotalLen > 10)
{
strTotal[0] = '\0';
nTotalLen = 0;
}
string::size_type nPos;
while ((nPos = strCmd.find("%d")) != string::npos)
{
strCmd.replace(nPos, 2, strTotal, nTotalLen);
}
}
catch (...)
{
return 1;
}
file = popen(strCmd.c_str(), "r");

}

if (!file)
{
printf("DoCoinbaser(): failed to popen: %s", strerror(errno));
return -1;
}

int rv;
try
{
rv = DoCoinbaser_I(pblock, nTotal, file);
}
catch (...)
{
rv = 1;
}
pclose(file);
if (rv)
pblock->vtx[0].vout.resize(1);
return rv;
}
#endif

CBlock* CreateNewBlock(CReserveKey& reservekey)
{
CBlockIndex* pindexPrev = pindexBest;
Expand Down Expand Up @@ -2787,7 +2901,12 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
}
}
}
pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
int64 nBlkValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
pblock->vtx[0].vout[0].nValue = nBlkValue;
#ifndef __WXMSW__
if (mapArgs.count("-coinbaser"))
DoCoinbaser(&*pblock, nBlkValue);
#endif

// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
Expand All @@ -2796,21 +2915,58 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
pblock->nBits = GetNextWorkRequired(pindexPrev);
pblock->nNonce = 0;

pblock->print();
return pblock.release();
}


std::map<std::string, CScript> mapAuxCoinbases;

CScript BuildCoinbaseScriptSig(uint64 nTime, unsigned int nExtraNonce, bool *pfOverflow)
{
CScript scriptSig = CScript() << nTime << CBigNum(nExtraNonce);

map<std::string, CScript>::iterator it;
for (it = mapAuxCoinbases.begin() ; it != mapAuxCoinbases.end(); ++it)
scriptSig += (*it).second;

if (scriptSig.size() > 100)
{
scriptSig.resize(100);
if (pfOverflow)
*pfOverflow = true;
}
else
if (pfOverflow)
*pfOverflow = false;

return scriptSig;
}

void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
{
// Update nExtraNonce
static uint256 hashPrevBlock;
if (hashPrevBlock != pblock->hashPrevBlock)
static uint64 nPrevTime = 0;
static bool fBackward = false;
uint64 nNow = GetTime();
if (nNow > nPrevTime + 1)
{
nExtraNonce = 0;
hashPrevBlock = pblock->hashPrevBlock;
nPrevTime = nNow;
fBackward = false;
}
else
{
if (nNow < nPrevTime && !fBackward)
{
printf("IncrementExtraNonce: WARNING: nNow moved backward: %d -> %d\n", nPrevTime, nNow);
fBackward = true;
}
if (nExtraNonce == UINT_MAX)
printf("IncrementExtraNonce: WARNING: nExtraNonce overflowing!\n");
++nExtraNonce;
}
++nExtraNonce;
pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nTime << CBigNum(nExtraNonce);
pblock->vtx[0].vin[0].scriptSig = BuildCoinbaseScriptSig(nNow, nExtraNonce);
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
}

Expand Down
2 changes: 2 additions & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto, bool fSendTrickle);
void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
CBlock* CreateNewBlock(CReserveKey& reservekey);
extern std::map<std::string, CScript> mapAuxCoinbases;
CScript BuildCoinbaseScriptSig(uint64 nTime, unsigned int nExtraNonce, bool *pfOverflow = NULL);
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
Expand Down
30 changes: 30 additions & 0 deletions src/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,35 @@ Value validateaddress(const Array& params, bool fHelp)
}


Value setworkaux(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"setworkaux <id> [data]\n"
"If [data] is not specified, deletes aux.\n"
);

std::string strId = params[0].get_str();
if (params.size() > 1)
{
std::string strData = params[1].get_str();
std::vector<unsigned char> vchData = ParseHex(strData);
if (vchData.size() * 2 != strData.size())
throw JSONRPCError(-8, "Failed to parse data as hexadecimal");
CScript scriptBackup = mapAuxCoinbases[strId];
mapAuxCoinbases[strId] = CScript(vchData);
bool fOverflow;
BuildCoinbaseScriptSig(0, UINT_MAX, &fOverflow);
if (fOverflow)
throw JSONRPCError(-7, "Change would overflow coinbase script");
}
else
mapAuxCoinbases.erase(strId);

return true;
}


Value getwork(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 1)
Expand Down Expand Up @@ -1640,6 +1669,7 @@ pair<string, rpcfn_type> pCallTable[] =
make_pair("sendmany", &sendmany),
make_pair("gettransaction", &gettransaction),
make_pair("listtransactions", &listtransactions),
make_pair("setworkaux", &setworkaux),
make_pair("getwork", &getwork),
make_pair("listaccounts", &listaccounts),
make_pair("settxfee", &settxfee),
Expand Down