From 30992b87c3470f10c37daa536293dd198f7ddae4 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Thu, 14 Nov 2013 00:57:51 -0200 Subject: [PATCH] use scrypt hash function like litecoin --- src/chainparams.cpp | 8 ++-- src/core.cpp | 3 +- src/core.h | 8 ++++ src/init.cpp | 32 +++++++++++++ src/main.cpp | 114 ++++++++++++++------------------------------ src/main.h | 2 +- src/scrypt-sse2.cpp | 4 +- src/scrypt.cpp | 4 +- 8 files changed, 88 insertions(+), 87 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index eec9d4de..2f601342 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -54,13 +54,13 @@ public: genesis.hashMerkleRoot = genesis.BuildMerkleTree(); genesis.nVersion = 1; genesis.nHeight = 0; - genesis.nTime = 1383612321; + genesis.nTime = 1384394255; //genesis.nBits = 0x1d00ffff; - genesis.nBits = 0x1d7fffff; - genesis.nNonce = 1353330432; + genesis.nBits = 0x1f03ffff; + genesis.nNonce = 2934; hashGenesisBlock = genesis.GetHash(); - assert(hashGenesisBlock == uint256("0000001d5eb70d639089eb9b31a4175aa906d6824aae78a9b450ab71de5e6e12")); + assert(hashGenesisBlock == uint256("9915158279673d101912be80f25c20627f1dd8bf5231e7c46bfec5ed19737f44")); vSeeds.push_back(CDNSSeedData("twister.net.co", "seed.twister.net.co")); vSeeds.push_back(CDNSSeedData("twister.net.co", "seed2.twister.net.co")); diff --git a/src/core.cpp b/src/core.cpp index 6885e0a8..8f4e7c8b 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -258,8 +258,9 @@ uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector& vMer void CBlock::print() const { - printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n", + printf("CBlock(hash=%s, PoW=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n", GetHash().ToString().c_str(), + GetPoWHash().ToString().c_str(), nVersion, hashPrevBlock.ToString().c_str(), hashMerkleRoot.ToString().c_str(), diff --git a/src/core.h b/src/core.h index fff039cc..d1e05763 100644 --- a/src/core.h +++ b/src/core.h @@ -8,6 +8,7 @@ #include "uint256.h" #include "serialize.h" #include "script.h" +#include "scrypt.h" #include @@ -530,6 +531,13 @@ public: vMerkleTree.clear(); } + uint256 GetPoWHash() const + { + uint256 thash; + scrypt_1024_1_1_256(BEGIN(nVersion), BEGIN(thash)); + return thash; + } + CBlockHeader GetBlockHeader() const { CBlockHeader block; diff --git a/src/init.cpp b/src/init.cpp index e5ecc5d1..fe003f59 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -27,6 +27,18 @@ #include #endif +#if defined(USE_SSE2) +#if !defined(MAC_OSX) && (defined(_M_IX86) || defined(__i386__) || defined(__i386)) +#ifdef _MSC_VER +// MSVC 64bit is unable to use inline asm +#include +#else +// GCC Linux or i686-w64-mingw32 +#include +#endif +#endif +#endif + using namespace std; using namespace boost; @@ -370,6 +382,23 @@ bool AppInit2(boost::thread_group& threadGroup) sigaction(SIGHUP, &sa_hup, NULL); #endif +#if defined(USE_SSE2) + unsigned int cpuid_edx=0; +#if !defined(MAC_OSX) && (defined(_M_IX86) || defined(__i386__) || defined(__i386)) + // 32bit x86 Linux or Windows, detect cpuid features +#if defined(_MSC_VER) + // MSVC + int x86cpuid[4]; + __cpuid(x86cpuid, 1); + cpuid_edx = (unsigned int)buffer[3]; +#else + // Linux or i686-w64-mingw32 (gcc-4.6.3) + unsigned int eax, ebx, ecx; + __get_cpuid(1, &eax, &ebx, &ecx, &cpuid_edx); +#endif +#endif +#endif + // ********************************************************* Step 2: parameter interactions Checkpoints::fEnabled = GetBoolArg("-checkpoints", true); @@ -641,6 +670,9 @@ bool AppInit2(boost::thread_group& threadGroup) AddOneShot(strDest); // ********************************************************* Step 7: load block chain +#if defined(USE_SSE2) + scrypt_detect_sse2(cpuid_edx); +#endif fReindex = GetBoolArg("-reindex", false); diff --git a/src/main.cpp b/src/main.cpp index 4dbeaed1..ca1dbbeb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -811,7 +811,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) } // Check the header - if (!CheckProofOfWork(block.GetHash(), block.nBits)) + if (!CheckProofOfWork(block.GetPoWHash(), block.nBits)) return error("ReadBlockFromDisk(CBlock&, CDiskBlockPos&) : errors in block header"); return true; @@ -1566,7 +1566,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo return state.DoS(100, error("CheckBlock() : size limits failed")); // Check proof of work matches claimed amount - if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits)) + if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(), block.nBits)) return state.DoS(50, error("CheckBlock() : proof of work failed")); // Check timestamp @@ -3783,7 +3783,7 @@ void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash bool CheckWork(CBlock* pblock, CWallet& wallet) { - uint256 hash = pblock->GetHash(); + uint256 hash = pblock->GetPoWHash(); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); if (hash > hashTarget) @@ -3829,47 +3829,31 @@ void GenesisMiner() printf("Running GenesisMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(), ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); - // - // Pre-build hash buffers - // - char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf); - char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf); - char phash1buf[64+16]; char* phash1 = alignup<16>(phash1buf); - - FormatHashBuffers(pblock, pmidstate, pdata, phash1); - - unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12 + 4); - // // Search // uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); - uint256 hashbuf[2]; - uint256& hash = *alignup<16>(hashbuf); + uint256 hash; loop { unsigned int nHashesDone = 0; - unsigned int nNonceFound; - // Crypto++ SHA256 - nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1, - (char*)&hash, nHashesDone); + + do { + pblock->nNonce++; + hash = pblock->GetPoWHash(); + } while( hash > hashTarget && + (pblock->nNonce & 0xffff) != 0 ); + nHashesDone = 0xffff+1; // Check if something found - if (nNonceFound != (unsigned int) -1) + if (hash <= hashTarget) { - for (unsigned int i = 0; i < sizeof(hash)/4; i++) - ((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]); - - if (hash <= hashTarget) - { - // Found a solution - pblock->nNonce = ByteReverse(nNonceFound); - assert(hash == pblock->GetHash()); - printf("genesishash: %s\n", pblock->GetHash().ToString().c_str()); - printf("merkle: %s\n", pblock->hashMerkleRoot.ToString().c_str()); - printf("nonce: %d\n", pblock->nNonce); - exit(0); - } + // Found a solution + printf("genesishash: %s\n", pblock->GetHash().ToString().c_str()); + printf("genesisPOWhash: %s\n", pblock->GetPoWHash().ToString().c_str()); + printf("merkle: %s\n", pblock->hashMerkleRoot.ToString().c_str()); + printf("nonce: %d\n", pblock->nNonce); + exit(0); } // Meter hashes/sec @@ -3903,7 +3887,7 @@ void GenesisMiner() // Check for stop or if block needs to be rebuilt boost::this_thread::interruption_point(); - if (nBlockNonce >= 0xffff0000) + if (pblock->nNonce >= 0xffff0000) break; } } @@ -3942,59 +3926,37 @@ void static BitcoinMiner(CWallet *pwallet) printf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(), ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); - // - // Pre-build hash buffers - // - char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf); - char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf); - char phash1buf[64+16]; char* phash1 = alignup<16>(phash1buf); - - FormatHashBuffers(pblock, pmidstate, pdata, phash1); - - unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4 + 4); - unsigned int& nBlockBits = *(unsigned int*)(pdata + 64 + 8 + 4); - unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12 + 4); - - // // Search // int64 nStart = GetTime(); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); - uint256 hashbuf[2]; - uint256& hash = *alignup<16>(hashbuf); + uint256 hash; loop { unsigned int nHashesDone = 0; - unsigned int nNonceFound; - // Crypto++ SHA256 - nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1, - (char*)&hash, nHashesDone); + do { + pblock->nNonce++; + hash = pblock->GetPoWHash(); + } while( hash > hashTarget && + (pblock->nNonce & 0xffff) != 0 ); + nHashesDone = 0xffff+1; // Check if something found - if (nNonceFound != (unsigned int) -1) + if (hash <= hashTarget) { - for (unsigned int i = 0; i < sizeof(hash)/4; i++) - ((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]); + // Found a solution + SetThreadPriority(THREAD_PRIORITY_NORMAL); + CheckWork(pblock, *pwalletMain); + SetThreadPriority(THREAD_PRIORITY_LOWEST); - if (hash <= hashTarget) - { - // Found a solution - pblock->nNonce = ByteReverse(nNonceFound); - assert(hash == pblock->GetHash()); - - SetThreadPriority(THREAD_PRIORITY_NORMAL); - CheckWork(pblock, *pwalletMain); - SetThreadPriority(THREAD_PRIORITY_LOWEST); - - // In regression test mode, stop mining after a block is found. This - // allows developers to controllably generate a block on demand. - if (Params().NetworkID() == CChainParams::REGTEST) - throw boost::thread_interrupted(); + // In regression test mode, stop mining after a block is found. This + // allows developers to controllably generate a block on demand. + if (Params().NetworkID() == CChainParams::REGTEST) + throw boost::thread_interrupted(); - break; - } + break; } // Meter hashes/sec @@ -4030,7 +3992,7 @@ void static BitcoinMiner(CWallet *pwallet) boost::this_thread::interruption_point(); if (vNodes.empty() && Params().NetworkID() != CChainParams::REGTEST) break; - if (nBlockNonce >= 0xffff0000) + if (pblock->nNonce >= 0xffff0000) break; if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60) break; @@ -4039,11 +4001,9 @@ void static BitcoinMiner(CWallet *pwallet) // Update nTime every few seconds UpdateTime(*pblock, pindexPrev); - nBlockTime = ByteReverse(pblock->nTime); if (TestNet()) { // Changing pblock->nTime can change work required on testnet: - nBlockBits = ByteReverse(pblock->nBits); hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); } } diff --git a/src/main.h b/src/main.h index 03ffb0cf..fcc85dcb 100644 --- a/src/main.h +++ b/src/main.h @@ -756,7 +756,7 @@ public: bool CheckIndex() const { - return CheckProofOfWork(GetBlockHash(), nBits); + return CheckProofOfWork(CBlock(GetBlockHeader()).GetPoWHash(), nBits); } enum { nMedianTimeSpan=11 }; diff --git a/src/scrypt-sse2.cpp b/src/scrypt-sse2.cpp index 711dfa92..b0a9599e 100644 --- a/src/scrypt-sse2.cpp +++ b/src/scrypt-sse2.cpp @@ -104,7 +104,7 @@ void scrypt_1024_1_1_256_sp_sse2(const char *input, char *output, char *scratchp V = (__m128i *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63)); - PBKDF2_SHA256((const uint8_t *)input, 80, (const uint8_t *)input, 80, 1, B, 128); + PBKDF2_SHA256((const uint8_t *)input, 84, (const uint8_t *)input, 84, 1, B, 128); for (k = 0; k < 2; k++) { for (i = 0; i < 16; i++) { @@ -132,5 +132,5 @@ void scrypt_1024_1_1_256_sp_sse2(const char *input, char *output, char *scratchp } } - PBKDF2_SHA256((const uint8_t *)input, 80, B, 128, 1, (uint8_t *)output, 32); + PBKDF2_SHA256((const uint8_t *)input, 84, B, 128, 1, (uint8_t *)output, 32); } diff --git a/src/scrypt.cpp b/src/scrypt.cpp index 772701db..2a7bd83d 100644 --- a/src/scrypt.cpp +++ b/src/scrypt.cpp @@ -252,7 +252,7 @@ void scrypt_1024_1_1_256_sp_generic(const char *input, char *output, char *scrat V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63)); - PBKDF2_SHA256((const uint8_t *)input, 80, (const uint8_t *)input, 80, 1, B, 128); + PBKDF2_SHA256((const uint8_t *)input, 84, (const uint8_t *)input, 84, 1, B, 128); for (k = 0; k < 32; k++) X[k] = le32dec(&B[4 * k]); @@ -273,7 +273,7 @@ void scrypt_1024_1_1_256_sp_generic(const char *input, char *output, char *scrat for (k = 0; k < 32; k++) le32enc(&B[4 * k], X[k]); - PBKDF2_SHA256((const uint8_t *)input, 80, B, 128, 1, (uint8_t *)output, 32); + PBKDF2_SHA256((const uint8_t *)input, 84, B, 128, 1, (uint8_t *)output, 32); } #if defined(USE_SSE2)