mining fixes: add salt to instance and use correct username for signing

This commit is contained in:
Miguel Freitas 2013-07-25 12:06:18 -03:00
parent f2699c4753
commit 9946d6ed72
3 changed files with 42 additions and 35 deletions

View File

@ -3416,19 +3416,19 @@ public:
}; };
static bool CreateSpamMsgTx(CTransaction &txNew) static bool CreateSpamMsgTx(CTransaction &txNew, std::vector<unsigned char> &salt)
{ {
txNew.message = CScript() << strSpamMessage; txNew.message = CScript() << strSpamMessage;
std::string strUsername = strSpamUser;
// get keyid from wallet (hopefully this is pubkey of strSpamUser) CKeyID keyID;
CKeyID defaultKeyId( pwalletMain->vchDefaultKey.GetID() ); if( !pwalletMain->GetKeyIdFromUsername(strSpamUser, keyID) ) {
printf("CreateSpamMsgTx: keyId = %s\n", defaultKeyId.ToString().c_str() ); if( pwalletMain->vchDefaultKey.IsValid() ) {
CKey key; keyID = pwalletMain->vchDefaultKey.GetID();
// get privkey from pubkey strUsername = pwalletMain->mapKeyMetadata[keyID].username;
if( !pwalletMain->GetKey(defaultKeyId, key) ) {
printf("CreateNewBlock: Failed to get privKey to sign SpamMessage\n");
return false;
} }
}
printf("CreateSpamMsgTx: keyId = %s\n", keyID.ToString().c_str() );
// compute message hash and sign it // compute message hash and sign it
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
@ -3437,25 +3437,36 @@ static bool CreateSpamMsgTx(CTransaction &txNew)
// vchSig is sig(hash(message)) // vchSig is sig(hash(message))
vector<unsigned char> vchSig; vector<unsigned char> vchSig;
if( keyID != CKeyID() ) {
CKey key;
// get privkey from pubkey
if( !pwalletMain->GetKey(keyID, key) ) {
printf("CreateNewBlock: Failed to get privKey to sign SpamMessage\n");
return false;
}
if (!key.Sign(hashMsg, vchSig)) { if (!key.Sign(hashMsg, vchSig)) {
printf("CreateNewBlock: Failed to sign SpamMessage\n"); printf("CreateNewBlock: Failed to sign SpamMessage\n");
return false; return false;
} }
}
printf("CreateSpamMsgTx: msg = %s user = %s hash = %s signedhash = %s\n", txNew.message.ToString().c_str(), strSpamUser.c_str(), printf("CreateSpamMsgTx: msg = %s user = %s hash = %s signedhash = %s\n",
txNew.message.ToString().c_str(), strUsername.c_str(),
hashMsg.ToString().c_str(), EncodeBase64(&vchSig[0], vchSig.size()).c_str() ); hashMsg.ToString().c_str(), EncodeBase64(&vchSig[0], vchSig.size()).c_str() );
// add username and signature // add username and signature
txNew.userName = CScript() << strSpamUser; txNew.userName = CScript() << strUsername;
txNew.userName += CScript() << vchSig; txNew.userName += CScript() << vchSig;
txNew.userName += CScript() << salt;
txNew.pubKey.clear(); // pubKey will be updated to include extranonce txNew.pubKey.clear(); // pubKey will be updated to include extranonce
txNew.nNonce = 0; // no update needed for spamMessage's nonce. txNew.nNonce = 0; // no update needed for spamMessage's nonce.
return true; return true;
} }
// [MF] FIXME: reservekey gives uniqueness to this worker thread, but it's not being used in twister. CBlockTemplate* CreateNewBlock(std::vector<unsigned char> &salt)
CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
{ {
// Create new block // Create new block
auto_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate()); auto_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
@ -3465,7 +3476,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// Create coinbase tx // Create coinbase tx
CTransaction txNew; CTransaction txNew;
if( !CreateSpamMsgTx(txNew) ) if( !CreateSpamMsgTx(txNew, salt) )
return NULL; return NULL;
// Add our coinbase tx as first transaction // Add our coinbase tx as first transaction
@ -3613,7 +3624,7 @@ void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash
} }
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) bool CheckWork(CBlock* pblock, CWallet& wallet)
{ {
uint256 hash = pblock->GetHash(); uint256 hash = pblock->GetHash();
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
@ -3633,9 +3644,6 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
if (pblock->hashPrevBlock != hashBestChain) if (pblock->hashPrevBlock != hashBestChain)
return error("BitcoinMiner : generated block is stale"); return error("BitcoinMiner : generated block is stale");
// Remove key from key pool
reservekey.KeepKey();
// Track how many getdata requests this block gets // Track how many getdata requests this block gets
{ {
LOCK(wallet.cs_wallet); LOCK(wallet.cs_wallet);
@ -3749,8 +3757,9 @@ void static BitcoinMiner(CWallet *pwallet)
SetThreadPriority(THREAD_PRIORITY_LOWEST); SetThreadPriority(THREAD_PRIORITY_LOWEST);
RenameThread("bitcoin-miner"); RenameThread("bitcoin-miner");
// Each thread has its own key and counter // Each thread has its own salt and counter
CReserveKey reservekey(pwallet); std::vector<unsigned char> salt(4);
RAND_bytes(salt.data(), sizeof(salt));
unsigned int nExtraNonce = 0; unsigned int nExtraNonce = 0;
try { loop { try { loop {
@ -3767,7 +3776,7 @@ void static BitcoinMiner(CWallet *pwallet)
unsigned int nTransactionsUpdatedLast = nTransactionsUpdated; unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
CBlockIndex* pindexPrev = pindexBest; CBlockIndex* pindexPrev = pindexBest;
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(reservekey)); auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(salt));
if (!pblocktemplate.get()) if (!pblocktemplate.get())
return; return;
CBlock *pblock = &pblocktemplate->block; CBlock *pblock = &pblocktemplate->block;
@ -3819,7 +3828,7 @@ void static BitcoinMiner(CWallet *pwallet)
assert(hash == pblock->GetHash()); assert(hash == pblock->GetHash());
SetThreadPriority(THREAD_PRIORITY_NORMAL); SetThreadPriority(THREAD_PRIORITY_NORMAL);
CheckWork(pblock, *pwalletMain, reservekey); CheckWork(pblock, *pwalletMain);
SetThreadPriority(THREAD_PRIORITY_LOWEST); SetThreadPriority(THREAD_PRIORITY_LOWEST);
// In regression test mode, stop mining after a block is found. This // In regression test mode, stop mining after a block is found. This

View File

@ -17,7 +17,6 @@ class CWallet;
class CBlock; class CBlock;
class CBlockIndex; class CBlockIndex;
class CKeyItem; class CKeyItem;
class CReserveKey;
class CAddress; class CAddress;
class CInv; class CInv;
@ -109,7 +108,6 @@ extern string strSpamUser;
static const uint64 nMinDiskSpace = 52428800; static const uint64 nMinDiskSpace = 52428800;
class CReserveKey;
class CCoinsDB; class CCoinsDB;
class CBlockTreeDB; class CBlockTreeDB;
struct CDiskBlockPos; struct CDiskBlockPos;
@ -166,13 +164,13 @@ bool SendMessages(CNode* pto, bool fSendTrickle);
/** Run the miner threads */ /** Run the miner threads */
void GenerateBitcoins(bool fGenerate, CWallet* pwallet); void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
/** Generate a new block, without valid proof-of-work */ /** Generate a new block, without valid proof-of-work */
CBlockTemplate* CreateNewBlock(CReserveKey& reservekey); CBlockTemplate* CreateNewBlock(std::vector<unsigned char> &salt);
/** Modify the extranonce in a block */ /** Modify the extranonce in a block */
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
/** Do mining precalculation */ /** Do mining precalculation */
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1); void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
/** Check mined block */ /** Check mined block */
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey); bool CheckWork(CBlock* pblock, CWallet& wallet);
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
bool CheckProofOfWork(uint256 hash, unsigned int nBits); bool CheckProofOfWork(uint256 hash, unsigned int nBits);
/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */ /** Calculate the minimum amount of work a received block needs, without knowing its direct parent */

View File

@ -13,17 +13,17 @@ using namespace std;
// Key used by getwork/getblocktemplate miners. // Key used by getwork/getblocktemplate miners.
// Allocated in InitRPCMining, free'd in ShutdownRPCMining // Allocated in InitRPCMining, free'd in ShutdownRPCMining
static CReserveKey* pMiningKey = NULL; static std::vector<unsigned char> salt;
void InitRPCMining() void InitRPCMining()
{ {
// getwork/getblocktemplate mining rewards paid here: // getwork/getblocktemplate mining rewards paid here:
pMiningKey = new CReserveKey(pwalletMain); salt.resize(4);
RAND_bytes(salt.data(), sizeof(salt));
} }
void ShutdownRPCMining() void ShutdownRPCMining()
{ {
delete pMiningKey; pMiningKey = NULL;
} }
Value getgenerate(const Array& params, bool fHelp) Value getgenerate(const Array& params, bool fHelp)
@ -148,7 +148,7 @@ Value getwork(const Array& params, bool fHelp)
nStart = GetTime(); nStart = GetTime();
// Create new block // Create new block
pblocktemplate = CreateNewBlock(*pMiningKey); pblocktemplate = CreateNewBlock(salt);
if (!pblocktemplate) if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
vNewBlockTemplate.push_back(pblocktemplate); vNewBlockTemplate.push_back(pblocktemplate);
@ -210,7 +210,7 @@ Value getwork(const Array& params, bool fHelp)
*/ */
pblock->hashMerkleRoot = pblock->BuildMerkleTree(); pblock->hashMerkleRoot = pblock->BuildMerkleTree();
return CheckWork(pblock, *pwalletMain, *pMiningKey); return CheckWork(pblock, *pwalletMain);
} }
} }
@ -283,7 +283,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
delete pblocktemplate; delete pblocktemplate;
pblocktemplate = NULL; pblocktemplate = NULL;
} }
pblocktemplate = CreateNewBlock(*pMiningKey); pblocktemplate = CreateNewBlock(salt);
if (!pblocktemplate) if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");