Litecoin: Scrypt n=1024 Pow hash based upon Colin Percival's Tarnsnap (2009)
Modified by Artforz, coblee, pooler, wtogami, Nikolay Belikov, Adrian Gallagher miner.cpp changes stripped during merge to Dogecoin
This commit is contained in:
parent
9b70a1f0b3
commit
8a7d5338c2
|
@ -226,6 +226,8 @@ crypto_libbitcoin_crypto_a_SOURCES = \
|
|||
crypto/hmac_sha512.h \
|
||||
crypto/ripemd160.cpp \
|
||||
crypto/ripemd160.h \
|
||||
crypto/scrypt.cpp \
|
||||
crypto/scrypt.h \
|
||||
crypto/sha1.cpp \
|
||||
crypto/sha1.h \
|
||||
crypto/sha256.cpp \
|
||||
|
@ -373,6 +375,7 @@ include_HEADERS = script/bitcoinconsensus.h
|
|||
libbitcoinconsensus_la_SOURCES = \
|
||||
crypto/hmac_sha512.cpp \
|
||||
crypto/ripemd160.cpp \
|
||||
crypto/scrypt.cpp \
|
||||
crypto/sha1.cpp \
|
||||
crypto/sha256.cpp \
|
||||
crypto/sha512.cpp \
|
||||
|
|
|
@ -65,6 +65,7 @@ BITCOIN_TESTS =\
|
|||
test/script_P2SH_tests.cpp \
|
||||
test/script_tests.cpp \
|
||||
test/scriptnum_tests.cpp \
|
||||
test/scrypt_tests.cpp \
|
||||
test/serialize_tests.cpp \
|
||||
test/sighash_tests.cpp \
|
||||
test/sigopcount_tests.cpp \
|
||||
|
|
136
src/crypto/scrypt-sse2.cpp
Normal file
136
src/crypto/scrypt-sse2.cpp
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright 2009 Colin Percival, 2011 ArtForz, 2012-2013 pooler
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
|
||||
#include "crypto/scrypt.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include <emmintrin.h>
|
||||
|
||||
static inline void xor_salsa8_sse2(__m128i B[4], const __m128i Bx[4])
|
||||
{
|
||||
__m128i X0, X1, X2, X3;
|
||||
__m128i T;
|
||||
int i;
|
||||
|
||||
X0 = B[0] = _mm_xor_si128(B[0], Bx[0]);
|
||||
X1 = B[1] = _mm_xor_si128(B[1], Bx[1]);
|
||||
X2 = B[2] = _mm_xor_si128(B[2], Bx[2]);
|
||||
X3 = B[3] = _mm_xor_si128(B[3], Bx[3]);
|
||||
|
||||
for (i = 0; i < 8; i += 2) {
|
||||
/* Operate on "columns". */
|
||||
T = _mm_add_epi32(X0, X3);
|
||||
X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 7));
|
||||
X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 25));
|
||||
T = _mm_add_epi32(X1, X0);
|
||||
X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));
|
||||
X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));
|
||||
T = _mm_add_epi32(X2, X1);
|
||||
X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 13));
|
||||
X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 19));
|
||||
T = _mm_add_epi32(X3, X2);
|
||||
X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));
|
||||
X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));
|
||||
|
||||
/* Rearrange data. */
|
||||
X1 = _mm_shuffle_epi32(X1, 0x93);
|
||||
X2 = _mm_shuffle_epi32(X2, 0x4E);
|
||||
X3 = _mm_shuffle_epi32(X3, 0x39);
|
||||
|
||||
/* Operate on "rows". */
|
||||
T = _mm_add_epi32(X0, X1);
|
||||
X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 7));
|
||||
X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 25));
|
||||
T = _mm_add_epi32(X3, X0);
|
||||
X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));
|
||||
X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));
|
||||
T = _mm_add_epi32(X2, X3);
|
||||
X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 13));
|
||||
X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 19));
|
||||
T = _mm_add_epi32(X1, X2);
|
||||
X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));
|
||||
X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));
|
||||
|
||||
/* Rearrange data. */
|
||||
X1 = _mm_shuffle_epi32(X1, 0x39);
|
||||
X2 = _mm_shuffle_epi32(X2, 0x4E);
|
||||
X3 = _mm_shuffle_epi32(X3, 0x93);
|
||||
}
|
||||
|
||||
B[0] = _mm_add_epi32(B[0], X0);
|
||||
B[1] = _mm_add_epi32(B[1], X1);
|
||||
B[2] = _mm_add_epi32(B[2], X2);
|
||||
B[3] = _mm_add_epi32(B[3], X3);
|
||||
}
|
||||
|
||||
void scrypt_1024_1_1_256_sp_sse2(const char *input, char *output, char *scratchpad)
|
||||
{
|
||||
uint8_t B[128];
|
||||
union {
|
||||
__m128i i128[8];
|
||||
uint32_t u32[32];
|
||||
} X;
|
||||
__m128i *V;
|
||||
uint32_t i, j, k;
|
||||
|
||||
V = (__m128i *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63));
|
||||
|
||||
PBKDF2_SHA256((const uint8_t *)input, 80, (const uint8_t *)input, 80, 1, B, 128);
|
||||
|
||||
for (k = 0; k < 2; k++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
X.u32[k * 16 + i] = le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (k = 0; k < 8; k++)
|
||||
V[i * 8 + k] = X.i128[k];
|
||||
xor_salsa8_sse2(&X.i128[0], &X.i128[4]);
|
||||
xor_salsa8_sse2(&X.i128[4], &X.i128[0]);
|
||||
}
|
||||
for (i = 0; i < 1024; i++) {
|
||||
j = 8 * (X.u32[16] & 1023);
|
||||
for (k = 0; k < 8; k++)
|
||||
X.i128[k] = _mm_xor_si128(X.i128[k], V[j + k]);
|
||||
xor_salsa8_sse2(&X.i128[0], &X.i128[4]);
|
||||
xor_salsa8_sse2(&X.i128[4], &X.i128[0]);
|
||||
}
|
||||
|
||||
for (k = 0; k < 2; k++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
le32enc(&B[(k * 16 + (i * 5 % 16)) * 4], X.u32[k * 16 + i]);
|
||||
}
|
||||
}
|
||||
|
||||
PBKDF2_SHA256((const uint8_t *)input, 80, B, 128, 1, (uint8_t *)output, 32);
|
||||
}
|
329
src/crypto/scrypt.cpp
Normal file
329
src/crypto/scrypt.cpp
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* Copyright 2009 Colin Percival, 2011 ArtForz, 2012-2013 pooler
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
|
||||
#include "crypto/scrypt.h"
|
||||
//#include "util.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#if defined(USE_SSE2) && !defined(USE_SSE2_ALWAYS)
|
||||
#ifdef _MSC_VER
|
||||
// MSVC 64bit is unable to use inline asm
|
||||
#include <intrin.h>
|
||||
#else
|
||||
// GCC Linux or i686-w64-mingw32
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline uint32_t be32dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
|
||||
((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
|
||||
}
|
||||
|
||||
static inline void be32enc(void *pp, uint32_t x)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)pp;
|
||||
p[3] = x & 0xff;
|
||||
p[2] = (x >> 8) & 0xff;
|
||||
p[1] = (x >> 16) & 0xff;
|
||||
p[0] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
typedef struct HMAC_SHA256Context {
|
||||
SHA256_CTX ictx;
|
||||
SHA256_CTX octx;
|
||||
} HMAC_SHA256_CTX;
|
||||
|
||||
/* Initialize an HMAC-SHA256 operation with the given key. */
|
||||
static void
|
||||
HMAC_SHA256_Init(HMAC_SHA256_CTX *ctx, const void *_K, size_t Klen)
|
||||
{
|
||||
unsigned char pad[64];
|
||||
unsigned char khash[32];
|
||||
const unsigned char *K = (const unsigned char *)_K;
|
||||
size_t i;
|
||||
|
||||
/* If Klen > 64, the key is really SHA256(K). */
|
||||
if (Klen > 64) {
|
||||
SHA256_Init(&ctx->ictx);
|
||||
SHA256_Update(&ctx->ictx, K, Klen);
|
||||
SHA256_Final(khash, &ctx->ictx);
|
||||
K = khash;
|
||||
Klen = 32;
|
||||
}
|
||||
|
||||
/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
|
||||
SHA256_Init(&ctx->ictx);
|
||||
memset(pad, 0x36, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
SHA256_Update(&ctx->ictx, pad, 64);
|
||||
|
||||
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
|
||||
SHA256_Init(&ctx->octx);
|
||||
memset(pad, 0x5c, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
SHA256_Update(&ctx->octx, pad, 64);
|
||||
|
||||
/* Clean the stack. */
|
||||
memset(khash, 0, 32);
|
||||
}
|
||||
|
||||
/* Add bytes to the HMAC-SHA256 operation. */
|
||||
static void
|
||||
HMAC_SHA256_Update(HMAC_SHA256_CTX *ctx, const void *in, size_t len)
|
||||
{
|
||||
/* Feed data to the inner SHA256 operation. */
|
||||
SHA256_Update(&ctx->ictx, in, len);
|
||||
}
|
||||
|
||||
/* Finish an HMAC-SHA256 operation. */
|
||||
static void
|
||||
HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX *ctx)
|
||||
{
|
||||
unsigned char ihash[32];
|
||||
|
||||
/* Finish the inner SHA256 operation. */
|
||||
SHA256_Final(ihash, &ctx->ictx);
|
||||
|
||||
/* Feed the inner hash to the outer SHA256 operation. */
|
||||
SHA256_Update(&ctx->octx, ihash, 32);
|
||||
|
||||
/* Finish the outer SHA256 operation. */
|
||||
SHA256_Final(digest, &ctx->octx);
|
||||
|
||||
/* Clean the stack. */
|
||||
memset(ihash, 0, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void
|
||||
PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen, const uint8_t *salt,
|
||||
size_t saltlen, uint64_t c, uint8_t *buf, size_t dkLen)
|
||||
{
|
||||
HMAC_SHA256_CTX PShctx, hctx;
|
||||
size_t i;
|
||||
uint8_t ivec[4];
|
||||
uint8_t U[32];
|
||||
uint8_t T[32];
|
||||
uint64_t j;
|
||||
int k;
|
||||
size_t clen;
|
||||
|
||||
/* Compute HMAC state after processing P and S. */
|
||||
HMAC_SHA256_Init(&PShctx, passwd, passwdlen);
|
||||
HMAC_SHA256_Update(&PShctx, salt, saltlen);
|
||||
|
||||
/* Iterate through the blocks. */
|
||||
for (i = 0; i * 32 < dkLen; i++) {
|
||||
/* Generate INT(i + 1). */
|
||||
be32enc(ivec, (uint32_t)(i + 1));
|
||||
|
||||
/* Compute U_1 = PRF(P, S || INT(i)). */
|
||||
memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
|
||||
HMAC_SHA256_Update(&hctx, ivec, 4);
|
||||
HMAC_SHA256_Final(U, &hctx);
|
||||
|
||||
/* T_i = U_1 ... */
|
||||
memcpy(T, U, 32);
|
||||
|
||||
for (j = 2; j <= c; j++) {
|
||||
/* Compute U_j. */
|
||||
HMAC_SHA256_Init(&hctx, passwd, passwdlen);
|
||||
HMAC_SHA256_Update(&hctx, U, 32);
|
||||
HMAC_SHA256_Final(U, &hctx);
|
||||
|
||||
/* ... xor U_j ... */
|
||||
for (k = 0; k < 32; k++)
|
||||
T[k] ^= U[k];
|
||||
}
|
||||
|
||||
/* Copy as many bytes as necessary into buf. */
|
||||
clen = dkLen - i * 32;
|
||||
if (clen > 32)
|
||||
clen = 32;
|
||||
memcpy(&buf[i * 32], T, clen);
|
||||
}
|
||||
|
||||
/* Clean PShctx, since we never called _Final on it. */
|
||||
memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX));
|
||||
}
|
||||
|
||||
#define ROTL(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
|
||||
static inline void xor_salsa8(uint32_t B[16], const uint32_t Bx[16])
|
||||
{
|
||||
uint32_t x00,x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15;
|
||||
int i;
|
||||
|
||||
x00 = (B[ 0] ^= Bx[ 0]);
|
||||
x01 = (B[ 1] ^= Bx[ 1]);
|
||||
x02 = (B[ 2] ^= Bx[ 2]);
|
||||
x03 = (B[ 3] ^= Bx[ 3]);
|
||||
x04 = (B[ 4] ^= Bx[ 4]);
|
||||
x05 = (B[ 5] ^= Bx[ 5]);
|
||||
x06 = (B[ 6] ^= Bx[ 6]);
|
||||
x07 = (B[ 7] ^= Bx[ 7]);
|
||||
x08 = (B[ 8] ^= Bx[ 8]);
|
||||
x09 = (B[ 9] ^= Bx[ 9]);
|
||||
x10 = (B[10] ^= Bx[10]);
|
||||
x11 = (B[11] ^= Bx[11]);
|
||||
x12 = (B[12] ^= Bx[12]);
|
||||
x13 = (B[13] ^= Bx[13]);
|
||||
x14 = (B[14] ^= Bx[14]);
|
||||
x15 = (B[15] ^= Bx[15]);
|
||||
for (i = 0; i < 8; i += 2) {
|
||||
/* Operate on columns. */
|
||||
x04 ^= ROTL(x00 + x12, 7); x09 ^= ROTL(x05 + x01, 7);
|
||||
x14 ^= ROTL(x10 + x06, 7); x03 ^= ROTL(x15 + x11, 7);
|
||||
|
||||
x08 ^= ROTL(x04 + x00, 9); x13 ^= ROTL(x09 + x05, 9);
|
||||
x02 ^= ROTL(x14 + x10, 9); x07 ^= ROTL(x03 + x15, 9);
|
||||
|
||||
x12 ^= ROTL(x08 + x04, 13); x01 ^= ROTL(x13 + x09, 13);
|
||||
x06 ^= ROTL(x02 + x14, 13); x11 ^= ROTL(x07 + x03, 13);
|
||||
|
||||
x00 ^= ROTL(x12 + x08, 18); x05 ^= ROTL(x01 + x13, 18);
|
||||
x10 ^= ROTL(x06 + x02, 18); x15 ^= ROTL(x11 + x07, 18);
|
||||
|
||||
/* Operate on rows. */
|
||||
x01 ^= ROTL(x00 + x03, 7); x06 ^= ROTL(x05 + x04, 7);
|
||||
x11 ^= ROTL(x10 + x09, 7); x12 ^= ROTL(x15 + x14, 7);
|
||||
|
||||
x02 ^= ROTL(x01 + x00, 9); x07 ^= ROTL(x06 + x05, 9);
|
||||
x08 ^= ROTL(x11 + x10, 9); x13 ^= ROTL(x12 + x15, 9);
|
||||
|
||||
x03 ^= ROTL(x02 + x01, 13); x04 ^= ROTL(x07 + x06, 13);
|
||||
x09 ^= ROTL(x08 + x11, 13); x14 ^= ROTL(x13 + x12, 13);
|
||||
|
||||
x00 ^= ROTL(x03 + x02, 18); x05 ^= ROTL(x04 + x07, 18);
|
||||
x10 ^= ROTL(x09 + x08, 18); x15 ^= ROTL(x14 + x13, 18);
|
||||
}
|
||||
B[ 0] += x00;
|
||||
B[ 1] += x01;
|
||||
B[ 2] += x02;
|
||||
B[ 3] += x03;
|
||||
B[ 4] += x04;
|
||||
B[ 5] += x05;
|
||||
B[ 6] += x06;
|
||||
B[ 7] += x07;
|
||||
B[ 8] += x08;
|
||||
B[ 9] += x09;
|
||||
B[10] += x10;
|
||||
B[11] += x11;
|
||||
B[12] += x12;
|
||||
B[13] += x13;
|
||||
B[14] += x14;
|
||||
B[15] += x15;
|
||||
}
|
||||
|
||||
void scrypt_1024_1_1_256_sp_generic(const char *input, char *output, char *scratchpad)
|
||||
{
|
||||
uint8_t B[128];
|
||||
uint32_t X[32];
|
||||
uint32_t *V;
|
||||
uint32_t i, j, k;
|
||||
|
||||
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);
|
||||
|
||||
for (k = 0; k < 32; k++)
|
||||
X[k] = le32dec(&B[4 * k]);
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
memcpy(&V[i * 32], X, 128);
|
||||
xor_salsa8(&X[0], &X[16]);
|
||||
xor_salsa8(&X[16], &X[0]);
|
||||
}
|
||||
for (i = 0; i < 1024; i++) {
|
||||
j = 32 * (X[16] & 1023);
|
||||
for (k = 0; k < 32; k++)
|
||||
X[k] ^= V[j + k];
|
||||
xor_salsa8(&X[0], &X[16]);
|
||||
xor_salsa8(&X[16], &X[0]);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#if defined(USE_SSE2)
|
||||
// By default, set to generic scrypt function. This will prevent crash in case when scrypt_detect_sse2() wasn't called
|
||||
void (*scrypt_1024_1_1_256_sp_detected)(const char *input, char *output, char *scratchpad) = &scrypt_1024_1_1_256_sp_generic;
|
||||
|
||||
void scrypt_detect_sse2()
|
||||
{
|
||||
#if defined(USE_SSE2_ALWAYS)
|
||||
printf("scrypt: using scrypt-sse2 as built.\n");
|
||||
#else // USE_SSE2_ALWAYS
|
||||
// 32bit x86 Linux or Windows, detect cpuid features
|
||||
unsigned int cpuid_edx=0;
|
||||
#if defined(_MSC_VER)
|
||||
// MSVC
|
||||
int x86cpuid[4];
|
||||
__cpuid(x86cpuid, 1);
|
||||
cpuid_edx = (unsigned int)buffer[3];
|
||||
#else // _MSC_VER
|
||||
// Linux or i686-w64-mingw32 (gcc-4.6.3)
|
||||
unsigned int eax, ebx, ecx;
|
||||
__get_cpuid(1, &eax, &ebx, &ecx, &cpuid_edx);
|
||||
#endif // _MSC_VER
|
||||
|
||||
if (cpuid_edx & 1<<26)
|
||||
{
|
||||
scrypt_1024_1_1_256_sp_detected = &scrypt_1024_1_1_256_sp_sse2;
|
||||
printf("scrypt: using scrypt-sse2 as detected.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
scrypt_1024_1_1_256_sp_detected = &scrypt_1024_1_1_256_sp_generic;
|
||||
printf("scrypt: using scrypt-generic, SSE2 unavailable.\n");
|
||||
}
|
||||
#endif // USE_SSE2_ALWAYS
|
||||
}
|
||||
#endif
|
||||
|
||||
void scrypt_1024_1_1_256(const char *input, char *output)
|
||||
{
|
||||
char scratchpad[SCRYPT_SCRATCHPAD_SIZE];
|
||||
scrypt_1024_1_1_256_sp(input, output, scratchpad);
|
||||
}
|
45
src/crypto/scrypt.h
Normal file
45
src/crypto/scrypt.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef SCRYPT_H
|
||||
#define SCRYPT_H
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static const int SCRYPT_SCRATCHPAD_SIZE = 131072 + 63;
|
||||
|
||||
void scrypt_1024_1_1_256(const char *input, char *output);
|
||||
void scrypt_1024_1_1_256_sp_generic(const char *input, char *output, char *scratchpad);
|
||||
|
||||
#if defined(USE_SSE2)
|
||||
#if defined(_M_X64) || defined(__x86_64__) || defined(_M_AMD64) || (defined(MAC_OSX) && defined(__i386__))
|
||||
#define USE_SSE2_ALWAYS 1
|
||||
#define scrypt_1024_1_1_256_sp(input, output, scratchpad) scrypt_1024_1_1_256_sp_sse2((input), (output), (scratchpad))
|
||||
#else
|
||||
#define scrypt_1024_1_1_256_sp(input, output, scratchpad) scrypt_1024_1_1_256_sp_detected((input), (output), (scratchpad))
|
||||
#endif
|
||||
|
||||
void scrypt_detect_sse2();
|
||||
void scrypt_1024_1_1_256_sp_sse2(const char *input, char *output, char *scratchpad);
|
||||
extern void (*scrypt_1024_1_1_256_sp_detected)(const char *input, char *output, char *scratchpad);
|
||||
#else
|
||||
#define scrypt_1024_1_1_256_sp(input, output, scratchpad) scrypt_1024_1_1_256_sp_generic((input), (output), (scratchpad))
|
||||
#endif
|
||||
|
||||
void
|
||||
PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen, const uint8_t *salt,
|
||||
size_t saltlen, uint64_t c, uint8_t *buf, size_t dkLen);
|
||||
|
||||
static inline uint32_t le32dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
|
||||
((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
|
||||
}
|
||||
|
||||
static inline void le32enc(void *pp, uint32_t x)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)pp;
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
}
|
||||
#endif
|
|
@ -945,6 +945,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
|
||||
int64_t nStart;
|
||||
|
||||
#if defined(USE_SSE2)
|
||||
scrypt_detect_sse2();
|
||||
#endif
|
||||
|
||||
// ********************************************************* Step 5: verify wallet database integrity
|
||||
#ifdef ENABLE_WALLET
|
||||
if (!fDisableWallet) {
|
||||
|
|
|
@ -1176,7 +1176,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
|
|||
}
|
||||
|
||||
// Check the header
|
||||
if (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus()))
|
||||
if (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus()))
|
||||
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
|
||||
|
||||
return true;
|
||||
|
@ -2645,7 +2645,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
|
|||
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW)
|
||||
{
|
||||
// Check proof of work matches claimed amount
|
||||
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus()))
|
||||
if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus()))
|
||||
return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),
|
||||
REJECT_INVALID, "high-hash");
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "primitives/block.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "crypto/scrypt.h"
|
||||
#include "tinyformat.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "crypto/common.h"
|
||||
|
@ -15,6 +16,13 @@ uint256 CBlockHeader::GetHash() const
|
|||
return SerializeHash(*this);
|
||||
}
|
||||
|
||||
uint256 CBlockHeader::GetPoWHash() const
|
||||
{
|
||||
uint256 thash;
|
||||
scrypt_1024_1_1_256(BEGIN(nVersion), BEGIN(thash));
|
||||
return thash;
|
||||
}
|
||||
|
||||
uint256 CBlock::BuildMerkleTree(bool* fMutated) const
|
||||
{
|
||||
/* WARNING! If you're reading this because you're learning about crypto
|
||||
|
|
|
@ -64,6 +64,8 @@ public:
|
|||
|
||||
uint256 GetHash() const;
|
||||
|
||||
uint256 GetPoWHash() const;
|
||||
|
||||
int64_t GetBlockTime() const
|
||||
{
|
||||
return (int64_t)nTime;
|
||||
|
|
35
src/test/scrypt_tests.cpp
Normal file
35
src/test/scrypt_tests.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "crypto/scrypt.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(scrypt_tests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(scrypt_hashtest)
|
||||
{
|
||||
// Test Scrypt hash with known inputs against expected outputs
|
||||
#define HASHCOUNT 5
|
||||
const char* inputhex[HASHCOUNT] = { "020000004c1271c211717198227392b029a64a7971931d351b387bb80db027f270411e398a07046f7d4a08dd815412a8712f874a7ebf0507e3878bd24e20a3b73fd750a667d2f451eac7471b00de6659", "0200000011503ee6a855e900c00cfdd98f5f55fffeaee9b6bf55bea9b852d9de2ce35828e204eef76acfd36949ae56d1fbe81c1ac9c0209e6331ad56414f9072506a77f8c6faf551eac7471b00389d01", "02000000a72c8a177f523946f42f22c3e86b8023221b4105e8007e59e81f6beb013e29aaf635295cb9ac966213fb56e046dc71df5b3f7f67ceaeab24038e743f883aff1aaafaf551eac7471b0166249b", "010000007824bc3a8a1b4628485eee3024abd8626721f7f870f8ad4d2f33a27155167f6a4009d1285049603888fe85a84b6c803a53305a8d497965a5e896e1a00568359589faf551eac7471b0065434e", "0200000050bfd4e4a307a8cb6ef4aef69abc5c0f2d579648bd80d7733e1ccc3fbc90ed664a7f74006cb11bde87785f229ecd366c2d4e44432832580e0608c579e4cb76f383f7f551eac7471b00c36982" };
|
||||
const char* expected[HASHCOUNT] = { "00000000002bef4107f882f6115e0b01f348d21195dacd3582aa2dabd7985806" , "00000000003a0d11bdd5eb634e08b7feddcfbbf228ed35d250daf19f1c88fc94", "00000000000b40f895f288e13244728a6c2d9d59d8aff29c65f8dd5114a8ca81", "00000000003007005891cd4923031e99d8e8d72f6e8e7edc6a86181897e105fe", "000000000018f0b426a4afc7130ccb47fa02af730d345b4fe7c7724d3800ec8c" };
|
||||
#if defined(USE_SSE2)
|
||||
scrypt_detect_sse2();
|
||||
#endif
|
||||
uint256 scrypthash;
|
||||
std::vector<unsigned char> inputbytes;
|
||||
char scratchpad[SCRYPT_SCRATCHPAD_SIZE];
|
||||
for (int i = 0; i < HASHCOUNT; i++) {
|
||||
inputbytes = ParseHex(inputhex[i]);
|
||||
#if defined(USE_SSE2)
|
||||
// Test SSE2 scrypt
|
||||
scrypt_1024_1_1_256_sp_sse2((const char*)&inputbytes[0], BEGIN(scrypthash), scratchpad);
|
||||
BOOST_CHECK_EQUAL(scrypthash.ToString().c_str(), expected[i]);
|
||||
#endif
|
||||
// Test generic scrypt
|
||||
scrypt_1024_1_1_256_sp_generic((const char*)&inputbytes[0], BEGIN(scrypthash), scratchpad);
|
||||
BOOST_CHECK_EQUAL(scrypthash.ToString().c_str(), expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in a new issue