Merge pull request #25 from myriadteam/dev

0.11.3.0-rc1
This commit is contained in:
8bitcoder
2016-07-01 12:24:25 +02:00
committed by GitHub
33 changed files with 4095 additions and 76 deletions
+12
View File
@@ -64,6 +64,18 @@ A common question is how to build from Ubuntu, instructions follow:
15. ./configure
16. make
Other Build Notes:
If you are compiling yourself, please configure with something like this:
```
CFLAGS="-O2 -fPIC" CPPFLAGS="-O2 -fPIC" ./configure
```
otherwise you'll probably get some errors later on. Additionally, if your CPU supports SSE2, and most modern CPU's do, use this:
```
CFLAGS="-O2 -fPIC -DUSE_SSE2" CPPFLAGS="-O2 -fPIC -DUSE_SSE2" ./configure
```
That will enable the SSE2 version of the Scrypt algorithm. This may reduce the CPU load when syncing the blockchain.
Development tips and tricks
---------------------------
+4 -3
View File
@@ -2,9 +2,9 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 0)
define(_CLIENT_VERSION_MINOR, 11)
define(_CLIENT_VERSION_REVISION, 2)
define(_CLIENT_VERSION_BUILD, 1)
define(_CLIENT_VERSION_IS_RELEASE, true)
define(_CLIENT_VERSION_REVISION, 3)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_IS_RELEASE, false)
define(_COPYRIGHT_YEAR, 2016)
AC_INIT([Myriad Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/myriadcoin/myriadcoin/issues],[myriad])
AC_CONFIG_SRCDIR([src/main.cpp])
@@ -211,6 +211,7 @@ case $host in
AC_CHECK_LIB([shlwapi], [main],, AC_MSG_ERROR(lib missing))
AC_CHECK_LIB([iphlpapi], [main],, AC_MSG_ERROR(lib missing))
AC_CHECK_LIB([crypt32], [main],, AC_MSG_ERROR(lib missing))
AC_CHECK_LIB([mman], [main],, AC_MSG_ERROR(lib missing))
# -static is interpreted by libtool, where it has a different meaning.
# In libtool-speak, it's -all-static.
+10 -1
View File
@@ -109,6 +109,7 @@ BITCOIN_CORE_H = \
merkleblock.h \
miner.h \
mruset.h \
myriad_params.h \
net.h \
netbase.h \
noui.h \
@@ -265,7 +266,15 @@ crypto_libbitcoin_crypto_a_SOURCES = \
crypto/sph_shavite.h \
crypto/sph_simd.h \
crypto/sph_skein.h \
crypto/sph_types.h
crypto/sph_types.h \
crypto/yescrypt.h \
crypto/sysendian.h \
crypto/yescryptcommon.c \
crypto/yescrypt-best.c \
crypto/yescrypt-platform.c \
crypto/sha256_Y.h \
crypto/sha256_Y.c
# univalue JSON library
univalue_libbitcoin_univalue_a_SOURCES = \
+1 -1
View File
@@ -27,5 +27,5 @@ CAmount CFeeRate::GetFee(size_t nSize) const
std::string CFeeRate::ToString() const
{
return strprintf("%d.%08d MYR/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN);
return strprintf("%d.%08d XMY/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN);
}
+11 -2
View File
@@ -61,12 +61,16 @@ public:
consensus.nBlockSequentialAlgoRuleStart2 = 766000; // block where sequential algo rule starts
consensus.nBlockSequentialAlgoMaxCount1 = 6; // maximum sequential blocks of same algo
consensus.nBlockSequentialAlgoMaxCount2 = 3; // maximum sequential blocks of same algo
consensus.nBlockSequentialAlgoMaxCount3 = 6; // maximum sequential blocks of same algo
consensus.nBlockAlgoWorkWeightStart = 142000; // block where algo work weighting starts
consensus.nBlockAlgoNormalisedWorkStart = 740000; // block where algo combined weight starts
consensus.nBlockAlgoNormalisedWorkDecayStart1 = 866000; // block where weight decay starts
consensus.nBlockAlgoNormalisedWorkDecayStart2 = 932000; // block where weight decay starts
consensus.nGeoAvgWork_Start = 1400000;
consensus.nFork1MinBlock = 1764000; // minimum block height where fork 1 takes effect (algo switch, seq algo count change)
consensus.nMajorityEnableAlgoSwitch1 = 600;
consensus.nAlgoSwitch1EnableWindow = 2000;
/**
* The message start string is designed to be unlikely to occur in normal data.
@@ -181,6 +185,7 @@ public:
consensus.nMajorityRejectBlockOutdated = 75;
consensus.nMajorityWindow = 100;
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.powLimit = ArithToUint256(~arith_uint256(0) >> 16);
consensus.nStartAuxPow = 150;
consensus.nAuxpowChainId = 0x005A;
@@ -197,16 +202,20 @@ public:
consensus.nMaxAdjustUpV2 = 4; // 4% adjustment up
consensus.nBlockSequentialAlgoRuleStart1 = 200; // block where sequential algo rule starts
consensus.nBlockSequentialAlgoRuleStart2 = 10000000; // block where sequential algo rule starts
consensus.nBlockSequentialAlgoRuleStart2 = 250; // block where sequential algo rule starts
consensus.nBlockSequentialAlgoMaxCount1 = 6; // maximum sequential blocks of same algo
consensus.nBlockSequentialAlgoMaxCount2 = 3; // maximum sequential blocks of same algo
consensus.nBlockSequentialAlgoMaxCount3 = 6; // maximum sequential blocks of same algo
consensus.nBlockAlgoWorkWeightStart = 0; // block where algo work weighting starts
consensus.nBlockAlgoNormalisedWorkStart = 0; // block where algo combined weight starts
consensus.nBlockAlgoNormalisedWorkDecayStart1 = 0; // block where weight decay starts
consensus.nBlockAlgoNormalisedWorkDecayStart2 = 0; // block where weight decay starts
consensus.nGeoAvgWork_Start = 150;
consensus.nFork1MinBlock = 300;
consensus.nMajorityEnableAlgoSwitch1 = 60;
consensus.nAlgoSwitch1EnableWindow = 200;
pchMessageStart[0] = 0x01;
pchMessageStart[1] = 0xf5;
pchMessageStart[2] = 0x55;
+1 -1
View File
@@ -18,7 +18,7 @@ const std::string CLIENT_NAME("Satoshi");
/**
* Client version number
*/
#define CLIENT_VERSION_SUFFIX ""
#define CLIENT_VERSION_SUFFIX "-rc1"
/**
+3 -3
View File
@@ -16,11 +16,11 @@
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 0
#define CLIENT_VERSION_MINOR 11
#define CLIENT_VERSION_REVISION 2
#define CLIENT_VERSION_BUILD 1
#define CLIENT_VERSION_REVISION 3
#define CLIENT_VERSION_BUILD 0
//! Set to true for release, false for prerelease or test build
#define CLIENT_VERSION_IS_RELEASE true
#define CLIENT_VERSION_IS_RELEASE false
/**
* Copyright year (2009-this)
+4
View File
@@ -38,11 +38,15 @@ struct Params {
int64_t nBlockSequentialAlgoRuleStart2;
int nBlockSequentialAlgoMaxCount1;
int nBlockSequentialAlgoMaxCount2;
int nBlockSequentialAlgoMaxCount3;
int64_t nBlockAlgoWorkWeightStart;
int64_t nBlockAlgoNormalisedWorkStart;
int64_t nBlockAlgoNormalisedWorkDecayStart1;
int64_t nBlockAlgoNormalisedWorkDecayStart2;
int64_t nGeoAvgWork_Start;
int64_t nFork1MinBlock;
int nMajorityEnableAlgoSwitch1;
int nAlgoSwitch1EnableWindow;
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacingV1; }
+411
View File
@@ -0,0 +1,411 @@
/*-
* Copyright 2005,2007,2009 Colin Percival
* 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.
*/
#include <sys/types.h>
#include <stdint.h>
#include <string.h>
#include "sysendian.h"
#include "sha256_Y.h"
/*
* Encode a length len/4 vector of (uint32_t) into a length len vector of
* (unsigned char) in big-endian form. Assumes len is a multiple of 4.
*/
static void
be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
{
size_t i;
for (i = 0; i < len / 4; i++)
be32enc(dst + i * 4, src[i]);
}
/*
* Decode a big-endian length len vector of (unsigned char) into a length
* len/4 vector of (uint32_t). Assumes len is a multiple of 4.
*/
static void
be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
{
size_t i;
for (i = 0; i < len / 4; i++)
dst[i] = be32dec(src + i * 4);
}
/* Elementary functions used by SHA256 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
#define SHR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
/* SHA256 round function */
#define RND(a, b, c, d, e, f, g, h, k) \
t0 = h + S1(e) + Ch(e, f, g) + k; \
t1 = S0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
/* Adjusted round function for rotating state */
#define RNDr(S, W, i, k) \
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
S[(66 - i) % 8], S[(67 - i) % 8], \
S[(68 - i) % 8], S[(69 - i) % 8], \
S[(70 - i) % 8], S[(71 - i) % 8], \
W[i] + k)
/*
* SHA256 block compression function. The 256-bit state is transformed via
* the 512-bit input block to produce a new state.
*/
static void
SHA256_Transform(uint32_t * state, const unsigned char block[64])
{
uint32_t W[64];
uint32_t S[8];
uint32_t t0, t1;
int i;
/* 1. Prepare message schedule W. */
be32dec_vect(W, block, 64);
for (i = 16; i < 64; i++)
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
/* 2. Initialize working variables. */
memcpy(S, state, 32);
/* 3. Mix. */
RNDr(S, W, 0, 0x428a2f98);
RNDr(S, W, 1, 0x71374491);
RNDr(S, W, 2, 0xb5c0fbcf);
RNDr(S, W, 3, 0xe9b5dba5);
RNDr(S, W, 4, 0x3956c25b);
RNDr(S, W, 5, 0x59f111f1);
RNDr(S, W, 6, 0x923f82a4);
RNDr(S, W, 7, 0xab1c5ed5);
RNDr(S, W, 8, 0xd807aa98);
RNDr(S, W, 9, 0x12835b01);
RNDr(S, W, 10, 0x243185be);
RNDr(S, W, 11, 0x550c7dc3);
RNDr(S, W, 12, 0x72be5d74);
RNDr(S, W, 13, 0x80deb1fe);
RNDr(S, W, 14, 0x9bdc06a7);
RNDr(S, W, 15, 0xc19bf174);
RNDr(S, W, 16, 0xe49b69c1);
RNDr(S, W, 17, 0xefbe4786);
RNDr(S, W, 18, 0x0fc19dc6);
RNDr(S, W, 19, 0x240ca1cc);
RNDr(S, W, 20, 0x2de92c6f);
RNDr(S, W, 21, 0x4a7484aa);
RNDr(S, W, 22, 0x5cb0a9dc);
RNDr(S, W, 23, 0x76f988da);
RNDr(S, W, 24, 0x983e5152);
RNDr(S, W, 25, 0xa831c66d);
RNDr(S, W, 26, 0xb00327c8);
RNDr(S, W, 27, 0xbf597fc7);
RNDr(S, W, 28, 0xc6e00bf3);
RNDr(S, W, 29, 0xd5a79147);
RNDr(S, W, 30, 0x06ca6351);
RNDr(S, W, 31, 0x14292967);
RNDr(S, W, 32, 0x27b70a85);
RNDr(S, W, 33, 0x2e1b2138);
RNDr(S, W, 34, 0x4d2c6dfc);
RNDr(S, W, 35, 0x53380d13);
RNDr(S, W, 36, 0x650a7354);
RNDr(S, W, 37, 0x766a0abb);
RNDr(S, W, 38, 0x81c2c92e);
RNDr(S, W, 39, 0x92722c85);
RNDr(S, W, 40, 0xa2bfe8a1);
RNDr(S, W, 41, 0xa81a664b);
RNDr(S, W, 42, 0xc24b8b70);
RNDr(S, W, 43, 0xc76c51a3);
RNDr(S, W, 44, 0xd192e819);
RNDr(S, W, 45, 0xd6990624);
RNDr(S, W, 46, 0xf40e3585);
RNDr(S, W, 47, 0x106aa070);
RNDr(S, W, 48, 0x19a4c116);
RNDr(S, W, 49, 0x1e376c08);
RNDr(S, W, 50, 0x2748774c);
RNDr(S, W, 51, 0x34b0bcb5);
RNDr(S, W, 52, 0x391c0cb3);
RNDr(S, W, 53, 0x4ed8aa4a);
RNDr(S, W, 54, 0x5b9cca4f);
RNDr(S, W, 55, 0x682e6ff3);
RNDr(S, W, 56, 0x748f82ee);
RNDr(S, W, 57, 0x78a5636f);
RNDr(S, W, 58, 0x84c87814);
RNDr(S, W, 59, 0x8cc70208);
RNDr(S, W, 60, 0x90befffa);
RNDr(S, W, 61, 0xa4506ceb);
RNDr(S, W, 62, 0xbef9a3f7);
RNDr(S, W, 63, 0xc67178f2);
/* 4. Mix local working variables into global state */
for (i = 0; i < 8; i++)
state[i] += S[i];
/* Clean the stack. */
memset(W, 0, 256);
memset(S, 0, 32);
t0 = t1 = 0;
}
static unsigned char PAD[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* Add padding and terminating bit-count. */
static void
SHA256_Pad(SHA256_CTX_Y * ctx)
{
unsigned char len[8];
uint32_t r, plen;
/*
* Convert length to a vector of bytes -- we do this now rather
* than later because the length will change after we pad.
*/
be32enc_vect(len, ctx->count, 8);
/* Add 1--64 bytes so that the resulting length is 56 mod 64 */
r = (ctx->count[1] >> 3) & 0x3f;
plen = (r < 56) ? (56 - r) : (120 - r);
SHA256_Update_Y(ctx, PAD, (size_t)plen);
/* Add the terminating bit-count */
SHA256_Update_Y(ctx, len, 8);
}
/* SHA-256 initialization. Begins a SHA-256 operation. */
void
SHA256_Init_Y(SHA256_CTX_Y * ctx)
{
/* Zero bits processed so far */
ctx->count[0] = ctx->count[1] = 0;
/* Magic initialization constants */
ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19;
}
/* Add bytes into the hash */
void
SHA256_Update_Y(SHA256_CTX_Y * ctx, const void *in, size_t len)
{
uint32_t bitlen[2];
uint32_t r;
const unsigned char *src = in;
/* Number of bytes left in the buffer from previous updates */
r = (ctx->count[1] >> 3) & 0x3f;
/* Convert the length into a number of bits */
bitlen[1] = ((uint32_t)len) << 3;
bitlen[0] = (uint32_t)(len >> 29);
/* Update number of bits */
if ((ctx->count[1] += bitlen[1]) < bitlen[1])
ctx->count[0]++;
ctx->count[0] += bitlen[0];
/* Handle the case where we don't need to perform any transforms */
if (len < 64 - r) {
memcpy(&ctx->buf[r], src, len);
return;
}
/* Finish the current block */
memcpy(&ctx->buf[r], src, 64 - r);
SHA256_Transform(ctx->state, ctx->buf);
src += 64 - r;
len -= 64 - r;
/* Perform complete blocks */
while (len >= 64) {
SHA256_Transform(ctx->state, src);
src += 64;
len -= 64;
}
/* Copy left over data into buffer */
memcpy(ctx->buf, src, len);
}
/*
* SHA-256 finalization. Pads the input data, exports the hash value,
* and clears the context state.
*/
void
SHA256_Final_Y(unsigned char digest[32], SHA256_CTX_Y * ctx)
{
/* Add padding */
SHA256_Pad(ctx);
/* Write the hash */
be32enc_vect(digest, ctx->state, 32);
/* Clear the context state */
memset((void *)ctx, 0, sizeof(*ctx));
}
/* Initialize an HMAC-SHA256 operation with the given key. */
void
HMAC_SHA256_Init_Y(HMAC_SHA256_CTX_Y * ctx, const void * _K, size_t Klen)
{
unsigned char pad[64];
unsigned char khash[32];
const unsigned char * K = _K;
size_t i;
/* If Klen > 64, the key is really SHA256(K). */
if (Klen > 64) {
SHA256_Init_Y(&ctx->ictx);
SHA256_Update_Y(&ctx->ictx, K, Klen);
SHA256_Final_Y(khash, &ctx->ictx);
K = khash;
Klen = 32;
}
/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
SHA256_Init_Y(&ctx->ictx);
memset(pad, 0x36, 64);
for (i = 0; i < Klen; i++)
pad[i] ^= K[i];
SHA256_Update_Y(&ctx->ictx, pad, 64);
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
SHA256_Init_Y(&ctx->octx);
memset(pad, 0x5c, 64);
for (i = 0; i < Klen; i++)
pad[i] ^= K[i];
SHA256_Update_Y(&ctx->octx, pad, 64);
/* Clean the stack. */
memset(khash, 0, 32);
}
/* Add bytes to the HMAC-SHA256 operation. */
void
HMAC_SHA256_Update_Y(HMAC_SHA256_CTX_Y * ctx, const void *in, size_t len)
{
/* Feed data to the inner SHA256 operation. */
SHA256_Update_Y(&ctx->ictx, in, len);
}
/* Finish an HMAC-SHA256 operation. */
void
HMAC_SHA256_Final_Y(unsigned char digest[32], HMAC_SHA256_CTX_Y * ctx)
{
unsigned char ihash[32];
/* Finish the inner SHA256 operation. */
SHA256_Final_Y(ihash, &ctx->ictx);
/* Feed the inner hash to the outer SHA256 operation. */
SHA256_Update_Y(&ctx->octx, ihash, 32);
/* Finish the outer SHA256 operation. */
SHA256_Final_Y(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_Y 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_Y(&PShctx, passwd, passwdlen);
HMAC_SHA256_Update_Y(&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_Y));
HMAC_SHA256_Update_Y(&hctx, ivec, 4);
HMAC_SHA256_Final_Y(U, &hctx);
/* T_i = U_1 ... */
memcpy(T, U, 32);
for (j = 2; j <= c; j++) {
/* Compute U_j. */
HMAC_SHA256_Init_Y(&hctx, passwd, passwdlen);
HMAC_SHA256_Update_Y(&hctx, U, 32);
HMAC_SHA256_Final_Y(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_Y));
}
+62
View File
@@ -0,0 +1,62 @@
/*-
* Copyright 2005,2007,2009 Colin Percival
* 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.
*
* $FreeBSD: src/lib/libmd/sha256_Y.h,v 1.2 2006/01/17 15:35:56 phk Exp $
*/
#ifndef _SHA256_H_
#define _SHA256_H_
#include <sys/types.h>
#include <stdint.h>
typedef struct SHA256Context {
uint32_t state[8];
uint32_t count[2];
unsigned char buf[64];
} SHA256_CTX_Y;
typedef struct HMAC_SHA256Context {
SHA256_CTX_Y ictx;
SHA256_CTX_Y octx;
} HMAC_SHA256_CTX_Y;
void SHA256_Init_Y(SHA256_CTX_Y *);
void SHA256_Update_Y(SHA256_CTX_Y *, const void *, size_t);
void SHA256_Final_Y(unsigned char [32], SHA256_CTX_Y *);
void HMAC_SHA256_Init_Y(HMAC_SHA256_CTX_Y *, const void *, size_t);
void HMAC_SHA256_Update_Y(HMAC_SHA256_CTX_Y *, const void *, size_t);
void HMAC_SHA256_Final_Y(unsigned char [32], HMAC_SHA256_CTX_Y *);
/**
* 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 *, size_t, const uint8_t *, size_t,
uint64_t, uint8_t *, size_t);
#endif /* !_SHA256_H_ */
+138
View File
@@ -0,0 +1,138 @@
/*-
* Copyright 2007-2009 Colin Percival
* 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.
*/
#ifndef _SYSENDIAN_H_
#define _SYSENDIAN_H_
/* If we don't have be64enc, the <sys/endian.h> we have isn't usable. */
#if !HAVE_DECL_BE64ENC
#undef HAVE_SYS_ENDIAN_H
#endif
#ifdef HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#else
#include <stdint.h>
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;
}
static inline uint64_t
be64dec(const void *pp)
{
const uint8_t *p = (uint8_t const *)pp;
return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
}
static inline void
be64enc(void *pp, uint64_t x)
{
uint8_t * p = (uint8_t *)pp;
p[7] = x & 0xff;
p[6] = (x >> 8) & 0xff;
p[5] = (x >> 16) & 0xff;
p[4] = (x >> 24) & 0xff;
p[3] = (x >> 32) & 0xff;
p[2] = (x >> 40) & 0xff;
p[1] = (x >> 48) & 0xff;
p[0] = (x >> 56) & 0xff;
}
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;
}
static inline uint64_t
le64dec(const void *pp)
{
const uint8_t *p = (uint8_t const *)pp;
return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
}
static inline void
le64enc(void *pp, uint64_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;
p[4] = (x >> 32) & 0xff;
p[5] = (x >> 40) & 0xff;
p[6] = (x >> 48) & 0xff;
p[7] = (x >> 56) & 0xff;
}
#endif /* !HAVE_SYS_ENDIAN_H */
#endif /* !_SYSENDIAN_H_ */
+5
View File
@@ -0,0 +1,5 @@
#ifdef __SSE2__
#include "yescrypt-simd.c"
#else
#include "yescrypt-opt.c"
#endif
+948
View File
@@ -0,0 +1,948 @@
/*-
* Copyright 2009 Colin Percival
* Copyright 2013,2014 Alexander Peslyak
* 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.
*/
#ifdef __i386__
#warning "This implementation does not use SIMD, and thus it runs a lot slower than the SIMD-enabled implementation. Enable at least SSE2 in the C compiler and use yescrypt-best.c instead unless you're building this SIMD-less implementation on purpose (portability to older CPUs or testing)."
#elif defined(__x86_64__)
#warning "This implementation does not use SIMD, and thus it runs a lot slower than the SIMD-enabled implementation. Use yescrypt-best.c instead unless you're building this SIMD-less implementation on purpose (for testing only)."
#endif
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include "sha256_Y.h"
#include "sysendian.h"
#include "yescrypt-platform.c"
static inline void
blkcpy(uint64_t * dest, const uint64_t * src, size_t count)
{
do {
*dest++ = *src++; *dest++ = *src++;
*dest++ = *src++; *dest++ = *src++;
} while (count -= 4);
}
static inline void
blkxor(uint64_t * dest, const uint64_t * src, size_t count)
{
do {
*dest++ ^= *src++; *dest++ ^= *src++;
*dest++ ^= *src++; *dest++ ^= *src++;
} while (count -= 4);
}
typedef union {
uint32_t w[16];
uint64_t d[8];
} salsa20_blk_t;
static inline void
salsa20_simd_shuffle(const salsa20_blk_t * Bin, salsa20_blk_t * Bout)
{
#define COMBINE(out, in1, in2) \
Bout->d[out] = Bin->w[in1 * 2] | ((uint64_t)Bin->w[in2 * 2 + 1] << 32);
COMBINE(0, 0, 2)
COMBINE(1, 5, 7)
COMBINE(2, 2, 4)
COMBINE(3, 7, 1)
COMBINE(4, 4, 6)
COMBINE(5, 1, 3)
COMBINE(6, 6, 0)
COMBINE(7, 3, 5)
#undef COMBINE
}
static inline void
salsa20_simd_unshuffle(const salsa20_blk_t * Bin, salsa20_blk_t * Bout)
{
#define COMBINE(out, in1, in2) \
Bout->w[out * 2] = Bin->d[in1]; \
Bout->w[out * 2 + 1] = Bin->d[in2] >> 32;
COMBINE(0, 0, 6)
COMBINE(1, 5, 3)
COMBINE(2, 2, 0)
COMBINE(3, 7, 5)
COMBINE(4, 4, 2)
COMBINE(5, 1, 7)
COMBINE(6, 6, 4)
COMBINE(7, 3, 1)
#undef COMBINE
}
/**
* salsa20_8(B):
* Apply the salsa20/8 core to the provided block.
*/
static void
salsa20_8(uint64_t B[8])
{
size_t i;
salsa20_blk_t X;
#define x X.w
salsa20_simd_unshuffle((const salsa20_blk_t *)B, &X);
for (i = 0; i < 8; i += 2) {
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
/* Operate on columns */
x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
/* Operate on rows */
x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
#undef R
}
#undef x
{
salsa20_blk_t Y;
salsa20_simd_shuffle(&X, &Y);
for (i = 0; i < 16; i += 4) {
((salsa20_blk_t *)B)->w[i] += Y.w[i];
((salsa20_blk_t *)B)->w[i + 1] += Y.w[i + 1];
((salsa20_blk_t *)B)->w[i + 2] += Y.w[i + 2];
((salsa20_blk_t *)B)->w[i + 3] += Y.w[i + 3];
}
}
}
/**
* blockmix_salsa8(Bin, Bout, X, r):
* Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
* bytes in length; the output Bout must also be the same size. The
* temporary space X must be 64 bytes.
*/
static void
blockmix_salsa8(const uint64_t * Bin, uint64_t * Bout, uint64_t * X, size_t r)
{
size_t i;
/* 1: X <-- B_{2r - 1} */
blkcpy(X, &Bin[(2 * r - 1) * 8], 8);
/* 2: for i = 0 to 2r - 1 do */
for (i = 0; i < 2 * r; i += 2) {
/* 3: X <-- H(X \xor B_i) */
blkxor(X, &Bin[i * 8], 8);
salsa20_8(X);
/* 4: Y_i <-- X */
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
blkcpy(&Bout[i * 4], X, 8);
/* 3: X <-- H(X \xor B_i) */
blkxor(X, &Bin[i * 8 + 8], 8);
salsa20_8(X);
/* 4: Y_i <-- X */
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
blkcpy(&Bout[i * 4 + r * 8], X, 8);
}
}
/* These are tunable */
#define S_BITS 8
#define S_SIMD 2
#define S_P 4
#define S_ROUNDS 6
/* Number of S-boxes. Not tunable, hard-coded in a few places. */
#define S_N 2
/* Derived values. Not tunable on their own. */
#define S_SIZE1 (1 << S_BITS)
#define S_MASK ((S_SIZE1 - 1) * S_SIMD * 8)
#define S_MASK2 (((uint64_t)S_MASK << 32) | S_MASK)
#define S_SIZE_ALL (S_N * S_SIZE1 * S_SIMD)
#define S_P_SIZE (S_P * S_SIMD)
#define S_MIN_R ((S_P * S_SIMD + 15) / 16)
/**
* pwxform(B):
* Transform the provided block using the provided S-boxes.
*/
static void
block_pwxform(uint64_t * B, const uint64_t * S)
{
uint64_t (*X)[S_SIMD] = (uint64_t (*)[S_SIMD])B;
const uint8_t *S0 = (const uint8_t *)S;
const uint8_t *S1 = (const uint8_t *)(S + S_SIZE1 * S_SIMD);
size_t i, j;
#if S_SIMD > 2
size_t k;
#endif
for (j = 0; j < S_P; j++) {
uint64_t *Xj = X[j];
uint64_t x0 = Xj[0];
#if S_SIMD > 1
uint64_t x1 = Xj[1];
#endif
for (i = 0; i < S_ROUNDS; i++) {
uint64_t x = x0 & S_MASK2;
const uint64_t *p0, *p1;
p0 = (const uint64_t *)(S0 + (uint32_t)x);
p1 = (const uint64_t *)(S1 + (x >> 32));
x0 = (uint64_t)(x0 >> 32) * (uint32_t)x0;
x0 += p0[0];
x0 ^= p1[0];
#if S_SIMD > 1
x1 = (uint64_t)(x1 >> 32) * (uint32_t)x1;
x1 += p0[1];
x1 ^= p1[1];
#endif
#if S_SIMD > 2
for (k = 2; k < S_SIMD; k++) {
x = Xj[k];
x = (uint64_t)(x >> 32) * (uint32_t)x;
x += p0[k];
x ^= p1[k];
Xj[k] = x;
}
#endif
}
Xj[0] = x0;
#if S_SIMD > 1
Xj[1] = x1;
#endif
}
}
/**
* blockmix_pwxform(Bin, Bout, S, r):
* Compute Bout = BlockMix_pwxform{salsa20/8, S, r}(Bin). The input Bin must
* be 128r bytes in length; the output Bout must also be the same size.
*
* S lacks const qualifier to match blockmix_salsa8()'s prototype, which we
* need to refer to both functions via the same function pointers.
*/
static void
blockmix_pwxform(const uint64_t * Bin, uint64_t * Bout, uint64_t * S, size_t r)
{
size_t r1, r2, i;
/* Convert 128-byte blocks to (S_P_SIZE * 64-bit) blocks */
r1 = r * 128 / (S_P_SIZE * 8);
/* X <-- B_{r1 - 1} */
blkcpy(Bout, &Bin[(r1 - 1) * S_P_SIZE], S_P_SIZE);
/* X <-- X \xor B_i */
blkxor(Bout, Bin, S_P_SIZE);
/* X <-- H'(X) */
/* B'_i <-- X */
block_pwxform(Bout, S);
/* for i = 0 to r1 - 1 do */
for (i = 1; i < r1; i++) {
/* X <-- X \xor B_i */
blkcpy(&Bout[i * S_P_SIZE], &Bout[(i - 1) * S_P_SIZE],
S_P_SIZE);
blkxor(&Bout[i * S_P_SIZE], &Bin[i * S_P_SIZE], S_P_SIZE);
/* X <-- H'(X) */
/* B'_i <-- X */
block_pwxform(&Bout[i * S_P_SIZE], S);
}
/* Handle partial blocks */
if (i * S_P_SIZE < r * 16)
blkcpy(&Bout[i * S_P_SIZE], &Bin[i * S_P_SIZE],
r * 16 - i * S_P_SIZE);
i = (r1 - 1) * S_P_SIZE / 8;
/* Convert 128-byte blocks to 64-byte blocks */
r2 = r * 2;
/* B'_i <-- H(B'_i) */
salsa20_8(&Bout[i * 8]);
i++;
for (; i < r2; i++) {
/* B'_i <-- H(B'_i \xor B'_{i-1}) */
blkxor(&Bout[i * 8], &Bout[(i - 1) * 8], 8);
salsa20_8(&Bout[i * 8]);
}
}
/**
* integerify(B, r):
* Return the result of parsing B_{2r-1} as a little-endian integer.
*/
static inline uint64_t
integerify(const uint64_t * B, size_t r)
{
/*
* Our 64-bit words are in host byte order, and word 6 holds the second 32-bit
* word of B_{2r-1} due to SIMD shuffling. The 64-bit value we return is also
* in host byte order, as it should be.
*/
const uint64_t * X = &B[(2 * r - 1) * 8];
uint32_t lo = X[0];
uint32_t hi = X[6] >> 32;
return ((uint64_t)hi << 32) + lo;
}
/**
* smix1(B, r, N, flags, V, NROM, shared, XY, S):
* Compute first loop of B = SMix_r(B, N). The input B must be 128r bytes in
* length; the temporary storage V must be 128rN bytes in length; the temporary
* storage XY must be 256r + 64 bytes in length. The value N must be even and
* no smaller than 2.
*/
static void
smix1(uint64_t * B, size_t r, uint64_t N, yescrypt_flags_t flags,
uint64_t * V, uint64_t NROM, const yescrypt_shared_t * shared,
uint64_t * XY, uint64_t * S)
{
void (*blockmix)(const uint64_t *, uint64_t *, uint64_t *, size_t) =
(S ? blockmix_pwxform : blockmix_salsa8);
const uint64_t * VROM = shared->shared1.aligned;
uint32_t VROM_mask = shared->mask1;
size_t s = 16 * r;
uint64_t * X = V;
uint64_t * Y = &XY[s];
uint64_t * Z = S ? S : &XY[2 * s];
uint64_t n, i, j;
size_t k;
/* 1: X <-- B */
/* 3: V_i <-- X */
for (i = 0; i < 2 * r; i++) {
const salsa20_blk_t *src = (const salsa20_blk_t *)&B[i * 8];
salsa20_blk_t *tmp = (salsa20_blk_t *)Y;
salsa20_blk_t *dst = (salsa20_blk_t *)&X[i * 8];
for (k = 0; k < 16; k++)
tmp->w[k] = le32dec(&src->w[k]);
salsa20_simd_shuffle(tmp, dst);
}
/* 4: X <-- H(X) */
/* 3: V_i <-- X */
blockmix(X, Y, Z, r);
blkcpy(&V[s], Y, s);
X = XY;
if (NROM && (VROM_mask & 1)) {
if ((1 & VROM_mask) == 1) {
/* j <-- Integerify(X) mod NROM */
j = integerify(Y, r) & (NROM - 1);
/* X <-- H(X \xor VROM_j) */
blkxor(Y, &VROM[j * s], s);
}
blockmix(Y, X, Z, r);
/* 2: for i = 0 to N - 1 do */
for (n = 1, i = 2; i < N; i += 2) {
/* 3: V_i <-- X */
blkcpy(&V[i * s], X, s);
if ((i & (i - 1)) == 0)
n <<= 1;
/* j <-- Wrap(Integerify(X), i) */
j = integerify(X, r) & (n - 1);
j += i - n;
/* X <-- X \xor V_j */
blkxor(X, &V[j * s], s);
/* 4: X <-- H(X) */
blockmix(X, Y, Z, r);
/* 3: V_i <-- X */
blkcpy(&V[(i + 1) * s], Y, s);
j = integerify(Y, r);
if (((i + 1) & VROM_mask) == 1) {
/* j <-- Integerify(X) mod NROM */
j &= NROM - 1;
/* X <-- H(X \xor VROM_j) */
blkxor(Y, &VROM[j * s], s);
} else {
/* j <-- Wrap(Integerify(X), i) */
j &= n - 1;
j += i + 1 - n;
/* X <-- H(X \xor V_j) */
blkxor(Y, &V[j * s], s);
}
blockmix(Y, X, Z, r);
}
} else {
yescrypt_flags_t rw = flags & YESCRYPT_RW;
/* 4: X <-- H(X) */
blockmix(Y, X, Z, r);
/* 2: for i = 0 to N - 1 do */
for (n = 1, i = 2; i < N; i += 2) {
/* 3: V_i <-- X */
blkcpy(&V[i * s], X, s);
if (rw) {
if ((i & (i - 1)) == 0)
n <<= 1;
/* j <-- Wrap(Integerify(X), i) */
j = integerify(X, r) & (n - 1);
j += i - n;
/* X <-- X \xor V_j */
blkxor(X, &V[j * s], s);
}
/* 4: X <-- H(X) */
blockmix(X, Y, Z, r);
/* 3: V_i <-- X */
blkcpy(&V[(i + 1) * s], Y, s);
if (rw) {
/* j <-- Wrap(Integerify(X), i) */
j = integerify(Y, r) & (n - 1);
j += (i + 1) - n;
/* X <-- X \xor V_j */
blkxor(Y, &V[j * s], s);
}
/* 4: X <-- H(X) */
blockmix(Y, X, Z, r);
}
}
/* B' <-- X */
for (i = 0; i < 2 * r; i++) {
const salsa20_blk_t *src = (const salsa20_blk_t *)&X[i * 8];
salsa20_blk_t *tmp = (salsa20_blk_t *)Y;
salsa20_blk_t *dst = (salsa20_blk_t *)&B[i * 8];
for (k = 0; k < 16; k++)
le32enc(&tmp->w[k], src->w[k]);
salsa20_simd_unshuffle(tmp, dst);
}
}
/**
* smix2(B, r, N, Nloop, flags, V, NROM, shared, XY, S):
* Compute second loop of B = SMix_r(B, N). The input B must be 128r bytes in
* length; the temporary storage V must be 128rN bytes in length; the temporary
* storage XY must be 256r + 64 bytes in length. The value N must be a
* power of 2 greater than 1. The value Nloop must be even.
*/
static void
smix2(uint64_t * B, size_t r, uint64_t N, uint64_t Nloop,
yescrypt_flags_t flags,
uint64_t * V, uint64_t NROM, const yescrypt_shared_t * shared,
uint64_t * XY, uint64_t * S)
{
void (*blockmix)(const uint64_t *, uint64_t *, uint64_t *, size_t) =
(S ? blockmix_pwxform : blockmix_salsa8);
const uint64_t * VROM = shared->shared1.aligned;
uint32_t VROM_mask = shared->mask1 | 1;
size_t s = 16 * r;
yescrypt_flags_t rw = flags & YESCRYPT_RW;
uint64_t * X = XY;
uint64_t * Y = &XY[s];
uint64_t * Z = S ? S : &XY[2 * s];
uint64_t i, j;
size_t k;
if (Nloop == 0)
return;
/* X <-- B' */
for (i = 0; i < 2 * r; i++) {
const salsa20_blk_t *src = (const salsa20_blk_t *)&B[i * 8];
salsa20_blk_t *tmp = (salsa20_blk_t *)Y;
salsa20_blk_t *dst = (salsa20_blk_t *)&X[i * 8];
for (k = 0; k < 16; k++)
tmp->w[k] = le32dec(&src->w[k]);
salsa20_simd_shuffle(tmp, dst);
}
if (NROM) {
/* 6: for i = 0 to N - 1 do */
for (i = 0; i < Nloop; i += 2) {
/* 7: j <-- Integerify(X) mod N */
j = integerify(X, r) & (N - 1);
/* 8: X <-- H(X \xor V_j) */
blkxor(X, &V[j * s], s);
/* V_j <-- Xprev \xor V_j */
if (rw)
blkcpy(&V[j * s], X, s);
blockmix(X, Y, Z, r);
j = integerify(Y, r);
if (((i + 1) & VROM_mask) == 1) {
/* j <-- Integerify(X) mod NROM */
j &= NROM - 1;
/* X <-- H(X \xor VROM_j) */
blkxor(Y, &VROM[j * s], s);
} else {
/* 7: j <-- Integerify(X) mod N */
j &= N - 1;
/* 8: X <-- H(X \xor V_j) */
blkxor(Y, &V[j * s], s);
/* V_j <-- Xprev \xor V_j */
if (rw)
blkcpy(&V[j * s], Y, s);
}
blockmix(Y, X, Z, r);
}
} else {
/* 6: for i = 0 to N - 1 do */
i = Nloop / 2;
do {
/* 7: j <-- Integerify(X) mod N */
j = integerify(X, r) & (N - 1);
/* 8: X <-- H(X \xor V_j) */
blkxor(X, &V[j * s], s);
/* V_j <-- Xprev \xor V_j */
if (rw)
blkcpy(&V[j * s], X, s);
blockmix(X, Y, Z, r);
/* 7: j <-- Integerify(X) mod N */
j = integerify(Y, r) & (N - 1);
/* 8: X <-- H(X \xor V_j) */
blkxor(Y, &V[j * s], s);
/* V_j <-- Xprev \xor V_j */
if (rw)
blkcpy(&V[j * s], Y, s);
blockmix(Y, X, Z, r);
} while (--i);
}
/* 10: B' <-- X */
for (i = 0; i < 2 * r; i++) {
const salsa20_blk_t *src = (const salsa20_blk_t *)&X[i * 8];
salsa20_blk_t *tmp = (salsa20_blk_t *)Y;
salsa20_blk_t *dst = (salsa20_blk_t *)&B[i * 8];
for (k = 0; k < 16; k++)
le32enc(&tmp->w[k], src->w[k]);
salsa20_simd_unshuffle(tmp, dst);
}
}
/**
* p2floor(x):
* Largest power of 2 not greater than argument.
*/
static uint64_t
p2floor(uint64_t x)
{
uint64_t y;
while ((y = x & (x - 1)))
x = y;
return x;
}
/**
* smix(B, r, N, p, t, flags, V, NROM, shared, XY, S):
* Compute B = SMix_r(B, N). The input B must be 128rp bytes in length; the
* temporary storage V must be 128rN bytes in length; the temporary storage
* XY must be 256r+64 or (256r+64)*p bytes in length (the larger size is
* required with OpenMP-enabled builds). The value N must be a power of 2
* greater than 1.
*/
static void
smix(uint64_t * B, size_t r, uint64_t N, uint32_t p, uint32_t t,
yescrypt_flags_t flags,
uint64_t * V, uint64_t NROM, const yescrypt_shared_t * shared,
uint64_t * XY, uint64_t * S)
{
size_t s = 16 * r;
uint64_t Nchunk = N / p, Nloop_all, Nloop_rw;
uint32_t i;
Nloop_all = Nchunk;
if (flags & YESCRYPT_RW) {
if (t <= 1) {
if (t)
Nloop_all *= 2; /* 2/3 */
Nloop_all = (Nloop_all + 2) / 3; /* 1/3, round up */
} else {
Nloop_all *= t - 1;
}
} else if (t) {
if (t == 1)
Nloop_all += (Nloop_all + 1) / 2; /* 1.5, round up */
Nloop_all *= t;
}
Nloop_rw = 0;
if (flags & __YESCRYPT_INIT_SHARED)
Nloop_rw = Nloop_all;
else if (flags & YESCRYPT_RW)
Nloop_rw = Nloop_all / p;
Nchunk &= ~(uint64_t)1; /* round down to even */
Nloop_all++; Nloop_all &= ~(uint64_t)1; /* round up to even */
Nloop_rw &= ~(uint64_t)1; /* round down to even */
#ifdef _OPENMP
#pragma omp parallel if (p > 1) default(none) private(i) shared(B, r, N, p, flags, V, NROM, shared, XY, S, s, Nchunk, Nloop_all, Nloop_rw)
{
#pragma omp for
#endif
for (i = 0; i < p; i++) {
uint64_t Vchunk = i * Nchunk;
uint64_t * Bp = &B[i * s];
uint64_t * Vp = &V[Vchunk * s];
#ifdef _OPENMP
uint64_t * XYp = &XY[i * (2 * s + 8)];
#else
uint64_t * XYp = XY;
#endif
uint64_t Np = (i < p - 1) ? Nchunk : (N - Vchunk);
uint64_t * Sp = S ? &S[i * S_SIZE_ALL] : S;
if (Sp)
smix1(Bp, 1, S_SIZE_ALL / 16,
flags & ~YESCRYPT_PWXFORM,
Sp, NROM, shared, XYp, NULL);
if (!(flags & __YESCRYPT_INIT_SHARED_2))
smix1(Bp, r, Np, flags, Vp, NROM, shared, XYp, Sp);
smix2(Bp, r, p2floor(Np), Nloop_rw, flags, Vp,
NROM, shared, XYp, Sp);
}
if (Nloop_all > Nloop_rw) {
#ifdef _OPENMP
#pragma omp for
#endif
for (i = 0; i < p; i++) {
uint64_t * Bp = &B[i * s];
#ifdef _OPENMP
uint64_t * XYp = &XY[i * (2 * s + 8)];
#else
uint64_t * XYp = XY;
#endif
uint64_t * Sp = S ? &S[i * S_SIZE_ALL] : S;
smix2(Bp, r, N, Nloop_all - Nloop_rw,
flags & ~YESCRYPT_RW, V, NROM, shared, XYp, Sp);
}
}
#ifdef _OPENMP
}
#endif
}
/**
* yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen,
* N, r, p, t, flags, buf, buflen):
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
* p, buflen), or a revision of scrypt as requested by flags and shared, and
* write the result into buf. The parameters r, p, and buflen must satisfy
* r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N must be a power
* of 2 greater than 1.
*
* t controls computation time while not affecting peak memory usage. shared
* and flags may request special modes as described in yescrypt.h. local is
* the thread-local data structure, allowing to preserve and reuse a memory
* allocation across calls, thereby reducing its overhead.
*
* Return 0 on success; or -1 on error.
*/
int
yescrypt_kdf(const yescrypt_shared_t * shared, yescrypt_local_t * local,
const uint8_t * passwd, size_t passwdlen,
const uint8_t * salt, size_t saltlen,
uint64_t N, uint32_t r, uint32_t p, uint32_t t, yescrypt_flags_t flags,
uint8_t * buf, size_t buflen)
{
yescrypt_region_t tmp;
uint64_t NROM;
size_t B_size, V_size, XY_size, need;
uint64_t * B, * V, * XY, * S;
uint64_t sha256[4];
/*
* YESCRYPT_PARALLEL_SMIX is a no-op at p = 1 for its intended purpose,
* so don't let it have side-effects. Without this adjustment, it'd
* enable the SHA-256 password pre-hashing and output post-hashing,
* because any deviation from classic scrypt implies those.
*/
if (p == 1)
flags &= ~YESCRYPT_PARALLEL_SMIX;
/* Sanity-check parameters */
if (flags & ~YESCRYPT_KNOWN_FLAGS) {
errno = EINVAL;
return -1;
}
#if SIZE_MAX > UINT32_MAX
if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
errno = EFBIG;
return -1;
}
#endif
if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
errno = EFBIG;
return -1;
}
if (((N & (N - 1)) != 0) || (N <= 1) || (r < 1) || (p < 1)) {
errno = EINVAL;
return -1;
}
if ((flags & YESCRYPT_PARALLEL_SMIX) && (N / p <= 1)) {
errno = EINVAL;
return -1;
}
#if S_MIN_R > 1
if ((flags & YESCRYPT_PWXFORM) && (r < S_MIN_R)) {
errno = EINVAL;
return -1;
}
#endif
if ((p > SIZE_MAX / ((size_t)256 * r + 64)) ||
#if SIZE_MAX / 256 <= UINT32_MAX
(r > SIZE_MAX / 256) ||
#endif
(N > SIZE_MAX / 128 / r)) {
errno = ENOMEM;
return -1;
}
if (N > UINT64_MAX / ((uint64_t)t + 1)) {
errno = EFBIG;
return -1;
}
#ifdef _OPENMP
if (!(flags & YESCRYPT_PARALLEL_SMIX) &&
(N > SIZE_MAX / 128 / (r * p))) {
errno = ENOMEM;
return -1;
}
#endif
if ((flags & YESCRYPT_PWXFORM) &&
#ifndef _OPENMP
(flags & YESCRYPT_PARALLEL_SMIX) &&
#endif
p > SIZE_MAX / (S_SIZE_ALL * sizeof(*S))) {
errno = ENOMEM;
return -1;
}
NROM = 0;
if (shared->shared1.aligned) {
NROM = shared->shared1.aligned_size / ((size_t)128 * r);
if (((NROM & (NROM - 1)) != 0) || (NROM <= 1) ||
!(flags & YESCRYPT_RW)) {
errno = EINVAL;
return -1;
}
}
/* Allocate memory */
V = NULL;
V_size = (size_t)128 * r * N;
#ifdef _OPENMP
if (!(flags & YESCRYPT_PARALLEL_SMIX))
V_size *= p;
#endif
need = V_size;
if (flags & __YESCRYPT_INIT_SHARED) {
if (local->aligned_size < need) {
if (local->base || local->aligned ||
local->base_size || local->aligned_size) {
errno = EINVAL;
return -1;
}
if (!alloc_region(local, need))
return -1;
}
V = (uint64_t *)local->aligned;
need = 0;
}
B_size = (size_t)128 * r * p;
need += B_size;
if (need < B_size) {
errno = ENOMEM;
return -1;
}
XY_size = (size_t)256 * r + 64;
#ifdef _OPENMP
XY_size *= p;
#endif
need += XY_size;
if (need < XY_size) {
errno = ENOMEM;
return -1;
}
if (flags & YESCRYPT_PWXFORM) {
size_t S_size = S_SIZE_ALL * sizeof(*S);
#ifdef _OPENMP
S_size *= p;
#else
if (flags & YESCRYPT_PARALLEL_SMIX)
S_size *= p;
#endif
need += S_size;
if (need < S_size) {
errno = ENOMEM;
return -1;
}
}
if (flags & __YESCRYPT_INIT_SHARED) {
if (!alloc_region(&tmp, need))
return -1;
B = (uint64_t *)tmp.aligned;
XY = (uint64_t *)((uint8_t *)B + B_size);
} else {
init_region(&tmp);
if (local->aligned_size < need) {
if (free_region(local))
return -1;
if (!alloc_region(local, need))
return -1;
}
B = (uint64_t *)local->aligned;
V = (uint64_t *)((uint8_t *)B + B_size);
XY = (uint64_t *)((uint8_t *)V + V_size);
}
S = NULL;
if (flags & YESCRYPT_PWXFORM)
S = (uint64_t *)((uint8_t *)XY + XY_size);
if (t || flags) {
SHA256_CTX_Y ctx;
SHA256_Init_Y(&ctx);
SHA256_Update_Y(&ctx, passwd, passwdlen);
SHA256_Final_Y((uint8_t *)sha256, &ctx);
passwd = (uint8_t *)sha256;
passwdlen = sizeof(sha256);
}
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1,
(uint8_t *)B, B_size);
if (t || flags)
blkcpy(sha256, B, sizeof(sha256) / sizeof(sha256[0]));
if (p == 1 || (flags & YESCRYPT_PARALLEL_SMIX)) {
smix(B, r, N, p, t, flags, V, NROM, shared, XY, S);
} else {
uint32_t i;
/* 2: for i = 0 to p - 1 do */
#ifdef _OPENMP
#pragma omp parallel for default(none) private(i) shared(B, r, N, p, t, flags, V, NROM, shared, XY, S)
#endif
for (i = 0; i < p; i++) {
/* 3: B_i <-- MF(B_i, N) */
#ifdef _OPENMP
smix(&B[(size_t)16 * r * i], r, N, 1, t, flags,
&V[(size_t)16 * r * i * N],
NROM, shared,
&XY[((size_t)32 * r + 8) * i],
S ? &S[S_SIZE_ALL * i] : S);
#else
smix(&B[(size_t)16 * r * i], r, N, 1, t, flags, V,
NROM, shared, XY, S);
#endif
}
}
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
PBKDF2_SHA256(passwd, passwdlen, (uint8_t *)B, B_size, 1, buf, buflen);
/*
* Except when computing classic scrypt, allow all computation so far
* to be performed on the client. The final steps below match those of
* SCRAM (RFC 5802), so that an extension of SCRAM (with the steps so
* far in place of SCRAM's use of PBKDF2 and with SHA-256 in place of
* SCRAM's use of SHA-1) would be usable with yescrypt hashes.
*/
if ((t || flags) && buflen == sizeof(sha256)) {
/* Compute ClientKey */
{
HMAC_SHA256_CTX_Y ctx;
HMAC_SHA256_Init_Y(&ctx, buf, buflen);
HMAC_SHA256_Update_Y(&ctx, salt, saltlen);
HMAC_SHA256_Final_Y((uint8_t *)sha256, &ctx);
}
/* Compute StoredKey */
{
SHA256_CTX_Y ctx;
SHA256_Init_Y(&ctx);
SHA256_Update_Y(&ctx, (uint8_t *)sha256, sizeof(sha256));
SHA256_Final_Y(buf, &ctx);
}
}
if (free_region(&tmp))
return -1;
/* Success! */
return 0;
}
+191
View File
@@ -0,0 +1,191 @@
/*-
* Copyright 2013,2014 Alexander Peslyak
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* 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.
*/
#include <sys/mman.h>
#include "yescrypt.h"
#define HUGEPAGE_THRESHOLD (12 * 1024 * 1024)
#ifdef __x86_64__
#define HUGEPAGE_SIZE (2 * 1024 * 1024)
#else
#undef HUGEPAGE_SIZE
#endif
static void *
alloc_region(yescrypt_region_t * region, size_t size)
{
size_t base_size = size;
uint8_t * base, * aligned;
#ifdef MAP_ANON
int flags =
#ifdef MAP_NOCORE
MAP_NOCORE |
#endif
MAP_ANON | MAP_PRIVATE;
#if defined(MAP_HUGETLB) && defined(HUGEPAGE_SIZE)
size_t new_size = size;
const size_t hugepage_mask = (size_t)HUGEPAGE_SIZE - 1;
if (size >= HUGEPAGE_THRESHOLD && size + hugepage_mask >= size) {
flags |= MAP_HUGETLB;
/*
* Linux's munmap() fails on MAP_HUGETLB mappings if size is not a multiple of
* huge page size, so let's round up to huge page size here.
*/
new_size = size + hugepage_mask;
new_size &= ~hugepage_mask;
}
base = mmap(NULL, new_size, PROT_READ | PROT_WRITE, flags, -1, 0);
if (base != MAP_FAILED) {
base_size = new_size;
} else
if (flags & MAP_HUGETLB) {
flags &= ~MAP_HUGETLB;
base = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0);
}
#else
base = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0);
#endif
if (base == MAP_FAILED)
base = NULL;
aligned = base;
#elif defined(HAVE_POSIX_MEMALIGN)
if ((errno = posix_memalign((void **)&base, 64, size)) != 0)
base = NULL;
aligned = base;
#else
base = aligned = NULL;
if (size + 63 < size) {
errno = ENOMEM;
} else if ((base = malloc(size + 63)) != NULL) {
aligned = base + 63;
aligned -= (uintptr_t)aligned & 63;
}
#endif
region->base = base;
region->aligned = aligned;
region->base_size = base ? base_size : 0;
region->aligned_size = base ? size : 0;
return aligned;
}
static inline void
init_region(yescrypt_region_t * region)
{
region->base = region->aligned = NULL;
region->base_size = region->aligned_size = 0;
}
static int
free_region(yescrypt_region_t * region)
{
if (region->base) {
#ifdef MAP_ANON
if (munmap(region->base, region->base_size))
return -1;
#else
free(region->base);
#endif
}
init_region(region);
return 0;
}
int
yescrypt_init_shared(yescrypt_shared_t * shared,
const uint8_t * param, size_t paramlen,
uint64_t N, uint32_t r, uint32_t p,
yescrypt_init_shared_flags_t flags, uint32_t mask,
uint8_t * buf, size_t buflen)
{
yescrypt_shared1_t * shared1 = &shared->shared1;
yescrypt_shared_t dummy, half1, half2;
uint8_t salt[32];
if (flags & YESCRYPT_SHARED_PREALLOCATED) {
if (!shared1->aligned || !shared1->aligned_size)
return -1;
} else {
init_region(shared1);
}
shared->mask1 = 1;
if (!param && !paramlen && !N && !r && !p && !buf && !buflen)
return 0;
init_region(&dummy.shared1);
dummy.mask1 = 1;
if (yescrypt_kdf(&dummy, shared1,
param, paramlen, NULL, 0, N, r, p, 0,
YESCRYPT_RW | YESCRYPT_PARALLEL_SMIX | __YESCRYPT_INIT_SHARED_1,
salt, sizeof(salt)))
goto out;
half1 = half2 = *shared;
half1.shared1.aligned_size /= 2;
half2.shared1.aligned += half1.shared1.aligned_size;
half2.shared1.aligned_size = half1.shared1.aligned_size;
N /= 2;
if (p > 1 && yescrypt_kdf(&half1, &half2.shared1,
param, paramlen, salt, sizeof(salt), N, r, p, 0,
YESCRYPT_RW | YESCRYPT_PARALLEL_SMIX | __YESCRYPT_INIT_SHARED_2,
salt, sizeof(salt)))
goto out;
if (yescrypt_kdf(&half2, &half1.shared1,
param, paramlen, salt, sizeof(salt), N, r, p, 0,
YESCRYPT_RW | YESCRYPT_PARALLEL_SMIX | __YESCRYPT_INIT_SHARED_1,
salt, sizeof(salt)))
goto out;
if (yescrypt_kdf(&half1, &half2.shared1,
param, paramlen, salt, sizeof(salt), N, r, p, 0,
YESCRYPT_RW | YESCRYPT_PARALLEL_SMIX | __YESCRYPT_INIT_SHARED_1,
buf, buflen))
goto out;
shared->mask1 = mask;
return 0;
out:
if (!(flags & YESCRYPT_SHARED_PREALLOCATED))
free_region(shared1);
return -1;
}
int
yescrypt_free_shared(yescrypt_shared_t * shared)
{
return free_region(&shared->shared1);
}
int
yescrypt_init_local(yescrypt_local_t * local)
{
init_region(local);
return 0;
}
int
yescrypt_free_local(yescrypt_local_t * local)
{
return free_region(local);
}
File diff suppressed because it is too large Load Diff
+375
View File
@@ -0,0 +1,375 @@
/*-
* Copyright 2009 Colin Percival
* Copyright 2013,2014 Alexander Peslyak
* 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.
*/
#ifndef _YESCRYPT_H_
#define _YESCRYPT_H_
#include <stdint.h>
#include <stdlib.h> /* for size_t */
#ifdef __cplusplus
extern "C" {
#endif
extern void yescrypt_hash_sp(const char *input, char *output);
extern void yescrypt_hash(const char *input, char *output);
/**
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
* p, buflen) and write the result into buf. The parameters r, p, and buflen
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
* must be a power of 2 greater than 1.
*
* Return 0 on success; or -1 on error.
*
* MT-safe as long as buf is local to the thread.
*/
extern int crypto_scrypt(const uint8_t * __passwd, size_t __passwdlen,
const uint8_t * __salt, size_t __saltlen,
uint64_t __N, uint32_t __r, uint32_t __p,
uint8_t * __buf, size_t __buflen);
/**
* Internal type used by the memory allocator. Please do not use it directly.
* Use yescrypt_shared_t and yescrypt_local_t as appropriate instead, since
* they might differ from each other in a future version.
*/
typedef struct {
void * base, * aligned;
size_t base_size, aligned_size;
} yescrypt_region_t;
/**
* Types for shared (ROM) and thread-local (RAM) data structures.
*/
typedef yescrypt_region_t yescrypt_shared1_t;
typedef struct {
yescrypt_shared1_t shared1;
uint32_t mask1;
} yescrypt_shared_t;
typedef yescrypt_region_t yescrypt_local_t;
/**
* Possible values for yescrypt_init_shared()'s flags argument.
*/
typedef enum {
YESCRYPT_SHARED_DEFAULTS = 0,
YESCRYPT_SHARED_PREALLOCATED = 0x100
} yescrypt_init_shared_flags_t;
/**
* Possible values for the flags argument of yescrypt_kdf(),
* yescrypt_gensalt_r(), yescrypt_gensalt(). These may be OR'ed together,
* except that YESCRYPT_WORM and YESCRYPT_RW are mutually exclusive.
* Please refer to the description of yescrypt_kdf() below for the meaning of
* these flags.
*/
typedef enum {
/* public */
YESCRYPT_WORM = 0,
YESCRYPT_RW = 1,
YESCRYPT_PARALLEL_SMIX = 2,
YESCRYPT_PWXFORM = 4,
/* private */
__YESCRYPT_INIT_SHARED_1 = 0x10000,
__YESCRYPT_INIT_SHARED_2 = 0x20000,
__YESCRYPT_INIT_SHARED = 0x30000
} yescrypt_flags_t;
#define YESCRYPT_KNOWN_FLAGS \
(YESCRYPT_RW | YESCRYPT_PARALLEL_SMIX | YESCRYPT_PWXFORM | \
__YESCRYPT_INIT_SHARED)
/**
* yescrypt_init_shared(shared, param, paramlen, N, r, p, flags, mask,
* buf, buflen):
* Optionally allocate memory for and initialize the shared (ROM) data
* structure. The parameters N, r, and p must satisfy the same conditions as
* with crypto_scrypt(). param and paramlen specify a local parameter with
* which the ROM is seeded. If buf is not NULL, then it is used to return
* buflen bytes of message digest for the initialized ROM (the caller may use
* this to verify that the ROM has been computed in the same way that it was on
* a previous run).
*
* Return 0 on success; or -1 on error.
*
* If bit YESCRYPT_SHARED_PREALLOCATED in flags is set, then memory for the
* ROM is assumed to have been preallocated by the caller, with
* shared->shared1.aligned being the start address of the ROM and
* shared->shared1.aligned_size being its size (which must be consistent with
* N, r, and p). This may be used e.g. when the ROM is to be placed in a SysV
* shared memory segment allocated by the caller.
*
* mask controls the frequency of ROM accesses by yescrypt_kdf(). Normally it
* should be set to 1, to interleave RAM and ROM accesses, which works well
* when both regions reside in the machine's RAM anyway. Other values may be
* used e.g. when the ROM is memory-mapped from a disk file. Recommended mask
* values are powers of 2 minus 1 or minus 2. Here's the effect of some mask
* values:
* mask value ROM accesses in SMix 1st loop ROM accesses in SMix 2nd loop
* 0 0 1/2
* 1 1/2 1/2
* 2 0 1/4
* 3 1/4 1/4
* 6 0 1/8
* 7 1/8 1/8
* 14 0 1/16
* 15 1/16 1/16
* 1022 0 1/1024
* 1023 1/1024 1/1024
*
* Actual computation of the ROM contents may be avoided, if you don't intend
* to use a ROM but need a dummy shared structure, by calling this function
* with NULL, 0, 0, 0, 0, YESCRYPT_SHARED_DEFAULTS, 0, NULL, 0 for the
* arguments starting with param and on.
*
* MT-safe as long as shared is local to the thread.
*/
extern int yescrypt_init_shared(yescrypt_shared_t * __shared,
const uint8_t * __param, size_t __paramlen,
uint64_t __N, uint32_t __r, uint32_t __p,
yescrypt_init_shared_flags_t __flags, uint32_t __mask,
uint8_t * __buf, size_t __buflen);
/**
* yescrypt_free_shared(shared):
* Free memory that had been allocated with yescrypt_init_shared().
*
* Return 0 on success; or -1 on error.
*
* MT-safe as long as shared is local to the thread.
*/
extern int yescrypt_free_shared(yescrypt_shared_t * __shared);
/**
* yescrypt_init_local(local):
* Initialize the thread-local (RAM) data structure. Actual memory allocation
* is currently fully postponed until a call to yescrypt_kdf() or yescrypt_r().
*
* Return 0 on success; or -1 on error.
*
* MT-safe as long as local is local to the thread.
*/
extern int yescrypt_init_local(yescrypt_local_t * __local);
/**
* yescrypt_free_local(local):
* Free memory that may have been allocated for an initialized thread-local
* (RAM) data structure.
*
* Return 0 on success; or -1 on error.
*
* MT-safe as long as local is local to the thread.
*/
extern int yescrypt_free_local(yescrypt_local_t * __local);
/**
* yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen,
* N, r, p, t, flags, buf, buflen):
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
* p, buflen), or a revision of scrypt as requested by flags and shared, and
* write the result into buf. The parameters N, r, p, and buflen must satisfy
* the same conditions as with crypto_scrypt(). t controls computation time
* while not affecting peak memory usage. shared and flags may request
* special modes as described below. local is the thread-local data
* structure, allowing to preserve and reuse a memory allocation across calls,
* thereby reducing its overhead.
*
* Return 0 on success; or -1 on error.
*
* t controls computation time. t = 0 is optimal in terms of achieving the
* highest area-time for ASIC attackers. Thus, higher computation time, if
* affordable, is best achieved by increasing N rather than by increasing t.
* However, if the higher memory usage (which goes along with higher N) is not
* affordable, or if fine-tuning of the time is needed (recall that N must be a
* power of 2), then t = 1 or above may be used to increase time while staying
* at the same peak memory usage. t = 1 increases the time by 25% and
* decreases the normalized area-time to 96% of optimal. (Of course, in
* absolute terms the area-time increases with higher t. It's just that it
* would increase slightly more with higher N*r rather than with higher t.)
* t = 2 increases the time by another 20% and decreases the normalized
* area-time to 89% of optimal. Thus, these two values are reasonable to use
* for fine-tuning. Values of t higher than 2 result in further increase in
* time while reducing the efficiency much further (e.g., down to around 50% of
* optimal for t = 5, which runs 3 to 4 times slower than t = 0, with exact
* numbers varying by the flags settings).
*
* Classic scrypt is available by setting t = 0 and flags to YESCRYPT_WORM and
* passing a dummy shared structure (see the description of
* yescrypt_init_shared() above for how to produce one). In this mode, the
* thread-local memory region (RAM) is first sequentially written to and then
* randomly read from. This algorithm is friendly towards time-memory
* tradeoffs (TMTO), available both to defenders (albeit not in this
* implementation) and to attackers.
*
* Setting YESCRYPT_RW adds extra random reads and writes to the thread-local
* memory region (RAM), which makes TMTO a lot less efficient. This may be
* used to slow down the kinds of attackers who would otherwise benefit from
* classic scrypt's efficient TMTO. Since classic scrypt's TMTO allows not
* only for the tradeoff, but also for a decrease of attacker's area-time (by
* up to a constant factor), setting YESCRYPT_RW substantially increases the
* cost of attacks in area-time terms as well. Yet another benefit of it is
* that optimal area-time is reached at an earlier time than with classic
* scrypt, and t = 0 actually corresponds to this earlier completion time,
* resulting in quicker hash computations (and thus in higher request rate
* capacity). Due to these properties, YESCRYPT_RW should almost always be
* set, except when compatibility with classic scrypt or TMTO-friendliness are
* desired.
*
* YESCRYPT_PARALLEL_SMIX moves parallelism that is present with p > 1 to a
* lower level as compared to where it is in classic scrypt. This reduces
* flexibility for efficient computation (for both attackers and defenders) by
* requiring that, short of resorting to TMTO, the full amount of memory be
* allocated as needed for the specified p, regardless of whether that
* parallelism is actually being fully made use of or not. (For comparison, a
* single instance of classic scrypt may be computed in less memory without any
* CPU time overhead, but in more real time, by not making full use of the
* parallelism.) This may be desirable when the defender has enough memory
* with sufficiently low latency and high bandwidth for efficient full parallel
* execution, yet the required memory size is high enough that some likely
* attackers might end up being forced to choose between using higher latency
* memory than they could use otherwise (waiting for data longer) or using TMTO
* (waiting for data more times per one hash computation). The area-time cost
* for other kinds of attackers (who would use the same memory type and TMTO
* factor or no TMTO either way) remains roughly the same, given the same
* running time for the defender. In the TMTO-friendly YESCRYPT_WORM mode, as
* long as the defender has enough memory that is just as fast as the smaller
* per-thread regions would be, doesn't expect to ever need greater
* flexibility (except possibly via TMTO), and doesn't need backwards
* compatibility with classic scrypt, there are no other serious drawbacks to
* this setting. In the YESCRYPT_RW mode, which is meant to discourage TMTO,
* this new approach to parallelization makes TMTO less inefficient. (This is
* an unfortunate side-effect of avoiding some random writes, as we have to in
* order to allow for parallel threads to access a common memory region without
* synchronization overhead.) Thus, in this mode this setting poses an extra
* tradeoff of its own (higher area-time cost for a subset of attackers vs.
* better TMTO resistance). Setting YESCRYPT_PARALLEL_SMIX also changes the
* way the running time is to be controlled from N*r*p (for classic scrypt) to
* N*r (in this modification). All of this applies only when p > 1. For
* p = 1, this setting is a no-op.
*
* Passing a real shared structure, with ROM contents previously computed by
* yescrypt_init_shared(), enables the use of ROM and requires YESCRYPT_RW for
* the thread-local RAM region. In order to allow for initialization of the
* ROM to be split into a separate program, the shared->shared1.aligned and
* shared->shared1.aligned_size fields may be set by the caller of
* yescrypt_kdf() manually rather than with yescrypt_init_shared().
*
* local must be initialized with yescrypt_init_local().
*
* MT-safe as long as local and buf are local to the thread.
*/
extern int yescrypt_kdf(const yescrypt_shared_t * __shared,
yescrypt_local_t * __local,
const uint8_t * __passwd, size_t __passwdlen,
const uint8_t * __salt, size_t __saltlen,
uint64_t __N, uint32_t __r, uint32_t __p, uint32_t __t,
yescrypt_flags_t __flags,
uint8_t * __buf, size_t __buflen);
/**
* yescrypt_r(shared, local, passwd, passwdlen, setting, buf, buflen):
* Compute and encode an scrypt or enhanced scrypt hash of passwd given the
* parameters and salt value encoded in setting. If the shared structure is
* not dummy, a ROM is used and YESCRYPT_RW is required. Otherwise, whether to
* use the YESCRYPT_WORM (classic scrypt) or YESCRYPT_RW (time-memory tradeoff
* discouraging modification) is determined by the setting string. shared and
* local must be initialized as described above for yescrypt_kdf(). buf must
* be large enough (as indicated by buflen) to hold the encoded hash string.
*
* Return the encoded hash string on success; or NULL on error.
*
* MT-safe as long as local and buf are local to the thread.
*/
extern uint8_t * yescrypt_r(const yescrypt_shared_t * __shared,
yescrypt_local_t * __local,
const uint8_t * __passwd, size_t __passwdlen,
const uint8_t * __setting,
uint8_t * __buf, size_t __buflen);
/**
* yescrypt(passwd, setting):
* Compute and encode an scrypt or enhanced scrypt hash of passwd given the
* parameters and salt value encoded in setting. Whether to use the
* YESCRYPT_WORM (classic scrypt) or YESCRYPT_RW (time-memory tradeoff
* discouraging modification) is determined by the setting string.
*
* Return the encoded hash string on success; or NULL on error.
*
* This is a crypt(3)-like interface, which is simpler to use than
* yescrypt_r(), but it is not MT-safe, it does not allow for the use of a ROM,
* and it is slower than yescrypt_r() for repeated calls because it allocates
* and frees memory on each call.
*
* MT-unsafe.
*/
extern uint8_t * yescrypt(const uint8_t * __passwd, const uint8_t * __setting);
/**
* yescrypt_gensalt_r(N_log2, r, p, flags, src, srclen, buf, buflen):
* Generate a setting string for use with yescrypt_r() and yescrypt() by
* encoding into it the parameters N_log2 (which is to be set to base 2
* logarithm of the desired value for N), r, p, flags, and a salt given by src
* (of srclen bytes). buf must be large enough (as indicated by buflen) to
* hold the setting string.
*
* Return the setting string on success; or NULL on error.
*
* MT-safe as long as buf is local to the thread.
*/
extern uint8_t * yescrypt_gensalt_r(
uint32_t __N_log2, uint32_t __r, uint32_t __p,
yescrypt_flags_t __flags,
const uint8_t * __src, size_t __srclen,
uint8_t * __buf, size_t __buflen);
/**
* yescrypt_gensalt(N_log2, r, p, flags, src, srclen):
* Generate a setting string for use with yescrypt_r() and yescrypt(). This
* function is the same as yescrypt_gensalt_r() except that it uses a static
* buffer and thus is not MT-safe.
*
* Return the setting string on success; or NULL on error.
*
* MT-unsafe.
*/
extern uint8_t * yescrypt_gensalt(
uint32_t __N_log2, uint32_t __r, uint32_t __p,
yescrypt_flags_t __flags,
const uint8_t * __src, size_t __srclen);
#ifdef __cplusplus
}
#endif
#endif /* !_YESCRYPT_H_ */
+374
View File
@@ -0,0 +1,374 @@
/*-
* Copyright 2013,2014 Alexander Peslyak
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* 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.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "yescrypt.h"
#define BYTES2CHARS(bytes) \
((((bytes) * 8) + 5) / 6)
#define HASH_SIZE 32 /* bytes */
#define HASH_LEN BYTES2CHARS(HASH_SIZE) /* base-64 chars */
#define YESCRYPT_FLAGS (YESCRYPT_RW | YESCRYPT_PWXFORM)
static const char * const itoa64 =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static uint8_t * encode64_uint32(uint8_t * dst, size_t dstlen,
uint32_t src, uint32_t srcbits)
{
uint32_t bit;
for (bit = 0; bit < srcbits; bit += 6) {
if (dstlen < 1)
return NULL;
*dst++ = itoa64[src & 0x3f];
dstlen--;
src >>= 6;
}
return dst;
}
static uint8_t * encode64(uint8_t * dst, size_t dstlen,
const uint8_t * src, size_t srclen)
{
size_t i;
for (i = 0; i < srclen; ) {
uint8_t * dnext;
uint32_t value = 0, bits = 0;
do {
value |= (uint32_t)src[i++] << bits;
bits += 8;
} while (bits < 24 && i < srclen);
dnext = encode64_uint32(dst, dstlen, value, bits);
if (!dnext)
return NULL;
dstlen -= dnext - dst;
dst = dnext;
}
return dst;
}
static int decode64_one(uint32_t * dst, uint8_t src)
{
const char * ptr = strchr(itoa64, src);
if (ptr) {
*dst = ptr - itoa64;
return 0;
}
*dst = 0;
return -1;
}
static const uint8_t * decode64_uint32(uint32_t * dst, uint32_t dstbits,
const uint8_t * src)
{
uint32_t bit;
uint32_t value;
value = 0;
for (bit = 0; bit < dstbits; bit += 6) {
uint32_t one;
if (decode64_one(&one, *src)) {
*dst = 0;
return NULL;
}
src++;
value |= one << bit;
}
*dst = value;
return src;
}
uint8_t *
yescrypt_r(const yescrypt_shared_t * shared, yescrypt_local_t * local,
const uint8_t * passwd, size_t passwdlen,
const uint8_t * setting,
uint8_t * buf, size_t buflen)
{
uint8_t hash[HASH_SIZE];
const uint8_t * src, * salt;
uint8_t * dst;
size_t prefixlen, saltlen, need;
uint8_t version;
uint64_t N;
uint32_t r, p;
yescrypt_flags_t flags = YESCRYPT_WORM;
printf("pass1 ...");
fflush(stdout);
if (setting[0] != '$' || setting[1] != '7')
{printf("died$7 ...");
fflush(stdout);
return NULL;
}
printf("died80 ...");
fflush(stdout);
src = setting + 2;
printf("hello '%p'\n", (char *)src);
fflush(stdout);
switch ((version = *src)) {
case '$':
printf("died2 ...");
fflush(stdout);
break;
case 'X':
src++;
flags = YESCRYPT_RW;
printf("died3 ...");
fflush(stdout);
break;
default:
{printf("died4 ...");
fflush(stdout);
return NULL;
}
}
printf("pass2 ...");
fflush(stdout);
if (*src != '$') {
uint32_t decoded_flags;
if (decode64_one(&decoded_flags, *src))
{printf("died5 ...");
fflush(stdout);
return NULL;
}
flags = decoded_flags;
if (*++src != '$')
{printf("died6 ...");
fflush(stdout);
return NULL;
}
}
src++;
{
uint32_t N_log2;
if (decode64_one(&N_log2, *src))
{printf("died7 ...");
return NULL;
}
src++;
N = (uint64_t)1 << N_log2;
}
src = decode64_uint32(&r, 30, src);
if (!src)
{printf("died6 ...");
return NULL;
}
src = decode64_uint32(&p, 30, src);
if (!src)
{printf("died7 ...");
return NULL;
}
prefixlen = src - setting;
salt = src;
src = (uint8_t *)strrchr((char *)salt, '$');
if (src)
saltlen = src - salt;
else
saltlen = strlen((char *)salt);
need = prefixlen + saltlen + 1 + HASH_LEN + 1;
if (need > buflen || need < saltlen)
{printf("'%d %d %d'",need,buflen, saltlen);fflush(stdout);
printf("died8killbuf ...");
fflush(stdout);
return NULL;
}
printf("pass3 ...");
fflush(stdout);
if (yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen,
N, r, p, 0, flags, hash, sizeof(hash)))
{printf("died10 ...");
fflush(stdout);
return NULL;
}
dst = buf;
memcpy(dst, setting, prefixlen + saltlen);
dst += prefixlen + saltlen;
*dst++ = '$';
dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash));
/* Could zeroize hash[] here, but yescrypt_kdf() doesn't zeroize its
* memory allocations yet anyway. */
if (!dst || dst >= buf + buflen) /* Can't happen */
{printf("died11 ...");
return NULL;
}
*dst = 0; /* NUL termination */
printf("died12 ...");
fflush(stdout);
return buf;
}
uint8_t *
yescrypt(const uint8_t * passwd, const uint8_t * setting)
{
static uint8_t buf[4 + 1 + 5 + 5 + BYTES2CHARS(32) + 1 + HASH_LEN + 1];
yescrypt_shared_t shared;
yescrypt_local_t local;
uint8_t * retval;
if (yescrypt_init_shared(&shared, NULL, 0,
0, 0, 0, YESCRYPT_SHARED_DEFAULTS, 0, NULL, 0))
return NULL;
if (yescrypt_init_local(&local)) {
yescrypt_free_shared(&shared);
return NULL;
}
retval = yescrypt_r(&shared, &local,
passwd, 80, setting, buf, sizeof(buf));
// printf("hashse='%s'\n", (char *)retval);
if (yescrypt_free_local(&local)) {
yescrypt_free_shared(&shared);
return NULL;
}
if (yescrypt_free_shared(&shared))
return NULL;
return retval;
}
uint8_t *
yescrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p,
yescrypt_flags_t flags,
const uint8_t * src, size_t srclen,
uint8_t * buf, size_t buflen)
{
uint8_t * dst;
size_t prefixlen = 3 + 1 + 5 + 5;
size_t saltlen = BYTES2CHARS(srclen);
size_t need;
if (p == 1)
flags &= ~YESCRYPT_PARALLEL_SMIX;
if (flags) {
if (flags & ~0x3f)
return NULL;
prefixlen++;
if (flags != YESCRYPT_RW)
prefixlen++;
}
need = prefixlen + saltlen + 1;
if (need > buflen || need < saltlen || saltlen < srclen)
return NULL;
if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30)))
return NULL;
dst = buf;
*dst++ = '$';
*dst++ = '7';
if (flags) {
*dst++ = 'X'; /* eXperimental, subject to change */
if (flags != YESCRYPT_RW)
*dst++ = itoa64[flags];
}
*dst++ = '$';
*dst++ = itoa64[N_log2];
dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
if (!dst) /* Can't happen */
return NULL;
dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
if (!dst) /* Can't happen */
return NULL;
dst = encode64(dst, buflen - (dst - buf), src, srclen);
if (!dst || dst >= buf + buflen) /* Can't happen */
return NULL;
*dst = 0; /* NUL termination */
return buf;
}
uint8_t *
yescrypt_gensalt(uint32_t N_log2, uint32_t r, uint32_t p,
yescrypt_flags_t flags,
const uint8_t * src, size_t srclen)
{
static uint8_t buf[4 + 1 + 5 + 5 + BYTES2CHARS(32) + 1];
return yescrypt_gensalt_r(N_log2, r, p, flags, src, srclen,
buf, sizeof(buf));
}
static int
yescrypt_bsty(const uint8_t * passwd, size_t passwdlen,
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
uint8_t * buf, size_t buflen)
{
static __thread int initialized = 0;
static __thread yescrypt_shared_t shared;
static __thread yescrypt_local_t local;
int retval;
if (!initialized) {
/* "shared" could in fact be shared, but it's simpler to keep it private
* along with "local". It's dummy and tiny anyway. */
if (yescrypt_init_shared(&shared, NULL, 0,
0, 0, 0, YESCRYPT_SHARED_DEFAULTS, 0, NULL, 0))
return -1;
if (yescrypt_init_local(&local)) {
yescrypt_free_shared(&shared);
return -1;
}
initialized = 1;
}
retval = yescrypt_kdf(&shared, &local,
passwd, passwdlen, salt, saltlen, N, r, p, 0, YESCRYPT_FLAGS,
buf, buflen);
#if 0
if (yescrypt_free_local(&local)) {
yescrypt_free_shared(&shared);
return -1;
}
if (yescrypt_free_shared(&shared))
return -1;
initialized = 0;
#endif
return retval;
}
void yescrypt_hash_sp(const char *input, char *output)
{
yescrypt_bsty((const uint8_t *)input, 80, (const uint8_t *) input, 80, 2048, 8, 1, (uint8_t *)output, 32);
}
void yescrypt_hash(const char *input, char *output)
{
yescrypt_hash_sp(input, output);
}
+6 -4
View File
@@ -339,9 +339,9 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), 100));
if (showDebug)
strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf("Fees (in MYR/Kb) smaller than this are considered zero fee for transaction creation (default: %s)",
strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf("Fees (in XMY/Kb) smaller than this are considered zero fee for transaction creation (default: %s)",
FormatMoney(CWallet::minTxFee.GetFeePerK())));
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in MYR/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())));
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in XMY/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())));
strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup"));
strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup"));
strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0));
@@ -388,7 +388,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", 1));
strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf("Limit size of signature cache to <n> entries (default: %u)", 50000));
}
strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf(_("Fees (in MYR/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())));
strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf(_("Fees (in XMY/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())));
strUsage += HelpMessageOpt("-printtoconsole", _("Send trace/debug info to console instead of debug.log file"));
if (showDebug)
{
@@ -408,7 +408,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-blockminsize=<n>", strprintf(_("Set minimum block size in bytes (default: %u)"), 0));
strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
strUsage += HelpMessageOpt("-algo=<algo>", _("Mining algorithm: sha256d, scrypt, groestl, skein, qubit"));
strUsage += HelpMessageOpt("-algo=<algo>", _("Mining algorithm: sha256d, scrypt, groestl, skein, qubit, yescrypt"));
strUsage += HelpMessageGroup(_("RPC server options:"));
strUsage += HelpMessageOpt("-server", _("Accept command line and JSON-RPC commands"));
@@ -742,6 +742,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
miningAlgo = ALGO_SKEIN;
else if (strAlgo == "q2c" || strAlgo == "qubit")
miningAlgo = ALGO_QUBIT;
else if (strAlgo == "yescrypt")
miningAlgo = ALGO_YESCRYPT;
else
miningAlgo = ALGO_SHA256D;
+60 -7
View File
@@ -84,6 +84,7 @@ void EraseOrphansFor(NodeId peer);
* in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards.
*/
static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams);
static bool IsAlgoSwitch1Active(const CBlockIndex* pstart, const Consensus::Params& consensusParams);
static void CheckBlockIndex();
/** Constant stuff for coinbase transactions we create: */
@@ -2248,8 +2249,9 @@ void static UpdateTip(CBlockIndex *pindexNew) {
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
LogPrintf("%s: new best=%s height=%d algo=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__,
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->GetAlgo(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
LogPrintf("%s: new best=%s height=%d algo=%d (%s) log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__,
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->GetAlgo(), GetAlgoName(chainActive.Tip()->GetAlgo()),
log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
@@ -2934,7 +2936,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
return state.DoS(100, error("%s : auxpow blocks are not allowed at height %d, parameters effective from %d",
__func__, pindexPrev->nHeight + 1, consensusParams.nStartAuxPow),
REJECT_INVALID, "early-auxpow-block");
// Check proof of work
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams, algo))
return state.DoS(100, error("%s: incorrect proof of work at height %d", __func__, nHeight),
@@ -2945,6 +2947,32 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
return state.Invalid(error("%s: block's timestamp is too early", __func__),
REJECT_INVALID, "time-too-old");
// Check for algo switch 1
// Active when:
// previous YESCRYPT block was mined or;
// mining majority and fork height reached
bool bAlgoSwitch1 = false;
if (nHeight >= consensusParams.nFork1MinBlock)
{
bAlgoSwitch1 = IsAlgoSwitch1Active(pindexPrev, consensusParams);
if (!bAlgoSwitch1)
bAlgoSwitch1 =
(block.nVersion > 3) &&
IsSuperMajority(4, pindexPrev, consensusParams.nMajorityEnableAlgoSwitch1, consensusParams);
}
if (bAlgoSwitch1)
{
if (algo == ALGO_QUBIT)
return state.Invalid(error("%s: invalid QUBIT block", __func__),
REJECT_INVALID, "invalid-algo");
}
else
{
if (algo == ALGO_YESCRYPT)
return state.Invalid(error("%s: invalid YESCRYPT block", __func__),
REJECT_INVALID, "invalid-algo");
}
if(fCheckpointsEnabled)
{
// Check that the block chain matches the known block chain up to a checkpoint
@@ -3045,18 +3073,32 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
int nAlgo = block.GetAlgo();
int nAlgoCount = 1;
CBlockIndex* piPrev = pindexPrev;
while (piPrev!=NULL && (nAlgoCount <= chainparams.GetConsensus().nBlockSequentialAlgoMaxCount1))
// Maximum sequence count allowed
int nMaxSeqCount;
if ( (nHeight > chainparams.GetConsensus().nFork1MinBlock) &&
(block.nVersion > 3) &&
IsSuperMajority(4, pindexPrev, chainparams.GetConsensus().nMajorityEnableAlgoSwitch1, chainparams.GetConsensus()) )
nMaxSeqCount = chainparams.GetConsensus().nBlockSequentialAlgoMaxCount3;
else
if (nHeight > chainparams.GetConsensus().nBlockSequentialAlgoRuleStart2)
nMaxSeqCount = chainparams.GetConsensus().nBlockSequentialAlgoMaxCount2;
else
nMaxSeqCount = chainparams.GetConsensus().nBlockSequentialAlgoMaxCount1;
while (piPrev!=NULL && (nAlgoCount <= nMaxSeqCount))
{
if (piPrev->GetAlgo() != nAlgo)
break;
nAlgoCount++;
piPrev = piPrev->pprev;
}
if ((nHeight > chainparams.GetConsensus().nBlockSequentialAlgoRuleStart2) && (nAlgoCount > chainparams.GetConsensus().nBlockSequentialAlgoMaxCount2))
if(fDebug)
{
return state.DoS(100, error("%s: too many blocks from same algo", __func__),REJECT_INVALID, "algo-toomany");
LogPrintf("SequentialAlgoRule DEBUG: nHeight: %d, nAlgoCount: %d, nMaxSeqCount: %d\n", nHeight, nAlgoCount, nMaxSeqCount);
}
else if (nAlgoCount > chainparams.GetConsensus().nBlockSequentialAlgoMaxCount1)
if (nAlgoCount > nMaxSeqCount)
{
return state.DoS(100, error("%s: too many blocks from same algo", __func__),REJECT_INVALID, "algo-toomany");
}
@@ -3151,6 +3193,17 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
return (nFound >= nRequired);
}
static bool IsAlgoSwitch1Active(const CBlockIndex* pstart, const Consensus::Params& consensusParams)
{
bool algoFound = false;
for (int i = 0; i < consensusParams.nAlgoSwitch1EnableWindow && !algoFound && pstart != NULL; i++)
{
if (pstart->GetAlgo() == ALGO_YESCRYPT)
algoFound = true;
pstart = pstart->pprev;
}
return (algoFound);
}
bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp)
{
+1 -1
View File
@@ -48,7 +48,7 @@ class CValidationState;
struct CNodeStateStats;
/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 200000;
static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0;
/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000;
+4
View File
@@ -814,6 +814,10 @@ void static ThreadMiner(CWallet *pwallet)
LogPrintf("MyriadMiner[Qubit] miner started\n");
GenericMiner(pwallet, ALGO_QUBIT);
break;
case ALGO_YESCRYPT:
LogPrintf("MyriadMiner[Yescrypt] miner started\n");
GenericMiner(pwallet, ALGO_YESCRYPT); // could be replaced with a decent yescrypt miner in the style of scrypt, but how much need?
break;
}
}
catch (boost::thread_interrupted)
+2 -2
View File
@@ -122,7 +122,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
}
}
}
int64_t nActualTimespan;
if (pindexLast->nHeight >= params.nBlockTimeWarpPreventStart3)
@@ -409,7 +409,7 @@ arith_uint256 GetGeometricMeanPrevWork(const CBlockIndex& block)
CBigNum bnBlockWork = CBigNum(ArithToUint256(nBlockWork));
int nAlgo = block.GetAlgo();
for (int algo = 0; algo < NUM_ALGOS; algo++)
for (int algo = 0; algo < NUM_ALGOS_IMPL; algo++)
{
if (algo != nAlgo)
{
+11
View File
@@ -10,6 +10,7 @@
#include "crypto/hashqubit.h"
#include "crypto/hashskein.h"
#include "crypto/scrypt.h"
#include "crypto/yescrypt.h"
#include "hash.h"
#include "utilstrencodings.h"
@@ -36,6 +37,12 @@ uint256 CPureBlockHeader::GetPoWHash(int algo) const
return HashSkein(BEGIN(nVersion), END(nNonce));
case ALGO_QUBIT:
return HashQubit(BEGIN(nVersion), END(nNonce));
case ALGO_YESCRYPT:
{
uint256 thash;
yescrypt_hash(BEGIN(nVersion), BEGIN(thash));
return thash;
}
}
return GetHash();
}
@@ -54,6 +61,8 @@ int GetAlgo(int nVersion)
return ALGO_SKEIN;
case BLOCK_VERSION_QUBIT:
return ALGO_QUBIT;
case BLOCK_VERSION_YESCRYPT:
return ALGO_YESCRYPT;
}
return ALGO_SHA256D;
}
@@ -72,6 +81,8 @@ std::string GetAlgoName(int Algo)
return std::string("skein");
case ALGO_QUBIT:
return std::string("qubit");
case ALGO_YESCRYPT:
return std::string("yescrypt");
}
return std::string("unknown");
}
+14 -7
View File
@@ -10,17 +10,20 @@
#include "uint256.h"
enum {
ALGO_SHA256D = 0,
ALGO_SCRYPT = 1,
ALGO_GROESTL = 2,
ALGO_SKEIN = 3,
ALGO_QUBIT = 4,
NUM_ALGOS };
ALGO_SHA256D = 0,
ALGO_SCRYPT = 1,
ALGO_GROESTL = 2,
ALGO_SKEIN = 3,
ALGO_QUBIT = 4,
ALGO_YESCRYPT = 5,
NUM_ALGOS_IMPL };
const int NUM_ALGOS = 5;
enum
{
// primary version
BLOCK_VERSION_DEFAULT = 2, // change this in later release for BIP66 (3) and BIP65 (4) softforks
BLOCK_VERSION_DEFAULT = 4, // change this in later release for BIP66 (3) and BIP65 (4) softforks
// algo
BLOCK_VERSION_ALGO = (7 << 9),
@@ -28,6 +31,7 @@ enum
BLOCK_VERSION_GROESTL = (2 << 9),
BLOCK_VERSION_SKEIN = (3 << 9),
BLOCK_VERSION_QUBIT = (4 << 9),
BLOCK_VERSION_YESCRYPT = (5 << 9),
};
int GetAlgo(int nVersion);
@@ -107,6 +111,9 @@ public:
case ALGO_QUBIT:
nVersion |= BLOCK_VERSION_QUBIT;
break;
case ALGO_YESCRYPT:
nVersion |= BLOCK_VERSION_YESCRYPT;
break;
default:
break;
}
+7 -7
View File
@@ -45,11 +45,11 @@ QString BitcoinUnits::name(int unit)
{
switch(unit)
{
case MBTC: return QString("MMYR");
case kBTC: return QString("kMYR");
case BTC: return QString("MYR");
case mBTC: return QString("mMYR");
case uBTC: return QString::fromUtf8("μMYR");
case MBTC: return QString("MXMY");
case kBTC: return QString("kXMY");
case BTC: return QString("XMY");
case mBTC: return QString("mXMY");
case uBTC: return QString::fromUtf8("μXMY");
default: return QString("???");
}
}
@@ -61,8 +61,8 @@ QString BitcoinUnits::description(int unit)
case MBTC: return QString("Mega-Myriad (1,000,000)");
case kBTC: return QString("Kilo-Myriad (1,000)");
case BTC: return QString("Myriad");
case mBTC: return QString("Milli-Bitcoins (1 / 1" THIN_SP_UTF8 "000)");
case uBTC: return QString("Micro-Bitcoins (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
case mBTC: return QString("Milli-Myriad (1 / 1" THIN_SP_UTF8 "000)");
case uBTC: return QString("Micro-Myriad (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
default: return QString("???");
}
}
+8 -8
View File
@@ -126,7 +126,7 @@
<string>Unconfirmed transactions to watch-only addresses</string>
</property>
<property name="text">
<string notr="true">0.000 000 00 MYR</string>
<string notr="true">0.000 000 00 XMY</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -151,7 +151,7 @@
<string>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</string>
</property>
<property name="text">
<string notr="true">0.000 000 00 MYR</string>
<string notr="true">0.000 000 00 XMY</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -176,7 +176,7 @@
<string>Mined balance in watch-only addresses that has not yet matured</string>
</property>
<property name="text">
<string notr="true">0.000 000 00 MYR</string>
<string notr="true">0.000 000 00 XMY</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -234,7 +234,7 @@
<string>Mined balance that has not yet matured</string>
</property>
<property name="text">
<string notr="true">0.000 000 00 MYR</string>
<string notr="true">0.000 000 00 XMY</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -279,7 +279,7 @@
<string>Your current total balance</string>
</property>
<property name="text">
<string notr="true">0.000 000 00 MYR</string>
<string notr="true">0.000 000 00 XMY</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -304,7 +304,7 @@
<string>Current total balance in watch-only addresses</string>
</property>
<property name="text">
<string notr="true">0.000 000 00 MYR</string>
<string notr="true">0.000 000 00 XMY</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -346,7 +346,7 @@
<string>Your current spendable balance</string>
</property>
<property name="text">
<string notr="true">0.000 000 00 MYR</string>
<string notr="true">0.000 000 00 XMY</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -371,7 +371,7 @@
<string>Your current balance in watch-only addresses</string>
</property>
<property name="text">
<string notr="true">0.000 000 00 MYR</string>
<string notr="true">0.000 000 00 XMY</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+5 -5
View File
@@ -324,7 +324,7 @@
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="text">
<string notr="true">0.00 MYR</string>
<string notr="true">0.00 XMY</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
@@ -404,7 +404,7 @@
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="text">
<string notr="true">0.00 MYR</string>
<string notr="true">0.00 XMY</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
@@ -484,7 +484,7 @@
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="text">
<string notr="true">0.00 MYR</string>
<string notr="true">0.00 XMY</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
@@ -513,7 +513,7 @@
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="text">
<string notr="true">0.00 MYR</string>
<string notr="true">0.00 XMY</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
@@ -1352,7 +1352,7 @@
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string notr="true">123.456 MYR</string>
<string notr="true">123.456 XMY</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+19 -2
View File
@@ -211,7 +211,7 @@ Value getrawmempool(const Array& params, bool fHelp)
"{ (json object)\n"
" \"transactionid\" : { (json object)\n"
" \"size\" : n, (numeric) transaction size in bytes\n"
" \"fee\" : n, (numeric) transaction fee in MYR\n"
" \"fee\" : n, (numeric) transaction fee in XMY\n"
" \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
" \"height\" : n, (numeric) block height when transaction entered pool\n"
" \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
@@ -421,7 +421,7 @@ Value gettxout(const Array& params, bool fHelp)
"{\n"
" \"bestblock\" : \"hash\", (string) the block hash\n"
" \"confirmations\" : n, (numeric) The number of confirmations\n"
" \"value\" : x.xxx, (numeric) The transaction value in MYR\n"
" \"value\" : x.xxx, (numeric) The transaction value in XMY\n"
" \"scriptPubKey\" : { (json object)\n"
" \"asm\" : \"code\", (string) \n"
" \"hex\" : \"hex\", (string) \n"
@@ -545,6 +545,21 @@ Object SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, c
return rv;
}
Object AlgoSwitch1ForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
{
Object rv;
rv.push_back(Pair("id", name));
rv.push_back(Pair("version", version));
Object bh;
int nHeight = (int)chainActive.Height();
bh.push_back(Pair("status", nHeight >= consensusParams.nFork1MinBlock));
bh.push_back(Pair("height", nHeight));
bh.push_back(Pair("height-active", consensusParams.nFork1MinBlock));
rv.push_back(Pair("enforce-condition-blockheight", bh));
rv.push_back(Pair("enforce-condition-majority", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnableAlgoSwitch1, consensusParams)));
return rv;
}
Value getblockchaininfo(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -597,6 +612,7 @@ Value getblockchaininfo(const Array& params, bool fHelp)
obj.push_back(Pair("difficulty_groestl", (double)GetDifficulty(NULL, ALGO_GROESTL)));
obj.push_back(Pair("difficulty_skein", (double)GetDifficulty(NULL, ALGO_SKEIN)));
obj.push_back(Pair("difficulty_qubit", (double)GetDifficulty(NULL, ALGO_QUBIT)));
obj.push_back(Pair("difficulty_yescrypt", (double)GetDifficulty(NULL, ALGO_YESCRYPT)));
obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
obj.push_back(Pair("pruned", fPruneMode));
@@ -607,6 +623,7 @@ Value getblockchaininfo(const Array& params, bool fHelp)
// softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
softforks.push_back(AlgoSwitch1ForkDesc("algoswitch1", 4, tip, consensusParams));
obj.push_back(Pair("softforks", softforks));
if (fPruneMode)
+1
View File
@@ -267,6 +267,7 @@ Value getmininginfo(const Array& params, bool fHelp)
obj.push_back(Pair("difficulty_groestl", (double)GetDifficulty(NULL, ALGO_GROESTL)));
obj.push_back(Pair("difficulty_skein", (double)GetDifficulty(NULL, ALGO_SKEIN)));
obj.push_back(Pair("difficulty_qubit", (double)GetDifficulty(NULL, ALGO_QUBIT)));
obj.push_back(Pair("difficulty_yescrypt",(double)GetDifficulty(NULL, ALGO_YESCRYPT)));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
// obj.push_back(Pair("networkhashps", getnetworkhashps(params, false)));
+4 -2
View File
@@ -67,8 +67,8 @@ Value getinfo(const Array& params, bool fHelp)
" \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
" \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
" \"paytxfee\": x.xxxx, (numeric) the transaction fee set in MYR/kb\n"
" \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in MYR/kb\n"
" \"paytxfee\": x.xxxx, (numeric) the transaction fee set in XMY/kb\n"
" \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in XMY/kb\n"
" \"errors\": \"...\" (string) any error messages\n"
"}\n"
"\nExamples:\n"
@@ -106,6 +106,8 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("difficulty_groestl", (double)GetDifficulty(NULL, ALGO_GROESTL)));
obj.push_back(Pair("difficulty_skein", (double)GetDifficulty(NULL, ALGO_SKEIN)));
obj.push_back(Pair("difficulty_qubit", (double)GetDifficulty(NULL, ALGO_QUBIT)));
obj.push_back(Pair("difficulty_yescrypt",(double)GetDifficulty(NULL, ALGO_YESCRYPT)));
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
#ifdef ENABLE_WALLET
if (pwalletMain) {
+1 -1
View File
@@ -389,7 +389,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
" ]\n"
"2. \"addresses\" (string, required) a json object with addresses as keys and amounts as values\n"
" {\n"
" \"address\": x.xxx (numeric, required) The key is the myriad address, the value is the MYR amount\n"
" \"address\": x.xxx (numeric, required) The key is the myriad address, the value is the XMY amount\n"
" ,...\n"
" }\n"
+4 -1
View File
@@ -9,7 +9,7 @@
* network protocol versioning
*/
static const int PROTOCOL_VERSION = 70003;
static const int PROTOCOL_VERSION = 70004;
//! initial proto version, to be increased after version/verack negotiation
static const int INIT_PROTO_VERSION = 209;
@@ -20,6 +20,9 @@ static const int GETHEADERS_VERSION = 31800;
//! AUX-POW on SHA256D and Scrypt algorithim starts with this version
static const int AUX_POW_SHA_SCRYPT_VERSION = 70003;
//! Switch algo Qubit to Yescrypt starts with this version
static const int QUBIT_TO_YESCRYPT_VERSION = 70004;
//! disconnect from peers older than this proto version
static const int MIN_PEER_PROTO_VERSION = AUX_POW_SHA_SCRYPT_VERSION;
+18 -18
View File
@@ -391,7 +391,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
+ HelpRequiringPassphrase() +
"\nArguments:\n"
"1. \"myriadaddress\" (string, required) The myriad address to send to.\n"
"2. \"amount\" (numeric, required) The amount in MYR to send. eg 0.1\n"
"2. \"amount\" (numeric, required) The amount in XMY to send. eg 0.1\n"
"3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
" This is not part of the transaction, just kept in your wallet.\n"
"4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n"
@@ -451,7 +451,7 @@ Value listaddressgroupings(const Array& params, bool fHelp)
" [\n"
" [\n"
" \"myriadaddress\", (string) The myriad address\n"
" amount, (numeric) The amount in MYR\n"
" amount, (numeric) The amount in XMY\n"
" \"account\" (string, optional) The account (DEPRECATED)\n"
" ]\n"
" ,...\n"
@@ -555,7 +555,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
"1. \"myriadaddress\" (string, required) The myriad address for transactions.\n"
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
"\nResult:\n"
"amount (numeric) The total amount in MYR received at this address.\n"
"amount (numeric) The total amount in XMY received at this address.\n"
"\nExamples:\n"
"\nThe amount from transactions with at least 1 confirmation\n"
+ HelpExampleCli("getreceivedbyaddress", "\"MJPyMHUJiQpwM5ZkzKXDo5UPYTNh5yJ9Vf\"") +
@@ -613,7 +613,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
"1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
"\nResult:\n"
"amount (numeric) The total amount in MYR received for this account.\n"
"amount (numeric) The total amount in XMY received for this account.\n"
"\nExamples:\n"
"\nAmount received by the default account with at least 1 confirmation\n"
+ HelpExampleCli("getreceivedbyaccount", "\"\"") +
@@ -706,7 +706,7 @@ Value getbalance(const Array& params, bool fHelp)
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
"3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
"\nResult:\n"
"amount (numeric) The total amount in MYR received for this account.\n"
"amount (numeric) The total amount in XMY received for this account.\n"
"\nExamples:\n"
"\nThe total amount in the wallet\n"
+ HelpExampleCli("getbalance", "") +
@@ -797,9 +797,9 @@ Value movecmd(const Array& params, bool fHelp)
"\nResult:\n"
"true|false (boolean) true if successful.\n"
"\nExamples:\n"
"\nMove 0.01 MYR from the default account to the account named tabby\n"
"\nMove 0.01 XMY from the default account to the account named tabby\n"
+ HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
"\nMove 0.01 MYR timotei to akiko with a comment and funds have 6 confirmations\n"
"\nMove 0.01 XMY timotei to akiko with a comment and funds have 6 confirmations\n"
+ HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
"\nAs a json rpc call\n"
+ HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
@@ -864,7 +864,7 @@ Value sendfrom(const Array& params, bool fHelp)
"\nArguments:\n"
"1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
"2. \"tomyriadaddress\" (string, required) The myriad address to send funds to.\n"
"3. amount (numeric, required) The amount in MYR. (transaction fee is added on top).\n"
"3. amount (numeric, required) The amount in XMY. (transaction fee is added on top).\n"
"4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
"5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
" This is not part of the transaction, just kept in your wallet.\n"
@@ -874,7 +874,7 @@ Value sendfrom(const Array& params, bool fHelp)
"\nResult:\n"
"\"transactionid\" (string) The transaction id.\n"
"\nExamples:\n"
"\nSend 0.01 MYR from the default account to the address, must have at least 1 confirmation\n"
"\nSend 0.01 XMY from the default account to the address, must have at least 1 confirmation\n"
+ HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
"\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
+ HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
@@ -927,7 +927,7 @@ Value sendmany(const Array& params, bool fHelp)
"1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
"2. \"amounts\" (string, required) A json object with addresses and amounts\n"
" {\n"
" \"address\":amount (numeric) The myriad address is the key, the numeric amount in MYR is the value\n"
" \"address\":amount (numeric) The myriad address is the key, the numeric amount in XMY is the value\n"
" ,...\n"
" }\n"
"3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
@@ -1223,7 +1223,7 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
" \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
" \"address\" : \"receivingaddress\", (string) The receiving address\n"
" \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
" \"amount\" : x.xxx, (numeric) The total amount in MYR received by the address\n"
" \"amount\" : x.xxx, (numeric) The total amount in XMY received by the address\n"
" \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
" }\n"
" ,...\n"
@@ -1395,11 +1395,11 @@ Value listtransactions(const Array& params, bool fHelp)
" transaction between accounts, and not associated with an address,\n"
" transaction id or block. 'send' and 'receive' transactions are \n"
" associated with an address, transaction id and block details\n"
" \"amount\": x.xxx, (numeric) The amount in MYR. This is negative for the 'send' category, and for the\n"
" \"amount\": x.xxx, (numeric) The amount in XMY. This is negative for the 'send' category, and for the\n"
" 'move' category for moves outbound. It is positive for the 'receive' category,\n"
" and for the 'move' category for inbound funds.\n"
" \"vout\" : n, (numeric) the vout value\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in MYR. This is negative and only available for the \n"
" \"fee\": x.xxx, (numeric) The amount of the fee in XMY. This is negative and only available for the \n"
" 'send' category of transactions.\n"
" \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
" 'receive' category of transactions.\n"
@@ -1583,10 +1583,10 @@ Value listsinceblock(const Array& params, bool fHelp)
" \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
" \"address\":\"myriadaddress\", (string) The myriad address of the transaction. Not present for move transactions (category = move).\n"
" \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
" \"amount\": x.xxx, (numeric) The amount in MYR. This is negative for the 'send' category, and for the 'move' category for moves \n"
" \"amount\": x.xxx, (numeric) The amount in XMY. This is negative for the 'send' category, and for the 'move' category for moves \n"
" outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
" \"vout\" : n, (numeric) the vout value\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in MYR. This is negative and only available for the 'send' category of transactions.\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in XMY. This is negative and only available for the 'send' category of transactions.\n"
" \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
" \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
" \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
@@ -1669,7 +1669,7 @@ Value gettransaction(const Array& params, bool fHelp)
"2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
"\nResult:\n"
"{\n"
" \"amount\" : x.xxx, (numeric) The transaction amount in MYR\n"
" \"amount\" : x.xxx, (numeric) The transaction amount in XMY\n"
" \"confirmations\" : n, (numeric) The number of confirmations\n"
" \"blockhash\" : \"hash\", (string) The block hash\n"
" \"blockindex\" : xx, (numeric) The block index\n"
@@ -1682,7 +1682,7 @@ Value gettransaction(const Array& params, bool fHelp)
" \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
" \"address\" : \"myriadaddress\", (string) The myriad address involved in the transaction\n"
" \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
" \"amount\" : x.xxx (numeric) The amount in MYR\n"
" \"amount\" : x.xxx (numeric) The amount in XMY\n"
" \"vout\" : n, (numeric) the vout value\n"
" }\n"
" ,...\n"
@@ -2261,7 +2261,7 @@ Value listunspent(const Array& params, bool fHelp)
" \"address\" : \"address\", (string) the myriad address\n"
" \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
" \"scriptPubKey\" : \"key\", (string) the script key\n"
" \"amount\" : x.xxx, (numeric) the transaction amount in MYR\n"
" \"amount\" : x.xxx, (numeric) the transaction amount in XMY\n"
" \"confirmations\" : n (numeric) The number of confirmations\n"
" }\n"
" ,...\n"