diff --git a/.gitignore b/.gitignore index 29a8aeb..ca18306 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ *.o *.a +.deps +.dirstamp stratum/stratum stratum/blocknotify blocknotify/blocknotify @@ -18,3 +20,6 @@ web/serverconfig.php web/assets/ *.rej *.orig +.idea/* +web/yaamp/.idea/ +*.0 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f954618 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: cpp +script: + - (cd blocknotify && make) + - (cd stratum/iniparser && make) + - (cd stratum && make) diff --git a/README.md b/README.md index c91ac23..ab89b65 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ To install the pool you will need: 1. Ubuntu 16.04 VPS 2. Install Script +WARNINGS +- Use at your own risks. + The install Script will install the pool and all dependencies needed. TO INSTALL: diff --git a/rc.local b/rc.local index 7ea3e67..9ecef08 100644 --- a/rc.local +++ b/rc.local @@ -25,8 +25,9 @@ screen -dmS deep $STRATUM_DIR/run.sh deep screen -dmS x11 $STRATUM_DIR/run.sh x11 screen -dmS x11evo $STRATUM_DIR/run.sh x11evo screen -dmS x13 $STRATUM_DIR/run.sh x13 -screen -dmS x14 $STRATUM_DIR/run.sh x14 -screen -dmS x15 $STRATUM_DIR/run.sh x15 +#screen -dmS x14 $STRATUM_DIR/run.sh x14 +#screen -dmS x15 $STRATUM_DIR/run.sh x15 +#screen -dmS x16r $STRATUM_DIR/run.sh x16r screen -dmS x17 $STRATUM_DIR/run.sh x17 screen -dmS xevan $STRATUM_DIR/run.sh xevan screen -dmS timetravel $STRATUM_DIR/run.sh timetravel @@ -48,9 +49,12 @@ screen -dmS jha $STRATUM_DIR/run.sh jha #screen -dmS dmd-gr $STRATUM_DIR/run.sh dmd-gr screen -dmS myr-gr $STRATUM_DIR/run.sh myr-gr screen -dmS lbry $STRATUM_DIR/run.sh lbry -screen -dmS lyra2 $STRATUM_DIR/run.sh lyra2 +screen -dmS allium $STRATUM_DIR/run.sh allium +#screen -dmS lyra2 $STRATUM_DIR/run.sh lyra2 screen -dmS lyra2v2 $STRATUM_DIR/run.sh lyra2v2 -screen -dmS zero $STRATUM_DIR/run.sh lyra2z +screen -dmS lyra2z $STRATUM_DIR/run.sh lyra2z +screen -dmS lyra2zz $STRATUM_DIR/run.sh lyra2zz +screen -dmS rainforest $STRATUM_DIR/run.sh rainforest screen -dmS blakecoin $STRATUM_DIR/run.sh blakecoin # blake 8 screen -dmS blake $STRATUM_DIR/run.sh blake @@ -59,15 +63,22 @@ screen -dmS vanilla $STRATUM_DIR/run.sh vanilla # blake 8 screen -dmS decred $STRATUM_DIR/run.sh decred # blake 14 #screen -dmS keccak $STRATUM_DIR/run.sh keccak +#screen -dmS keccakc $STRATUM_DIR/run.sh keccakc +#screen -dmS phi $STRATUM_DIR/run.sh phi +#screen -dmS polytimos $STRATUM_DIR/run.sh polytimos screen -dmS whirlpool $STRATUM_DIR/run.sh whirlpool screen -dmS skein $STRATUM_DIR/run.sh skein screen -dmS skein2 $STRATUM_DIR/run.sh skein2 screen -dmS yescrypt $STRATUM_DIR/run.sh yescrypt +#screen -dmS yescryptR16 $STRATUM_DIR/run.sh yescryptR16 screen -dmS zr5 $STRATUM_DIR/run.sh zr5 screen -dmS sib $STRATUM_DIR/run.sh sib screen -dmS m7m $STRATUM_DIR/run.sh m7m screen -dmS veltor $STRATUM_DIR/run.sh veltor screen -dmS velvet $STRATUM_DIR/run.sh velvet screen -dmS argon2 $STRATUM_DIR/run.sh argon2 +screen -dmS argon2d-dyn $STRATUM_DIR/run.sh argon2d-dyn +screen -dmS x22i $STRATUM_DIR/run.sh x22i +screen -dmS lbk3 $STRATUM_DIR/run.sh lbk3 diff --git a/sql/2018-02-coins_getinfo.sql b/sql/2018-02-coins_getinfo.sql new file mode 100644 index 0000000..b3ea822 --- /dev/null +++ b/sql/2018-02-coins_getinfo.sql @@ -0,0 +1,13 @@ +-- Recent additions to add after db init (.gz) +-- mysql yaamp -p < file.sql + +-- filled by the stratum instance, to allow to handle/watch multiple instances + +ALTER TABLE `coins` ADD `hasgetinfo` tinyint(1) UNSIGNED NOT NULL DEFAULT '1' AFTER `account`; + +UPDATE coins SET hassubmitblock=0 WHERE hassubmitblock IS NULL; +UPDATE coins SET hassubmitblock=1 WHERE hassubmitblock > 0; +ALTER TABLE `coins` CHANGE `hassubmitblock` `hassubmitblock` tinyint(1) UNSIGNED NOT NULL DEFAULT '1'; + +ALTER TABLE `coins` ADD `no_explorer` tinyint(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `visible`; + diff --git a/stratum/Makefile b/stratum/Makefile index 8bf6a9f..3bf978b 100755 --- a/stratum/Makefile +++ b/stratum/Makefile @@ -8,12 +8,6 @@ SQLFLAGS= `mysql_config --cflags --libs` # if you use the auto exchange feature... CFLAGS += -DNO_EXCHANGE -#CFLAGS += -DHASH_DEBUGLOG_ -#CFLAGS += -DRPC_DEBUGLOG_ -#CFLAGS += -DREMOTE_DEBUGLOG_ -#CFLAGS += -DSOCKET_DEBUGLOG_ -#CFLAGS += -DCLIENT_DEBUGLOG_ - #CFLAGS=-c -O2 -I /usr/include/mysql LDFLAGS=-O2 `mysql_config --libs` diff --git a/stratum/algos/Lyra2z.c b/stratum/algos/Lyra2-z.c similarity index 100% rename from stratum/algos/Lyra2z.c rename to stratum/algos/Lyra2-z.c diff --git a/stratum/algos/Lyra2z.h b/stratum/algos/Lyra2-z.h similarity index 100% rename from stratum/algos/Lyra2z.h rename to stratum/algos/Lyra2-z.h diff --git a/stratum/algos/Lyra2-zz.c b/stratum/algos/Lyra2-zz.c new file mode 100644 index 0000000..b6d43cf --- /dev/null +++ b/stratum/algos/Lyra2-zz.c @@ -0,0 +1,210 @@ +/** + * Implementation of the Lyra2 Password Hashing Scheme (PHS). + * + * Author: The Lyra PHC team (http://www.lyra-kdf.net/) -- 2014. + * + * This software is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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 +#include +#include +#include + +#include "Lyra2-zz.h" +#include "Sponge.h" + +/** + * Executes Lyra2 based on the G function from Blake2b. This version supports salts and passwords + * whose combined length is smaller than the size of the memory matrix, (i.e., (nRows x nCols x b) bits, + * where "b" is the underlying sponge's bitrate). In this implementation, the "basil" is composed by all + * integer parameters (treated as type "unsigned int") in the order they are provided, plus the value + * of nCols, (i.e., basil = kLen || pwdlen || saltlen || timeCost || nRows || nCols). + * + * @param K The derived key to be output by the algorithm + * @param kLen Desired key length + * @param pwd User password + * @param pwdlen Password length + * @param salt Salt + * @param saltlen Salt length + * @param timeCost Parameter to determine the processing time (T) + * @param nRows Number or rows of the memory matrix (R) + * @param nCols Number of columns of the memory matrix (C) + * + * @return 0 if the key is generated correctly; -1 if there is an error (usually due to lack of memory for allocation) + */ +int LYRA2ZZ(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols) +{ + //============================= Basic variables ============================// + int64_t row = 2; //index of row to be processed + int64_t prev = 1; //index of prev (last row ever computed/modified) + int64_t rowa = 0; //index of row* (a previous row, deterministically picked during Setup and randomly picked while Wandering) + int64_t tau; //Time Loop iterator + int64_t step = 1; //Visitation step (used during Setup and Wandering phases) + int64_t window = 2; //Visitation window (used to define which rows can be revisited during Setup) + int64_t gap = 1; //Modifier to the step, assuming the values 1 or -1 + int64_t i; //auxiliary iteration counter + //==========================================================================/ + + //========== Initializing the Memory Matrix and pointers to it =============// + //Tries to allocate enough space for the whole memory matrix + const int64_t ROW_LEN_INT64 = BLOCK_LEN_INT64 * nCols; + const int64_t ROW_LEN_BYTES = ROW_LEN_INT64 * 8; + + i = (int64_t) ((int64_t) nRows * (int64_t) ROW_LEN_BYTES); + uint64_t *wholeMatrix = malloc(i); + if (wholeMatrix == NULL) { + return -1; + } + memset(wholeMatrix, 0, i); + + //Allocates pointers to each row of the matrix + uint64_t **memMatrix = malloc(nRows * sizeof (uint64_t*)); + if (memMatrix == NULL) { + return -1; + } + //Places the pointers in the correct positions + uint64_t *ptrWord = wholeMatrix; + for (i = 0; i < nRows; i++) { + memMatrix[i] = ptrWord; + ptrWord += ROW_LEN_INT64; + } + //==========================================================================/ + + //============= Getting the password + salt + basil padded with 10*1 ===============// + //OBS.:The memory matrix will temporarily hold the password: not for saving memory, + //but this ensures that the password copied locally will be overwritten as soon as possible + + //First, we clean enough blocks for the password, salt, basil and padding + uint64_t nBlocksInput = ((saltlen + pwdlen + 6 * sizeof (uint64_t)) / BLOCK_LEN_BLAKE2_SAFE_BYTES) + 1; + byte *ptrByte = (byte*) wholeMatrix; + memset(ptrByte, 0, nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES); + + //Prepends the password + memcpy(ptrByte, pwd, pwdlen); + ptrByte += pwdlen; + + //Concatenates the salt + memcpy(ptrByte, salt, saltlen); + ptrByte += saltlen; + + //Concatenates the basil: every integer passed as parameter, in the order they are provided by the interface + memcpy(ptrByte, &kLen, sizeof (uint64_t)); + ptrByte += sizeof (uint64_t); + memcpy(ptrByte, &pwdlen, sizeof (uint64_t)); + ptrByte += sizeof (uint64_t); + memcpy(ptrByte, &saltlen, sizeof (uint64_t)); + ptrByte += sizeof (uint64_t); + memcpy(ptrByte, &timeCost, sizeof (uint64_t)); + ptrByte += sizeof (uint64_t); + memcpy(ptrByte, &nRows, sizeof (uint64_t)); + ptrByte += sizeof (uint64_t); + memcpy(ptrByte, &nCols, sizeof (uint64_t)); + ptrByte += sizeof (uint64_t); + + //Now comes the padding + *ptrByte = 0x80; //first byte of padding: right after the password + ptrByte = (byte*) wholeMatrix; //resets the pointer to the start of the memory matrix + ptrByte += nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - 1; //sets the pointer to the correct position: end of incomplete block + *ptrByte ^= 0x01; //last byte of padding: at the end of the last incomplete block + //==========================================================================/ + + //======================= Initializing the Sponge State ====================// + //Sponge state: 16 uint64_t, BLOCK_LEN_INT64 words of them for the bitrate (b) and the remainder for the capacity (c) + uint64_t *state = malloc(16 * sizeof (uint64_t)); + if (state == NULL) { + return -1; + } + initState(state); + //==========================================================================/ + + //================================ Setup Phase =============================// + //Absorbing salt, password and basil: this is the only place in which the block length is hard-coded to 512 bits + ptrWord = wholeMatrix; + for (i = 0; i < nBlocksInput; i++) { + absorbBlockBlake2Safe(state, ptrWord); //absorbs each block of pad(pwd || salt || basil) + ptrWord += BLOCK_LEN_BLAKE2_SAFE_INT64; //goes to next block of pad(pwd || salt || basil) + } + + //Initializes M[0] and M[1] + reducedSqueezeRow0(state, memMatrix[0], nCols); //The locally copied password is most likely overwritten here + reducedDuplexRow1(state, memMatrix[0], memMatrix[1], nCols); + + do { + //M[row] = rand; //M[row*] = M[row*] XOR rotW(rand) + reducedDuplexRowSetup(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols); + + //updates the value of row* (deterministically picked during Setup)) + rowa = (rowa + step) & (window - 1); + //update prev: it now points to the last row ever computed + prev = row; + //updates row: goes to the next row to be computed + row++; + + //Checks if all rows in the window where visited. + if (rowa == 0) { + step = window + gap; //changes the step: approximately doubles its value + window *= 2; //doubles the size of the re-visitation window + gap = -gap; //inverts the modifier to the step + } + + } while (row < nRows); + //==========================================================================/ + + //============================ Wandering Phase =============================// + row = 0; //Resets the visitation to the first row of the memory matrix + for (tau = 1; tau <= timeCost; tau++) { + //Step is approximately half the number of all rows of the memory matrix for an odd tau; otherwise, it is -1 + step = (tau % 2 == 0) ? -1 : nRows / 2 - 1; + do { + //Selects a pseudorandom index row* + //------------------------------------------------------------------------------------------ + //rowa = ((unsigned int)state[0]) & (nRows-1); //(USE THIS IF nRows IS A POWER OF 2) + rowa = ((uint64_t) (state[0])) % nRows; //(USE THIS FOR THE "GENERIC" CASE) + //------------------------------------------------------------------------------------------ + + //Performs a reduced-round duplexing operation over M[row*] XOR M[prev], updating both M[row*] and M[row] + reducedDuplexRow(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols); + + //update prev: it now points to the last row ever computed + prev = row; + + //updates row: goes to the next row to be computed + //------------------------------------------------------------------------------------------ + //row = (row + step) & (nRows-1); //(USE THIS IF nRows IS A POWER OF 2) + row = (row + step) % nRows; //(USE THIS FOR THE "GENERIC" CASE) + //------------------------------------------------------------------------------------------ + } while (row != 0); + } + //==========================================================================/ + + //============================ Wrap-up Phase ===============================// + //Absorbs the last block of the memory matrix + absorbBlock(state, memMatrix[rowa]); + + //Squeezes the key + squeeze(state, K, kLen); + //==========================================================================/ + + //========================= Freeing the memory =============================// + free(memMatrix); + free(wholeMatrix); + + //Wiping out the sponge's internal state before freeing it + memset(state, 0, 16 * sizeof (uint64_t)); + free(state); + //==========================================================================/ + + return 0; +} diff --git a/stratum/algos/Lyra2-zz.h b/stratum/algos/Lyra2-zz.h new file mode 100644 index 0000000..e56a5a7 --- /dev/null +++ b/stratum/algos/Lyra2-zz.h @@ -0,0 +1,55 @@ +/** + * Header file for the Lyra2 Password Hashing Scheme (PHS). + * + * Author: The Lyra PHC team (http://www.lyra-kdf.net/) -- 2014. + * + * This software is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + */ +#ifndef LYRA2ZZ_H_ +#define LYRA2ZZ_H_ + +#include + +typedef unsigned char byte; + +//Block length required so Blake2's Initialization Vector (IV) is not overwritten (THIS SHOULD NOT BE MODIFIED) +#define BLOCK_LEN_BLAKE2_SAFE_INT64 12 //768 bits (=96 bytes, =12 uint64_t) +#define BLOCK_LEN_BLAKE2_SAFE_BYTES (BLOCK_LEN_BLAKE2_SAFE_INT64 * 8) //same as above, in bytes + +#define LYRA2ZZ_BLOCK_HEADER_LEN_BYTES 112 +#define LYRA2ZZ_BLOCK_HEADER_NONCE_OFFSET 19 /* 19 * 4 bytes */ + +#define LYRA2ZZ_BLOCK_HEADER_UINT32_LEN 32 + +#ifdef BLOCK_LEN_BITS + #define BLOCK_LEN_INT64 (BLOCK_LEN_BITS/64) //Block length: 1024 bits (=128 bytes, =16 uint64_t) + #define BLOCK_LEN_BYTES (BLOCK_LEN_BITS/8) //Block length, in bytes +#else //default block length: 1024 bits + #define BLOCK_LEN_INT64 16 //Block length: 1024 bits (=128 bytes, =16 uint64_t) + #define BLOCK_LEN_BYTES (BLOCK_LEN_INT64 * 8) //Block length, in bytes +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +int LYRA2ZZ(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols); + +#ifdef __cplusplus +} + +#endif + +#endif /* LYRA2ZZ_H_ */ diff --git a/stratum/algos/Lyra2.c b/stratum/algos/Lyra2.c index dbcc3fa..a2016be 100644 --- a/stratum/algos/Lyra2.c +++ b/stratum/algos/Lyra2.c @@ -44,7 +44,7 @@ * * @return 0 if the key is generated correctly; -1 if there is an error (usually due to lack of memory for allocation) */ -int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int64_t nRows, const int16_t nCols) +int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols) { //============================= Basic variables ============================// int64_t row = 2; //index of row to be processed @@ -212,3 +212,175 @@ int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *sa return 0; } + +int LYRA2_3(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols) +{ + //============================= Basic variables ============================// + int64_t row = 2; //index of row to be processed + int64_t prev = 1; //index of prev (last row ever computed/modified) + int64_t rowa = 0; //index of row* (a previous row, deterministically picked during Setup and randomly picked while Wandering) + int64_t tau; //Time Loop iterator + int64_t step = 1; //Visitation step (used during Setup and Wandering phases) + int64_t window = 2; //Visitation window (used to define which rows can be revisited during Setup) + int64_t gap = 1; //Modifier to the step, assuming the values 1 or -1 + int64_t i; //auxiliary iteration counter + int64_t v64; // 64bit var for memcpy + uint64_t instance = 0; + //==========================================================================/ + + //========== Initializing the Memory Matrix and pointers to it =============// + //Tries to allocate enough space for the whole memory matrix + + const int64_t ROW_LEN_INT64 = BLOCK_LEN_INT64 * nCols; + const int64_t ROW_LEN_BYTES = ROW_LEN_INT64 * 8; + const int64_t BLOCK_LEN = BLOCK_LEN_BLAKE2_SAFE_INT64; + + size_t sz = (size_t)ROW_LEN_BYTES * nRows; + uint64_t *wholeMatrix = malloc(sz); + if (wholeMatrix == NULL) { + return -1; + } + memset(wholeMatrix, 0, sz); + + //Allocates pointers to each row of the matrix + uint64_t **memMatrix = malloc(sizeof(uint64_t*) * nRows); + if (memMatrix == NULL) { + return -1; + } + //Places the pointers in the correct positions + uint64_t *ptrWord = wholeMatrix; + for (i = 0; i < nRows; i++) { + memMatrix[i] = ptrWord; + ptrWord += ROW_LEN_INT64; + } + //==========================================================================/ + + //============= Getting the password + salt + basil padded with 10*1 ===============// + //OBS.:The memory matrix will temporarily hold the password: not for saving memory, + //but this ensures that the password copied locally will be overwritten as soon as possible + + //First, we clean enough blocks for the password, salt, basil and padding + int64_t nBlocksInput = ((saltlen + pwdlen + 6 * sizeof(uint64_t)) / BLOCK_LEN_BLAKE2_SAFE_BYTES) + 1; + + byte *ptrByte = (byte*) wholeMatrix; + + //Prepends the password + memcpy(ptrByte, pwd, pwdlen); + ptrByte += pwdlen; + + //Concatenates the salt + memcpy(ptrByte, salt, saltlen); + ptrByte += saltlen; + + memset(ptrByte, 0, (size_t) (nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - (saltlen + pwdlen))); + + //Concatenates the basil: every integer passed as parameter, in the order they are provided by the interface + memcpy(ptrByte, &kLen, sizeof(int64_t)); + ptrByte += sizeof(uint64_t); + v64 = pwdlen; + memcpy(ptrByte, &v64, sizeof(int64_t)); + ptrByte += sizeof(uint64_t); + v64 = saltlen; + memcpy(ptrByte, &v64, sizeof(int64_t)); + ptrByte += sizeof(uint64_t); + v64 = timeCost; + memcpy(ptrByte, &v64, sizeof(int64_t)); + ptrByte += sizeof(uint64_t); + v64 = nRows; + memcpy(ptrByte, &v64, sizeof(int64_t)); + ptrByte += sizeof(uint64_t); + v64 = nCols; + memcpy(ptrByte, &v64, sizeof(int64_t)); + ptrByte += sizeof(uint64_t); + + //Now comes the padding + *ptrByte = 0x80; //first byte of padding: right after the password + ptrByte = (byte*) wholeMatrix; //resets the pointer to the start of the memory matrix + ptrByte += nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - 1; //sets the pointer to the correct position: end of incomplete block + *ptrByte ^= 0x01; //last byte of padding: at the end of the last incomplete block + //==========================================================================/ + + //======================= Initializing the Sponge State ====================// + //Sponge state: 16 uint64_t, BLOCK_LEN_INT64 words of them for the bitrate (b) and the remainder for the capacity (c) + uint64_t state[16]; + initState(state); + //==========================================================================/ + + //================================ Setup Phase =============================// + //Absorbing salt, password and basil: this is the only place in which the block length is hard-coded to 512 bits + ptrWord = wholeMatrix; + for (i = 0; i < nBlocksInput; i++) { + absorbBlockBlake2Safe(state, ptrWord); //absorbs each block of pad(pwd || salt || basil) + ptrWord += BLOCK_LEN; //goes to next block of pad(pwd || salt || basil) + } + + //Initializes M[0] and M[1] + reducedSqueezeRow0(state, memMatrix[0], nCols); //The locally copied password is most likely overwritten here + + reducedDuplexRow1(state, memMatrix[0], memMatrix[1], nCols); + + do { + //M[row] = rand; //M[row*] = M[row*] XOR rotW(rand) + + reducedDuplexRowSetup(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols); + + //updates the value of row* (deterministically picked during Setup)) + rowa = (rowa + step) & (window - 1); + //update prev: it now points to the last row ever computed + prev = row; + //updates row: goes to the next row to be computed + row++; + + //Checks if all rows in the window where visited. + if (rowa == 0) { + step = window + gap; //changes the step: approximately doubles its value + window *= 2; //doubles the size of the re-visitation window + gap = -gap; //inverts the modifier to the step + } + + } while (row < nRows); + //==========================================================================/ + + //============================ Wandering Phase =============================// + row = 0; //Resets the visitation to the first row of the memory matrix + for (tau = 1; tau <= timeCost; tau++) { + //Step is approximately half the number of all rows of the memory matrix for an odd tau; otherwise, it is -1 + step = ((tau & 1) == 0) ? -1 : (nRows >> 1) - 1; + do { + //Selects a pseudorandom index row* + //------------------------------------------------------------------------------------------ + instance = state[instance & 0xF]; + rowa = state[instance & 0xF] & (unsigned int)(nRows-1); + + //rowa = state[0] & (unsigned int)(nRows-1); //(USE THIS IF nRows IS A POWER OF 2) + //rowa = state[0] % nRows; //(USE THIS FOR THE "GENERIC" CASE) + //------------------------------------------------------------------------------------------ + + //Performs a reduced-round duplexing operation over M[row*] XOR M[prev], updating both M[row*] and M[row] + reducedDuplexRow(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols); + + //update prev: it now points to the last row ever computed + prev = row; + + //updates row: goes to the next row to be computed + //------------------------------------------------------------------------------------------ + row = (row + step) & (unsigned int)(nRows-1); //(USE THIS IF nRows IS A POWER OF 2) + //row = (row + step) % nRows; //(USE THIS FOR THE "GENERIC" CASE) + //------------------------------------------------------------------------------------------ + + } while (row != 0); + } + + //============================ Wrap-up Phase ===============================// + //Absorbs the last block of the memory matrix + absorbBlock(state, memMatrix[rowa]); + + //Squeezes the key + squeeze(state, K, (unsigned int) kLen); + + //========================= Freeing the memory =============================// + free(memMatrix); + free(wholeMatrix); + + return 0; +} diff --git a/stratum/algos/Lyra2.h b/stratum/algos/Lyra2.h index e25432a..a6aa87a 100644 --- a/stratum/algos/Lyra2.h +++ b/stratum/algos/Lyra2.h @@ -37,6 +37,8 @@ typedef unsigned char byte; #define BLOCK_LEN_BYTES (BLOCK_LEN_INT64 * 8) //Block length, in bytes #endif -int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int64_t nRows, const int16_t nCols); +int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols); + +int LYRA2_3(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols); #endif /* LYRA2_H_ */ diff --git a/stratum/algos/SWIFFTX/SWIFFTX.c b/stratum/algos/SWIFFTX/SWIFFTX.c new file mode 100644 index 0000000..7acead1 --- /dev/null +++ b/stratum/algos/SWIFFTX/SWIFFTX.c @@ -0,0 +1,1155 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// +// SWIFFTX ANSI C OPTIMIZED 32BIT IMPLEMENTATION FOR NIST SHA-3 COMPETITION +// +// SWIFFTX.c +// +// October 2008 +// +// This is the source file of the OPTIMIZED 32BIT implementation of SWIFFTX hash function. +// SWIFFTX is a candidate function for SHA-3 NIST competition. +// More details about SWIFFTX can be found in the accompanying submission documents. +// +/////////////////////////////////////////////////////////////////////////////////////////////// +#include "SWIFFTX.h" +// See the remarks concerning compatibility issues inside stdint.h. +#include "stdint.h" +// Remove this while using gcc: +//#include "stdbool.h" +#include + +/////////////////////////////////////////////////////////////////////////////////////////////// +// Constants and static tables portion. +/////////////////////////////////////////////////////////////////////////////////////////////// + +// In SWIFFTX we work over Z_257, so this is the modulus and the arithmetic is performed modulo +// this number. +#define FIELD_SIZE 257 + +// The size of FFT we use: +#define N 64 + +#define LOGN 6 + +#define EIGHTH_N (N / 8) + +// The number of FFTS done on the input. +#define M (SWIFFTX_INPUT_BLOCK_SIZE / 8) // 32 + +// Omega is the 128th root of unity in Z_257. +// We choose w = 42. +#define OMEGA 42 + +// The size of the inner FFT lookup table: +#define W 8 + +// Calculates the sum and the difference of two numbers. +// +// Parameters: +// - A: the first operand. After the operation stores the sum of the two operands. +// - B: the second operand. After the operation stores the difference between the first and the +// second operands. +#define ADD_SUB(A, B) {register int temp = (B); B = ((A) - (B)); A = ((A) + (temp));} + +// Quickly reduces an integer modulo 257. +// +// Parameters: +// - A: the input. +#define Q_REDUCE(A) (((A) & 0xff) - ((A) >> 8)) + +// Since we need to do the setup only once, this is the indicator variable: +static bool wasSetupDone = false; + +// This array stores the powers of omegas that correspond to the indices, which are the input +// values. Known also as the "outer FFT twiddle factors". +swift_int16_t multipliers[N]; + +// This array stores the powers of omegas, multiplied by the corresponding values. +// We store this table to save computation time. +// +// To calculate the intermediate value of the compression function (the first out of two +// stages), we multiply the k-th bit of x_i by w^[(2i + 1) * k]. {x_i} is the input to the +// compression function, i is between 0 and 31, x_i is a 64-bit value. +// One can see the formula for this (intermediate) stage in the SWIFFT FSE 2008 paper -- +// formula (2), section 3, page 6. +swift_int16_t fftTable[256 * EIGHTH_N]; + +// The A's we use in SWIFFTX shall be random elements of Z_257. +// We generated these A's from the decimal expansion of PI as follows: we converted each +// triple of digits into a decimal number d. If d < (257 * 3) we used (d % 257) for the next A +// element, otherwise move to the next triple of digits in the expansion. This guarntees that +// the A's are random, provided that PI digits are. +const swift_int16_t As[3 * M * N] = +{141, 78, 139, 75, 238, 205, 129, 126, 22, 245, 197, 169, 142, 118, 105, 78, + 50, 149, 29, 208, 114, 34, 85, 117, 67, 148, 86, 256, 25, 49, 133, 93, + 95, 36, 68, 231, 211, 102, 151, 128, 224, 117, 193, 27, 102, 187, 7, 105, + 45, 130, 108, 124, 171, 151, 189, 128, 218, 134, 233, 165, 14, 201, 145, 134, + 52, 203, 91, 96, 197, 69, 134, 213, 136, 93, 3, 249, 141, 16, 210, 73, + 6, 92, 58, 74, 174, 6, 254, 91, 201, 107, 110, 76, 103, 11, 73, 16, + 34, 209, 7, 127, 146, 254, 95, 176, 57, 13, 108, 245, 77, 92, 186, 117, + 124, 97, 105, 118, 34, 74, 205, 122, 235, 53, 94, 238, 210, 227, 183, 11, + 129, 159, 105, 183, 142, 129, 86, 21, 137, 138, 224, 223, 190, 188, 179, 188, + 256, 25, 217, 176, 36, 176, 238, 127, 160, 210, 155, 148, 132, 0, 54, 127, + 145, 6, 46, 85, 243, 95, 173, 123, 178, 207, 211, 183, 224, 173, 146, 35, + 71, 114, 50, 22, 175, 1, 28, 19, 112, 129, 21, 34, 161, 159, 115, 52, + 4, 193, 211, 92, 115, 49, 59, 217, 218, 96, 61, 81, 24, 202, 198, 89, + 45, 128, 8, 51, 253, 87, 171, 35, 4, 188, 171, 10, 3, 137, 238, 73, + 19, 208, 124, 163, 103, 177, 155, 147, 46, 84, 253, 233, 171, 241, 211, 217, + 159, 48, 96, 79, 237, 18, 171, 226, 99, 1, 97, 195, 216, 163, 198, 95, + 0, 201, 65, 228, 21, 153, 124, 230, 44, 35, 44, 108, 85, 156, 249, 207, + 26, 222, 131, 1, 60, 242, 197, 150, 181, 19, 116, 213, 75, 98, 124, 240, + 123, 207, 62, 255, 60, 143, 187, 157, 139, 9, 12, 104, 89, 49, 193, 146, + 104, 196, 181, 82, 198, 253, 192, 191, 255, 122, 212, 104, 47, 20, 132, 208, + 46, 170, 2, 69, 234, 36, 56, 163, 28, 152, 104, 238, 162, 56, 24, 58, + 38, 150, 193, 254, 253, 125, 173, 35, 73, 126, 247, 239, 216, 6, 199, 15, + 90, 12, 97, 122, 9, 84, 207, 127, 219, 72, 58, 30, 29, 182, 41, 192, + 235, 248, 237, 74, 72, 176, 210, 252, 45, 64, 165, 87, 202, 241, 236, 223, + 151, 242, 119, 239, 52, 112, 169, 28, 13, 37, 160, 60, 158, 81, 133, 60, + 16, 145, 249, 192, 173, 217, 214, 93, 141, 184, 54, 34, 161, 104, 157, 95, + 38, 133, 218, 227, 211, 181, 9, 66, 137, 143, 77, 33, 248, 159, 4, 55, + 228, 48, 99, 219, 222, 184, 15, 36, 254, 256, 157, 237, 87, 139, 209, 113, + 232, 85, 126, 167, 197, 100, 103, 166, 64, 225, 125, 205, 117, 135, 84, 128, + 231, 112, 90, 241, 28, 22, 210, 147, 186, 49, 230, 21, 108, 39, 194, 47, + 123, 199, 107, 114, 30, 210, 250, 143, 59, 156, 131, 133, 221, 27, 76, 99, + 208, 250, 78, 12, 211, 141, 95, 81, 195, 106, 8, 232, 150, 212, 205, 221, + 11, 225, 87, 219, 126, 136, 137, 180, 198, 48, 68, 203, 239, 252, 194, 235, + 142, 137, 174, 172, 190, 145, 250, 221, 182, 204, 1, 195, 130, 153, 83, 241, + 161, 239, 211, 138, 11, 169, 155, 245, 174, 49, 10, 166, 16, 130, 181, 139, + 222, 222, 112, 99, 124, 94, 51, 243, 133, 194, 244, 136, 35, 248, 201, 177, + 178, 186, 129, 102, 89, 184, 180, 41, 149, 96, 165, 72, 225, 231, 134, 158, + 199, 28, 249, 16, 225, 195, 10, 210, 164, 252, 138, 8, 35, 152, 213, 199, + 82, 116, 97, 230, 63, 199, 241, 35, 79, 120, 54, 174, 67, 112, 1, 76, + 69, 222, 194, 96, 82, 94, 25, 228, 196, 145, 155, 136, 228, 234, 46, 101, + 246, 51, 103, 166, 246, 75, 9, 200, 161, 4, 108, 35, 129, 168, 208, 144, + 50, 14, 13, 220, 41, 132, 122, 127, 194, 9, 232, 234, 107, 28, 187, 8, + 51, 141, 97, 221, 225, 9, 113, 170, 166, 102, 135, 22, 231, 185, 227, 187, + 110, 145, 251, 146, 76, 22, 146, 228, 7, 53, 64, 25, 62, 198, 130, 190, + 221, 232, 169, 64, 188, 199, 237, 249, 173, 218, 196, 191, 48, 224, 5, 113, + 100, 166, 160, 21, 191, 197, 61, 162, 149, 171, 240, 183, 129, 231, 123, 204, + 192, 179, 134, 15, 47, 161, 142, 177, 239, 234, 186, 237, 231, 53, 208, 95, + 146, 36, 225, 231, 89, 142, 93, 248, 137, 124, 83, 39, 69, 77, 89, 208, + 182, 48, 85, 147, 244, 164, 246, 68, 38, 190, 220, 35, 202, 91, 157, 151, + 201, 240, 185, 218, 4, 152, 2, 132, 177, 88, 190, 196, 229, 74, 220, 135, + 137, 196, 11, 47, 5, 251, 106, 144, 163, 60, 222, 127, 52, 57, 202, 102, + 64, 140, 110, 206, 23, 182, 39, 245, 1, 163, 157, 186, 163, 80, 7, 230, + 44, 249, 176, 102, 164, 125, 147, 120, 18, 191, 186, 125, 64, 65, 198, 157, + 164, 213, 95, 61, 13, 181, 208, 91, 242, 197, 158, 34, 98, 169, 91, 14, + 17, 93, 157, 17, 65, 30, 183, 6, 139, 58, 255, 108, 100, 136, 209, 144, + 164, 6, 237, 33, 210, 110, 57, 126, 197, 136, 125, 244, 165, 151, 168, 3, + 143, 251, 247, 155, 136, 130, 88, 14, 74, 121, 250, 133, 21, 226, 185, 232, + 118, 132, 89, 64, 204, 161, 2, 70, 224, 159, 35, 204, 123, 180, 13, 52, + 231, 57, 25, 78, 66, 69, 97, 42, 198, 84, 176, 59, 8, 232, 125, 134, + 193, 2, 232, 109, 216, 69, 90, 142, 32, 38, 249, 37, 75, 180, 184, 188, + 19, 47, 120, 87, 146, 70, 232, 120, 191, 45, 33, 38, 19, 248, 110, 110, + 44, 64, 2, 84, 244, 228, 252, 228, 170, 123, 38, 144, 213, 144, 171, 212, + 243, 87, 189, 46, 128, 110, 84, 77, 65, 183, 61, 184, 101, 44, 168, 68, + 14, 106, 105, 8, 227, 211, 166, 39, 152, 43, 52, 254, 197, 55, 119, 89, + 168, 65, 53, 138, 177, 56, 219, 0, 58, 121, 148, 18, 44, 100, 215, 103, + 145, 229, 117, 196, 91, 89, 113, 143, 172, 239, 249, 184, 154, 39, 112, 65, + 204, 42, 84, 38, 155, 151, 151, 16, 100, 87, 174, 162, 145, 147, 149, 186, + 237, 145, 134, 144, 198, 235, 213, 163, 48, 230, 24, 47, 57, 71, 127, 0, + 150, 219, 12, 81, 197, 150, 131, 13, 169, 63, 175, 184, 48, 235, 65, 243, + 149, 200, 163, 254, 202, 114, 247, 67, 143, 250, 126, 228, 80, 130, 216, 214, + 36, 2, 230, 33, 119, 125, 3, 142, 237, 100, 3, 152, 197, 174, 244, 129, + 232, 30, 206, 199, 39, 210, 220, 43, 237, 221, 201, 54, 179, 42, 28, 133, + 246, 203, 198, 177, 0, 28, 194, 85, 223, 109, 155, 147, 221, 60, 133, 108, + 157, 254, 26, 75, 157, 185, 49, 142, 31, 137, 71, 43, 63, 64, 237, 148, + 237, 172, 159, 160, 155, 254, 234, 224, 140, 193, 114, 140, 62, 109, 136, 39, + 255, 8, 158, 146, 128, 49, 222, 96, 57, 209, 180, 249, 202, 127, 113, 231, + 78, 178, 46, 33, 228, 215, 104, 31, 207, 186, 82, 41, 42, 39, 103, 119, + 123, 133, 243, 254, 238, 156, 90, 186, 37, 212, 33, 107, 252, 51, 177, 36, + 237, 76, 159, 245, 93, 214, 97, 56, 190, 38, 160, 94, 105, 222, 220, 158, + 49, 16, 191, 52, 120, 87, 179, 2, 27, 144, 223, 230, 184, 6, 129, 227, + 69, 47, 215, 181, 162, 139, 72, 200, 45, 163, 159, 62, 2, 221, 124, 40, + 159, 242, 35, 208, 179, 166, 98, 67, 178, 68, 143, 225, 178, 146, 187, 159, + 57, 66, 176, 192, 236, 250, 168, 224, 122, 43, 159, 120, 133, 165, 122, 64, + 87, 74, 161, 241, 9, 87, 90, 24, 255, 113, 203, 220, 57, 139, 197, 159, + 31, 151, 27, 140, 77, 162, 7, 27, 84, 228, 187, 220, 53, 126, 162, 242, + 84, 181, 223, 103, 86, 177, 207, 31, 140, 18, 207, 256, 201, 166, 96, 23, + 233, 103, 197, 84, 161, 75, 59, 149, 138, 154, 119, 92, 16, 53, 116, 97, + 220, 114, 35, 45, 77, 209, 40, 196, 71, 22, 81, 178, 110, 14, 3, 180, + 110, 129, 112, 47, 18, 61, 134, 78, 73, 79, 254, 232, 125, 180, 205, 54, + 220, 119, 63, 89, 181, 52, 77, 109, 151, 77, 80, 207, 144, 25, 20, 6, + 208, 47, 201, 206, 192, 14, 73, 176, 256, 201, 207, 87, 216, 60, 56, 73, + 92, 243, 179, 113, 49, 59, 55, 168, 121, 137, 69, 154, 95, 57, 187, 47, + 129, 4, 15, 92, 6, 116, 69, 196, 48, 134, 84, 81, 111, 56, 38, 176, + 239, 6, 128, 72, 242, 134, 36, 221, 59, 48, 242, 68, 130, 110, 171, 89, + 13, 220, 48, 29, 5, 75, 104, 233, 91, 129, 105, 162, 44, 113, 163, 163, + 85, 147, 190, 111, 197, 80, 213, 153, 81, 68, 203, 33, 161, 165, 10, 61, + 120, 252, 0, 205, 28, 42, 193, 64, 39, 37, 83, 175, 5, 218, 215, 174, + 128, 121, 231, 11, 150, 145, 135, 197, 136, 91, 193, 5, 107, 88, 82, 6, + 4, 188, 256, 70, 40, 2, 167, 57, 169, 203, 115, 254, 215, 172, 84, 80, + 188, 167, 34, 137, 43, 243, 2, 79, 178, 38, 188, 135, 233, 194, 208, 13, + 11, 151, 231, 196, 12, 122, 162, 56, 17, 114, 191, 207, 90, 132, 64, 238, + 187, 6, 198, 176, 240, 88, 118, 236, 15, 226, 166, 22, 193, 229, 82, 246, + 213, 64, 37, 63, 31, 243, 252, 37, 156, 38, 175, 204, 138, 141, 211, 82, + 106, 217, 97, 139, 153, 56, 129, 218, 158, 9, 83, 26, 87, 112, 71, 21, + 250, 5, 65, 141, 68, 116, 231, 113, 10, 218, 99, 205, 201, 92, 157, 4, + 97, 46, 49, 220, 72, 139, 103, 171, 149, 129, 193, 19, 69, 245, 43, 31, + 58, 68, 36, 195, 159, 22, 54, 34, 233, 141, 205, 100, 226, 96, 22, 192, + 41, 231, 24, 79, 234, 138, 30, 120, 117, 216, 172, 197, 172, 107, 86, 29, + 181, 151, 0, 6, 146, 186, 68, 55, 54, 58, 213, 182, 60, 231, 33, 232, + 77, 210, 216, 154, 80, 51, 141, 122, 68, 148, 219, 122, 254, 48, 64, 175, + 41, 115, 62, 243, 141, 81, 119, 121, 5, 68, 121, 88, 239, 29, 230, 90, + 135, 159, 35, 223, 168, 112, 49, 37, 146, 60, 126, 134, 42, 145, 115, 90, + 73, 133, 211, 86, 120, 141, 122, 241, 127, 56, 130, 36, 174, 75, 83, 246, + 112, 45, 136, 194, 201, 115, 1, 156, 114, 167, 208, 12, 176, 147, 32, 170, + 251, 100, 102, 220, 122, 210, 6, 49, 75, 201, 38, 105, 132, 135, 126, 102, + 13, 121, 76, 228, 202, 20, 61, 213, 246, 13, 207, 42, 148, 168, 37, 253, + 34, 94, 141, 185, 18, 234, 157, 109, 104, 64, 250, 125, 49, 236, 86, 48, + 196, 77, 75, 237, 156, 103, 225, 19, 110, 229, 22, 68, 177, 93, 221, 181, + 152, 153, 61, 108, 101, 74, 247, 195, 127, 216, 30, 166, 168, 61, 83, 229, + 120, 156, 96, 120, 201, 124, 43, 27, 253, 250, 120, 143, 89, 235, 189, 243, + 150, 7, 127, 119, 149, 244, 84, 185, 134, 34, 128, 193, 236, 234, 132, 117, + 137, 32, 145, 184, 44, 121, 51, 76, 11, 228, 142, 251, 39, 77, 228, 251, + 41, 58, 246, 107, 125, 187, 9, 240, 35, 8, 11, 162, 242, 220, 158, 163, + 2, 184, 163, 227, 242, 2, 100, 101, 2, 78, 129, 34, 89, 28, 26, 157, + 79, 31, 107, 250, 194, 156, 186, 69, 212, 66, 41, 180, 139, 42, 211, 253, + 256, 239, 29, 129, 104, 248, 182, 68, 1, 189, 48, 226, 36, 229, 3, 158, + 41, 53, 241, 22, 115, 174, 16, 163, 224, 19, 112, 219, 177, 233, 42, 27, + 250, 134, 18, 28, 145, 122, 68, 34, 134, 31, 147, 17, 39, 188, 150, 76, + 45, 42, 167, 249, 12, 16, 23, 182, 13, 79, 121, 3, 70, 197, 239, 44, + 86, 177, 255, 81, 64, 171, 138, 131, 73, 110, 44, 201, 254, 198, 146, 91, + 48, 9, 104, 31, 29, 161, 101, 31, 138, 180, 231, 233, 79, 137, 61, 236, + 140, 15, 249, 218, 234, 119, 99, 195, 110, 137, 237, 207, 8, 31, 45, 24, + 90, 155, 203, 253, 192, 203, 65, 176, 210, 171, 142, 214, 220, 122, 136, 237, + 189, 186, 147, 40, 80, 254, 173, 33, 191, 46, 192, 26, 108, 255, 228, 205, + 61, 76, 39, 107, 225, 126, 228, 182, 140, 251, 143, 134, 252, 168, 221, 8, + 185, 85, 60, 233, 147, 244, 87, 137, 8, 140, 96, 80, 53, 45, 175, 160, + 124, 189, 112, 37, 144, 19, 70, 17, 170, 242, 2, 3, 28, 95, 120, 199, + 212, 43, 9, 117, 86, 151, 101, 241, 200, 145, 241, 19, 178, 69, 204, 197, + 227, 166, 94, 7, 193, 45, 247, 234, 19, 187, 212, 212, 236, 125, 33, 95, + 198, 121, 122, 103, 77, 155, 235, 49, 25, 237, 249, 11, 162, 7, 238, 24, + 16, 150, 129, 25, 152, 17, 42, 67, 247, 162, 77, 154, 31, 133, 55, 137, + 79, 119, 153, 10, 86, 28, 244, 186, 41, 169, 106, 44, 10, 49, 110, 179, + 32, 133, 155, 244, 61, 70, 131, 168, 170, 39, 231, 252, 32, 69, 92, 238, + 239, 35, 132, 136, 236, 167, 90, 32, 123, 88, 69, 22, 20, 89, 145, 166, + 30, 118, 75, 4, 49, 31, 225, 54, 11, 50, 56, 191, 246, 1, 187, 33, + 119, 107, 139, 68, 19, 240, 131, 55, 94, 113, 31, 252, 12, 179, 121, 2, + 120, 252, 0, 76, 41, 80, 185, 42, 62, 121, 105, 159, 121, 109, 111, 98, + 7, 118, 86, 29, 210, 70, 231, 179, 223, 229, 164, 70, 62, 47, 0, 206, + 204, 178, 168, 120, 224, 166, 99, 25, 103, 63, 246, 224, 117, 204, 75, 124, + 140, 133, 110, 110, 222, 88, 151, 118, 46, 37, 22, 143, 158, 40, 2, 50, + 153, 94, 190, 199, 13, 198, 127, 211, 180, 90, 183, 98, 0, 142, 210, 154, + 100, 187, 67, 231, 202, 100, 198, 235, 252, 160, 247, 124, 247, 14, 121, 221, + 57, 88, 253, 243, 185, 89, 45, 249, 221, 194, 108, 175, 193, 119, 50, 141, + 223, 133, 136, 64, 176, 250, 129, 100, 124, 94, 181, 159, 99, 185, 177, 240, + 135, 42, 103, 52, 202, 208, 143, 186, 193, 103, 154, 237, 102, 88, 225, 161, + 50, 188, 191, 109, 12, 87, 19, 227, 247, 183, 13, 52, 205, 170, 205, 146, + 89, 160, 18, 105, 192, 73, 231, 225, 184, 157, 252, 220, 61, 59, 169, 183, + 221, 20, 141, 20, 158, 101, 245, 7, 245, 225, 118, 137, 84, 55, 19, 27, + 164, 110, 35, 25, 202, 94, 150, 46, 91, 152, 130, 1, 7, 46, 16, 237, + 171, 109, 19, 200, 65, 38, 10, 213, 70, 96, 126, 226, 185, 225, 181, 46, + 10, 165, 11, 123, 53, 158, 22, 147, 64, 22, 227, 69, 182, 237, 197, 37, + 39, 49, 186, 223, 139, 128, 55, 36, 166, 178, 220, 20, 98, 172, 166, 253, + 45, 0, 120, 180, 189, 185, 158, 159, 196, 6, 214, 79, 141, 52, 156, 107, + 5, 109, 142, 159, 33, 64, 190, 133, 95, 132, 95, 202, 160, 63, 186, 23, + 231, 107, 163, 33, 234, 15, 244, 77, 108, 49, 51, 7, 164, 87, 142, 99, + 240, 202, 47, 256, 118, 190, 196, 178, 217, 42, 39, 153, 21, 192, 232, 202, + 14, 82, 179, 64, 233, 4, 219, 10, 133, 78, 43, 144, 146, 216, 202, 81, + 71, 252, 8, 201, 68, 256, 85, 233, 164, 88, 176, 30, 5, 152, 126, 179, + 249, 84, 140, 190, 159, 54, 118, 98, 2, 159, 27, 133, 74, 121, 239, 196, + 71, 149, 119, 135, 102, 20, 87, 112, 44, 75, 221, 3, 151, 158, 5, 98, + 152, 25, 97, 106, 63, 171, 240, 79, 234, 240, 230, 92, 76, 70, 173, 196, + 36, 225, 218, 133, 64, 240, 150, 41, 146, 66, 133, 51, 134, 73, 170, 238, + 140, 90, 45, 89, 46, 147, 96, 169, 174, 174, 244, 151, 90, 40, 32, 74, + 38, 154, 246, 57, 31, 14, 189, 151, 83, 243, 197, 183, 220, 185, 53, 225, + 51, 106, 188, 208, 222, 248, 93, 13, 93, 215, 131, 25, 142, 185, 113, 222, + 131, 215, 149, 50, 159, 85, 32, 5, 205, 192, 2, 227, 42, 214, 197, 42, + 126, 182, 68, 123, 109, 36, 237, 179, 170, 199, 77, 256, 5, 128, 214, 243, + 137, 177, 170, 253, 179, 180, 153, 236, 100, 196, 216, 231, 198, 37, 192, 80, + 121, 221, 246, 1, 16, 246, 29, 78, 64, 148, 124, 38, 96, 125, 28, 20, + 48, 51, 73, 187, 139, 208, 98, 253, 221, 188, 84, 129, 1, 205, 95, 205, + 117, 79, 71, 126, 134, 237, 19, 184, 137, 125, 129, 178, 223, 54, 188, 112, + 30, 7, 225, 228, 205, 184, 233, 87, 117, 22, 58, 10, 8, 42, 2, 114, + 254, 19, 17, 13, 150, 92, 233, 179, 63, 12, 60, 171, 127, 35, 50, 5, + 195, 113, 241, 25, 249, 184, 166, 44, 221, 35, 151, 116, 8, 54, 195, 89, + 218, 186, 132, 5, 41, 89, 226, 177, 11, 41, 87, 172, 5, 23, 20, 59, + 228, 94, 76, 33, 137, 43, 151, 221, 61, 232, 4, 120, 93, 217, 80, 228, + 228, 6, 58, 25, 62, 84, 91, 48, 209, 20, 247, 243, 55, 106, 80, 79, + 235, 34, 20, 180, 146, 2, 236, 13, 236, 206, 243, 222, 204, 83, 148, 213, + 214, 117, 237, 98, 0, 90, 204, 168, 32, 41, 126, 67, 191, 74, 27, 255, + 26, 75, 240, 113, 185, 105, 167, 154, 112, 67, 151, 63, 161, 134, 239, 176, + 42, 87, 249, 130, 45, 242, 17, 100, 107, 120, 212, 218, 237, 76, 231, 162, + 175, 172, 118, 155, 92, 36, 124, 17, 121, 71, 13, 9, 82, 126, 147, 142, + 218, 148, 138, 80, 163, 106, 164, 123, 140, 129, 35, 42, 186, 154, 228, 214, + 75, 73, 8, 253, 42, 153, 232, 164, 95, 24, 110, 90, 231, 197, 90, 196, + 57, 164, 252, 181, 31, 7, 97, 256, 35, 77, 200, 212, 99, 179, 92, 227, + 17, 180, 49, 176, 9, 188, 13, 182, 93, 44, 128, 219, 134, 92, 151, 6, + 23, 126, 200, 109, 66, 30, 140, 180, 146, 134, 67, 200, 7, 9, 223, 168, + 186, 221, 3, 154, 150, 165, 43, 53, 138, 27, 86, 213, 235, 160, 70, 2, + 240, 20, 89, 212, 84, 141, 168, 246, 183, 227, 30, 167, 138, 185, 253, 83, + 52, 143, 236, 94, 59, 65, 89, 218, 194, 157, 164, 156, 111, 95, 202, 168, + 245, 256, 151, 28, 222, 194, 72, 130, 217, 134, 253, 77, 246, 100, 76, 32, + 254, 174, 182, 193, 14, 237, 74, 1, 74, 26, 135, 216, 152, 208, 112, 38, + 181, 62, 25, 71, 61, 234, 254, 97, 191, 23, 92, 256, 190, 205, 6, 16, + 134, 147, 210, 219, 148, 59, 73, 185, 24, 247, 174, 143, 116, 220, 128, 144, + 111, 126, 101, 98, 130, 136, 101, 102, 69, 127, 24, 168, 146, 226, 226, 207, + 176, 122, 149, 254, 134, 196, 22, 151, 197, 21, 50, 205, 116, 154, 65, 116, + 177, 224, 127, 77, 177, 159, 225, 69, 176, 54, 100, 104, 140, 8, 11, 126, + 11, 188, 185, 159, 107, 16, 254, 142, 80, 28, 5, 157, 104, 57, 109, 82, + 102, 80, 173, 242, 238, 207, 57, 105, 237, 160, 59, 189, 189, 199, 26, 11, + 190, 156, 97, 118, 20, 12, 254, 189, 165, 147, 142, 199, 5, 213, 64, 133, + 108, 217, 133, 60, 94, 28, 116, 136, 47, 165, 125, 42, 183, 143, 14, 129, + 223, 70, 212, 205, 181, 180, 3, 201, 182, 46, 57, 104, 239, 60, 99, 181, + 220, 231, 45, 79, 156, 89, 149, 143, 190, 103, 153, 61, 235, 73, 136, 20, + 89, 243, 16, 130, 247, 141, 134, 93, 80, 68, 85, 84, 8, 72, 194, 4, + 242, 110, 19, 133, 199, 70, 172, 92, 132, 254, 67, 74, 36, 94, 13, 90, + 154, 184, 9, 109, 118, 243, 214, 71, 36, 95, 0, 90, 201, 105, 112, 215, + 69, 196, 224, 210, 236, 242, 155, 211, 37, 134, 69, 113, 157, 97, 68, 26, + 230, 149, 219, 180, 20, 76, 172, 145, 154, 40, 129, 8, 93, 56, 162, 124, + 207, 233, 105, 19, 3, 183, 155, 134, 8, 244, 213, 78, 139, 88, 156, 37, + 51, 152, 111, 102, 112, 250, 114, 252, 201, 241, 133, 24, 136, 153, 5, 90, + 210, 197, 216, 24, 131, 17, 147, 246, 13, 86, 3, 253, 179, 237, 101, 114, + 243, 191, 207, 2, 220, 133, 244, 53, 87, 125, 154, 158, 197, 20, 8, 83, + 32, 191, 38, 241, 204, 22, 168, 59, 217, 123, 162, 82, 21, 50, 130, 89, + 239, 253, 195, 56, 253, 74, 147, 125, 234, 199, 250, 28, 65, 193, 22, 237, + 193, 94, 58, 229, 139, 176, 69, 42, 179, 164, 150, 168, 246, 214, 86, 174, + 59, 117, 15, 19, 76, 37, 214, 238, 153, 226, 154, 45, 109, 114, 198, 107, + 45, 70, 238, 196, 142, 252, 244, 71, 123, 136, 134, 188, 99, 132, 25, 42, + 240, 0, 196, 33, 26, 124, 256, 145, 27, 102, 153, 35, 28, 132, 221, 167, + 138, 133, 41, 170, 95, 224, 40, 139, 239, 153, 1, 106, 255, 106, 170, 163, + 127, 44, 155, 232, 194, 119, 232, 117, 239, 143, 108, 41, 3, 9, 180, 256, + 144, 113, 133, 200, 79, 69, 128, 216, 31, 50, 102, 209, 249, 136, 150, 154, + 182, 51, 228, 39, 127, 142, 87, 15, 94, 92, 187, 245, 31, 236, 64, 58, + 114, 11, 17, 166, 189, 152, 218, 34, 123, 39, 58, 37, 153, 91, 63, 121, + 31, 34, 12, 254, 106, 96, 171, 14, 155, 247, 214, 69, 24, 98, 3, 204, + 202, 194, 207, 30, 253, 44, 119, 70, 14, 96, 82, 250, 63, 6, 232, 38, + 89, 144, 102, 191, 82, 254, 20, 222, 96, 162, 110, 6, 159, 58, 200, 226, + 98, 128, 42, 70, 84, 247, 128, 211, 136, 54, 143, 166, 60, 118, 99, 218, + 27, 193, 85, 81, 219, 223, 46, 41, 23, 233, 152, 222, 36, 236, 54, 181, + 56, 50, 4, 207, 129, 92, 78, 88, 197, 251, 131, 105, 31, 172, 38, 131, + 19, 204, 129, 47, 227, 106, 202, 183, 23, 6, 77, 224, 102, 147, 11, 218, + 131, 132, 60, 192, 208, 223, 236, 23, 103, 115, 89, 18, 185, 171, 70, 174, + 139, 0, 100, 160, 221, 11, 228, 60, 12, 122, 114, 12, 157, 235, 148, 57, + 83, 62, 173, 131, 169, 126, 85, 99, 93, 243, 81, 80, 29, 245, 206, 82, + 236, 227, 166, 14, 230, 213, 144, 97, 27, 111, 99, 164, 105, 150, 89, 111, + 252, 118, 140, 232, 120, 183, 137, 213, 232, 157, 224, 33, 134, 118, 186, 80, + 159, 2, 186, 193, 54, 242, 25, 237, 232, 249, 226, 213, 90, 149, 90, 160, + 118, 69, 64, 37, 10, 183, 109, 246, 30, 52, 219, 69, 189, 26, 116, 220, + 50, 244, 243, 243, 139, 137, 232, 98, 38, 45, 256, 143, 171, 101, 73, 238, + 123, 45, 194, 167, 250, 123, 12, 29, 136, 237, 141, 21, 89, 96, 199, 44, + 8, 214, 208, 17, 113, 41, 137, 26, 166, 155, 89, 85, 54, 58, 97, 160, + 50, 239, 58, 71, 21, 157, 139, 12, 37, 198, 182, 131, 149, 134, 16, 204, + 164, 181, 248, 166, 52, 216, 136, 201, 37, 255, 187, 240, 5, 101, 147, 231, + 14, 163, 253, 134, 146, 216, 8, 54, 224, 90, 220, 195, 75, 215, 186, 58, + 71, 204, 124, 105, 239, 53, 16, 85, 69, 163, 195, 223, 33, 38, 69, 88, + 88, 203, 99, 55, 176, 13, 156, 204, 236, 99, 194, 134, 75, 247, 126, 129, + 160, 124, 233, 206, 139, 144, 154, 45, 233, 51, 206, 61, 60, 55, 205, 107, + 84, 108, 96, 188, 203, 31, 89, 20, 115, 144, 137, 90, 237, 78, 231, 185, + 120, 217, 1, 176, 169, 30, 155, 176, 100, 113, 53, 42, 193, 108, 14, 121, + 176, 158, 137, 92, 178, 44, 110, 249, 108, 234, 94, 101, 128, 12, 250, 173, + 72, 202, 232, 66, 139, 152, 189, 18, 32, 197, 9, 238, 246, 55, 119, 183, + 196, 119, 113, 247, 191, 100, 200, 245, 46, 16, 234, 112, 136, 116, 232, 48, + 176, 108, 11, 237, 14, 153, 93, 177, 124, 72, 67, 121, 135, 143, 45, 18, + 97, 251, 184, 172, 136, 55, 213, 8, 103, 12, 221, 212, 13, 160, 116, 91, + 237, 127, 218, 190, 103, 131, 77, 82, 36, 100, 22, 252, 79, 69, 54, 26, + 65, 182, 115, 142, 247, 20, 89, 81, 188, 244, 27, 120, 240, 248, 13, 230, + 67, 133, 32, 201, 129, 87, 9, 245, 66, 88, 166, 34, 46, 184, 119, 218, + 144, 235, 163, 40, 138, 134, 127, 217, 64, 227, 116, 67, 55, 202, 130, 48, + 199, 42, 251, 112, 124, 153, 123, 194, 243, 49, 250, 12, 78, 157, 167, 134, + 210, 73, 156, 102, 21, 88, 216, 123, 45, 11, 208, 18, 47, 187, 20, 43, + 3, 180, 124, 2, 136, 176, 77, 111, 138, 139, 91, 225, 126, 8, 74, 255, + 88, 192, 193, 239, 138, 204, 139, 194, 166, 130, 252, 184, 140, 168, 30, 177, + 121, 98, 131, 124, 69, 171, 75, 49, 184, 34, 76, 122, 202, 115, 184, 253, + 120, 182, 33, 251, 1, 74, 216, 217, 243, 168, 70, 162, 119, 158, 197, 198, + 61, 89, 7, 5, 54, 199, 211, 170, 23, 226, 44, 247, 165, 195, 7, 225, + 91, 23, 50, 15, 51, 208, 106, 94, 12, 31, 43, 112, 146, 139, 246, 182, + 113, 1, 97, 15, 66, 2, 51, 76, 164, 184, 237, 200, 218, 176, 72, 98, + 33, 135, 38, 147, 140, 229, 50, 94, 81, 187, 129, 17, 238, 168, 146, 203, + 181, 99, 164, 3, 104, 98, 255, 189, 114, 142, 86, 102, 229, 102, 80, 129, + 64, 84, 79, 161, 81, 156, 128, 111, 164, 197, 18, 15, 55, 196, 198, 191, + 28, 113, 117, 96, 207, 253, 19, 158, 231, 13, 53, 130, 252, 211, 58, 180, + 212, 142, 7, 219, 38, 81, 62, 109, 167, 113, 33, 56, 97, 185, 157, 130, + 186, 129, 119, 182, 196, 26, 54, 110, 65, 170, 166, 236, 30, 22, 162, 0, + 106, 12, 248, 33, 48, 72, 159, 17, 76, 244, 172, 132, 89, 171, 196, 76, + 254, 166, 76, 218, 226, 3, 52, 220, 238, 181, 179, 144, 225, 23, 3, 166, + 158, 35, 228, 154, 204, 23, 203, 71, 134, 189, 18, 168, 236, 141, 117, 138, + 2, 132, 78, 57, 154, 21, 250, 196, 184, 40, 161, 40, 10, 178, 134, 120, + 132, 123, 101, 82, 205, 121, 55, 140, 231, 56, 231, 71, 206, 246, 198, 150, + 146, 192, 45, 105, 242, 1, 125, 18, 176, 46, 222, 122, 19, 80, 113, 133, + 131, 162, 81, 51, 98, 168, 247, 161, 139, 39, 63, 162, 22, 153, 170, 92, + 91, 130, 174, 200, 45, 112, 99, 164, 132, 184, 191, 186, 200, 167, 86, 145, + 167, 227, 130, 44, 12, 158, 172, 249, 204, 17, 54, 249, 16, 200, 21, 174, + 67, 223, 105, 201, 50, 36, 133, 203, 244, 131, 228, 67, 29, 195, 91, 91, + 55, 107, 167, 154, 170, 137, 218, 183, 169, 61, 99, 175, 128, 23, 142, 183, + 66, 255, 59, 187, 66, 85, 212, 109, 168, 82, 16, 43, 67, 139, 114, 176, + 216, 255, 130, 94, 152, 79, 183, 64, 100, 23, 214, 82, 34, 230, 48, 15, + 242, 130, 50, 241, 81, 32, 5, 125, 183, 182, 184, 99, 248, 109, 159, 210, + 226, 61, 119, 129, 39, 149, 78, 214, 107, 78, 147, 124, 228, 18, 143, 188, + 84, 180, 233, 119, 64, 39, 158, 133, 177, 168, 6, 150, 80, 117, 150, 56, + 49, 72, 49, 37, 30, 242, 49, 142, 33, 156, 34, 44, 44, 72, 58, 22, + 249, 46, 168, 80, 25, 196, 64, 174, 97, 179, 244, 134, 213, 105, 63, 151, + 21, 90, 168, 90, 245, 28, 157, 65, 250, 232, 188, 27, 99, 160, 156, 127, + 68, 193, 10, 80, 205, 36, 138, 229, 12, 223, 70, 169, 251, 41, 48, 94, + 41, 177, 99, 256, 158, 0, 6, 83, 231, 191, 120, 135, 157, 146, 218, 213, + 160, 7, 47, 234, 98, 211, 79, 225, 179, 95, 175, 105, 185, 79, 115, 0, + 104, 14, 65, 124, 15, 188, 52, 9, 253, 27, 132, 137, 13, 127, 75, 238, + 185, 253, 33, 8, 52, 157, 164, 68, 232, 188, 69, 28, 209, 233, 5, 129, + 216, 90, 252, 212, 33, 200, 222, 9, 112, 15, 43, 36, 226, 114, 15, 249, + 217, 8, 148, 22, 147, 23, 143, 67, 222, 116, 235, 250, 212, 210, 39, 142, + 108, 64, 209, 83, 73, 66, 99, 34, 17, 29, 45, 151, 244, 114, 28, 241, + 144, 208, 146, 179, 132, 89, 217, 198, 252, 219, 205, 165, 75, 107, 11, 173, + 76, 6, 196, 247, 152, 216, 248, 91, 209, 178, 57, 250, 174, 60, 79, 123, + 18, 135, 9, 241, 230, 159, 184, 68, 156, 251, 215, 9, 113, 234, 75, 235, + 103, 194, 205, 129, 230, 45, 96, 73, 157, 20, 200, 212, 212, 228, 161, 7, + 231, 228, 108, 43, 198, 87, 140, 140, 4, 182, 164, 3, 53, 104, 250, 213, + 85, 38, 89, 61, 52, 187, 35, 204, 86, 249, 100, 71, 248, 213, 163, 215, + 66, 106, 252, 129, 40, 111, 47, 24, 186, 221, 85, 205, 199, 237, 122, 181, + 32, 46, 182, 135, 33, 251, 142, 34, 208, 242, 128, 255, 4, 234, 15, 33, + 167, 222, 32, 186, 191, 34, 255, 244, 98, 240, 228, 204, 30, 142, 32, 70, + 69, 83, 110, 151, 10, 243, 141, 21, 223, 69, 61, 37, 59, 209, 102, 114, + 223, 33, 129, 254, 255, 103, 86, 247, 235, 72, 126, 177, 102, 226, 102, 30, + 149, 221, 62, 247, 251, 120, 163, 173, 57, 202, 204, 24, 39, 106, 120, 143, + 202, 176, 191, 147, 37, 38, 51, 133, 47, 245, 157, 132, 154, 71, 183, 111, + 30, 180, 18, 202, 82, 96, 170, 91, 157, 181, 212, 140, 256, 8, 196, 121, + 149, 79, 66, 127, 113, 78, 4, 197, 84, 256, 111, 222, 102, 63, 228, 104, + 136, 223, 67, 193, 93, 154, 249, 83, 204, 101, 200, 234, 84, 252, 230, 195, + 43, 140, 120, 242, 89, 63, 166, 233, 209, 94, 43, 170, 126, 5, 205, 78, + 112, 80, 143, 151, 146, 248, 137, 203, 45, 183, 61, 1, 155, 8, 102, 59, + 68, 212, 230, 61, 254, 191, 128, 223, 176, 123, 229, 27, 146, 120, 96, 165, + 213, 12, 232, 40, 186, 225, 66, 105, 200, 195, 212, 110, 237, 238, 151, 19, + 12, 171, 150, 82, 7, 228, 79, 52, 15, 78, 62, 43, 21, 154, 114, 21, + 12, 212, 256, 232, 125, 127, 5, 51, 37, 252, 136, 13, 47, 195, 168, 191, + 231, 55, 57, 251, 214, 116, 15, 86, 210, 41, 249, 242, 119, 27, 250, 203, + 107, 69, 90, 43, 206, 154, 127, 54, 100, 78, 187, 54, 244, 177, 234, 167, + 202, 136, 209, 171, 69, 114, 133, 173, 26, 139, 78, 141, 128, 32, 124, 39, + 45, 218, 96, 68, 90, 44, 67, 62, 83, 190, 188, 256, 103, 42, 102, 64, + 249, 0, 141, 11, 61, 69, 70, 66, 233, 237, 29, 200, 251, 157, 71, 51, + 64, 133, 113, 76, 35, 125, 76, 137, 217, 145, 35, 69, 226, 180, 56, 249, + 156, 163, 176, 237, 81, 54, 85, 169, 115, 211, 129, 70, 248, 40, 252, 192, + 194, 101, 247, 8, 181, 124, 217, 191, 194, 93, 99, 127, 117, 177, 144, 151, + 228, 121, 32, 11, 89, 81, 26, 29, 183, 76, 249, 132, 179, 70, 34, 102, + 20, 66, 87, 63, 124, 205, 174, 177, 87, 219, 73, 218, 91, 87, 176, 72, + 15, 211, 47, 61, 251, 165, 39, 247, 146, 70, 150, 57, 1, 212, 36, 162, + 39, 38, 16, 216, 3, 50, 116, 200, 32, 234, 77, 181, 155, 19, 90, 188, + 36, 6, 254, 46, 46, 203, 25, 230, 181, 196, 4, 151, 225, 65, 122, 216, + 168, 86, 158, 131, 136, 16, 49, 102, 233, 64, 154, 88, 228, 52, 146, 69, + 93, 157, 243, 121, 70, 209, 126, 213, 88, 145, 236, 65, 70, 96, 204, 47, + 10, 200, 77, 8, 103, 150, 48, 153, 5, 37, 52, 235, 209, 31, 181, 126, + 83, 142, 224, 140, 6, 32, 200, 171, 160, 179, 115, 229, 75, 194, 208, 39, + 59, 223, 52, 247, 38, 197, 135, 1, 6, 189, 106, 114, 168, 5, 211, 222, + 44, 63, 90, 160, 116, 172, 170, 133, 125, 138, 39, 131, 23, 178, 10, 214, + 36, 93, 28, 59, 68, 17, 123, 25, 255, 184, 204, 102, 194, 214, 129, 94, + 159, 245, 112, 141, 62, 11, 61, 197, 124, 221, 205, 11, 79, 71, 201, 54, + 58, 150, 29, 121, 87, 46, 240, 201, 68, 20, 194, 209, 47, 152, 158, 174, + 193, 164, 120, 255, 216, 165, 247, 58, 85, 130, 220, 23, 122, 223, 188, 98, + 21, 70, 72, 170, 150, 237, 76, 143, 112, 238, 206, 146, 215, 110, 4, 250, + 68, 44, 174, 177, 30, 98, 143, 241, 180, 127, 113, 48, 0, 1, 179, 199, + 59, 106, 201, 114, 29, 86, 173, 133, 217, 44, 200, 141, 107, 172, 16, 60, + 82, 58, 239, 94, 141, 234, 186, 235, 109, 173, 249, 139, 141, 59, 100, 248, + 84, 144, 49, 160, 51, 207, 164, 103, 74, 97, 146, 202, 193, 125, 168, 134, + 236, 111, 135, 121, 59, 145, 168, 200, 181, 173, 109, 2, 255, 6, 9, 245, + 90, 202, 214, 143, 121, 65, 85, 232, 132, 77, 228, 84, 26, 54, 184, 15, + 161, 29, 177, 79, 43, 0, 156, 184, 163, 165, 62, 90, 179, 93, 45, 239, + 1, 16, 120, 189, 127, 47, 74, 166, 20, 214, 233, 226, 89, 217, 229, 26, + 156, 53, 162, 60, 21, 3, 192, 72, 111, 51, 53, 101, 181, 208, 88, 82, + 179, 160, 219, 113, 240, 108, 43, 224, 162, 147, 62, 14, 95, 81, 205, 4, + 160, 177, 225, 115, 29, 69, 235, 168, 148, 29, 128, 114, 124, 129, 172, 165, + 215, 231, 214, 86, 160, 44, 157, 91, 248, 183, 73, 164, 56, 181, 162, 92, + 141, 118, 127, 240, 196, 77, 0, 9, 244, 79, 250, 100, 195, 25, 255, 85, + 94, 35, 212, 137, 107, 34, 110, 20, 200, 104, 17, 32, 231, 43, 150, 159, + 231, 216, 223, 190, 226, 109, 162, 197, 87, 92, 224, 11, 111, 73, 60, 225, + 238, 73, 246, 169, 19, 217, 119, 38, 121, 118, 70, 82, 99, 241, 110, 67, + 31, 76, 146, 215, 124, 240, 31, 103, 139, 224, 75, 160, 31, 78, 93, 4, + 64, 9, 103, 223, 6, 227, 119, 85, 116, 81, 21, 43, 46, 206, 234, 132, + 85, 99, 22, 131, 135, 97, 86, 13, 234, 188, 21, 14, 89, 169, 207, 238, + 219, 177, 190, 72, 157, 41, 114, 140, 92, 141, 186, 1, 63, 107, 225, 184, + 118, 150, 153, 254, 241, 106, 120, 210, 104, 144, 151, 161, 88, 206, 125, 164, + 15, 211, 173, 49, 146, 241, 71, 36, 58, 201, 46, 27, 33, 187, 91, 162, + 117, 19, 210, 213, 187, 97, 193, 50, 190, 114, 217, 60, 61, 167, 207, 213, + 213, 53, 135, 34, 156, 91, 115, 119, 46, 99, 242, 1, 90, 52, 198, 227, + 201, 91, 216, 146, 210, 82, 121, 38, 73, 133, 182, 193, 132, 148, 246, 75, + 109, 157, 179, 113, 176, 134, 205, 159, 148, 58, 103, 171, 132, 156, 133, 147, + 161, 231, 39, 100, 175, 97, 125, 28, 183, 129, 135, 191, 202, 181, 29, 218, + 43, 104, 148, 203, 189, 204, 4, 182, 169, 1, 134, 122, 141, 202, 13, 187, + 177, 112, 162, 35, 231, 6, 8, 241, 99, 6, 191, 45, 113, 113, 101, 104}; + +// The S-Box we use for further linearity breaking. +// We created it by taking the digits of decimal expansion of e. +// The code that created it can be found in 'ProduceRandomSBox.c'. +unsigned char SBox[256] = { +//0 1 2 3 4 5 6 7 8 9 A B C D E F +0x7d, 0xd1, 0x70, 0x0b, 0xfa, 0x39, 0x18, 0xc3, 0xf3, 0xbb, 0xa7, 0xd4, 0x84, 0x25, 0x3b, 0x3c, // 0 +0x2c, 0x15, 0x69, 0x9a, 0xf9, 0x27, 0xfb, 0x02, 0x52, 0xba, 0xa8, 0x4b, 0x20, 0xb5, 0x8b, 0x3a, // 1 +0x88, 0x8e, 0x26, 0xcb, 0x71, 0x5e, 0xaf, 0xad, 0x0c, 0xac, 0xa1, 0x93, 0xc6, 0x78, 0xce, 0xfc, // 2 +0x2a, 0x76, 0x17, 0x1f, 0x62, 0xc2, 0x2e, 0x99, 0x11, 0x37, 0x65, 0x40, 0xfd, 0xa0, 0x03, 0xc1, // 3 +0xca, 0x48, 0xe2, 0x9b, 0x81, 0xe4, 0x1c, 0x01, 0xec, 0x68, 0x7a, 0x5a, 0x50, 0xf8, 0x0e, 0xa3, // 4 +0xe8, 0x61, 0x2b, 0xa2, 0xeb, 0xcf, 0x8c, 0x3d, 0xb4, 0x95, 0x13, 0x08, 0x46, 0xab, 0x91, 0x7b, // 5 +0xea, 0x55, 0x67, 0x9d, 0xdd, 0x29, 0x6a, 0x8f, 0x9f, 0x22, 0x4e, 0xf2, 0x57, 0xd2, 0xa9, 0xbd, // 6 +0x38, 0x16, 0x5f, 0x4c, 0xf7, 0x9e, 0x1b, 0x2f, 0x30, 0xc7, 0x41, 0x24, 0x5c, 0xbf, 0x05, 0xf6, // 7 +0x0a, 0x31, 0xa5, 0x45, 0x21, 0x33, 0x6b, 0x6d, 0x6c, 0x86, 0xe1, 0xa4, 0xe6, 0x92, 0x9c, 0xdf, // 8 +0xe7, 0xbe, 0x28, 0xe3, 0xfe, 0x06, 0x4d, 0x98, 0x80, 0x04, 0x96, 0x36, 0x3e, 0x14, 0x4a, 0x34, // 9 +0xd3, 0xd5, 0xdb, 0x44, 0xcd, 0xf5, 0x54, 0xdc, 0x89, 0x09, 0x90, 0x42, 0x87, 0xff, 0x7e, 0x56, // A +0x5d, 0x59, 0xd7, 0x23, 0x75, 0x19, 0x97, 0x73, 0x83, 0x64, 0x53, 0xa6, 0x1e, 0xd8, 0xb0, 0x49, // B +0x3f, 0xef, 0xbc, 0x7f, 0x43, 0xf0, 0xc9, 0x72, 0x0f, 0x63, 0x79, 0x2d, 0xc0, 0xda, 0x66, 0xc8, // C +0x32, 0xde, 0x47, 0x07, 0xb8, 0xe9, 0x1d, 0xc4, 0x85, 0x74, 0x82, 0xcc, 0x60, 0x51, 0x77, 0x0d, // D +0xaa, 0x35, 0xed, 0x58, 0x7c, 0x5b, 0xb9, 0x94, 0x6e, 0x8d, 0xb1, 0xc5, 0xb7, 0xee, 0xb6, 0xae, // E +0x10, 0xe0, 0xd6, 0xd9, 0xe5, 0x4f, 0xf1, 0x12, 0x00, 0xd0, 0xf4, 0x1a, 0x6f, 0x8a, 0xb3, 0xb2 }; // F + +/////////////////////////////////////////////////////////////////////////////////////////////// +// +// Helper functions definition portion. +// +/////////////////////////////////////////////////////////////////////////////////////////////// + +// Translates an input array with values in base 257 to output array with values in base 256. +// Returns the carry bit. +// +// Parameters: +// - input: the input array of size EIGHTH_N. Each value in the array is a number in Z_257. +// The MSB is assumed to be the last one in the array. +// - output: the input array encoded in base 256. +// +// Returns: +// - The carry bit (MSB). +swift_int16_t TranslateToBase256(swift_int32_t input[EIGHTH_N], unsigned char output[EIGHTH_N]); + +// Translates an input integer into the range (-FIELD_SIZE / 2) <= result <= (FIELD_SIZE / 2). +// +// Parameters: +// - x: the input integer. +// +// Returns: +// - The result, which equals (x MOD FIELD_SIZE), such that |result| <= (FIELD_SIZE / 2). +int Center(int x); + +// Calculates bit reversal permutation. +// +// Parameters: +// - input: the input to reverse. +// - numOfBits: the number of bits in the input to reverse. +// +// Returns: +// - The resulting number, which is obtained from the input by reversing its bits. +int ReverseBits(int input, int numOfBits); + +// Initializes the FFT fast lookup table. +// Shall be called only once. +void InitializeSWIFFTX(); + +// Calculates the FFT. +// +// Parameters: +// - input: the input to the FFT. +// - output: the resulting output. +void FFT(const unsigned char input[EIGHTH_N], swift_int32_t *output); + +/////////////////////////////////////////////////////////////////////////////////////////////// +// Helper functions implementation portion. +/////////////////////////////////////////////////////////////////////////////////////////////// + +swift_int16_t TranslateToBase256(swift_int32_t input[EIGHTH_N], unsigned char output[EIGHTH_N]) +{ + swift_int32_t pairs[EIGHTH_N / 2]; + int i; + + for (i = 0; i < EIGHTH_N; i += 2) + { + // input[i] + 257 * input[i + 1] + pairs[i >> 1] = input[i] + input[i + 1] + (input[i + 1] << 8); + } + + for (i = (EIGHTH_N / 2) - 1; i > 0; --i) + { + int j; + + for (j = i - 1; j < (EIGHTH_N / 2) - 1; ++j) + { + // pairs[j + 1] * 513, because 257^2 = 513 % 256^2. + register swift_int32_t temp = pairs[j] + pairs[j + 1] + (pairs[j + 1] << 9); + pairs[j] = temp & 0xffff; + pairs[j + 1] += (temp >> 16); + } + } + + for (i = 0; i < EIGHTH_N; i += 2) + { + output[i] = (unsigned char) (pairs[i >> 1] & 0xff); + output[i + 1] = (unsigned char) ((pairs[i >> 1] >> 8) & 0xff); + } + + return (pairs[EIGHTH_N/2 - 1] >> 16); +} + +int Center(int x) +{ + int result = x % FIELD_SIZE; + + if (result > (FIELD_SIZE / 2)) + result -= FIELD_SIZE; + + if (result < (FIELD_SIZE / -2)) + result += FIELD_SIZE; + + return result; +} + +int ReverseBits(int input, int numOfBits) +{ + register int reversed = 0; + + for (input |= numOfBits; input > 1; input >>= 1) + reversed = (reversed << 1) | (input & 1); + + return reversed; +} + +void InitializeSWIFFTX() +{ + int i, j, k, x; + // The powers of OMEGA + int omegaPowers[2 * N]; + omegaPowers[0] = 1; + + if (wasSetupDone) + return; + + for (i = 1; i < (2 * N); ++i) + { + omegaPowers[i] = Center(omegaPowers[i - 1] * OMEGA); + } + + for (i = 0; i < (N / W); ++i) + { + for (j = 0; j < W; ++j) + { + multipliers[(i << 3) + j] = omegaPowers[ReverseBits(i, N / W) * (2 * j + 1)]; + } + } + + for (x = 0; x < 256; ++x) + { + for (j = 0; j < 8; ++j) + { + register int temp = 0; + for (k = 0; k < 8; ++k) + { + temp += omegaPowers[(EIGHTH_N * (2 * j + 1) * ReverseBits(k, W)) % (2 * N)] + * ((x >> k) & 1); + } + + fftTable[(x << 3) + j] = Center(temp); + } + } + + wasSetupDone = true; +} + +void FFT(const unsigned char input[EIGHTH_N], swift_int32_t *output) +{ + register swift_int16_t *mult = multipliers; + register swift_int32_t F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, + F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, + F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, + F30, F31, F32, F33, F34, F35, F36, F37, F38, F39, + F40, F41, F42, F43, F44, F45, F46, F47, F48, F49, + F50, F51, F52, F53, F54, F55, F56, F57, F58, F59, + F60, F61, F62, F63; + + // First loop unrolling: + register swift_int16_t *table = &(fftTable[input[0] << 3]); + + F0 = mult[0] * table[0]; + F8 = mult[1] * table[1]; + F16 = mult[2] * table[2]; + F24 = mult[3] * table[3]; + F32 = mult[4] * table[4]; + F40 = mult[5] * table[5]; + F48 = mult[6] * table[6]; + F56 = mult[7] * table[7]; + + mult += 8; + table = &(fftTable[input[1] << 3]); + + F1 = mult[0] * table[0]; + F9 = mult[1] * table[1]; + F17 = mult[2] * table[2]; + F25 = mult[3] * table[3]; + F33 = mult[4] * table[4]; + F41 = mult[5] * table[5]; + F49 = mult[6] * table[6]; + F57 = mult[7] * table[7]; + + mult += 8; + table = &(fftTable[input[2] << 3]); + + F2 = mult[0] * table[0]; + F10 = mult[1] * table[1]; + F18 = mult[2] * table[2]; + F26 = mult[3] * table[3]; + F34 = mult[4] * table[4]; + F42 = mult[5] * table[5]; + F50 = mult[6] * table[6]; + F58 = mult[7] * table[7]; + + mult += 8; + table = &(fftTable[input[3] << 3]); + + F3 = mult[0] * table[0]; + F11 = mult[1] * table[1]; + F19 = mult[2] * table[2]; + F27 = mult[3] * table[3]; + F35 = mult[4] * table[4]; + F43 = mult[5] * table[5]; + F51 = mult[6] * table[6]; + F59 = mult[7] * table[7]; + + mult += 8; + table = &(fftTable[input[4] << 3]); + + F4 = mult[0] * table[0]; + F12 = mult[1] * table[1]; + F20 = mult[2] * table[2]; + F28 = mult[3] * table[3]; + F36 = mult[4] * table[4]; + F44 = mult[5] * table[5]; + F52 = mult[6] * table[6]; + F60 = mult[7] * table[7]; + + mult += 8; + table = &(fftTable[input[5] << 3]); + + F5 = mult[0] * table[0]; + F13 = mult[1] * table[1]; + F21 = mult[2] * table[2]; + F29 = mult[3] * table[3]; + F37 = mult[4] * table[4]; + F45 = mult[5] * table[5]; + F53 = mult[6] * table[6]; + F61 = mult[7] * table[7]; + + mult += 8; + table = &(fftTable[input[6] << 3]); + + F6 = mult[0] * table[0]; + F14 = mult[1] * table[1]; + F22 = mult[2] * table[2]; + F30 = mult[3] * table[3]; + F38 = mult[4] * table[4]; + F46 = mult[5] * table[5]; + F54 = mult[6] * table[6]; + F62 = mult[7] * table[7]; + + mult += 8; + table = &(fftTable[input[7] << 3]); + + F7 = mult[0] * table[0]; + F15 = mult[1] * table[1]; + F23 = mult[2] * table[2]; + F31 = mult[3] * table[3]; + F39 = mult[4] * table[4]; + F47 = mult[5] * table[5]; + F55 = mult[6] * table[6]; + F63 = mult[7] * table[7]; + + // Second loop unrolling: + // Iteration 0: + ADD_SUB(F0, F1); + ADD_SUB(F2, F3); + ADD_SUB(F4, F5); + ADD_SUB(F6, F7); + + F3 <<= 4; + F7 <<= 4; + + ADD_SUB(F0, F2); + ADD_SUB(F1, F3); + ADD_SUB(F4, F6); + ADD_SUB(F5, F7); + + F5 <<= 2; + F6 <<= 4; + F7 <<= 6; + + ADD_SUB(F0, F4); + ADD_SUB(F1, F5); + ADD_SUB(F2, F6); + ADD_SUB(F3, F7); + + output[0] = Q_REDUCE(F0); + output[8] = Q_REDUCE(F1); + output[16] = Q_REDUCE(F2); + output[24] = Q_REDUCE(F3); + output[32] = Q_REDUCE(F4); + output[40] = Q_REDUCE(F5); + output[48] = Q_REDUCE(F6); + output[56] = Q_REDUCE(F7); + + // Iteration 1: + ADD_SUB(F8, F9); + ADD_SUB(F10, F11); + ADD_SUB(F12, F13); + ADD_SUB(F14, F15); + + F11 <<= 4; + F15 <<= 4; + + ADD_SUB(F8, F10); + ADD_SUB(F9, F11); + ADD_SUB(F12, F14); + ADD_SUB(F13, F15); + + F13 <<= 2; + F14 <<= 4; + F15 <<= 6; + + ADD_SUB(F8, F12); + ADD_SUB(F9, F13); + ADD_SUB(F10, F14); + ADD_SUB(F11, F15); + + output[1] = Q_REDUCE(F8); + output[9] = Q_REDUCE(F9); + output[17] = Q_REDUCE(F10); + output[25] = Q_REDUCE(F11); + output[33] = Q_REDUCE(F12); + output[41] = Q_REDUCE(F13); + output[49] = Q_REDUCE(F14); + output[57] = Q_REDUCE(F15); + + // Iteration 2: + ADD_SUB(F16, F17); + ADD_SUB(F18, F19); + ADD_SUB(F20, F21); + ADD_SUB(F22, F23); + + F19 <<= 4; + F23 <<= 4; + + ADD_SUB(F16, F18); + ADD_SUB(F17, F19); + ADD_SUB(F20, F22); + ADD_SUB(F21, F23); + + F21 <<= 2; + F22 <<= 4; + F23 <<= 6; + + ADD_SUB(F16, F20); + ADD_SUB(F17, F21); + ADD_SUB(F18, F22); + ADD_SUB(F19, F23); + + output[2] = Q_REDUCE(F16); + output[10] = Q_REDUCE(F17); + output[18] = Q_REDUCE(F18); + output[26] = Q_REDUCE(F19); + output[34] = Q_REDUCE(F20); + output[42] = Q_REDUCE(F21); + output[50] = Q_REDUCE(F22); + output[58] = Q_REDUCE(F23); + + // Iteration 3: + ADD_SUB(F24, F25); + ADD_SUB(F26, F27); + ADD_SUB(F28, F29); + ADD_SUB(F30, F31); + + F27 <<= 4; + F31 <<= 4; + + ADD_SUB(F24, F26); + ADD_SUB(F25, F27); + ADD_SUB(F28, F30); + ADD_SUB(F29, F31); + + F29 <<= 2; + F30 <<= 4; + F31 <<= 6; + + ADD_SUB(F24, F28); + ADD_SUB(F25, F29); + ADD_SUB(F26, F30); + ADD_SUB(F27, F31); + + output[3] = Q_REDUCE(F24); + output[11] = Q_REDUCE(F25); + output[19] = Q_REDUCE(F26); + output[27] = Q_REDUCE(F27); + output[35] = Q_REDUCE(F28); + output[43] = Q_REDUCE(F29); + output[51] = Q_REDUCE(F30); + output[59] = Q_REDUCE(F31); + + // Iteration 4: + ADD_SUB(F32, F33); + ADD_SUB(F34, F35); + ADD_SUB(F36, F37); + ADD_SUB(F38, F39); + + F35 <<= 4; + F39 <<= 4; + + ADD_SUB(F32, F34); + ADD_SUB(F33, F35); + ADD_SUB(F36, F38); + ADD_SUB(F37, F39); + + F37 <<= 2; + F38 <<= 4; + F39 <<= 6; + + ADD_SUB(F32, F36); + ADD_SUB(F33, F37); + ADD_SUB(F34, F38); + ADD_SUB(F35, F39); + + output[4] = Q_REDUCE(F32); + output[12] = Q_REDUCE(F33); + output[20] = Q_REDUCE(F34); + output[28] = Q_REDUCE(F35); + output[36] = Q_REDUCE(F36); + output[44] = Q_REDUCE(F37); + output[52] = Q_REDUCE(F38); + output[60] = Q_REDUCE(F39); + + // Iteration 5: + ADD_SUB(F40, F41); + ADD_SUB(F42, F43); + ADD_SUB(F44, F45); + ADD_SUB(F46, F47); + + F43 <<= 4; + F47 <<= 4; + + ADD_SUB(F40, F42); + ADD_SUB(F41, F43); + ADD_SUB(F44, F46); + ADD_SUB(F45, F47); + + F45 <<= 2; + F46 <<= 4; + F47 <<= 6; + + ADD_SUB(F40, F44); + ADD_SUB(F41, F45); + ADD_SUB(F42, F46); + ADD_SUB(F43, F47); + + output[5] = Q_REDUCE(F40); + output[13] = Q_REDUCE(F41); + output[21] = Q_REDUCE(F42); + output[29] = Q_REDUCE(F43); + output[37] = Q_REDUCE(F44); + output[45] = Q_REDUCE(F45); + output[53] = Q_REDUCE(F46); + output[61] = Q_REDUCE(F47); + + // Iteration 6: + ADD_SUB(F48, F49); + ADD_SUB(F50, F51); + ADD_SUB(F52, F53); + ADD_SUB(F54, F55); + + F51 <<= 4; + F55 <<= 4; + + ADD_SUB(F48, F50); + ADD_SUB(F49, F51); + ADD_SUB(F52, F54); + ADD_SUB(F53, F55); + + F53 <<= 2; + F54 <<= 4; + F55 <<= 6; + + ADD_SUB(F48, F52); + ADD_SUB(F49, F53); + ADD_SUB(F50, F54); + ADD_SUB(F51, F55); + + output[6] = Q_REDUCE(F48); + output[14] = Q_REDUCE(F49); + output[22] = Q_REDUCE(F50); + output[30] = Q_REDUCE(F51); + output[38] = Q_REDUCE(F52); + output[46] = Q_REDUCE(F53); + output[54] = Q_REDUCE(F54); + output[62] = Q_REDUCE(F55); + + // Iteration 7: + ADD_SUB(F56, F57); + ADD_SUB(F58, F59); + ADD_SUB(F60, F61); + ADD_SUB(F62, F63); + + F59 <<= 4; + F63 <<= 4; + + ADD_SUB(F56, F58); + ADD_SUB(F57, F59); + ADD_SUB(F60, F62); + ADD_SUB(F61, F63); + + F61 <<= 2; + F62 <<= 4; + F63 <<= 6; + + ADD_SUB(F56, F60); + ADD_SUB(F57, F61); + ADD_SUB(F58, F62); + ADD_SUB(F59, F63); + + output[7] = Q_REDUCE(F56); + output[15] = Q_REDUCE(F57); + output[23] = Q_REDUCE(F58); + output[31] = Q_REDUCE(F59); + output[39] = Q_REDUCE(F60); + output[47] = Q_REDUCE(F61); + output[55] = Q_REDUCE(F62); + output[63] = Q_REDUCE(F63); +} + +// Calculates the FFT part of SWIFFT. +// We divided the SWIFFT calculation into two, because that way we could save 2 computations of +// the FFT part, since in the first stage of SWIFFTX the difference between the first 3 SWIFFTs +// is only the A's part. +// +// Parameters: +// - input: the input to FFT. +// - m: the input size divided by 8. The function performs m FFTs. +// - output: will store the result. +void SWIFFTFFT(const unsigned char *input, int m, swift_int32_t *output) +{ + int i; + + for (i = 0; + i < m; + i++, input += EIGHTH_N, output += N) + { + FFT(input, output); + } +} + +// Calculates the 'sum' part of SWIFFT, including the base change at the end. +// We divided the SWIFFT calculation into two, because that way we could save 2 computations of +// the FFT part, since in the first stage of SWIFFTX the difference between the first 3 SWIFFTs +// is only the A's part. +// +// Parameters: +// - input: the input. Of size 64 * m. +// - m: the input size divided by 64. +// - output: will store the result. +// - a: the coefficients in the sum. Of size 64 * m. +void SWIFFTSum(const swift_int32_t *input, int m, unsigned char *output, const swift_int16_t *a) +{ + int i, j; + swift_int32_t result[N]; + register swift_int16_t carry = 0; + + for (j = 0; j < N; ++j) + { + register swift_int32_t sum = 0; + const register swift_int32_t *f = input + j; + const register swift_int16_t *k = a + j; + + for (i = 0; i < m; i++, f += N,k += N) + { + sum += (*f) * (*k); + } + + result[j] = sum; + } + + for (j = 0; j < N; ++j) + { + result[j] = ((FIELD_SIZE << 22) + result[j]) % FIELD_SIZE; + } + + for (j = 0; j < 8; ++j) + { + int register carryBit = TranslateToBase256(result + (j << 3), output + (j << 3)); + carry |= carryBit << j; + } + + output[N] = carry; +} + +void ComputeSingleSWIFFTX(unsigned char input[SWIFFTX_INPUT_BLOCK_SIZE], + unsigned char output[SWIFFTX_OUTPUT_BLOCK_SIZE], + bool doSmooth) +{ + int i; + // Will store the result of the FFT parts: + swift_int32_t fftOut[N * M]; + unsigned char intermediate[N * 3 + 8]; + unsigned char carry0,carry1,carry2; + + // Do the three SWIFFTS while remembering the three carry bytes (each carry byte gets + // overriden by the following SWIFFT): + + // 1. Compute the FFT of the input - the common part for the first 3 SWIFFTs: + SWIFFTFFT(input, M, fftOut); + + // 2. Compute the sums of the 3 SWIFFTs, each using a different set of coefficients: + + // 2a. The first SWIFFT: + SWIFFTSum(fftOut, M, intermediate, As); + // Remember the carry byte: + carry0 = intermediate[N]; + + // 2b. The second one: + SWIFFTSum(fftOut, M, intermediate + N, As + (M * N)); + carry1 = intermediate[2 * N]; + + // 2c. The third one: + SWIFFTSum(fftOut, M, intermediate + (2 * N), As + 2 * (M * N)); + carry2 = intermediate[3 * N]; + + //2d. Put three carry bytes in their place + intermediate[3 * N] = carry0; + intermediate[(3 * N) + 1] = carry1; + intermediate[(3 * N) + 2] = carry2; + + // Padding intermediate output with 5 zeroes. + memset(intermediate + (3 * N) + 3, 0, 5); + + // Apply the S-Box: + for (i = 0; i < (3 * N) + 8; ++i) + { + intermediate[i] = SBox[intermediate[i]]; + } + + // 3. The final and last SWIFFT: + SWIFFTFFT(intermediate, 3 * (N/8) + 1, fftOut); + SWIFFTSum(fftOut, 3 * (N/8) + 1, output, As); + + if (doSmooth) + { + unsigned char sum[N]; + register int i, j; + memset(sum, 0, N); + + for (i = 0; i < (N + 1) * 8; ++i) + { + register const swift_int16_t *AsRow; + register int AShift; + + if (!(output[i >> 3] & (1 << (i & 7)))) + { + continue; + } + + AsRow = As + N * M + (i & ~(N - 1)) ; + AShift = i & 63; + + for (j = AShift; j < N; ++j) + { + sum[j] += AsRow[j - AShift]; + } + + for(j = 0; j < AShift; ++j) + { + sum[j] -= AsRow[N - AShift + j]; + } + } + + for (i = 0; i < N; ++i) + { + output[i] = sum[i]; + } + + output[N] = 0; + } +} diff --git a/stratum/algos/SWIFFTX/SWIFFTX.h b/stratum/algos/SWIFFTX/SWIFFTX.h new file mode 100644 index 0000000..8b9aff6 --- /dev/null +++ b/stratum/algos/SWIFFTX/SWIFFTX.h @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// +// SWIFFTX ANSI C OPTIMIZED 32BIT IMPLEMENTATION FOR NIST SHA-3 COMPETITION +// +// SWIFFTX.h +// +// October 2008 +// +// This file is the exact copy from the reference implementation. +// +/////////////////////////////////////////////////////////////////////////////////////////////// +#ifndef __SWIFFTX__ +#define __SWIFFTX__ + +#ifdef __cplusplus +extern "C"{ +#endif + +// See the remarks concerning compatibility issues inside stdint.h. +#include "stdint.h" +#include "stdbool.h" + +// The size of SWIFFTX input in bytes. +#define SWIFFTX_INPUT_BLOCK_SIZE 256 + +// The size of output block in bytes. The compression function of SWIFFT outputs a block of +// this size (i.e., this is the size of the resulting hash value). +#define SWIFFTX_OUTPUT_BLOCK_SIZE 65 + +// Computes the result of a single SWIFFT operation. +// This is the simple implementation, where our main concern is to show our design principles. +// It is made more efficient in the optimized version, by using FFT instead of DFT, and +// through other speed-up techniques. +// +// Parameters: +// - input: the input string. Consists of 8*m input bytes, where each octet passes the DFT +// processing. +// - m: the length of the input in bytes. +// - output: the resulting hash value of SWIFFT, of size 65 bytes (520 bit). This is the +// result of summing the dot products of the DFTS with the A's after applying the base +// change transformation +// - A: the A's coefficients to work with (since every SWIFFT in SWIFFTX uses different As). +// A single application of SWIFFT uses 64*m A's. +void ComputeSingleSWIFFT(unsigned char *input, unsigned short m, + unsigned char output[SWIFFTX_OUTPUT_BLOCK_SIZE], + const swift_int16_t *a); + +// Computes the result of a single SWIFFTX operation. +// NOTE: for simplicity we use 'ComputeSingleSWIFFT()' as a subroutine. This is only to show +// the design idea. In the optimized versions we don't do this for efficiency concerns, since +// there we compute the first part (which doesn't involve the A coefficients) only once for all +// of the 3 invocations of SWIFFT. This enables us to introduce a significant speedup. +// +// Parameters: +// - input: the input input of 256 bytes (2048 bit). +// - output: the resulting hash value of SWIFFT, of size 64 bytes (512 bit). +// - doSMooth: if true, a final smoothing stage is performed and the output is of size 512 bits. +// +// Returns: +// - Success value. +void ComputeSingleSWIFFTX(unsigned char input[SWIFFTX_INPUT_BLOCK_SIZE], + unsigned char output[SWIFFTX_OUTPUT_BLOCK_SIZE], + bool doSmooth); + +// Calculates the powers of OMEGA and generates the bit reversal permutation. +// You must call this function before doing SWIFFT/X, otherwise you will get zeroes everywhere. +void InitializeSWIFFTX(); + +#ifdef __cplusplus +} +#endif + +#endif // __SWIFFTX__ diff --git a/stratum/algos/SWIFFTX/inttypes.h b/stratum/algos/SWIFFTX/inttypes.h new file mode 100644 index 0000000..2b6b941 --- /dev/null +++ b/stratum/algos/SWIFFTX/inttypes.h @@ -0,0 +1,39 @@ + /* + inttypes.h + + Contributors: + Created by Marek Michalkiewicz + + THIS SOFTWARE IS NOT COPYRIGHTED + + This source code is offered for use in the public domain. You may + use, modify or distribute it freely. + + This code is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + DISCLAIMED. This includes but is not limited to warranties of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ + + #ifndef __INTTYPES_H_ + #define __INTTYPES_H_ + + /* Use [u]intN_t if you need exactly N bits. + XXX - doesn't handle the -mint8 option. */ + + typedef signed char swift_int8_t; + typedef unsigned char swift_uint8_t; + + typedef int swift_int16_t; + typedef unsigned int swift_uint16_t; + + typedef long swift_int32_t; + typedef unsigned long swift_uint32_t; + + typedef long long swift_int64_t; + typedef unsigned long long swift_uint64_t; + + //typedef swift_int16_t intptr_t; + //typedef swift_uint16_t uintptr_t; + + #endif diff --git a/stratum/algos/SWIFFTX/stdbool.h b/stratum/algos/SWIFFTX/stdbool.h new file mode 100644 index 0000000..8b10960 --- /dev/null +++ b/stratum/algos/SWIFFTX/stdbool.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2000 Jeroen Ruigrok van der Werven + * 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/include/stdbool.h,v 1.6 2002/08/16 07:33:14 alfred Exp $ + */ + +#ifndef _STDBOOL_H_ +#define _STDBOOL_H_ + +#define __bool_true_false_are_defined 1 + +#ifndef __cplusplus + +#define false 0 +#define true 1 + +#define bool _Bool +#if __STDC_VERSION__ < 199901L && __GNUC__ < 3 +typedef int _Bool; +#endif + +#endif /* !__cplusplus */ + +#endif /* !_STDBOOL_H_ */ diff --git a/stratum/algos/SWIFFTX/stdint.h b/stratum/algos/SWIFFTX/stdint.h new file mode 100644 index 0000000..59f4cfc --- /dev/null +++ b/stratum/algos/SWIFFTX/stdint.h @@ -0,0 +1,54 @@ +#ifndef _SWIFFT_STDINT_H +#define _SWIFFT_STDINT_H + +/////////////////////////////////////////////////////////////////////////////////////////////// +// +// A note from SWIFFTX implementers: +// +// Although the submission was targeted for Microsoft Visual Studio 2005 compiler, we strived +// to make the code as portable as possible. This is why we preferred to use the types defined +// here, instead of Microsoft-specific types. We compiled the code with gcc to make this sure. +// However, we couldn't use this header as is, due to VS2005 compiler objections. This is why +// we commented out certain defines and clearly marked it. +// To compile our code on gcc you may define SYS_STDINT. +// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef SYS_STDINT + +#include + +#else + +#include "inttypes.h" +// The following was commented out by SWIFFTX implementers: +// __BEGIN_DECLS + +typedef swift_int8_t swifftx_int_least8_t; +typedef swift_int16_t swifftx_int_least16_t; +typedef swift_int32_t swifftx_int_least32_t; +typedef swift_uint8_t swifftx_uint_least8_t; +typedef swift_uint16_t swifftx_uint_least16_t; +typedef swift_uint32_t swifftx_uint_least32_t; + +#ifndef __STRICT_ANSI__ +typedef swift_int64_t swifftx_int_least64_t; +typedef swift_uint64_t swifftx_uint_least64_t; +#endif + +/*typedef signed char int_fast8_t; +typedef signed long int int_fast16_t; +typedef signed long int int_fast32_t; +typedef signed long long int int_fast64_t; + +typedef unsigned char uint_fast8_t; +typedef unsigned long int uint_fast16_t; +typedef unsigned long int uint_fast32_t; +typedef unsigned long long int uint_fast64_t;*/ + +// The following was commented out by SWIFFTX implementers: +// #include +// __END_DECLS +#endif + +#endif diff --git a/stratum/algos/a5a.c b/stratum/algos/a5a.c new file mode 100644 index 0000000..fbf608b --- /dev/null +++ b/stratum/algos/a5a.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include +#include +#include +#include "a5amath.h" + +#include "../sha3/sph_sha2.h" +#include "../sha3/sph_keccak.h" +#include "../sha3/sph_whirlpool.h" +#include "../sha3/sph_ripemd.h" + +static void mpz_set_uint256(mpz_t r, uint8_t *u) +{ + mpz_import(r, 32 / sizeof(unsigned long), -1, sizeof(unsigned long), -1, 0, u); +} + +static void mpz_get_uint256(mpz_t r, uint8_t *u) +{ + u=0; + mpz_export(u, 0, -1, sizeof(unsigned long), -1, 0, r); +} + +static void mpz_set_uint512(mpz_t r, uint8_t *u) +{ + mpz_import(r, 64 / sizeof(unsigned long), -1, sizeof(unsigned long), -1, 0, u); +} + +static void set_one_if_zero(uint8_t *hash512) { + int i; + for (i = 0; i < 32; i++) { + if (hash512[i] != 0) { + return; + } + } + hash512[0] = 1; +} + +#define BITS_PER_DIGIT 3.32192809488736234787 +//#define EPS (std::numeric_limits::epsilon()) +#define EPS (DBL_EPSILON) + +#define Na5a 5 +#define SW_DIVS 5 +//#define SW_MAX 1000 + +void a5a_hash(const char* input, char* output, uint32_t len) +{ + unsigned int nnNonce; + uint32_t pdata[32]; + memcpy(pdata, input, 80); +// memcpy(&nnNonce, input+76, 4); + + int i, j, bytes, nnNonce2; + nnNonce2 = (int)(pdata[19]/2); + size_t sz = 80; + uint8_t bhash[5][64]; + uint32_t hash[6]; + memset(bhash, 0, 5 * 64); + + sph_sha256_context ctx_final_sha256; + + sph_sha256_context ctx_sha256; + sph_sha512_context ctx_sha512; + sph_keccak512_context ctx_keccak; + sph_whirlpool_context ctx_whirlpool; + sph_ripemd160_context ctx_ripemd; + + sph_sha256_init(&ctx_sha256); + // ZSHA256; + sph_sha256 (&ctx_sha256, input, sz); + sph_sha256_close(&ctx_sha256, (void*)(bhash[0])); + + sph_sha512_init(&ctx_sha512); + // ZSHA512; + sph_sha512 (&ctx_sha512, input, sz); + sph_sha512_close(&ctx_sha512, (void*)(bhash[1])); + + sph_keccak512_init(&ctx_keccak); + // ZKECCAK; + sph_keccak512 (&ctx_keccak, input, sz); + sph_keccak512_close(&ctx_keccak, (void*)(bhash[2])); + + sph_whirlpool_init(&ctx_whirlpool); + // ZWHIRLPOOL; + sph_whirlpool (&ctx_whirlpool, input, sz); + sph_whirlpool_close(&ctx_whirlpool, (void*)(bhash[3])); + + sph_ripemd160_init(&ctx_ripemd); + // ZRIPEMD; + sph_ripemd160 (&ctx_ripemd, input, sz); + sph_ripemd160_close(&ctx_ripemd, (void*)(bhash[4])); + +// printf("%s\n", hash[4].GetHex().c_str()); + + mpz_t bns[6]; + for(i=0; i < 6; i++){ + mpz_init(bns[i]); + } + //Take care of zeros and load gmp + for(i=0; i < 5; i++){ + set_one_if_zero(bhash[i]); + mpz_set_uint512(bns[i],bhash[i]); + } + + mpz_set_ui(bns[5],0); + for(i=0; i < 5; i++) + mpz_add(bns[5], bns[5], bns[i]); + + mpz_t product; + mpz_init(product); + mpz_set_ui(product,1); +// mpz_pow_ui(bns[5], bns[5], 2); + for(i=0; i < 6; i++){ + mpz_mul(product,product,bns[i]); + } + mpz_pow_ui(product, product, 2); + + bytes = mpz_sizeinbase(product, 256); +// printf("a5a data space: %iB\n", bytes); + char *data = (char*)malloc(bytes); + mpz_export(data, NULL, -1, 1, 0, 0, product); + + sph_sha256_init(&ctx_final_sha256); + // ZSHA256; + sph_sha256 (&ctx_final_sha256, data, bytes); + sph_sha256_close(&ctx_final_sha256, (void*)(hash)); + free(data); + + int digits=(int)((sqrt((double)(nnNonce2))*(1.+EPS))/9000+75); +// int iterations=(int)((sqrt((double)(nnNonce2))+EPS)/500+350); // <= 500 +// int digits=100; + int iterations=20; // <= 500 + mpf_set_default_prec((long int)(digits*BITS_PER_DIGIT+16)); + + mpz_t a5api; + mpz_t a5asw; + mpf_t a5afpi; + mpf_t mpa1, mpb1, mpt1, mpp1; + mpf_t mpa2, mpb2, mpt2, mpp2; + mpf_t mpsft; + + mpz_init(a5api); + mpz_init(a5asw); + mpf_init(a5afpi); + mpf_init(mpsft); + mpf_init(mpa1); + mpf_init(mpb1); + mpf_init(mpt1); + mpf_init(mpp1); + + mpf_init(mpa2); + mpf_init(mpb2); + mpf_init(mpt2); + mpf_init(mpp2); + + uint32_t usw_; + usw_ = sw_(nnNonce2, SW_DIVS); + if (usw_ < 1) usw_ = 1; +// if(fDebuga5a) printf("usw_: %d\n", usw_); + mpz_set_ui(a5asw, usw_); + uint32_t mpzscale=mpz_size(a5asw); +for(i=0; i < Na5a; i++) +{ + if (mpzscale > 1000) { + mpzscale = 1000; + } + else if (mpzscale < 1) { + mpzscale = 1; + } +// if(fDebuga5a) printf("mpzscale: %d\n", mpzscale); + + mpf_set_ui(mpa1, 1); + mpf_set_ui(mpb1, 2); + mpf_set_d(mpt1, 0.25*mpzscale); + mpf_set_ui(mpp1, 1); + mpf_sqrt(mpb1, mpb1); + mpf_ui_div(mpb1, 1, mpb1); + mpf_set_ui(mpsft, 10); + + for(j=0; j <= iterations; j++) + { + mpf_add(mpa2, mpa1, mpb1); + mpf_div_ui(mpa2, mpa2, 2); + mpf_mul(mpb2, mpa1, mpb1); + mpf_abs(mpb2, mpb2); + mpf_sqrt(mpb2, mpb2); + mpf_sub(mpt2, mpa1, mpa2); + mpf_abs(mpt2, mpt2); + mpf_sqrt(mpt2, mpt2); + mpf_mul(mpt2, mpt2, mpp1); + mpf_sub(mpt2, mpt1, mpt2); + mpf_mul_ui(mpp2, mpp1, 2); + mpf_swap(mpa1, mpa2); + mpf_swap(mpb1, mpb2); + mpf_swap(mpt1, mpt2); + mpf_swap(mpp1, mpp2); + } + mpf_add(a5afpi, mpa1, mpb1); + mpf_pow_ui(a5afpi, a5afpi, 2); + mpf_div_ui(a5afpi, a5afpi, 4); + mpf_abs(mpt1, mpt1); + mpf_div(a5afpi, a5afpi, mpt1); + +// mpf_out_str(stdout, 10, digits+2, a5afpi); + + mpf_pow_ui(mpsft, mpsft, digits/2); + mpf_mul(a5afpi, a5afpi, mpsft); + + mpz_set_f(a5api, a5afpi); + +//mpz_set_ui(a5api,1); + + mpz_add(product,product,a5api); + mpz_add(product,product,a5asw); + + mpz_set_uint256(bns[0], (void*)(hash)); + mpz_add(bns[5], bns[5], bns[0]); + + mpz_mul(product,product,bns[5]); + mpz_cdiv_q (product, product, bns[0]); + if (mpz_sgn(product) <= 0) mpz_set_ui(product,1); + + bytes = mpz_sizeinbase(product, 256); + mpzscale=bytes; +// printf("a5a data space: %iB\n", bytes); + char *bdata = (char*)malloc(bytes); + mpz_export(bdata, NULL, -1, 1, 0, 0, product); + + sph_sha256_init(&ctx_final_sha256); + // ZSHA256; + sph_sha256 (&ctx_final_sha256, bdata, bytes); + sph_sha256_close(&ctx_final_sha256, (void*)(hash)); + free(bdata); +} + //Free the memory + for(i=0; i < 6; i++){ + mpz_clear(bns[i]); + } +// mpz_clear(dSpectralWeight); + mpz_clear(product); + + mpz_clear(a5api); + mpz_clear(a5asw); + mpf_clear(a5afpi); + mpf_clear(mpsft); + mpf_clear(mpa1); + mpf_clear(mpb1); + mpf_clear(mpt1); + mpf_clear(mpp1); + + mpf_clear(mpa2); + mpf_clear(mpb2); + mpf_clear(mpt2); + mpf_clear(mpp2); + + memcpy(output, hash, 32); +} \ No newline at end of file diff --git a/stratum/algos/a5a.h b/stratum/algos/a5a.h new file mode 100644 index 0000000..3470d8f --- /dev/null +++ b/stratum/algos/a5a.h @@ -0,0 +1,14 @@ +#ifndef SCRYPT_H +#define SCRYPT_H +#include +#ifdef __cplusplus +extern "C" { +#endif + +void a5a_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/stratum/algos/a5amath.c b/stratum/algos/a5amath.c new file mode 100644 index 0000000..1c61c5f --- /dev/null +++ b/stratum/algos/a5amath.c @@ -0,0 +1,116 @@ +// Copyright (c) 2014 The a5a developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include +#include +#include +//#include +#include "a5amath.h" + +//#define EPS1 (std::numeric_limits::epsilon()) +#define EPS1 (DBL_EPSILON) +#define EPS2 3.0e-11 + +double exp_n(double xt) +{ + double p1 = -700.0, p3 = -0.8e-8, p4 = 0.8e-8, p6 = 700.0; + if(xt < p1) + return 0; + else if(xt > p6) + return 1e200; + else if(xt > p3 && xt < p4) + return (1.0 + xt); + else + return exp(xt); +} + +// 1 / (1 + exp(x1-x2)) +double exp_n2(double x1, double x2) +{ + double p1 = -700., p2 = -37., p3 = -0.8e-8, p4 = 0.8e-8, p5 = 37., p6 = 700.; + double xt = x1 - x2; + if (xt < p1+1.e-200) + return 1.; + else if (xt > p1 && xt < p2 + 1.e-200) + return ( 1. - exp(xt) ); + else if (xt > p2 && xt < p3 + 1.e-200) + return ( 1. / (1. + exp(xt)) ); + else if (xt > p3 && xt < p4) + return ( 1. / (2. + xt) ); + else if (xt > p4 - 1.e-200 && xt < p5) + return ( exp(-xt) / (1. + exp(-xt)) ); + else if (xt > p5 - 1.e-200 && xt < p6) + return ( exp(-xt) ); + else if (xt > p6 - 1.e-200) + return 0.; +} + +void gauleg(double x1, double x2, double x[], double w[], int n) +{ + int m,j,i; + double z1, z, xm, xl, pp, p3, p2, p1; + m=(n+1)/2; + xm=0.5*(x2+x1); + xl=0.5*(x2-x1); + for (i=1;i<=m;i++) { + z=cos(3.141592654*(i-0.25)/(n+0.5)); + do { + p1=1.0; + p2=0.0; + for (j=1;j<=n;j++) { + p3=p2; + p2=p1; + p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j; + } + pp=n*(z*p1-p2)/(z*z-1.0); + z1=z; + z=z1-p1/pp; + } while (fabs(z-z1) > EPS2); + x[i]=xm-xl*z; + x[n+1-i]=xm+xl*z; + w[i]=2.0*xl/((1.0-z*z)*pp*pp); + w[n+1-i]=w[i]; + } +} + +double GaussianQuad_N(double func(const double), const double a2, const double b2, int NptGQ) +{ + double s=0.0; + double x[NptGQ], w[NptGQ]; + int j; +// double dh=(b2-a2)/double(divs); + gauleg(a2, b2, x, w, NptGQ); + for (j=1; j<=NptGQ; j++) { + s += w[j]*func(x[j]); + } +/* + for (i=1; i<=divs; i++) + { + a0 = a2 + (i-1)*dh; + b0 = a0 + dh; + gauleg(a0, b0, x, w, NptGQ); + for (j=1; j<=NptGQ; j++) + { + s += w[j]*func(x[j]); + } + } +*/ + return s; +} + +double swit_(double wvnmb) +{ + return pow( (5.55243*(exp_n(-0.3*wvnmb/15.762) - exp_n(-0.6*wvnmb/15.762)))*wvnmb, 0.5) + / 1034.66 * pow(sin(wvnmb/65.), 2.); +} + +uint32_t sw_(int nnounce, int divs) +{ + double wmax = ((sqrt((double)(nnounce))*(1.+EPS1))/450+100); + return ((uint32_t)(GaussianQuad_N(swit_, 0., wmax, divs)*(1.+EPS1)*1.e6)); +} \ No newline at end of file diff --git a/stratum/algos/a5amath.h b/stratum/algos/a5amath.h new file mode 100644 index 0000000..d2f4ca8 --- /dev/null +++ b/stratum/algos/a5amath.h @@ -0,0 +1,16 @@ +// Copyright (c) 2014 The a5a developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef a5a_MATH_H +#define a5a_MATH_H + +double exp_n(double xt); +double exp_n2(double x1, double x2); +void gauleg(double x1, double x2, double x[], double w[], int n); +double GaussianQuad_N(double func(const double), const double a2, const double b2, int NptGQ); +double swit_(double wvnmb); +uint32_t sw_(int nnounce, int divs); + + + +#endif \ No newline at end of file diff --git a/stratum/algos/aergo.c b/stratum/algos/aergo.c new file mode 100644 index 0000000..7a79184 --- /dev/null +++ b/stratum/algos/aergo.c @@ -0,0 +1,162 @@ +#include "aergo.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gost.h" + +#include "common.h" + +void aergo_hash(const char* input, char* output, uint32_t len) +{ + uint32_t hash[16]; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_skein512_context ctx_skein; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_gost512_context ctx_gost; + sph_whirlpool_context ctx_whirlpool; + sph_haval256_5_context ctx_haval; + + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, input, len); + sph_echo512_close(&ctx_echo, hash); + + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, hash, 64); + sph_blake512_close(&ctx_blake, hash); + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, hash, 64); + sph_whirlpool_close(&ctx_whirlpool, hash); + + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_gost512_init(&ctx_gost); + sph_gost512(&ctx_gost, hash, 64); + sph_gost512_close(&ctx_gost, hash); + + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_gost512_init(&ctx_gost); + sph_gost512(&ctx_gost, hash, 64); + sph_gost512_close(&ctx_gost, hash); + + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, hash, 64); + sph_fugue512_close(&ctx_fugue, hash); + + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, hash, 64); + sph_shabal512_close(&ctx_shabal, hash); + + sph_haval256_5_init(&ctx_haval); + sph_haval256_5(&ctx_haval,(const void*) hash, 64); + sph_haval256_5_close(&ctx_haval, hash); + + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_gost512_init(&ctx_gost); + sph_gost512(&ctx_gost, hash, 64); + sph_gost512_close(&ctx_gost, hash); + + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, hash, 64); + sph_blake512_close(&ctx_blake, hash); + + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + memcpy(output, hash, 32); +} diff --git a/stratum/algos/aergo.h b/stratum/algos/aergo.h new file mode 100644 index 0000000..ad129b3 --- /dev/null +++ b/stratum/algos/aergo.h @@ -0,0 +1,17 @@ + +#ifndef AERGO_H +#define AERGO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void aergo_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/stratum/algos/allium.c b/stratum/algos/allium.c new file mode 100644 index 0000000..4c3569d --- /dev/null +++ b/stratum/algos/allium.c @@ -0,0 +1,46 @@ +#include + +#include "sha3/sph_blake.h" +#include "sha3/sph_groestl.h" +#include "sha3/sph_skein.h" +#include "sha3/sph_keccak.h" +#include "sha3/sph_cubehash.h" + +#include "Lyra2.h" + +void allium_hash(const char* input, char* output, uint32_t len) +{ + uint32_t hashA[8], hashB[8]; + + sph_blake256_context ctx_blake; + sph_keccak256_context ctx_keccak; + sph_cubehash512_context ctx_cubehash; + sph_skein256_context ctx_skein; + sph_groestl256_context ctx_groestl; + + sph_blake256_init(&ctx_blake); + sph_blake256(&ctx_blake, input, 80); + sph_blake256_close(&ctx_blake, hashA); + + sph_keccak256_init(&ctx_keccak); + sph_keccak256(&ctx_keccak, hashA, 32); + sph_keccak256_close(&ctx_keccak, hashB); + + LYRA2(hashA, 32, hashB, 32, hashB, 32, 1, 8, 8); + + sph_cubehash256_init(&ctx_cubehash); + sph_cubehash256(&ctx_cubehash, hashA, 32); + sph_cubehash256_close(&ctx_cubehash, hashB); + + LYRA2(hashA, 32, hashB, 32, hashB, 32, 1, 8, 8); + + sph_skein256_init(&ctx_skein); + sph_skein256(&ctx_skein, hashA, 32); + sph_skein256_close(&ctx_skein, hashB); + + sph_groestl256_init(&ctx_groestl); + sph_groestl256(&ctx_groestl, hashB, 32); + sph_groestl256_close(&ctx_groestl, hashA); + + memcpy(output, hashA, 32); +} diff --git a/stratum/algos/allium.h b/stratum/algos/allium.h new file mode 100644 index 0000000..3705161 --- /dev/null +++ b/stratum/algos/allium.h @@ -0,0 +1,16 @@ +#ifndef ALLIUM_H +#define ALLIUM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void allium_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/ar2/argon2.c b/stratum/algos/ar2/argon2.c index 58ef79f..665f8b7 100644 --- a/stratum/algos/ar2/argon2.c +++ b/stratum/algos/ar2/argon2.c @@ -1,279 +1,378 @@ /* - * Argon2 source code package + * Argon2 reference source code package - reference C implementations * - * Written by Daniel Dinu and Dmitry Khovratovich, 2015 + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves * - * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: * - * You should have received a copy of the CC0 Public Domain Dedication along - * with - * this software. If not, see - * . + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. */ -#include #include +#include #include -#include #include "argon2.h" -#include "cores.h" +#include "encoding.h" +#include "core.h" -/* Error messages */ -static const char *Argon2_ErrorMessage[] = { - /*{ARGON2_OK, */ "OK", - /*}, +const char *argon2_type2string(argon2_type type, int uppercase) { + switch (type) { + case Argon2_d: + return uppercase ? "Argon2d" : "argon2d"; + } - {ARGON2_OUTPUT_PTR_NULL, */ "Output pointer is NULL", - /*}, + return NULL; +} -{ARGON2_OUTPUT_TOO_SHORT, */ "Output is too short", - /*}, -{ARGON2_OUTPUT_TOO_LONG, */ "Output is too long", - /*}, - -{ARGON2_PWD_TOO_SHORT, */ "Password is too short", - /*}, -{ARGON2_PWD_TOO_LONG, */ "Password is too long", - /*}, - -{ARGON2_SALT_TOO_SHORT, */ "Salt is too short", - /*}, -{ARGON2_SALT_TOO_LONG, */ "Salt is too long", - /*}, - -{ARGON2_AD_TOO_SHORT, */ "Associated data is too short", - /*}, -{ARGON2_AD_TOO_LONG, */ "Associated date is too long", - /*}, - -{ARGON2_SECRET_TOO_SHORT, */ "Secret is too short", - /*}, -{ARGON2_SECRET_TOO_LONG, */ "Secret is too long", - /*}, - -{ARGON2_TIME_TOO_SMALL, */ "Time cost is too small", - /*}, -{ARGON2_TIME_TOO_LARGE, */ "Time cost is too large", - /*}, - -{ARGON2_MEMORY_TOO_LITTLE, */ "Memory cost is too small", - /*}, -{ARGON2_MEMORY_TOO_MUCH, */ "Memory cost is too large", - /*}, - -{ARGON2_LANES_TOO_FEW, */ "Too few lanes", - /*}, -{ARGON2_LANES_TOO_MANY, */ "Too many lanes", - /*}, - -{ARGON2_PWD_PTR_MISMATCH, */ "Password pointer is NULL, but password length is not 0", - /*}, -{ARGON2_SALT_PTR_MISMATCH, */ "Salt pointer is NULL, but salt length is not 0", - /*}, -{ARGON2_SECRET_PTR_MISMATCH, */ "Secret pointer is NULL, but secret length is not 0", - /*}, -{ARGON2_AD_PTR_MISMATCH, */ "Associated data pointer is NULL, but ad length is not 0", - /*}, - -{ARGON2_MEMORY_ALLOCATION_ERROR, */ "Memory allocation error", - /*}, - -{ARGON2_FREE_MEMORY_CBK_NULL, */ "The free memory callback is NULL", - /*}, -{ARGON2_ALLOCATE_MEMORY_CBK_NULL, */ "The allocate memory callback is NULL", - /*}, - -{ARGON2_INCORRECT_PARAMETER, */ "Argon2_Context context is NULL", - /*}, -{ARGON2_INCORRECT_TYPE, */ "There is no such version of Argon2", - /*}, - -{ARGON2_OUT_PTR_MISMATCH, */ "Output pointer mismatch", - /*}, - -{ARGON2_THREADS_TOO_FEW, */ "Not enough threads", - /*}, -{ARGON2_THREADS_TOO_MANY, */ "Too many threads", - /*}, -{ARGON2_MISSING_ARGS, */ "Missing arguments", /*},*/ -}; - -int argon2d(argon2_context *context) { return argon2_core(context, Argon2_d); } - -int argon2i(argon2_context *context) { return argon2_core(context, Argon2_i); } - -int verify_d(argon2_context *context, const char *hash) { - int result; - /*if (0 == context->outlen || NULL == hash) { - return ARGON2_OUT_PTR_MISMATCH; - }*/ - - result = argon2_core(context, Argon2_d); +int argon2_ctx(argon2_context *context, argon2_type type) { + /* 1. Validate all inputs */ + int result = validate_inputs(context); + uint32_t memory_blocks, segment_length; + argon2_instance_t instance; if (ARGON2_OK != result) { return result; } - return 0 == memcmp(hash, context->out, 32); -} - -const char *error_message(int error_code) { - enum { - /* Make sure---at compile time---that the enum size matches the array - size */ - ERROR_STRING_CHECK = - 1 / - !!((sizeof(Argon2_ErrorMessage) / sizeof(Argon2_ErrorMessage[0])) == - ARGON2_ERROR_CODES_LENGTH) - }; - if (error_code < ARGON2_ERROR_CODES_LENGTH) { - return Argon2_ErrorMessage[(argon2_error_codes)error_code]; + if (Argon2_d != type) { + return ARGON2_INCORRECT_TYPE; } - return "Unknown error code."; -} -/* encoding/decoding helpers */ + /* 2. Align memory size */ + /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */ + memory_blocks = context->m_cost; -/* - * Some macros for constant-time comparisons. These work over values in - * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true". - */ -#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF) -#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF) -#define GE(x, y) (GT(y, x) ^ 0xFF) -#define LT(x, y) GT(y, x) -#define LE(x, y) GE(y, x) - -/* - * Convert value x (0..63) to corresponding Base64 character. - */ -static int b64_byte_to_char(unsigned x) { - return (LT(x, 26) & (x + 'A')) | - (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) | - (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') | - (EQ(x, 63) & '/'); -} - -/* - * Convert some bytes to Base64. 'dst_len' is the length (in characters) - * of the output buffer 'dst'; if that buffer is not large enough to - * receive the result (including the terminating 0), then (size_t)-1 - * is returned. Otherwise, the zero-terminated Base64 string is written - * in the buffer, and the output length (counted WITHOUT the terminating - * zero) is returned. - */ -static size_t to_base64(char *dst, size_t dst_len, const void *src) { - size_t olen; - const unsigned char *buf; - unsigned acc, acc_len; - - olen = 43; - /*switch (32 % 3) { - case 2: - olen++;*/ - /* fall through */ - /*case 1: - olen += 2; - break; - }*/ - if (dst_len <= olen) { - return (size_t)-1; + if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) { + memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes; } - acc = 0; - acc_len = 0; - buf = (const unsigned char *)src; - size_t src_len = 32; - while (src_len-- > 0) { - acc = (acc << 8) + (*buf++); - acc_len += 8; - while (acc_len >= 6) { - acc_len -= 6; - *dst++ = b64_byte_to_char((acc >> acc_len) & 0x3F); + + segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS); + /* Ensure that all segments have equal length */ + memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS); + + instance.memory = NULL; + instance.passes = context->t_cost; + instance.memory_blocks = memory_blocks; + instance.segment_length = segment_length; + instance.lane_length = segment_length * ARGON2_SYNC_POINTS; + instance.lanes = context->lanes; + instance.threads = context->threads; + instance.type = type; + + if (instance.threads > instance.lanes) { + instance.threads = instance.lanes; + } + + /* 3. Initialization: Hashing inputs, allocating memory, filling first + * blocks + */ + result = initialize(&instance, context); + + if (ARGON2_OK != result) { + return result; + } + + /* 4. Filling memory */ + result = fill_memory_blocks(&instance); + + if (ARGON2_OK != result) { + return result; + } + /* 5. Finalization */ + finalize(context, &instance); + + return ARGON2_OK; +} + +int argon2_hash(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, const size_t saltlen, + void *hash, const size_t hashlen, char *encoded, + const size_t encodedlen, argon2_type type){ + + argon2_context context; + int result; + uint8_t *out; + + if (pwdlen > ARGON2_MAX_PWD_LENGTH) { + return ARGON2_PWD_TOO_LONG; + } + + if (saltlen > ARGON2_MAX_SALT_LENGTH) { + return ARGON2_SALT_TOO_LONG; + } + + if (hashlen > ARGON2_MAX_OUTLEN) { + return ARGON2_OUTPUT_TOO_LONG; + } + + if (hashlen < ARGON2_MIN_OUTLEN) { + return ARGON2_OUTPUT_TOO_SHORT; + } + + out = malloc(hashlen); + if (!out) { + return ARGON2_MEMORY_ALLOCATION_ERROR; + } + + context.out = (uint8_t *)out; + context.outlen = (uint32_t)hashlen; + context.pwd = CONST_CAST(uint8_t *)pwd; + context.pwdlen = (uint32_t)pwdlen; + context.salt = CONST_CAST(uint8_t *)salt; + context.saltlen = (uint32_t)saltlen; + context.secret = NULL; + context.secretlen = 0; + context.ad = NULL; + context.adlen = 0; + context.t_cost = t_cost; + context.m_cost = m_cost; + context.lanes = parallelism; + context.threads = parallelism; + context.allocate_cbk = NULL; + context.free_cbk = NULL; + context.flags = ARGON2_DEFAULT_FLAGS; + + result = argon2_ctx(&context, type); + + if (result != ARGON2_OK) { + clear_internal_memory(out, hashlen); + free(out); + return result; + } + + /* if raw hash requested, write it */ + if (hash) { + memcpy(hash, out, hashlen); + } + + /* if encoding requested, write it */ + if (encoded && encodedlen) { + if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) { + clear_internal_memory(out, hashlen); /* wipe buffers if error */ + clear_internal_memory(encoded, encodedlen); + free(out); + return ARGON2_ENCODING_FAIL; } } - if (acc_len > 0) { - *dst++ = b64_byte_to_char((acc << (6 - acc_len)) & 0x3F); + clear_internal_memory(out, hashlen); + free(out); + + return ARGON2_OK; +} + +int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, const size_t hashlen, + char *encoded, const size_t encodedlen) { + + return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, + NULL, hashlen, encoded, encodedlen, Argon2_d); +} + +int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, const size_t hashlen) { + + return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, + hash, hashlen, NULL, 0, Argon2_d); +} + +static int argon2_compare(const uint8_t *b1, const uint8_t *b2, size_t len) { + size_t i; + uint8_t d = 0U; + + for (i = 0U; i < len; i++) { + d |= b1[i] ^ b2[i]; } - *dst++ = 0; - return olen; + return (int)((1 & ((d - 1) >> 8)) - 1); } -/* ==================================================================== */ -/* - * Code specific to Argon2i. - * - * The code below applies the following format: - * - * $argon2i$m=,t=,p=[,keyid=][,data=][$[$]] - * - * where is a decimal integer (positive, fits in an 'unsigned long') - * and is Base64-encoded data (no '=' padding characters, no newline - * or whitespace). The "keyid" is a binary identifier for a key (up to 8 - * bytes); "data" is associated data (up to 32 bytes). When the 'keyid' - * (resp. the 'data') is empty, then it is ommitted from the output. - * - * The last two binary chunks (encoded in Base64) are, in that order, - * the salt and the output. Both are optional, but you cannot have an - * output without a salt. The binary salt length is between 8 and 48 bytes. - * The output length is always exactly 32 bytes. - */ +int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen, + argon2_type type) { -int encode_string(char *dst, size_t dst_len, argon2_context *ctx) { -#define SS(str) \ - do { \ - size_t pp_len = strlen(str); \ - if (pp_len >= dst_len) { \ - return 0; \ - } \ - memcpy(dst, str, pp_len + 1); \ - dst += pp_len; \ - dst_len -= pp_len; \ - } while (0) + argon2_context ctx; + uint8_t *desired_result = NULL; -#define SX(x) \ - do { \ - char tmp[30]; \ - sprintf(tmp, "%lu", (unsigned long)(x)); \ - SS(tmp); \ - } while (0); + int ret = ARGON2_OK; -#define SB(buf) \ - do { \ - size_t sb_len = to_base64(dst, dst_len, buf); \ - if (sb_len == (size_t)-1) { \ - return 0; \ - } \ - dst += sb_len; \ - dst_len -= sb_len; \ - } while (0); + size_t encoded_len; + uint32_t max_field_len; - SS("$argon2i$m="); - SX(16); - SS(",t="); - SX(2); - SS(",p="); - SX(1); + if (pwdlen > ARGON2_MAX_PWD_LENGTH) { + return ARGON2_PWD_TOO_LONG; + } - /*if (ctx->adlen > 0) { - SS(",data="); - SB(ctx->ad, ctx->adlen); - }*/ + if (encoded == NULL) { + return ARGON2_DECODING_FAIL; + } - /*if (ctx->saltlen == 0) - return 1;*/ + encoded_len = strlen(encoded); + if (encoded_len > UINT32_MAX) { + return ARGON2_DECODING_FAIL; + } - SS("$"); - SB(ctx->salt); + /* No field can be longer than the encoded length */ + max_field_len = (uint32_t)encoded_len; - /*if (ctx->outlen32 == 0) - return 1;*/ + ctx.saltlen = max_field_len; + ctx.outlen = max_field_len; - SS("$"); - SB(ctx->out); - return 1; + ctx.salt = malloc(ctx.saltlen); + ctx.out = malloc(ctx.outlen); + if (!ctx.salt || !ctx.out) { + ret = ARGON2_MEMORY_ALLOCATION_ERROR; + goto fail; + } -#undef SS -#undef SX -#undef SB + ctx.pwd = (uint8_t *)pwd; + ctx.pwdlen = (uint32_t)pwdlen; + + ret = decode_string(&ctx, encoded, type); + if (ret != ARGON2_OK) { + goto fail; + } + + /* Set aside the desired result, and get a new buffer. */ + desired_result = ctx.out; + ctx.out = malloc(ctx.outlen); + if (!ctx.out) { + ret = ARGON2_MEMORY_ALLOCATION_ERROR; + goto fail; + } + + ret = argon2_verify_ctx(&ctx, (char *)desired_result, type); + if (ret != ARGON2_OK) { + goto fail; + } + +fail: + free(ctx.salt); + free(ctx.out); + free(desired_result); + + return ret; } + +int argon2d_verify(const char *encoded, const void *pwd, const size_t pwdlen) { + + return argon2_verify(encoded, pwd, pwdlen, Argon2_d); +} + +int argon2d_ctx(argon2_context *context) { + return argon2_ctx(context, Argon2_d); +} + +int argon2_verify_ctx(argon2_context *context, const char *hash, + argon2_type type) { + int ret = argon2_ctx(context, type); + if (ret != ARGON2_OK) { + return ret; + } + + if (argon2_compare((uint8_t *)hash, context->out, context->outlen)) { + return ARGON2_VERIFY_MISMATCH; + } + + return ARGON2_OK; +} + +int argon2d_verify_ctx(argon2_context *context, const char *hash) { + return argon2_verify_ctx(context, hash, Argon2_d); +} + +const char *argon2_error_message(int error_code) { + switch (error_code) { + case ARGON2_OK: + return "OK"; + case ARGON2_OUTPUT_PTR_NULL: + return "Output pointer is NULL"; + case ARGON2_OUTPUT_TOO_SHORT: + return "Output is too short"; + case ARGON2_OUTPUT_TOO_LONG: + return "Output is too long"; + case ARGON2_PWD_TOO_SHORT: + return "Password is too short"; + case ARGON2_PWD_TOO_LONG: + return "Password is too long"; + case ARGON2_SALT_TOO_SHORT: + return "Salt is too short"; + case ARGON2_SALT_TOO_LONG: + return "Salt is too long"; + case ARGON2_AD_TOO_SHORT: + return "Associated data is too short"; + case ARGON2_AD_TOO_LONG: + return "Associated data is too long"; + case ARGON2_SECRET_TOO_SHORT: + return "Secret is too short"; + case ARGON2_SECRET_TOO_LONG: + return "Secret is too long"; + case ARGON2_TIME_TOO_SMALL: + return "Time cost is too small"; + case ARGON2_TIME_TOO_LARGE: + return "Time cost is too large"; + case ARGON2_MEMORY_TOO_LITTLE: + return "Memory cost is too small"; + case ARGON2_MEMORY_TOO_MUCH: + return "Memory cost is too large"; + case ARGON2_LANES_TOO_FEW: + return "Too few lanes"; + case ARGON2_LANES_TOO_MANY: + return "Too many lanes"; + case ARGON2_PWD_PTR_MISMATCH: + return "Password pointer is NULL, but password length is not 0"; + case ARGON2_SALT_PTR_MISMATCH: + return "Salt pointer is NULL, but salt length is not 0"; + case ARGON2_SECRET_PTR_MISMATCH: + return "Secret pointer is NULL, but secret length is not 0"; + case ARGON2_AD_PTR_MISMATCH: + return "Associated data pointer is NULL, but ad length is not 0"; + case ARGON2_MEMORY_ALLOCATION_ERROR: + return "Memory allocation error"; + case ARGON2_FREE_MEMORY_CBK_NULL: + return "The free memory callback is NULL"; + case ARGON2_ALLOCATE_MEMORY_CBK_NULL: + return "The allocate memory callback is NULL"; + case ARGON2_INCORRECT_PARAMETER: + return "Argon2_Context context is NULL"; + case ARGON2_INCORRECT_TYPE: + return "There is no such version of Argon2"; + case ARGON2_OUT_PTR_MISMATCH: + return "Output pointer mismatch"; + case ARGON2_THREADS_TOO_FEW: + return "Not enough threads"; + case ARGON2_THREADS_TOO_MANY: + return "Too many threads"; + case ARGON2_MISSING_ARGS: + return "Missing arguments"; + case ARGON2_ENCODING_FAIL: + return "Encoding failed"; + case ARGON2_DECODING_FAIL: + return "Decoding failed"; + case ARGON2_THREAD_FAIL: + return "Threading failure"; + case ARGON2_DECODING_LENGTH_FAIL: + return "Some of encoded parameters are too long or too short"; + case ARGON2_VERIFY_MISMATCH: + return "The password does not match the supplied hash"; + default: + return "Unknown error code"; + } +} + +size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism, + uint32_t saltlen, uint32_t hashlen, argon2_type type) { + return strlen("$$v=$m=,t=,p=$$") + strlen(argon2_type2string(type, 0)) + + numlen(t_cost) + numlen(m_cost) + numlen(parallelism) + + b64len(saltlen) + b64len(hashlen); +} \ No newline at end of file diff --git a/stratum/algos/ar2/argon2.h b/stratum/algos/ar2/argon2.h index cecb2c7..35e5243 100644 --- a/stratum/algos/ar2/argon2.h +++ b/stratum/algos/ar2/argon2.h @@ -1,18 +1,27 @@ /* - * Argon2 source code package + * Argon2 reference source code package - reference C implementations * - * Written by Daniel Dinu and Dmitry Khovratovich, 2015 + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves * - * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: * - * You should have received a copy of the CC0 Public Domain Dedication along - * with - * this software. If not, see - * . + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. */ + #ifndef ARGON2_H #define ARGON2_H +#if defined(HAVE_CONFIG_H) +#include "config/dynamic-config.h" +#endif + #include #include #include @@ -21,8 +30,18 @@ extern "C" { #endif -/*************************Argon2 input parameter - * restrictions**************************************************/ +/* Symbols visibility control */ +#ifdef A2_VISCTL +#define ARGON2_PUBLIC __attribute__((visibility("default"))) +#elif _MSC_VER +#define ARGON2_PUBLIC __declspec(dllexport) +#else +#define ARGON2_PUBLIC +#endif + +/* + * Argon2 input parameter restrictions + */ /* Minimum and maximum number of lanes (degree of parallelism) */ #define ARGON2_MIN_LANES UINT32_C(1) @@ -43,8 +62,7 @@ extern "C" { #define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */ #define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b)) -/* Max memory size is half the addressing space, topping at 2^32 blocks (4 TB) - */ +/* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */ #define ARGON2_MAX_MEMORY_BITS \ ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1)) #define ARGON2_MAX_MEMORY \ @@ -70,65 +88,74 @@ extern "C" { #define ARGON2_MIN_SECRET UINT32_C(0) #define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF) +/* Flags to determine which fields are securely wiped (default = no wipe). */ +#define ARGON2_DEFAULT_FLAGS UINT32_C(0) #define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0) #define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1) -#define ARGON2_FLAG_CLEAR_MEMORY (UINT32_C(1) << 2) -#define ARGON2_DEFAULT_FLAGS \ - (ARGON2_FLAG_CLEAR_PASSWORD | ARGON2_FLAG_CLEAR_MEMORY) + +/* Global flag to determine if we are wiping internal memory buffers. This flag + * is defined in core.c and deafults to 1 (wipe internal memory). */ +extern int FLAG_clear_internal_memory; /* Error codes */ typedef enum Argon2_ErrorCodes { ARGON2_OK = 0, - ARGON2_OUTPUT_PTR_NULL = 1, + ARGON2_OUTPUT_PTR_NULL = -1, - ARGON2_OUTPUT_TOO_SHORT = 2, - ARGON2_OUTPUT_TOO_LONG = 3, + ARGON2_OUTPUT_TOO_SHORT = -2, + ARGON2_OUTPUT_TOO_LONG = -3, - ARGON2_PWD_TOO_SHORT = 4, - ARGON2_PWD_TOO_LONG = 5, + ARGON2_PWD_TOO_SHORT = -4, + ARGON2_PWD_TOO_LONG = -5, - ARGON2_SALT_TOO_SHORT = 6, - ARGON2_SALT_TOO_LONG = 7, + ARGON2_SALT_TOO_SHORT = -6, + ARGON2_SALT_TOO_LONG = -7, - ARGON2_AD_TOO_SHORT = 8, - ARGON2_AD_TOO_LONG = 9, + ARGON2_AD_TOO_SHORT = -8, + ARGON2_AD_TOO_LONG = -9, - ARGON2_SECRET_TOO_SHORT = 10, - ARGON2_SECRET_TOO_LONG = 11, + ARGON2_SECRET_TOO_SHORT = -10, + ARGON2_SECRET_TOO_LONG = -11, - ARGON2_TIME_TOO_SMALL = 12, - ARGON2_TIME_TOO_LARGE = 13, + ARGON2_TIME_TOO_SMALL = -12, + ARGON2_TIME_TOO_LARGE = -13, - ARGON2_MEMORY_TOO_LITTLE = 14, - ARGON2_MEMORY_TOO_MUCH = 15, + ARGON2_MEMORY_TOO_LITTLE = -14, + ARGON2_MEMORY_TOO_MUCH = -15, - ARGON2_LANES_TOO_FEW = 16, - ARGON2_LANES_TOO_MANY = 17, + ARGON2_LANES_TOO_FEW = -16, + ARGON2_LANES_TOO_MANY = -17, - ARGON2_PWD_PTR_MISMATCH = 18, /* NULL ptr with non-zero length */ - ARGON2_SALT_PTR_MISMATCH = 19, /* NULL ptr with non-zero length */ - ARGON2_SECRET_PTR_MISMATCH = 20, /* NULL ptr with non-zero length */ - ARGON2_AD_PTR_MISMATCH = 21, /* NULL ptr with non-zero length */ + ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */ + ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */ + ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */ + ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */ - ARGON2_MEMORY_ALLOCATION_ERROR = 22, + ARGON2_MEMORY_ALLOCATION_ERROR = -22, - ARGON2_FREE_MEMORY_CBK_NULL = 23, - ARGON2_ALLOCATE_MEMORY_CBK_NULL = 24, + ARGON2_FREE_MEMORY_CBK_NULL = -23, + ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24, - ARGON2_INCORRECT_PARAMETER = 25, - ARGON2_INCORRECT_TYPE = 26, + ARGON2_INCORRECT_PARAMETER = -25, + ARGON2_INCORRECT_TYPE = -26, - ARGON2_OUT_PTR_MISMATCH = 27, + ARGON2_OUT_PTR_MISMATCH = -27, - ARGON2_THREADS_TOO_FEW = 28, - ARGON2_THREADS_TOO_MANY = 29, + ARGON2_THREADS_TOO_FEW = -28, + ARGON2_THREADS_TOO_MANY = -29, - ARGON2_MISSING_ARGS = 30, + ARGON2_MISSING_ARGS = -30, - ARGON2_ERROR_CODES_LENGTH /* Do NOT remove; Do NOT add error codes after - this - error code */ + ARGON2_ENCODING_FAIL = -31, + + ARGON2_DECODING_FAIL = -32, + + ARGON2_THREAD_FAIL = -33, + + ARGON2_DECODING_LENGTH_FAIL = -34, + + ARGON2_VERIFY_MISMATCH = -35 } argon2_error_codes; /* Memory allocator types --- for external allocation */ @@ -138,155 +165,173 @@ typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate); /* Argon2 external data structures */ /* - *****Context: structure to hold Argon2 inputs: - * output array and its length, - * password and its length, - * salt and its length, - * secret and its length, - * associated data and its length, - * number of passes, amount of used memory (in KBytes, can be rounded up a bit) - * number of parallel threads that will be run. + ***** + * Context: structure to hold Argon2 inputs: + * output array and its length, + * password and its length, + * salt and its length, + * secret and its length, + * associated data and its length, + * number of passes, amount of used memory (in KBytes, can be rounded up a bit) + * number of parallel threads that will be run. * All the parameters above affect the output hash value. * Additionally, two function pointers can be provided to allocate and - deallocate the memory (if NULL, memory will be allocated internally). + * deallocate the memory (if NULL, memory will be allocated internally). * Also, three flags indicate whether to erase password, secret as soon as they - are pre-hashed (and thus not needed anymore), and the entire memory - **************************** - Simplest situation: you have output array out[8], password is stored in - pwd[32], salt is stored in salt[16], you do not have keys nor associated data. - You need to spend 1 GB of RAM and you run 5 passes of Argon2d with 4 parallel - lanes. - You want to erase the password, but you're OK with last pass not being erased. - You want to use the default memory allocator. + * are pre-hashed (and thus not needed anymore), and the entire memory + ***** + * Simplest situation: you have output array out[8], password is stored in + * pwd[32], salt is stored in salt[16], you do not have keys nor associated + * data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with + * 4 parallel lanes. + * You want to erase the password, but you're OK with last pass not being + * erased. You want to use the default memory allocator. + * Then you initialize: + Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false) */ typedef struct Argon2_Context { uint8_t *out; /* output array */ + uint32_t outlen; /* digest length */ + uint8_t *pwd; /* password array */ + uint32_t pwdlen; /* password length */ + uint8_t *salt; /* salt array */ - /*uint8_t *secret;*/ /* key array */ - /*uint8_t *ad;*/ /* associated data array */ + uint32_t saltlen; /* salt length */ + + uint8_t *secret; /* key array */ + uint32_t secretlen; /* key length */ + + uint8_t *ad; /* associated data array */ + uint32_t adlen; /* associated data length */ + + uint32_t t_cost; /* number of passes */ + uint32_t m_cost; /* amount of memory requested (KB) */ + uint32_t lanes; /* number of lanes */ + uint32_t threads; /* maximum number of threads */ allocate_fptr allocate_cbk; /* pointer to memory allocator */ deallocate_fptr free_cbk; /* pointer to memory deallocator */ - /*uint32_t outlen;*/ /* digest length */ - uint32_t pwdlen; /* password length */ - /*uint32_t saltlen;*/ /* salt length */ - /*uint32_t secretlen;*/ /* key length */ - /*uint32_t adlen;*/ /* associated data length */ - /*uint32_t t_cost;*/ /* number of passes */ - /*uint32_t m_cost;*/ /* amount of memory requested (KB) */ - /*uint32_t lanes;*/ /* number of lanes */ - /*uint32_t threads;*/ /* maximum number of threads */ - /*uint32_t flags;*/ /* array of bool options */ - + uint32_t flags; /* array of bool options */ } argon2_context; +/* Argon2 primitive type */ +typedef enum Argon2_type { + Argon2_d = 0 +} argon2_type; + +/* + * Function that gives the string representation of an argon2_type. + * @param type The argon2_type that we want the string for + * @param uppercase Whether the string should have the first letter uppercase + * @return NULL if invalid type, otherwise the string representation. + */ +ARGON2_PUBLIC const char *argon2_type2string(argon2_type type, int uppercase); + +/* + * Function that performs memory-hard hashing with certain degree of parallelism + * @param context Pointer to the Argon2 internal structure + * @return Error code if smth is wrong, ARGON2_OK otherwise + */ +ARGON2_PUBLIC int argon2_ctx(argon2_context *context, argon2_type type); + /** - * Function to hash the inputs in the memory-hard fashion (uses Argon2i) - * @param out Pointer to the memory where the hash digest will be written - * @param outlen Digest length in bytes - * @param in Pointer to the input (password) - * @param inlen Input length in bytes - * @param salt Pointer to the salt - * @param saltlen Salt length in bytes - * @pre @a out must have at least @a outlen bytes allocated - * @pre @a in must be at least @inlen bytes long - * @pre @a saltlen must be at least @saltlen bytes long - * @return Zero if successful, 1 otherwise. + * Hashes a password with Argon2i, producing a raw hash by allocating memory at + * @hash + * @param t_cost Number of iterations + * @param m_cost Sets memory usage to m_cost kibibytes + * @param parallelism Number of threads and compute lanes + * @param pwd Pointer to password + * @param pwdlen Password size in bytes + * @param salt Pointer to salt + * @param saltlen Salt size in bytes + * @param hash Buffer where to write the raw hash - updated by the function + * @param hashlen Desired length of the hash in bytes + * @pre Different parallelism levels will give different results + * @pre Returns ARGON2_OK if successful */ -/*int hash_argon2i(void *out, size_t outlen, const void *in, size_t inlen, - const void *salt, size_t saltlen, unsigned int t_cost, - unsigned int m_cost);*/ +ARGON2_PUBLIC int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, + const size_t hashlen); -/* same for argon2d */ -/*int hash_argon2d(void *out, size_t outlen, const void *in, size_t inlen, - const void *salt, size_t saltlen, unsigned int t_cost, - unsigned int m_cost);*/ +ARGON2_PUBLIC int argon2d_hash_encoded(const uint32_t t_cost, + const uint32_t m_cost, + const uint32_t parallelism, + const void *pwd, const size_t pwdlen, + const void *salt, const size_t saltlen, + const size_t hashlen, char *encoded, + const size_t encodedlen); -/* - * **************Argon2d: Version of Argon2 that picks memory blocks depending +/* generic function underlying the above ones */ +ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, + const size_t hashlen, char *encoded, + const size_t encodedlen, argon2_type type); + +/** + * Verifies a password against an encoded string + * Encoded string is restricted as in validate_inputs() + * @param encoded String encoding parameters, salt, hash + * @param pwd Pointer to password + * @pre Returns ARGON2_OK if successful + */ +ARGON2_PUBLIC int argon2d_verify(const char *encoded, const void *pwd, + const size_t pwdlen); + +/* generic function underlying the above ones */ +ARGON2_PUBLIC int argon2_verify(const char *encoded, const void *pwd, + const size_t pwdlen, argon2_type type); + +/** + * Argon2d: Version of Argon2 that picks memory blocks depending * on the password and salt. Only for side-channel-free - * environment!!*************** + * environment!! + ***** * @param context Pointer to current Argon2 context * @return Zero if successful, a non zero error code otherwise */ -int argon2d(argon2_context *context); +ARGON2_PUBLIC int argon2d_ctx(argon2_context *context); -/* - * * **************Argon2i: Version of Argon2 that picks memory blocks - *independent on the password and salt. Good for side-channels, - ******************* but worse w.r.t. tradeoff attacks if - *******************only one pass is used*************** - * @param context Pointer to current Argon2 context - * @return Zero if successful, a non zero error code otherwise - */ -int argon2i(argon2_context *context); - -/* - * * **************Argon2di: Reserved name*************** - * @param context Pointer to current Argon2 context - * @return Zero if successful, a non zero error code otherwise - */ -int argon2di(argon2_context *context); - -/* - * * **************Argon2ds: Argon2d hardened against GPU attacks, 20% - * slower*************** - * @param context Pointer to current Argon2 context - * @return Zero if successful, a non zero error code otherwise - */ -int argon2ds(argon2_context *context); - -/* - * * **************Argon2id: First half-pass over memory is - *password-independent, the rest are password-dependent - ********************OK against side channels: they reduce to 1/2-pass - *Argon2i*************** - * @param context Pointer to current Argon2 context - * @return Zero if successful, a non zero error code otherwise - */ -int argon2id(argon2_context *context); - -/* +/** * Verify if a given password is correct for Argon2d hashing * @param context Pointer to current Argon2 context * @param hash The password hash to verify. The length of the hash is * specified by the context outlen member * @return Zero if successful, a non zero error code otherwise */ -int verify_d(argon2_context *context, const char *hash); +ARGON2_PUBLIC int argon2d_verify_ctx(argon2_context *context, const char *hash); -/* +/* generic function underlying the above ones */ +ARGON2_PUBLIC int argon2_verify_ctx(argon2_context *context, const char *hash, + argon2_type type); + +/** * Get the associated error message for given error code * @return The error message associated with the given error code */ -const char *error_message(int error_code); +ARGON2_PUBLIC const char *argon2_error_message(int error_code); -/* ==================================================================== */ -/* - * Code specific to Argon2i. - * - * The code below applies the following format: - * - * $argon2i$m=,t=,p=[,keyid=][,data=][$[$]] - * - * where is a decimal integer (positive, fits in an 'unsigned long') - * and is Base64-encoded data (no '=' padding characters, no newline - * or whitespace). The "keyid" is a binary identifier for a key (up to 8 - * bytes); "data" is associated data (up to 32 bytes). When the 'keyid' - * (resp. the 'data') is empty, then it is ommitted from the output. - * - * The last two binary chunks (encoded in Base64) are, in that order, - * the salt and the output. Both are optional, but you cannot have an - * output without a salt. The binary salt length is between 8 and 48 bytes. - * The output length is always exactly 32 bytes. +/** + * Returns the encoded hash length for the given input parameters + * @param t_cost Number of iterations + * @param m_cost Memory usage in kibibytes + * @param parallelism Number of threads; used to compute lanes + * @param saltlen Salt size in bytes + * @param hashlen Hash size in bytes + * @param type The argon2_type that we want the encoded length for + * @return The encoded hash length in bytes */ - -int encode_string(char *dst, size_t dst_len, argon2_context *ctx); +ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, + uint32_t parallelism, uint32_t saltlen, + uint32_t hashlen, argon2_type type); #if defined(__cplusplus) } #endif -#endif +#endif \ No newline at end of file diff --git a/stratum/algos/ar2/bench.c b/stratum/algos/ar2/bench.c deleted file mode 100644 index 7a6edc5..0000000 --- a/stratum/algos/ar2/bench.c +++ /dev/null @@ -1,111 +0,0 @@ -#include -#include -#include -#include -#include -#ifdef _MSC_VER -#include -#endif - -#include "argon2.h" - -static uint64_t rdtsc(void) { -#ifdef _MSC_VER - return __rdtsc(); -#else -#if defined(__amd64__) || defined(__x86_64__) - uint64_t rax, rdx; - __asm__ __volatile__("rdtsc" : "=a"(rax), "=d"(rdx) : :); - return (rdx << 32) | rax; -#elif defined(__i386__) || defined(__i386) || defined(__X86__) - uint64_t rax; - __asm__ __volatile__("rdtsc" : "=A"(rax) : :); - return rax; -#else -#error "Not implemented!" -#endif -#endif -} - -/* - * Benchmarks Argon2 with salt length 16, password length 16, t_cost 1, - and different m_cost and threads - */ -static void benchmark() { -#define BENCH_OUTLEN 16 -#define BENCH_INLEN 16 - const uint32_t inlen = BENCH_INLEN; - const unsigned outlen = BENCH_OUTLEN; - unsigned char out[BENCH_OUTLEN]; - unsigned char pwd_array[BENCH_INLEN]; - unsigned char salt_array[BENCH_INLEN]; -#undef BENCH_INLEN -#undef BENCH_OUTLEN - - uint32_t t_cost = 1; - uint32_t m_cost; - uint32_t thread_test[6] = {1, 2, 4, 6, 8, 16}; - - memset(pwd_array, 0, inlen); - memset(salt_array, 1, inlen); - - for (m_cost = (uint32_t)1 << 10; m_cost <= (uint32_t)1 << 22; m_cost *= 2) { - unsigned i; - for (i = 0; i < 6; ++i) { - argon2_context context; - uint32_t thread_n = thread_test[i]; - uint64_t stop_cycles, stop_cycles_i; - clock_t stop_time; - uint64_t delta_d, delta_i; - double mcycles_d, mcycles_i, run_time; - - clock_t start_time = clock(); - uint64_t start_cycles = rdtsc(); - - context.out = out; - context.outlen = outlen; - context.pwd = pwd_array; - context.pwdlen = inlen; - context.salt = salt_array; - context.saltlen = inlen; - context.secret = NULL; - context.secretlen = 0; - context.ad = NULL; - context.adlen = 0; - context.t_cost = t_cost; - context.m_cost = m_cost; - context.lanes = thread_n; - context.threads = thread_n; - context.allocate_cbk = NULL; - context.free_cbk = NULL; - context.flags = 0; - - argon2d(&context); - stop_cycles = rdtsc(); - argon2i(&context); - stop_cycles_i = rdtsc(); - stop_time = clock(); - - delta_d = (stop_cycles - start_cycles) / (m_cost); - delta_i = (stop_cycles_i - stop_cycles) / (m_cost); - mcycles_d = (double)(stop_cycles - start_cycles) / (1UL << 20); - mcycles_i = (double)(stop_cycles_i - stop_cycles) / (1UL << 20); - printf("Argon2d %d iterations %d MiB %d threads: %2.2f cpb %2.2f " - "Mcycles \n", - t_cost, m_cost >> 10, thread_n, (float)delta_d / 1024, - mcycles_d); - printf("Argon2i %d iterations %d MiB %d threads: %2.2f cpb %2.2f " - "Mcycles \n", - t_cost, m_cost >> 10, thread_n, (float)delta_i / 1024, - mcycles_i); - - run_time = ((double)stop_time - start_time) / (CLOCKS_PER_SEC); - printf("%2.4f seconds\n\n", run_time); - } - } -} - -int main() { - benchmark(); - return ARGON2_OK; -} diff --git a/stratum/algos/ar2/blake2/blamka-round-opt.h b/stratum/algos/ar2/blake2/blamka-round-opt.h deleted file mode 100644 index 690686d..0000000 --- a/stratum/algos/ar2/blake2/blamka-round-opt.h +++ /dev/null @@ -1,162 +0,0 @@ -#ifndef BLAKE_ROUND_MKA_OPT_H -#define BLAKE_ROUND_MKA_OPT_H - -#include "blake2-impl.h" - -#if defined(_MSC_VER) -#include -#endif - -#include -#if defined(__XOP__) && (defined(__GNUC__) || defined(__clang__)) -#include -#endif - -#if !defined(__XOP__) -#if defined(__SSSE3__) -#define r16 \ - (_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9)) -#define r24 \ - (_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10)) -#define _mm_roti_epi64(x, c) \ - (-(c) == 32) \ - ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \ - : (-(c) == 24) \ - ? _mm_shuffle_epi8((x), r24) \ - : (-(c) == 16) \ - ? _mm_shuffle_epi8((x), r16) \ - : (-(c) == 63) \ - ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \ - _mm_add_epi64((x), (x))) \ - : _mm_xor_si128(_mm_srli_epi64((x), -(c)), \ - _mm_slli_epi64((x), 64 - (-(c)))) -#else /* defined(__SSE2__) */ -#define _mm_roti_epi64(r, c) \ - _mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-(c)))) -#endif -#else -#endif - -static BLAKE2_INLINE __m128i fBlaMka(__m128i x, __m128i y) { - const __m128i z = _mm_mul_epu32(x, y); - return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z)); -} - -#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \ - do { \ - A0 = fBlaMka(A0, B0); \ - A1 = fBlaMka(A1, B1); \ - \ - D0 = _mm_xor_si128(D0, A0); \ - D1 = _mm_xor_si128(D1, A1); \ - \ - D0 = _mm_roti_epi64(D0, -32); \ - D1 = _mm_roti_epi64(D1, -32); \ - \ - C0 = fBlaMka(C0, D0); \ - C1 = fBlaMka(C1, D1); \ - \ - B0 = _mm_xor_si128(B0, C0); \ - B1 = _mm_xor_si128(B1, C1); \ - \ - B0 = _mm_roti_epi64(B0, -24); \ - B1 = _mm_roti_epi64(B1, -24); \ - } while ((void)0, 0) - -#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \ - do { \ - A0 = fBlaMka(A0, B0); \ - A1 = fBlaMka(A1, B1); \ - \ - D0 = _mm_xor_si128(D0, A0); \ - D1 = _mm_xor_si128(D1, A1); \ - \ - D0 = _mm_roti_epi64(D0, -16); \ - D1 = _mm_roti_epi64(D1, -16); \ - \ - C0 = fBlaMka(C0, D0); \ - C1 = fBlaMka(C1, D1); \ - \ - B0 = _mm_xor_si128(B0, C0); \ - B1 = _mm_xor_si128(B1, C1); \ - \ - B0 = _mm_roti_epi64(B0, -63); \ - B1 = _mm_roti_epi64(B1, -63); \ - } while ((void)0, 0) - -#if defined(__SSSE3__) -#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ - do { \ - __m128i t0 = _mm_alignr_epi8(B1, B0, 8); \ - __m128i t1 = _mm_alignr_epi8(B0, B1, 8); \ - B0 = t0; \ - B1 = t1; \ - \ - t0 = C0; \ - C0 = C1; \ - C1 = t0; \ - \ - t0 = _mm_alignr_epi8(D1, D0, 8); \ - t1 = _mm_alignr_epi8(D0, D1, 8); \ - D0 = t1; \ - D1 = t0; \ - } while ((void)0, 0) - -#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ - do { \ - __m128i t0 = _mm_alignr_epi8(B0, B1, 8); \ - __m128i t1 = _mm_alignr_epi8(B1, B0, 8); \ - B0 = t0; \ - B1 = t1; \ - \ - t0 = C0; \ - C0 = C1; \ - C1 = t0; \ - \ - t0 = _mm_alignr_epi8(D0, D1, 8); \ - t1 = _mm_alignr_epi8(D1, D0, 8); \ - D0 = t1; \ - D1 = t0; \ - } while ((void)0, 0) -#else /* SSE2 */ -#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ - do { \ - __m128i t0 = D0; \ - __m128i t1 = B0; \ - D0 = C0; \ - C0 = C1; \ - C1 = D0; \ - D0 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t0, t0)); \ - D1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(D1, D1)); \ - B0 = _mm_unpackhi_epi64(B0, _mm_unpacklo_epi64(B1, B1)); \ - B1 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(t1, t1)); \ - } while ((void)0, 0) - -#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ - do { \ - __m128i t0 = C0; \ - C0 = C1; \ - C1 = t0; \ - t0 = B0; \ - __m128i t1 = D0; \ - B0 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(B0, B0)); \ - B1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(B1, B1)); \ - D0 = _mm_unpackhi_epi64(D0, _mm_unpacklo_epi64(D1, D1)); \ - D1 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t1, t1)); \ - } while ((void)0, 0) -#endif - -#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \ - do { \ - G1(A0, B0, C0, D0, A1, B1, C1, D1); \ - G2(A0, B0, C0, D0, A1, B1, C1, D1); \ - \ - DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \ - \ - G1(A0, B0, C0, D0, A1, B1, C1, D1); \ - G2(A0, B0, C0, D0, A1, B1, C1, D1); \ - \ - UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \ - } while ((void)0, 0) - -#endif diff --git a/stratum/algos/ar2/blake2b.c b/stratum/algos/ar2/blake2b.c deleted file mode 100644 index be691b1..0000000 --- a/stratum/algos/ar2/blake2b.c +++ /dev/null @@ -1,305 +0,0 @@ -#include -#include -#include -#include - -#include "blake2/blake2.h" -#include "blake2/blake2-impl.h" - -static const uint64_t blake2b_IV[8] = { - UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b), - UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1), - UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f), - UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179) -}; - -static const unsigned int blake2b_sigma[12][16] = { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, - {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, - {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, - {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, - {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, - {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, - {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, - {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, - {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, -}; - -static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) { - S->f[1] = (uint64_t)-1; -} - -static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) { - if (S->last_node) { - blake2b_set_lastnode(S); - } - S->f[0] = (uint64_t)-1; -} - -static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S, - uint64_t inc) { - S->t[0] += inc; - S->t[1] += (S->t[0] < inc); -} - -static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) { - burn(S, sizeof(*S)); /* wipe */ - blake2b_set_lastblock(S); /* invalidate for further use */ -} - -static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) { - memset(S, 0, sizeof(*S)); - memcpy(S->h, blake2b_IV, sizeof(S->h)); -} - - -/*void print_state(blake2b_state BlakeHash) { - printf(".h = {UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 "),\n" - "UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 "),\n" - "UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 "),\n" - "UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 ")},\n" - ".t = {UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 ")},\n" - ".f = {UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 ")}\n", - BlakeHash.h[0], BlakeHash.h[1], BlakeHash.h[2], BlakeHash.h[3], - BlakeHash.h[4], BlakeHash.h[5], BlakeHash.h[6], BlakeHash.h[7], - BlakeHash.t[0], BlakeHash.t[1], - BlakeHash.f[0], BlakeHash.f[1]); - printf(".buf = {"); - for (register uint8_t i = 0; i < BLAKE2B_BLOCKBYTES; i++) - printf("%" PRIu8 ", ", BlakeHash.buf[i]); - puts("\n"); - printf("}\n.buflen = %d\n.outlen = %d\n", - BlakeHash.buflen, BlakeHash.outlen); - printf(".last_node = %" PRIu8 "\n", BlakeHash.last_node); - fflush(stdout); -}*/ - -static const blake2b_state miou = { - .h = { - UINT64_C(7640891576939301128), UINT64_C(13503953896175478587), - UINT64_C(4354685564936845355), UINT64_C(11912009170470909681), - UINT64_C(5840696475078001361), UINT64_C(11170449401992604703), - UINT64_C(2270897969802886507), UINT64_C(6620516959819538809) - }, - .t = {UINT64_C(0), UINT64_C(0)}, - .f = {UINT64_C(0), UINT64_C(0)}, - .buf = { - 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, 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, 0, 0 - }, - .buflen = 0, - .outlen = 64, - .last_node = 0 -}; - - -int blake2b_init_param(blake2b_state *S, const blake2b_param *P) { - const unsigned char *p = (const unsigned char *)P; - unsigned int i; - - if (NULL == P || NULL == S) { - return -1; - } - - blake2b_init0(S); - - /* IV XOR Parameter Block */ - for (i = 0; i < 8; ++i) { - S->h[i] ^= load64(&p[i * sizeof(S->h[i])]); - } - S->outlen = P->digest_length; - return 0; -} - -void compare_buffs(uint64_t *h, size_t outlen) -{ - // printf("CMP : %d", memcmp(h, miou.h, 8*(sizeof(uint64_t)))); - printf("miou : %" PRIu64 " - h : %" PRIu64 " - outlen : %ld\n", miou.h[0], h[0], outlen); - fflush(stdout); -} - -/* Sequential blake2b initialization */ -int blake2b_init(blake2b_state *S, size_t outlen) { - memcpy(S, &miou, sizeof(*S)); - S->h[0] += outlen; - return 0; -} - - -void print64(const char *name, const uint64_t *array, uint16_t size) { - printf("%s = {", name); - for (uint8_t i = 0; i < size; i++) printf("UINT64_C(%" PRIu64 "), ", array[i]); - printf("};\n"); -} -int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, - size_t keylen) { - return 0; -} - -static void blake2b_compress(blake2b_state *S, const uint8_t *block) { - uint64_t m[16]; - uint64_t v[16]; - unsigned int i, r; - - for (i = 0; i < 16; ++i) { - m[i] = load64(block + i * 8); - } - - for (i = 0; i < 8; ++i) { - v[i] = S->h[i]; - } - - v[8] = blake2b_IV[0]; - v[9] = blake2b_IV[1]; - v[10] = blake2b_IV[2]; - v[11] = blake2b_IV[3]; - v[12] = blake2b_IV[4] ^ S->t[0]; - v[13] = blake2b_IV[5]/* ^ S->t[1]*/; - v[14] = blake2b_IV[6] ^ S->f[0]; - v[15] = blake2b_IV[7]/* ^ S->f[1]*/; - -#define G(r, i, a, b, c, d) \ - do { \ - a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ - d = rotr64(d ^ a, 32); \ - c = c + d; \ - b = rotr64(b ^ c, 24); \ - a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ - d = rotr64(d ^ a, 16); \ - c = c + d; \ - b = rotr64(b ^ c, 63); \ - } while ((void)0, 0) - -#define ROUND(r) \ - do { \ - G(r, 0, v[0], v[4], v[8], v[12]); \ - G(r, 1, v[1], v[5], v[9], v[13]); \ - G(r, 2, v[2], v[6], v[10], v[14]); \ - G(r, 3, v[3], v[7], v[11], v[15]); \ - G(r, 4, v[0], v[5], v[10], v[15]); \ - G(r, 5, v[1], v[6], v[11], v[12]); \ - G(r, 6, v[2], v[7], v[8], v[13]); \ - G(r, 7, v[3], v[4], v[9], v[14]); \ - } while ((void)0, 0) - - for (r = 0; r < 12; ++r) ROUND(r); - - for (i = 0; i < 8; ++i) S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; - -#undef G -#undef ROUND -} - -int blake2b_update(blake2b_state *S, const void *in, size_t inlen) { - const uint8_t *pin = (const uint8_t *)in; - /* Complete current block */ - memcpy(&S->buf[4], pin, 124); - blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); - blake2b_compress(S, S->buf); - S->buflen = 0; - pin += 124; - - register int8_t i = 7; - /* Avoid buffer copies when possible */ - while (i--) { - blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); - blake2b_compress(S, pin); - pin += BLAKE2B_BLOCKBYTES; - } - memcpy(&S->buf[S->buflen], pin, 4); - S->buflen += 4; - return 0; -} - -void my_blake2b_update(blake2b_state *S, const void *in, size_t inlen) { - - memcpy(&S->buf[S->buflen], in, inlen); - S->buflen += (unsigned int)inlen; -} - -int blake2b_final(blake2b_state *S, void *out, size_t outlen) { - uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; - unsigned int i; - - blake2b_increment_counter(S, S->buflen); - blake2b_set_lastblock(S); - memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */ - blake2b_compress(S, S->buf); - - for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ - store64(buffer + sizeof(S->h[i]) * i, S->h[i]); - } - - memcpy(out, buffer, S->outlen); - - burn(buffer, sizeof(buffer)); - burn(S->buf, sizeof(S->buf)); - burn(S->h, sizeof(S->h)); - return 0; -} - -int blake2b(void *out, const void *in, const void *key, size_t keylen) -{ - blake2b_state S; - - blake2b_init(&S, 64); - my_blake2b_update(&S, in, 64); - blake2b_final(&S, out, 64); - burn(&S, sizeof(S)); - return 0; -} - -void blake2b_too(void *pout, const void *in) -{ - uint8_t *out = (uint8_t *)pout; - uint8_t out_buffer[64]; - uint8_t in_buffer[64]; - - blake2b_state blake_state; - blake2b_init(&blake_state, 64); - blake_state.buflen = blake_state.buf[1] = 4; - my_blake2b_update(&blake_state, in, 72); - blake2b_final(&blake_state, out_buffer, 64); - memcpy(out, out_buffer, 32); - out += 32; - - register uint8_t i = 29; - while (i--) { - memcpy(in_buffer, out_buffer, 64); - blake2b(out_buffer, in_buffer, NULL, 0); - memcpy(out, out_buffer, 32); - out += 32; - } - - memcpy(in_buffer, out_buffer, 64); - blake2b(out_buffer, in_buffer, NULL, 0); - memcpy(out, out_buffer, 64); - - burn(&blake_state, sizeof(blake_state)); -} - -/* Argon2 Team - Begin Code */ -int blake2b_long(void *pout, const void *in) -{ - uint8_t *out = (uint8_t *)pout; - blake2b_state blake_state; - uint8_t outlen_bytes[sizeof(uint32_t)] = {0}; - - store32(outlen_bytes, 32); - - blake2b_init(&blake_state, 32); - my_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)); - blake2b_update(&blake_state, in, 1024); - blake2b_final(&blake_state, out, 32); - burn(&blake_state, sizeof(blake_state)); - return 0; - -} -/* Argon2 Team - End Code */ diff --git a/stratum/algos/ar2/core.c b/stratum/algos/ar2/core.c new file mode 100644 index 0000000..9256ce5 --- /dev/null +++ b/stratum/algos/ar2/core.c @@ -0,0 +1,615 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +/*For memory wiping*/ +#ifdef _MSC_VER +#include +#include /* For SecureZeroMemory */ +#endif +#if defined __STDC_LIB_EXT1__ +#define __STDC_WANT_LIB_EXT1__ 1 +#endif +#define VC_GE_2005(version) (version >= 1400) + +#include +#include +#include + +#include "core.h" +#include "thread.h" +#include "../blake2/blake2.h" +#include "../blake2/blake2-impl.h" + +#if defined(__clang__) +#if __has_attribute(optnone) +#define NOT_OPTIMIZED __attribute__((optnone)) +#endif +#elif defined(__GNUC__) +#define GCC_VERSION \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#if GCC_VERSION >= 40400 +#define NOT_OPTIMIZED __attribute__((optimize("O0"))) +#endif +#endif +#ifndef NOT_OPTIMIZED +#define NOT_OPTIMIZED +#endif + +/***************Instance and Position constructors**********/ +void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); } + +void copy_block(block *dst, const block *src) { + memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK); +} + +void xor_block(block *dst, const block *src) { + int i; + for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { + dst->v[i] ^= src->v[i]; + } +} + +static void load_block(block *dst, const void *input) { + unsigned i; + for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { + dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i])); + } +} + +static void store_block(void *output, const block *src) { + unsigned i; + for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { + store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]); + } +} + +/***************Memory functions*****************/ + +int allocate_memory(const argon2_context *context, uint8_t **memory, + size_t num, size_t size) { + size_t memory_size = num*size; + if (memory == NULL) { + return ARGON2_MEMORY_ALLOCATION_ERROR; + } + + /* 1. Check for multiplication overflow */ + if (size != 0 && memory_size / size != num) { + return ARGON2_MEMORY_ALLOCATION_ERROR; + } + + /* 2. Try to allocate with appropriate allocator */ + if (context->allocate_cbk) { + (context->allocate_cbk)(memory, memory_size); + } else { + *memory = malloc(memory_size); + } + + if (*memory == NULL) { + return ARGON2_MEMORY_ALLOCATION_ERROR; + } + + return ARGON2_OK; +} + +void free_memory(const argon2_context *context, uint8_t *memory, + size_t num, size_t size) { + size_t memory_size = num*size; + clear_internal_memory(memory, memory_size); + if (context->free_cbk) { + (context->free_cbk)(memory, memory_size); + } else { + free(memory); + } +} + +void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) { +#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER) + SecureZeroMemory(v, n); +#elif defined memset_s + memset_s(v, n, 0, n); +#elif defined(__OpenBSD__) + explicit_bzero(v, n); +#else + static void *(*const volatile memset_sec)(void *, int, size_t) = &memset; + memset_sec(v, 0, n); +#endif +} + +/* Memory clear flag defaults to true. */ +int FLAG_clear_internal_memory = 1; +void clear_internal_memory(void *v, size_t n) { + if (FLAG_clear_internal_memory && v) { + secure_wipe_memory(v, n); + } +} + +void finalize(const argon2_context *context, argon2_instance_t *instance) { + if (context != NULL && instance != NULL) { + block blockhash; + uint32_t l; + + copy_block(&blockhash, instance->memory + instance->lane_length - 1); + + /* XOR the last blocks */ + for (l = 1; l < instance->lanes; ++l) { + uint32_t last_block_in_lane = + l * instance->lane_length + (instance->lane_length - 1); + xor_block(&blockhash, instance->memory + last_block_in_lane); + } + + /* Hash the result */ + { + uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; + store_block(blockhash_bytes, &blockhash); + blake2b_long(context->out, context->outlen, blockhash_bytes, + ARGON2_BLOCK_SIZE); + /* clear blockhash and blockhash_bytes */ + clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE); + clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); + } + + free_memory(context, (uint8_t *)instance->memory, + instance->memory_blocks, sizeof(block)); + } +} + +uint32_t index_alpha(const argon2_instance_t *instance, + const argon2_position_t *position, uint32_t pseudo_rand, + int same_lane) { + /* + * Pass 0: + * This lane : all already finished segments plus already constructed + * blocks in this segment + * Other lanes : all already finished segments + * Pass 1+: + * This lane : (SYNC_POINTS - 1) last segments plus already constructed + * blocks in this segment + * Other lanes : (SYNC_POINTS - 1) last segments + */ + uint32_t reference_area_size; + uint64_t relative_position; + uint32_t start_position, absolute_position; + + if (0 == position->pass) { + /* First pass */ + if (0 == position->slice) { + /* First slice */ + reference_area_size = + position->index - 1; /* all but the previous */ + } else { + if (same_lane) { + /* The same lane => add current segment */ + reference_area_size = + position->slice * instance->segment_length + + position->index - 1; + } else { + reference_area_size = + position->slice * instance->segment_length + + ((position->index == 0) ? (-1) : 0); + } + } + } else { + /* Second pass */ + if (same_lane) { + reference_area_size = instance->lane_length - + instance->segment_length + position->index - + 1; + } else { + reference_area_size = instance->lane_length - + instance->segment_length + + ((position->index == 0) ? (-1) : 0); + } + } + + /* 1.2.4. Mapping pseudo_rand to 0.. and produce + * relative position */ + relative_position = pseudo_rand; + relative_position = relative_position * relative_position >> 32; + relative_position = reference_area_size - 1 - + (reference_area_size * relative_position >> 32); + + /* 1.2.5 Computing starting position */ + start_position = 0; + + if (0 != position->pass) { + start_position = (position->slice == ARGON2_SYNC_POINTS - 1) + ? 0 + : (position->slice + 1) * instance->segment_length; + } + + /* 1.2.6. Computing absolute position */ + absolute_position = (start_position + relative_position) % + instance->lane_length; /* absolute position */ + return absolute_position; +} + +/* Single-threaded version for p=1 case */ +static int fill_memory_blocks_st(argon2_instance_t *instance) { + uint32_t r, s, l; + + for (r = 0; r < instance->passes; ++r) { + for (s = 0; s < ARGON2_SYNC_POINTS; ++s) { + for (l = 0; l < instance->lanes; ++l) { + argon2_position_t position = {r, l, (uint8_t)s, 0}; + fill_segment(instance, position); + } + } + } + return ARGON2_OK; +} + +#if !defined(ARGON2_NO_THREADS) + +#ifdef _WIN32 +static unsigned __stdcall fill_segment_thr(void *thread_data) +#else +static void *fill_segment_thr(void *thread_data) +#endif +{ + argon2_thread_data *my_data = thread_data; + fill_segment(my_data->instance_ptr, my_data->pos); + argon2_thread_exit(); + return 0; +} + +/* Multi-threaded version for p > 1 case */ +static int fill_memory_blocks_mt(argon2_instance_t *instance) { + uint32_t r, s; + argon2_thread_handle_t *thread = NULL; + argon2_thread_data *thr_data = NULL; + int rc = ARGON2_OK; + + /* 1. Allocating space for threads */ + thread = calloc(instance->lanes, sizeof(argon2_thread_handle_t)); + if (thread == NULL) { + rc = ARGON2_MEMORY_ALLOCATION_ERROR; + goto fail; + } + + thr_data = calloc(instance->lanes, sizeof(argon2_thread_data)); + if (thr_data == NULL) { + rc = ARGON2_MEMORY_ALLOCATION_ERROR; + goto fail; + } + + for (r = 0; r < instance->passes; ++r) { + for (s = 0; s < ARGON2_SYNC_POINTS; ++s) { + uint32_t l; + + /* 2. Calling threads */ + for (l = 0; l < instance->lanes; ++l) { + argon2_position_t position; + + /* 2.1 Join a thread if limit is exceeded */ + if (l >= instance->threads) { + if (argon2_thread_join(thread[l - instance->threads])) { + rc = ARGON2_THREAD_FAIL; + goto fail; + } + } + + /* 2.2 Create thread */ + position.pass = r; + position.lane = l; + position.slice = (uint8_t)s; + position.index = 0; + thr_data[l].instance_ptr = + instance; /* preparing the thread input */ + memcpy(&(thr_data[l].pos), &position, + sizeof(argon2_position_t)); + if (argon2_thread_create(&thread[l], &fill_segment_thr, + (void *)&thr_data[l])) { + rc = ARGON2_THREAD_FAIL; + goto fail; + } + + /* fill_segment(instance, position); */ + /*Non-thread equivalent of the lines above */ + } + + /* 3. Joining remaining threads */ + for (l = instance->lanes - instance->threads; l < instance->lanes; + ++l) { + if (argon2_thread_join(thread[l])) { + rc = ARGON2_THREAD_FAIL; + goto fail; + } + } + } + } + +fail: + if (thread != NULL) { + free(thread); + } + if (thr_data != NULL) { + free(thr_data); + } + return rc; +} + +#endif /* ARGON2_NO_THREADS */ + +int fill_memory_blocks(argon2_instance_t *instance) { + if (instance == NULL || instance->lanes == 0) { + return ARGON2_INCORRECT_PARAMETER; + } +#if defined(ARGON2_NO_THREADS) + return fill_memory_blocks_st(instance); +#else + return instance->threads == 1 ? + fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance); +#endif +} + +int validate_inputs(const argon2_context *context) { + if (NULL == context) { + return ARGON2_INCORRECT_PARAMETER; + } + + if (NULL == context->out) { + return ARGON2_OUTPUT_PTR_NULL; + } + + /* Validate output length */ + if (ARGON2_MIN_OUTLEN > context->outlen) { + return ARGON2_OUTPUT_TOO_SHORT; + } + + if (ARGON2_MAX_OUTLEN < context->outlen) { + return ARGON2_OUTPUT_TOO_LONG; + } + + /* Validate password (required param) */ + if (NULL == context->pwd) { + if (0 != context->pwdlen) { + return ARGON2_PWD_PTR_MISMATCH; + } + } + + if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) { + return ARGON2_PWD_TOO_SHORT; + } + + if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) { + return ARGON2_PWD_TOO_LONG; + } + + /* Validate salt (required param) */ + if (NULL == context->salt) { + if (0 != context->saltlen) { + return ARGON2_SALT_PTR_MISMATCH; + } + } + + if (ARGON2_MIN_SALT_LENGTH > context->saltlen) { + return ARGON2_SALT_TOO_SHORT; + } + + if (ARGON2_MAX_SALT_LENGTH < context->saltlen) { + return ARGON2_SALT_TOO_LONG; + } + + /* Validate secret (optional param) */ + if (NULL == context->secret) { + if (0 != context->secretlen) { + return ARGON2_SECRET_PTR_MISMATCH; + } + } else { + if (ARGON2_MIN_SECRET > context->secretlen) { + return ARGON2_SECRET_TOO_SHORT; + } + if (ARGON2_MAX_SECRET < context->secretlen) { + return ARGON2_SECRET_TOO_LONG; + } + } + + /* Validate associated data (optional param) */ + if (NULL == context->ad) { + if (0 != context->adlen) { + return ARGON2_AD_PTR_MISMATCH; + } + } else { + if (ARGON2_MIN_AD_LENGTH > context->adlen) { + return ARGON2_AD_TOO_SHORT; + } + if (ARGON2_MAX_AD_LENGTH < context->adlen) { + return ARGON2_AD_TOO_LONG; + } + } + + /* Validate memory cost */ + if (ARGON2_MIN_MEMORY > context->m_cost) { + return ARGON2_MEMORY_TOO_LITTLE; + } + + if (ARGON2_MAX_MEMORY < context->m_cost) { + return ARGON2_MEMORY_TOO_MUCH; + } + + if (context->m_cost < 8 * context->lanes) { + return ARGON2_MEMORY_TOO_LITTLE; + } + + /* Validate time cost */ + if (ARGON2_MIN_TIME > context->t_cost) { + return ARGON2_TIME_TOO_SMALL; + } + + if (ARGON2_MAX_TIME < context->t_cost) { + return ARGON2_TIME_TOO_LARGE; + } + + /* Validate lanes */ + if (ARGON2_MIN_LANES > context->lanes) { + return ARGON2_LANES_TOO_FEW; + } + + if (ARGON2_MAX_LANES < context->lanes) { + return ARGON2_LANES_TOO_MANY; + } + + /* Validate threads */ + if (ARGON2_MIN_THREADS > context->threads) { + return ARGON2_THREADS_TOO_FEW; + } + + if (ARGON2_MAX_THREADS < context->threads) { + return ARGON2_THREADS_TOO_MANY; + } + + if (NULL != context->allocate_cbk && NULL == context->free_cbk) { + return ARGON2_FREE_MEMORY_CBK_NULL; + } + + if (NULL == context->allocate_cbk && NULL != context->free_cbk) { + return ARGON2_ALLOCATE_MEMORY_CBK_NULL; + } + + return ARGON2_OK; +} + +void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) { + uint32_t l; + /* Make the first and second block in each lane as G(H0||0||i) or + G(H0||1||i) */ + uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; + for (l = 0; l < instance->lanes; ++l) { + + store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0); + store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l); + blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash, + ARGON2_PREHASH_SEED_LENGTH); + load_block(&instance->memory[l * instance->lane_length + 0], + blockhash_bytes); + + store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1); + blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash, + ARGON2_PREHASH_SEED_LENGTH); + load_block(&instance->memory[l * instance->lane_length + 1], + blockhash_bytes); + } + clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); +} + +void initial_hash(uint8_t *blockhash, argon2_context *context, + argon2_type type) { + blake2b_state BlakeHash; + uint8_t value[sizeof(uint32_t)]; + + if (NULL == context || NULL == blockhash) { + return; + } + + blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH); + + store32(&value, context->lanes); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, context->outlen); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, context->m_cost); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, context->t_cost); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, ARGON2_VERSION_NUMBER); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, (uint32_t)type); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, context->pwdlen); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + if (context->pwd != NULL) { + blake2b_update(&BlakeHash, (const uint8_t *)context->pwd, + context->pwdlen); + + if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) { + secure_wipe_memory(context->pwd, context->pwdlen); + context->pwdlen = 0; + } + } + + store32(&value, context->saltlen); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + if (context->salt != NULL) { + blake2b_update(&BlakeHash, (const uint8_t *)context->salt, + context->saltlen); + } + + store32(&value, context->secretlen); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + if (context->secret != NULL) { + blake2b_update(&BlakeHash, (const uint8_t *)context->secret, + context->secretlen); + + if (context->flags & ARGON2_FLAG_CLEAR_SECRET) { + secure_wipe_memory(context->secret, context->secretlen); + context->secretlen = 0; + } + } + + store32(&value, context->adlen); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + if (context->ad != NULL) { + blake2b_update(&BlakeHash, (const uint8_t *)context->ad, + context->adlen); + } + + blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH); +} + +int initialize(argon2_instance_t *instance, argon2_context *context) { + uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; + int result = ARGON2_OK; + + if (instance == NULL || context == NULL) + return ARGON2_INCORRECT_PARAMETER; + instance->context_ptr = context; + + /* 1. Memory allocation */ + result = allocate_memory(context, (uint8_t **)&(instance->memory), + instance->memory_blocks, sizeof(block)); + if (result != ARGON2_OK) { + return result; + } + + /* 2. Initial hashing */ + /* H_0 + 8 extra bytes to produce the first blocks */ + /* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */ + /* Hashing all inputs */ + initial_hash(blockhash, context, instance->type); + /* Zeroing 8 extra bytes */ + clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, + ARGON2_PREHASH_SEED_LENGTH - + ARGON2_PREHASH_DIGEST_LENGTH); + + /* 3. Creating first blocks, we always have at least two blocks in a slice + */ + fill_first_blocks(blockhash, instance); + /* Clearing the hash */ + clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH); + + return ARGON2_OK; +} \ No newline at end of file diff --git a/stratum/algos/ar2/cores.h b/stratum/algos/ar2/core.h similarity index 62% rename from stratum/algos/ar2/cores.h rename to stratum/algos/ar2/core.h index 8cf5dda..be5a787 100644 --- a/stratum/algos/ar2/cores.h +++ b/stratum/algos/ar2/core.h @@ -1,39 +1,39 @@ /* - * Argon2 source code package + * Argon2 reference source code package - reference C implementations * - * Written by Daniel Dinu and Dmitry Khovratovich, 2015 + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves * - * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: * - * You should have received a copy of the CC0 Public Domain Dedication along - * with - * this software. If not, see - * . + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. */ -#ifndef ARGON2_CORES_H -#define ARGON2_CORES_H +#ifndef ARGON2_CORE_H +#define ARGON2_CORE_H -#if defined(_MSC_VER) -#define ALIGN(n) __declspec(align(16)) -#elif defined(__GNUC__) || defined(__clang) -#define ALIGN(x) __attribute__((__aligned__(x))) -#else -#define ALIGN(x) -#endif +#include "argon2.h" -/*************************Argon2 internal - * constants**************************************************/ +#define CONST_CAST(x) (x)(uintptr_t) + +/**********************Argon2 internal constants*******************************/ enum argon2_core_constants { - /* Version of the algorithm */ + /* Version of the algorithm */ ARGON2_VERSION_NUMBER = 0x10, - /* Memory block size in bytes */ ARGON2_BLOCK_SIZE = 1024, - ARGON2_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8, - ARGON2_QWORDS_IN_BLOCK = 64, - + ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8, + ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16, + ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32, + ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64, + /* Number of pseudo-random values generated by one call to Blake in Argon2i to generate reference block positions */ @@ -44,18 +44,14 @@ enum argon2_core_constants { ARGON2_PREHASH_SEED_LENGTH = 72 }; -/* Argon2 primitive type */ -typedef enum Argon2_type { Argon2_d = 0, Argon2_i = 1 } argon2_type; - -/*************************Argon2 internal data - * types**************************************************/ +/*************************Argon2 internal data types***********************/ /* * Structure for the (1KB) memory block implemented as 128 64-bit words. * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no * bounds checking). */ -typedef struct _block { uint64_t v[ARGON2_WORDS_IN_BLOCK]; } __attribute__ ((aligned (16))) block; +typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block; /*****************Functions that work with the block******************/ @@ -76,8 +72,16 @@ void xor_block(block *dst, const block *src); */ typedef struct Argon2_instance_t { block *memory; /* Memory pointer */ + uint32_t version; + uint32_t passes; /* Number of passes */ + uint32_t memory_blocks; /* Number of blocks in memory */ + uint32_t segment_length; + uint32_t lane_length; + uint32_t lanes; + uint32_t threads; argon2_type type; int print_internals; /* whether to print the memory blocks */ + argon2_context *context_ptr; /* points back to original context */ } argon2_instance_t; /* @@ -97,32 +101,43 @@ typedef struct Argon2_thread_data { argon2_position_t pos; } argon2_thread_data; -/*************************Argon2 core - * functions**************************************************/ +/*************************Argon2 core functions********************************/ -/* Allocates memory to the given pointer +/* Allocates memory to the given pointer, uses the appropriate allocator as + * specified in the context. Total allocated memory is num*size. + * @param context argon2_context which specifies the allocator * @param memory pointer to the pointer to the memory - * @param m_cost number of blocks to allocate in the memory + * @param size the size in bytes for each element to be allocated + * @param num the number of elements to be allocated * @return ARGON2_OK if @memory is a valid pointer and memory is allocated */ -int allocate_memory(block **memory, uint32_t m_cost); +int allocate_memory(const argon2_context *context, uint8_t **memory, + size_t num, size_t size); -/* Function that securely cleans the memory +/* + * Frees memory at the given pointer, uses the appropriate deallocator as + * specified in the context. Also cleans the memory using clear_internal_memory. + * @param context argon2_context which specifies the deallocator + * @param memory pointer to buffer to be freed + * @param size the size in bytes for each element to be deallocated + * @param num the number of elements to be deallocated + */ +void free_memory(const argon2_context *context, uint8_t *memory, + size_t num, size_t size); + +/* Function that securely cleans the memory. This ignores any flags set + * regarding clearing memory. Usually one just calls clear_internal_memory. * @param mem Pointer to the memory * @param s Memory size in bytes */ void secure_wipe_memory(void *v, size_t n); -/* Clears memory - * @param instance pointer to the current instance - * @param clear_memory indicates if we clear the memory with zeros. +/* Function that securely clears the memory if FLAG_clear_internal_memory is + * set. If the flag isn't set, this function does nothing. + * @param mem Pointer to the memory + * @param s Memory size in bytes */ -void clear_memory(argon2_instance_t *instance, int clear); - -/* Deallocates memory - * @param memory pointer to the blocks - */ -void free_memory(block *memory); +void clear_internal_memory(void *v, size_t n); /* * Computes absolute position of reference block in the lane following a skewed @@ -166,7 +181,7 @@ void initial_hash(uint8_t *blockhash, argon2_context *context, * @param blockhash Pointer to the pre-hashing digest * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values */ -void fill_firsts_blocks(uint8_t *blockhash, const argon2_instance_t *instance); +void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance); /* * Function allocates memory, hashes the inputs with Blake, and creates first @@ -196,6 +211,7 @@ void finalize(const argon2_context *context, argon2_instance_t *instance); /* * Function that fills the segment using previous segments also from other * threads + * @param context current context * @param instance Pointer to the current instance * @param position Current position * @pre all block pointers must be valid @@ -207,14 +223,8 @@ void fill_segment(const argon2_instance_t *instance, * Function that fills the entire memory t_cost times based on the first two * blocks in each lane * @param instance Pointer to the current instance + * @return ARGON2_OK if successful, @context->state */ -void fill_memory_blocks(argon2_instance_t *instance); +int fill_memory_blocks(argon2_instance_t *instance); -/* - * Function that performs memory-hard hashing with certain degree of parallelism - * @param context Pointer to the Argon2 internal structure - * @return Error code if smth is wrong, ARGON2_OK otherwise - */ -int argon2_core(argon2_context *context, argon2_type type); - -#endif +#endif \ No newline at end of file diff --git a/stratum/algos/ar2/cores.c b/stratum/algos/ar2/cores.c deleted file mode 100644 index f4b2878..0000000 --- a/stratum/algos/ar2/cores.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Argon2 source code package - * - * Written by Daniel Dinu and Dmitry Khovratovich, 2015 - * - * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. - * - * You should have received a copy of the CC0 Public Domain Dedication along - * with - * this software. If not, see - * . - */ - -/*For memory wiping*/ -#ifdef _MSC_VER -#include -#include /* For SecureZeroMemory */ -#endif -#if defined __STDC_LIB_EXT1__ -#define __STDC_WANT_LIB_EXT1__ 1 -#endif -#define VC_GE_2005(version) (version >= 1400) - -#include -#include -#include -#include - -#include "argon2.h" -#include "cores.h" -#include "blake2/blake2.h" -#include "blake2/blake2-impl.h" - -#ifdef GENKAT -#include "genkat.h" -#endif - -#if defined(__clang__) -#if __has_attribute(optnone) -#define NOT_OPTIMIZED __attribute__((optnone)) -#endif -#elif defined(__GNUC__) -#define GCC_VERSION \ - (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#if GCC_VERSION >= 40400 -#define NOT_OPTIMIZED __attribute__((optimize("O0"))) -#endif -#endif -#ifndef NOT_OPTIMIZED -#define NOT_OPTIMIZED -#endif - -/***************Instance and Position constructors**********/ -void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); } - -void copy_block(block *dst, const block *src) { - memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_WORDS_IN_BLOCK); -} - -void xor_block(block *dst, const block *src) { - int i; - for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) { - dst->v[i] ^= src->v[i]; - } -} - -static void load_block(block *dst, const void *input) { - unsigned i; - for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) { - dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i])); - } -} - -static void store_block(void *output, const block *src) { - unsigned i; - for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) { - store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]); - } -} - -/***************Memory allocators*****************/ -int allocate_memory(block **memory, uint32_t m_cost) { - if (memory != NULL) { - size_t memory_size = sizeof(block) * m_cost; - if (m_cost != 0 && - memory_size / m_cost != - sizeof(block)) { /*1. Check for multiplication overflow*/ - return ARGON2_MEMORY_ALLOCATION_ERROR; - } - - *memory = (block *)malloc(memory_size); /*2. Try to allocate*/ - - if (!*memory) { - return ARGON2_MEMORY_ALLOCATION_ERROR; - } - - return ARGON2_OK; - } else { - return ARGON2_MEMORY_ALLOCATION_ERROR; - } -} - -void secure_wipe_memory(void *v, size_t n) { memset(v, 0, n); } - -/*********Memory functions*/ - -void clear_memory(argon2_instance_t *instance, int clear) { - if (instance->memory != NULL && clear) { - secure_wipe_memory(instance->memory, - sizeof(block) * /*instance->memory_blocks*/16); - } -} - -void free_memory(block *memory) { free(memory); } - -void finalize(const argon2_context *context, argon2_instance_t *instance) { - if (context != NULL && instance != NULL) { - block blockhash; - copy_block(&blockhash, instance->memory + 15); - - /* Hash the result */ - { - uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; - store_block(blockhash_bytes, &blockhash); - blake2b_long(context->out, blockhash_bytes); - secure_wipe_memory(blockhash.v, ARGON2_BLOCK_SIZE); - secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */ - } - -#ifdef GENKAT - print_tag(context->out, context->outlen); -#endif - - /* Clear memory */ - clear_memory(instance, 1); - - free_memory(instance->memory); - } -} - -uint32_t index_alpha(const argon2_instance_t *instance, - const argon2_position_t *position, uint32_t pseudo_rand, - int same_lane) { - /* - * Pass 0: - * This lane : all already finished segments plus already constructed - * blocks in this segment - * Other lanes : all already finished segments - * Pass 1+: - * This lane : (SYNC_POINTS - 1) last segments plus already constructed - * blocks in this segment - * Other lanes : (SYNC_POINTS - 1) last segments - */ - uint32_t reference_area_size; - uint64_t relative_position; - uint32_t start_position, absolute_position; - - if (0 == position->pass) { - /* First pass */ - if (0 == position->slice) { - /* First slice */ - reference_area_size = - position->index - 1; /* all but the previous */ - } else { - if (same_lane) { - /* The same lane => add current segment */ - reference_area_size = - position->slice * 4 + - position->index - 1; - } else { - reference_area_size = - position->slice * 4 + - ((position->index == 0) ? (-1) : 0); - } - } - } else { - /* Second pass */ - if (same_lane) {reference_area_size = 11 + position->index;} - else {reference_area_size = 12 - (position->index == 0);} - } - - /* 1.2.4. Mapping pseudo_rand to 0.. and produce - * relative position */ - relative_position = pseudo_rand; - relative_position = relative_position * relative_position >> 32; - relative_position = reference_area_size - 1 - - (reference_area_size * relative_position >> 32); - - /* 1.2.5 Computing starting position */ - start_position = 0; - - if (0 != position->pass) { - start_position = (position->slice == ARGON2_SYNC_POINTS - 1) - ? 0 : (position->slice + 1) * 4; - } - - /* 1.2.6. Computing absolute position */ - absolute_position = (start_position + relative_position) % 16; - return absolute_position; -} - -void fill_memory_blocks(argon2_instance_t *instance) { - uint32_t r, s; - - for (r = 0; r < 2; ++r) { - for (s = 0; s < ARGON2_SYNC_POINTS; ++s) { - - argon2_position_t position; - position.pass = r; - position.lane = 0; - position.slice = (uint8_t)s; - position.index = 0; - fill_segment(instance, position); - } - -#ifdef GENKAT - internal_kat(instance, r); /* Print all memory blocks */ -#endif - } -} - -void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) { - /* Make the first and second block in each lane as G(H0||i||0) or - G(H0||i||1) */ - uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; - store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0); - store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, 0); - blake2b_too(blockhash_bytes, blockhash); - load_block(&instance->memory[0], blockhash_bytes); - - store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1); - blake2b_too(blockhash_bytes, blockhash); - load_block(&instance->memory[1], blockhash_bytes); - secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); -} - - -static const blake2b_state base_hash = { - .h = { - UINT64_C(7640891576939301192), UINT64_C(13503953896175478587), - UINT64_C(4354685564936845355), UINT64_C(11912009170470909681), - UINT64_C(5840696475078001361), UINT64_C(11170449401992604703), - UINT64_C(2270897969802886507), UINT64_C(6620516959819538809) - }, - .t = {UINT64_C(0),UINT64_C(0)}, - .f = {UINT64_C(0),UINT64_C(0)}, - .buf = { - 1, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 16, 0, 0, 0, 1, 0, - 0, 0, 32, 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, 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}, - .buflen = 28, - .outlen = 64, - .last_node = 0 -}; - -#define PWDLEN 32 -#define SALTLEN 32 -#define SECRETLEN 0 -#define ADLEN 0 -void initial_hash(uint8_t *blockhash, argon2_context *context, - argon2_type type) { - - uint8_t value[sizeof(uint32_t)]; - - /* Is it generating cache invalidation between cores ? */ - blake2b_state BlakeHash = base_hash; - BlakeHash.buf[20] = (uint8_t) type; - my_blake2b_update(&BlakeHash, (const uint8_t *)context->pwd, - PWDLEN); - - - secure_wipe_memory(context->pwd, PWDLEN); - context->pwdlen = 0; - - store32(&value, SALTLEN); - my_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); - - my_blake2b_update(&BlakeHash, (const uint8_t *)context->salt, - SALTLEN); - - store32(&value, SECRETLEN); - my_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); - - store32(&value, ADLEN); - my_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); - - blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH); -} - -int initialize(argon2_instance_t *instance, argon2_context *context) { - /* 1. Memory allocation */ - - - allocate_memory(&(instance->memory), 16); - - /* 2. Initial hashing */ - /* H_0 + 8 extra bytes to produce the first blocks */ - /* Hashing all inputs */ - uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; - initial_hash(blockhash, context, instance->type); - /* Zeroing 8 extra bytes */ - secure_wipe_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, - ARGON2_PREHASH_SEED_LENGTH - - ARGON2_PREHASH_DIGEST_LENGTH); - -#ifdef GENKAT - initial_kat(blockhash, context, instance->type); -#endif - - /* 3. Creating first blocks, we always have at least two blocks in a slice - */ - fill_first_blocks(blockhash, instance); - /* Clearing the hash */ - secure_wipe_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH); - - return ARGON2_OK; -} - -int argon2_core(argon2_context *context, argon2_type type) { - argon2_instance_t instance; - instance.memory = NULL; - instance.type = type; - - /* 3. Initialization: Hashing inputs, allocating memory, filling first - * blocks - */ - - int result = initialize(&instance, context); - if (ARGON2_OK != result) return result; - - /* 4. Filling memory */ - fill_memory_blocks(&instance); - - /* 5. Finalization */ - finalize(context, &instance); - - return ARGON2_OK; -} diff --git a/stratum/algos/ar2/encoding.c b/stratum/algos/ar2/encoding.c new file mode 100644 index 0000000..fae47f7 --- /dev/null +++ b/stratum/algos/ar2/encoding.c @@ -0,0 +1,455 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#include +#include +#include +#include +#include "encoding.h" +#include "core.h" + +/* + * Example code for a decoder and encoder of "hash strings", with Argon2 + * parameters. + * + * This code comprises three sections: + * + * -- The first section contains generic Base64 encoding and decoding + * functions. It is conceptually applicable to any hash function + * implementation that uses Base64 to encode and decode parameters, + * salts and outputs. It could be made into a library, provided that + * the relevant functions are made public (non-static) and be given + * reasonable names to avoid collisions with other functions. + * + * -- The second section is specific to Argon2. It encodes and decodes + * the parameters, salts and outputs. It does not compute the hash + * itself. + * + * The code was originally written by Thomas Pornin , + * to whom comments and remarks may be sent. It is released under what + * should amount to Public Domain or its closest equivalent; the + * following mantra is supposed to incarnate that fact with all the + * proper legal rituals: + * + * --------------------------------------------------------------------- + * This file is provided under the terms of Creative Commons CC0 1.0 + * Public Domain Dedication. To the extent possible under law, the + * author (Thomas Pornin) has waived all copyright and related or + * neighboring rights to this file. This work is published from: Canada. + * --------------------------------------------------------------------- + * + * Copyright (c) 2015 Thomas Pornin + */ + +/* ==================================================================== */ +/* + * Common code; could be shared between different hash functions. + * + * Note: the Base64 functions below assume that uppercase letters (resp. + * lowercase letters) have consecutive numerical codes, that fit on 8 + * bits. All modern systems use ASCII-compatible charsets, where these + * properties are true. If you are stuck with a dinosaur of a system + * that still defaults to EBCDIC then you already have much bigger + * interoperability issues to deal with. + */ + +/* + * Some macros for constant-time comparisons. These work over values in + * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true". + */ +#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF) +#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF) +#define GE(x, y) (GT(y, x) ^ 0xFF) +#define LT(x, y) GT(y, x) +#define LE(x, y) GE(y, x) + +/* + * Convert value x (0..63) to corresponding Base64 character. + */ +static int b64_byte_to_char(unsigned x) { + return (LT(x, 26) & (x + 'A')) | + (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) | + (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') | + (EQ(x, 63) & '/'); +} + +/* + * Convert character c to the corresponding 6-bit value. If character c + * is not a Base64 character, then 0xFF (255) is returned. + */ +static unsigned b64_char_to_byte(int c) { + unsigned x; + + x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) | + (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) | + (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) | + (EQ(c, '/') & 63); + return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF)); +} + +/* + * Convert some bytes to Base64. 'dst_len' is the length (in characters) + * of the output buffer 'dst'; if that buffer is not large enough to + * receive the result (including the terminating 0), then (size_t)-1 + * is returned. Otherwise, the zero-terminated Base64 string is written + * in the buffer, and the output length (counted WITHOUT the terminating + * zero) is returned. + */ +static size_t to_base64(char *dst, size_t dst_len, const void *src, + size_t src_len) { + size_t olen; + const unsigned char *buf; + unsigned acc, acc_len; + + olen = (src_len / 3) << 2; + switch (src_len % 3) { + case 2: + olen++; + /* fall through */ + case 1: + olen += 2; + break; + } + if (dst_len <= olen) { + return (size_t)-1; + } + acc = 0; + acc_len = 0; + buf = (const unsigned char *)src; + while (src_len-- > 0) { + acc = (acc << 8) + (*buf++); + acc_len += 8; + while (acc_len >= 6) { + acc_len -= 6; + *dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F); + } + } + if (acc_len > 0) { + *dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F); + } + *dst++ = 0; + return olen; +} + +/* + * Decode Base64 chars into bytes. The '*dst_len' value must initially + * contain the length of the output buffer '*dst'; when the decoding + * ends, the actual number of decoded bytes is written back in + * '*dst_len'. + * + * Decoding stops when a non-Base64 character is encountered, or when + * the output buffer capacity is exceeded. If an error occurred (output + * buffer is too small, invalid last characters leading to unprocessed + * buffered bits), then NULL is returned; otherwise, the returned value + * points to the first non-Base64 character in the source stream, which + * may be the terminating zero. + */ +static const char *from_base64(void *dst, size_t *dst_len, const char *src) { + size_t len; + unsigned char *buf; + unsigned acc, acc_len; + + buf = (unsigned char *)dst; + len = 0; + acc = 0; + acc_len = 0; + for (;;) { + unsigned d; + + d = b64_char_to_byte(*src); + if (d == 0xFF) { + break; + } + src++; + acc = (acc << 6) + d; + acc_len += 6; + if (acc_len >= 8) { + acc_len -= 8; + if ((len++) >= *dst_len) { + return NULL; + } + *buf++ = (acc >> acc_len) & 0xFF; + } + } + + /* + * If the input length is equal to 1 modulo 4 (which is + * invalid), then there will remain 6 unprocessed bits; + * otherwise, only 0, 2 or 4 bits are buffered. The buffered + * bits must also all be zero. + */ + if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) { + return NULL; + } + *dst_len = len; + return src; +} + +/* + * Decode decimal integer from 'str'; the value is written in '*v'. + * Returned value is a pointer to the next non-decimal character in the + * string. If there is no digit at all, or the value encoding is not + * minimal (extra leading zeros), or the value does not fit in an + * 'unsigned long', then NULL is returned. + */ +static const char *decode_decimal(const char *str, unsigned long *v) { + const char *orig; + unsigned long acc; + + acc = 0; + for (orig = str;; str++) { + int c; + + c = *str; + if (c < '0' || c > '9') { + break; + } + c -= '0'; + if (acc > (ULONG_MAX / 10)) { + return NULL; + } + acc *= 10; + if ((unsigned long)c > (ULONG_MAX - acc)) { + return NULL; + } + acc += (unsigned long)c; + } + if (str == orig || (*orig == '0' && str != (orig + 1))) { + return NULL; + } + *v = acc; + return str; +} + +/* ==================================================================== */ +/* + * Code specific to Argon2. + * + * The code below applies the following format: + * + * $argon2[$v=]$m=,t=,p=$$ + * + * where is either 'd', 'id', or 'i', is a decimal integer (positive, + * fits in an 'unsigned long'), and is Base64-encoded data (no '=' padding + * characters, no newline or whitespace). + * + * The last two binary chunks (encoded in Base64) are, in that order, + * the salt and the output. Both are required. The binary salt length and the + * output length must be in the allowed ranges defined in argon2.h. + * + * The ctx struct must contain buffers large enough to hold the salt and pwd + * when it is fed into decode_string. + */ + +int decode_string(argon2_context *ctx, const char *str, argon2_type type) { + +/* check for prefix */ +#define CC(prefix) \ + do { \ + size_t cc_len = strlen(prefix); \ + if (strncmp(str, prefix, cc_len) != 0) { \ + return ARGON2_DECODING_FAIL; \ + } \ + str += cc_len; \ + } while ((void)0, 0) + +/* optional prefix checking with supplied code */ +#define CC_opt(prefix, code) \ + do { \ + size_t cc_len = strlen(prefix); \ + if (strncmp(str, prefix, cc_len) == 0) { \ + str += cc_len; \ + { code; } \ + } \ + } while ((void)0, 0) + +/* Decoding prefix into decimal */ +#define DECIMAL(x) \ + do { \ + unsigned long dec_x; \ + str = decode_decimal(str, &dec_x); \ + if (str == NULL) { \ + return ARGON2_DECODING_FAIL; \ + } \ + (x) = dec_x; \ + } while ((void)0, 0) + + +/* Decoding prefix into uint32_t decimal */ +#define DECIMAL_U32(x) \ + do { \ + unsigned long dec_x; \ + str = decode_decimal(str, &dec_x); \ + if (str == NULL || dec_x > UINT32_MAX) { \ + return ARGON2_DECODING_FAIL; \ + } \ + (x) = (uint32_t)dec_x; \ + } while ((void)0, 0) + + +/* Decoding base64 into a binary buffer */ +#define BIN(buf, max_len, len) \ + do { \ + size_t bin_len = (max_len); \ + str = from_base64(buf, &bin_len, str); \ + if (str == NULL || bin_len > UINT32_MAX) { \ + return ARGON2_DECODING_FAIL; \ + } \ + (len) = (uint32_t)bin_len; \ + } while ((void)0, 0) + + size_t maxsaltlen = ctx->saltlen; + size_t maxoutlen = ctx->outlen; + int validation_result; + const char* type_string; + + /* We should start with the argon2_type we are using */ + type_string = argon2_type2string(type, 0); + if (!type_string) { + return ARGON2_INCORRECT_TYPE; + } + + CC("$"); + CC(type_string); + + CC("$m="); + DECIMAL_U32(ctx->m_cost); + CC(",t="); + DECIMAL_U32(ctx->t_cost); + CC(",p="); + DECIMAL_U32(ctx->lanes); + ctx->threads = ctx->lanes; + + CC("$"); + BIN(ctx->salt, maxsaltlen, ctx->saltlen); + CC("$"); + BIN(ctx->out, maxoutlen, ctx->outlen); + + /* The rest of the fields get the default values */ + ctx->secret = NULL; + ctx->secretlen = 0; + ctx->ad = NULL; + ctx->adlen = 0; + ctx->allocate_cbk = NULL; + ctx->free_cbk = NULL; + ctx->flags = ARGON2_DEFAULT_FLAGS; + + /* On return, must have valid context */ + validation_result = validate_inputs(ctx); + if (validation_result != ARGON2_OK) { + return validation_result; + } + + /* Can't have any additional characters */ + if (*str == 0) { + return ARGON2_OK; + } else { + return ARGON2_DECODING_FAIL; + } +#undef CC +#undef CC_opt +#undef DECIMAL +#undef BIN +} + +int encode_string(char *dst, size_t dst_len, argon2_context *ctx, + argon2_type type) { +#define SS(str) \ + do { \ + size_t pp_len = strlen(str); \ + if (pp_len >= dst_len) { \ + return ARGON2_ENCODING_FAIL; \ + } \ + memcpy(dst, str, pp_len + 1); \ + dst += pp_len; \ + dst_len -= pp_len; \ + } while ((void)0, 0) + +#define SX(x) \ + do { \ + char tmp[30]; \ + sprintf(tmp, "%lu", (unsigned long)(x)); \ + SS(tmp); \ + } while ((void)0, 0) + +#define SB(buf, len) \ + do { \ + size_t sb_len = to_base64(dst, dst_len, buf, len); \ + if (sb_len == (size_t)-1) { \ + return ARGON2_ENCODING_FAIL; \ + } \ + dst += sb_len; \ + dst_len -= sb_len; \ + } while ((void)0, 0) + + const char* type_string = argon2_type2string(type, 0); + int validation_result = validate_inputs(ctx); + + if (!type_string) { + return ARGON2_ENCODING_FAIL; + } + + if (validation_result != ARGON2_OK) { + return validation_result; + } + + + SS("$"); + SS(type_string); + + SS("$m="); + SX(ctx->m_cost); + SS(",t="); + SX(ctx->t_cost); + SS(",p="); + SX(ctx->lanes); + + SS("$"); + SB(ctx->salt, ctx->saltlen); + + SS("$"); + SB(ctx->out, ctx->outlen); + return ARGON2_OK; + +#undef SS +#undef SX +#undef SB +} + +size_t b64len(uint32_t len) { + size_t olen = ((size_t)len / 3) << 2; + + switch (len % 3) { + case 2: + olen++; + /* fall through */ + case 1: + olen += 2; + break; + } + + return olen; +} + +size_t numlen(uint32_t num) { + size_t len = 1; + while (num >= 10) { + ++len; + num = num / 10; + } + return len; +} diff --git a/stratum/algos/ar2/encoding.h b/stratum/algos/ar2/encoding.h new file mode 100644 index 0000000..580af75 --- /dev/null +++ b/stratum/algos/ar2/encoding.h @@ -0,0 +1,57 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef ENCODING_H +#define ENCODING_H +#include "argon2.h" + +#define ARGON2_MAX_DECODED_LANES UINT32_C(255) +#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8) +#define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12) + +/* +* encode an Argon2 hash string into the provided buffer. 'dst_len' +* contains the size, in characters, of the 'dst' buffer; if 'dst_len' +* is less than the number of required characters (including the +* terminating 0), then this function returns ARGON2_ENCODING_ERROR. +* +* on success, ARGON2_OK is returned. +*/ +int encode_string(char *dst, size_t dst_len, argon2_context *ctx, + argon2_type type); + +/* +* Decodes an Argon2 hash string into the provided structure 'ctx'. +* The only fields that must be set prior to this call are ctx.saltlen and +* ctx.outlen (which must be the maximal salt and out length values that are +* allowed), ctx.salt and ctx.out (which must be buffers of the specified +* length), and ctx.pwd and ctx.pwdlen which must hold a valid password. +* +* Invalid input string causes an error. On success, the ctx is valid and all +* fields have been initialized. +* +* Returned value is ARGON2_OK on success, other ARGON2_ codes on error. +*/ +int decode_string(argon2_context *ctx, const char *str, argon2_type type); + +/* Returns the length of the encoded byte stream with length len */ +size_t b64len(uint32_t len); + +/* Returns the length of the encoded number num */ +size_t numlen(uint32_t num); + +#endif \ No newline at end of file diff --git a/stratum/algos/ar2/genkat.c b/stratum/algos/ar2/genkat.c deleted file mode 100644 index 7aa482d..0000000 --- a/stratum/algos/ar2/genkat.c +++ /dev/null @@ -1,182 +0,0 @@ -#include -#include -#include -#include - -#include "argon2.h" -#include "cores.h" - -void initial_kat(const uint8_t *blockhash, const argon2_context *context, - argon2_type type) { - unsigned i; - - if (blockhash != NULL && context != NULL) { - printf("======================================="); - - switch (type) { - case Argon2_d: - printf("Argon2d\n"); - break; - - case Argon2_i: - printf("Argon2i\n"); - break; - - default: - break; - } - - printf("Memory: %u KiB, Iterations: %u, Parallelism: %u lanes, Tag " - "length: %u bytes\n", - context->m_cost, context->t_cost, context->lanes, - context->outlen); - - printf("Password[%u]: ", context->pwdlen); - - if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) { - printf("CLEARED\n"); - } else { - for (i = 0; i < context->pwdlen; ++i) { - printf("%2.2x ", ((unsigned char *)context->pwd)[i]); - } - - printf("\n"); - } - - printf("Salt[%u]: ", context->saltlen); - - for (i = 0; i < context->saltlen; ++i) { - printf("%2.2x ", ((unsigned char *)context->salt)[i]); - } - - printf("\n"); - - printf("Secret[%u]: ", context->secretlen); - - if (context->flags & ARGON2_FLAG_CLEAR_SECRET) { - printf("CLEARED\n"); - } else { - for (i = 0; i < context->secretlen; ++i) { - printf("%2.2x ", ((unsigned char *)context->secret)[i]); - } - - printf("\n"); - } - - printf("Associated data[%u]: ", context->adlen); - - for (i = 0; i < context->adlen; ++i) { - printf("%2.2x ", ((unsigned char *)context->ad)[i]); - } - - printf("\n"); - - printf("Pre-hashing digest: "); - - for (i = 0; i < ARGON2_PREHASH_DIGEST_LENGTH; ++i) { - printf("%2.2x ", ((unsigned char *)blockhash)[i]); - } - - printf("\n"); - } -} - -void print_tag(const void *out, uint32_t outlen) { - unsigned i; - if (out != NULL) { - printf("Tag: "); - - for (i = 0; i < outlen; ++i) { - printf("%2.2x ", ((uint8_t *)out)[i]); - } - - printf("\n"); - } -} - -void internal_kat(const argon2_instance_t *instance, uint32_t pass) { - - if (instance != NULL) { - uint32_t i, j; - printf("\n After pass %u:\n", pass); - - for (i = 0; i < instance->memory_blocks; ++i) { - uint32_t how_many_words = - (instance->memory_blocks > ARGON2_WORDS_IN_BLOCK) - ? 1 - : ARGON2_WORDS_IN_BLOCK; - - for (j = 0; j < how_many_words; ++j) - printf("Block %.4u [%3u]: %016" PRIx64 "\n", i, j, - instance->memory[i].v[j]); - } - } -} - -static void fatal(const char *error) { - fprintf(stderr, "Error: %s\n", error); - exit(1); -} - -static void generate_testvectors(const char *type) { -#define TEST_OUTLEN 32 -#define TEST_PWDLEN 32 -#define TEST_SALTLEN 16 -#define TEST_SECRETLEN 8 -#define TEST_ADLEN 12 - argon2_context context; - - unsigned char out[TEST_OUTLEN]; - unsigned char pwd[TEST_PWDLEN]; - unsigned char salt[TEST_SALTLEN]; - unsigned char secret[TEST_SECRETLEN]; - unsigned char ad[TEST_ADLEN]; - const allocate_fptr myown_allocator = NULL; - const deallocate_fptr myown_deallocator = NULL; - - unsigned t_cost = 3; - unsigned m_cost = 16; - unsigned lanes = 4; - - memset(pwd, 1, TEST_OUTLEN); - memset(salt, 2, TEST_SALTLEN); - memset(secret, 3, TEST_SECRETLEN); - memset(ad, 4, TEST_ADLEN); - - context.out = out; - context.outlen = TEST_OUTLEN; - context.pwd = pwd; - context.pwdlen = TEST_PWDLEN; - context.salt = salt; - context.saltlen = TEST_SALTLEN; - context.secret = secret; - context.secretlen = TEST_SECRETLEN; - context.ad = ad; - context.adlen = TEST_ADLEN; - context.t_cost = t_cost; - context.m_cost = m_cost; - context.lanes = lanes; - context.threads = lanes; - context.allocate_cbk = myown_allocator; - context.free_cbk = myown_deallocator; - context.flags = 0; - -#undef TEST_OUTLEN -#undef TEST_PWDLEN -#undef TEST_SALTLEN -#undef TEST_SECRETLEN -#undef TEST_ADLEN - - if (!strcmp(type, "d")) { - argon2d(&context); - } else if (!strcmp(type, "i")) { - argon2i(&context); - } else - fatal("wrong Argon2 type"); -} - -int main(int argc, char *argv[]) { - const char *type = (argc > 1) ? argv[1] : "i"; - generate_testvectors(type); - return ARGON2_OK; -} diff --git a/stratum/algos/ar2/genkat.h b/stratum/algos/ar2/genkat.h deleted file mode 100644 index 9c776bf..0000000 --- a/stratum/algos/ar2/genkat.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Argon2 source code package - * - * Written by Daniel Dinu and Dmitry Khovratovich, 2015 - * - * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. - * - * You should have received a copy of the CC0 Public Domain Dedication along - * with - * this software. If not, see - * . - */ - -#ifndef ARGON2_KAT_H -#define ARGON2_KAT_H - -/* - * Initial KAT function that prints the inputs to the file - * @param blockhash Array that contains pre-hashing digest - * @param context Holds inputs - * @param type Argon2 type - * @pre blockhash must point to INPUT_INITIAL_HASH_LENGTH bytes - * @pre context member pointers must point to allocated memory of size according - * to the length values - */ -void initial_kat(const uint8_t *blockhash, const argon2_context *context, - argon2_type type); - -/* - * Function that prints the output tag - * @param out output array pointer - * @param outlen digest length - * @pre out must point to @a outlen bytes - **/ -void print_tag(const void *out, uint32_t outlen); - -/* - * Function that prints the internal state at given moment - * @param instance pointer to the current instance - * @param pass current pass number - * @pre instance must have necessary memory allocated - **/ -void internal_kat(const argon2_instance_t *instance, uint32_t pass); - -#endif diff --git a/stratum/algos/ar2/opt.c b/stratum/algos/ar2/opt.c index 755a894..2ff7b3f 100644 --- a/stratum/algos/ar2/opt.c +++ b/stratum/algos/ar2/opt.c @@ -1,150 +1,214 @@ /* - * Argon2 source code package + * Argon2 reference source code package - reference C implementations * - * Written by Daniel Dinu and Dmitry Khovratovich, 2015 + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves * - * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: * - * You should have received a copy of the CC0 Public Domain Dedication along - * with - * this software. If not, see - * . + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. */ #include #include #include -#include -#include - -#include #include "argon2.h" -#include "cores.h" -#include "opt.h" +#include "core.h" -#include "blake2/blake2.h" -#include "blake2/blamka-round-opt.h" +#include "../blake2/blake2.h" +#include "../blake2/blamka-round-opt.h" -void fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_block) -{ - __m128i block_XY[ARGON2_QWORDS_IN_BLOCK] __attribute__ ((aligned (16))); - uint32_t i; - for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) { - block_XY[i] = state[i] = _mm_xor_si128( - state[i], _mm_load_si128(&ref_block[i])); +/* + * Function fills a new memory block and optionally XORs the old block over the new one. + * Memory must be initialized. + * @param state Pointer to the just produced block. Content will be updated(!) + * @param ref_block Pointer to the reference block + * @param next_block Pointer to the block to be XORed over. May coincide with @ref_block + * @param with_xor Whether to XOR into the new block (1) or just overwrite (0) + * @pre all block pointers must be valid + */ +#if defined(__AVX512F__) +static void fill_block(__m512i *state, const block *ref_block, + block *next_block, int with_xor) { + __m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK]; + unsigned int i; + + if (with_xor) { + for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) { + state[i] = _mm512_xor_si512( + state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i)); + block_XY[i] = _mm512_xor_si512( + state[i], _mm512_loadu_si512((const __m512i *)next_block->v + i)); + } + } else { + for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) { + block_XY[i] = state[i] = _mm512_xor_si512( + state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i)); + } } - BLAKE2_ROUND(state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7]); - BLAKE2_ROUND(state[8], state[9], state[10], state[11], state[12], state[13], state[14], state[15]); - BLAKE2_ROUND(state[16], state[17], state[18], state[19], state[20], state[21], state[22], state[23]); - BLAKE2_ROUND(state[24], state[25], state[26], state[27], state[28], state[29], state[30], state[31]); - BLAKE2_ROUND(state[32], state[33], state[34], state[35], state[36], state[37], state[38], state[39]); - BLAKE2_ROUND(state[40], state[41], state[42], state[43], state[44], state[45], state[46], state[47]); - BLAKE2_ROUND(state[48], state[49], state[50], state[51], state[52], state[53], state[54], state[55]); - BLAKE2_ROUND(state[56], state[57], state[58], state[59], state[60], state[61], state[62], state[63]); - /*for (i = 0; i < 8; ++i) { + for (i = 0; i < 2; ++i) { + BLAKE2_ROUND_1( + state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3], + state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]); + } + + for (i = 0; i < 2; ++i) { + BLAKE2_ROUND_2( + state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i], + state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]); + } + + for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) { + state[i] = _mm512_xor_si512(state[i], block_XY[i]); + _mm512_storeu_si512((__m512i *)next_block->v + i, state[i]); + } +} +#elif defined(__AVX2__) +static void fill_block(__m256i *state, const block *ref_block, + block *next_block, int with_xor) { + __m256i block_XY[ARGON2_HWORDS_IN_BLOCK]; + unsigned int i; + + if (with_xor) { + for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) { + state[i] = _mm256_xor_si256( + state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i)); + block_XY[i] = _mm256_xor_si256( + state[i], _mm256_loadu_si256((const __m256i *)next_block->v + i)); + } + } else { + for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) { + block_XY[i] = state[i] = _mm256_xor_si256( + state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i)); + } + } + + for (i = 0; i < 4; ++i) { + BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5], + state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]); + } + + for (i = 0; i < 4; ++i) { + BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i], + state[16 + i], state[20 + i], state[24 + i], state[28 + i]); + } + + for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) { + state[i] = _mm256_xor_si256(state[i], block_XY[i]); + _mm256_storeu_si256((__m256i *)next_block->v + i, state[i]); + } +} +#else +static void fill_block(__m128i *state, const block *ref_block, + block *next_block, int with_xor) { + __m128i block_XY[ARGON2_OWORDS_IN_BLOCK]; + unsigned int i; + + if (with_xor) { + for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { + state[i] = _mm_xor_si128( + state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i)); + block_XY[i] = _mm_xor_si128( + state[i], _mm_loadu_si128((const __m128i *)next_block->v + i)); + } + } else { + for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { + block_XY[i] = state[i] = _mm_xor_si128( + state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i)); + } + } + + for (i = 0; i < 8; ++i) { BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], - state[8 * i + 3], state[8 * i + 4], state[8 * i + 5], - state[8 * i + 6], state[8 * i + 7]); - }*/ + state[8 * i + 3], state[8 * i + 4], state[8 * i + 5], + state[8 * i + 6], state[8 * i + 7]); + } - BLAKE2_ROUND(state[0], state[8], state[16], state[24], state[32], state[40], state[48], state[56]); - BLAKE2_ROUND(state[1], state[9], state[17], state[25], state[33], state[41], state[49], state[57]); - BLAKE2_ROUND(state[2], state[10], state[18], state[26], state[34], state[42], state[50], state[58]); - BLAKE2_ROUND(state[3], state[11], state[19], state[27], state[35], state[43], state[51], state[59]); - BLAKE2_ROUND(state[4], state[12], state[20], state[28], state[36], state[44], state[52], state[60]); - BLAKE2_ROUND(state[5], state[13], state[21], state[29], state[37], state[45], state[53], state[61]); - BLAKE2_ROUND(state[6], state[14], state[22], state[30], state[38], state[46], state[54], state[62]); - BLAKE2_ROUND(state[7], state[15], state[23], state[31], state[39], state[47], state[55], state[63]); - /*for (i = 0; i < 8; ++i) { + for (i = 0; i < 8; ++i) { BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i], - state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i], - state[8 * 6 + i], state[8 * 7 + i]); - }*/ + state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i], + state[8 * 6 + i], state[8 * 7 + i]); + } - for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) { + for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { state[i] = _mm_xor_si128(state[i], block_XY[i]); - _mm_storeu_si128(&next_block[i], state[i]); + _mm_storeu_si128((__m128i *)next_block->v + i, state[i]); } } +#endif -static const uint64_t bad_rands[32] = { - UINT64_C(17023632018251376180), UINT64_C(4911461131397773491), - UINT64_C(15927076453364631751), UINT64_C(7860239898779391109), +static void next_addresses(block *address_block, block *input_block) { + /*Temporary zero-initialized blocks*/ +#if defined(__AVX512F__) + __m512i zero_block[ARGON2_512BIT_WORDS_IN_BLOCK]; + __m512i zero2_block[ARGON2_512BIT_WORDS_IN_BLOCK]; +#elif defined(__AVX2__) + __m256i zero_block[ARGON2_HWORDS_IN_BLOCK]; + __m256i zero2_block[ARGON2_HWORDS_IN_BLOCK]; +#else + __m128i zero_block[ARGON2_OWORDS_IN_BLOCK]; + __m128i zero2_block[ARGON2_OWORDS_IN_BLOCK]; +#endif - UINT64_C(11820267568857244377), UINT64_C(12188179869468676617), - UINT64_C(3732913385414474778), UINT64_C(7651458777762572084), + memset(zero_block, 0, sizeof(zero_block)); + memset(zero2_block, 0, sizeof(zero2_block)); - UINT64_C(3062274162574341415), UINT64_C(17922653540258786897), - UINT64_C(17393848266100524980), UINT64_C(8539695715554563839), + /*Increasing index counter*/ + input_block->v[6]++; - UINT64_C(13824538050656654359), UINT64_C(12078939433126460936), - UINT64_C(15331979418564540430), UINT64_C(12058346794217174273), + /*First iteration of G*/ + fill_block(zero_block, input_block, address_block, 0); - UINT64_C(13593922096015221049), UINT64_C(18356682276374416500), - UINT64_C(4968040514092703824), UINT64_C(11202790346130235567), - - UINT64_C(2276229735041314644), UINT64_C(220837743321691382), - UINT64_C(4861211596230784273), UINT64_C(6330592584132590331), - - UINT64_C(3515580430960296763), UINT64_C(9869356316971855173), - UINT64_C(485533243489193056), UINT64_C(14596447761048148032), - - UINT64_C(16531790085730132900), UINT64_C(17328824500878824371), - UINT64_C(8548260058287621283), UINT64_C(8641748798041936364) -}; - -void generate_addresses(const argon2_instance_t *instance, - const argon2_position_t *position, - uint64_t *pseudo_rands) -{ - uint8_t offset = position->pass * 16 + position->slice * 4; - pseudo_rands[0] = bad_rands[offset++]; - pseudo_rands[1] = bad_rands[offset++]; - pseudo_rands[2] = bad_rands[offset++]; - pseudo_rands[3] = bad_rands[offset++]; - - /*if ((position->pass == 1 && position->slice == 3)) - print64("pseudo_rands", pseudo_rands, 4);*/ + /*Second iteration of G*/ + fill_block(zero2_block, address_block, address_block, 0); } -#define SEGMENT_LENGTH 4 -#define LANE_LENGTH 16 -#define POS_LANE 0 - void fill_segment(const argon2_instance_t *instance, - argon2_position_t position) -{ + argon2_position_t position) { block *ref_block = NULL, *curr_block = NULL; - uint64_t pseudo_rand, ref_index; + block address_block, input_block; + uint64_t pseudo_rand, ref_index, ref_lane; uint32_t prev_offset, curr_offset; - uint8_t i; - __m128i state[64]; - int data_independent_addressing = (instance->type == Argon2_i); + uint32_t starting_index, i; +#if defined(__AVX512F__) + __m512i state[ARGON2_512BIT_WORDS_IN_BLOCK]; +#elif defined(__AVX2__) + __m256i state[ARGON2_HWORDS_IN_BLOCK]; +#else + __m128i state[ARGON2_OWORDS_IN_BLOCK]; +#endif + int data_independent_addressing; - /* Pseudo-random values that determine the reference block position */ - uint64_t *pseudo_rands = NULL; - - pseudo_rands = (uint64_t *)malloc(/*sizeof(uint64_t) * 4*/32); - - if (data_independent_addressing) { - generate_addresses(instance, &position, pseudo_rands); + if (instance == NULL) { + return; } - i = 0; + starting_index = 0; if ((0 == position.pass) && (0 == position.slice)) { - i = 2; /* we have already generated the first two blocks */ + starting_index = 2; /* we have already generated the first two blocks */ + + /* Don't forget to generate the first block of addresses: */ + if (data_independent_addressing) { + next_addresses(&address_block, &input_block); + } } - /*printf("Position.lane = %d\nPosition.slice = %d\nStarting index : %d\n", position.lane, position.slice, starting_index);*/ /* Offset of the current block */ - curr_offset = position.slice * 4 + i; + curr_offset = position.lane * instance->lane_length + + position.slice * instance->segment_length + starting_index; - if (0 == curr_offset % 16) { + if (0 == curr_offset % instance->lane_length) { /* Last block in this lane */ - prev_offset = curr_offset + /*instance->lane_length - 1*/15; + prev_offset = curr_offset + instance->lane_length - 1; } else { /* Previous block */ prev_offset = curr_offset - 1; @@ -152,34 +216,45 @@ void fill_segment(const argon2_instance_t *instance, memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE); - for (; i < SEGMENT_LENGTH; + for (i = starting_index; i < instance->segment_length; ++i, ++curr_offset, ++prev_offset) { /*1.1 Rotating prev_offset if needed */ - if (curr_offset % LANE_LENGTH == 1) { + if (curr_offset % instance->lane_length == 1) { prev_offset = curr_offset - 1; } /* 1.2 Computing the index of the reference block */ /* 1.2.1 Taking pseudo-random value from the previous block */ if (data_independent_addressing) { - pseudo_rand = pseudo_rands[i]; + if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { + next_addresses(&address_block, &input_block); + } + pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK]; } else { pseudo_rand = instance->memory[prev_offset].v[0]; } /* 1.2.2 Computing the lane of the reference block */ + ref_lane = ((pseudo_rand >> 32)) % instance->lanes; + + if ((position.pass == 0) && (position.slice == 0)) { + /* Can not reference other lanes yet */ + ref_lane = position.lane; + } /* 1.2.3 Computing the number of possible reference block within the * lane. */ position.index = i; - ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,1); + ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF, + ref_lane == position.lane); /* 2 Creating a new block */ - ref_block = instance->memory + ref_index; + ref_block = + instance->memory + instance->lane_length * ref_lane + ref_index; curr_block = instance->memory + curr_offset; - fill_block(state, (__m128i const *)ref_block->v, (__m128i *)curr_block->v); - } + + fill_block(state, ref_block, curr_block, 0); - free(pseudo_rands); -} + } +} \ No newline at end of file diff --git a/stratum/algos/ar2/opt.h b/stratum/algos/ar2/opt.h deleted file mode 100644 index ec89b96..0000000 --- a/stratum/algos/ar2/opt.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Argon2 source code package - * - * Written by Daniel Dinu and Dmitry Khovratovich, 2015 - * - * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. - * - * You should have received a copy of the CC0 Public Domain Dedication along - * with - * this software. If not, see - * . - */ - -#ifndef ARGON2_OPT_H -#define ARGON2_OPT_H - -/* - * Function fills a new memory block. Differs from the - * @param state Pointer to the just produced block. Content will be updated(!) - * @param ref_block Pointer to the reference block - * @param next_block Pointer to the block to be constructed - * @pre all block pointers must be valid - */ -void fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_block); - -/* - * Generate pseudo-random values to reference blocks in the segment and puts - * them into the array - * @param instance Pointer to the current instance - * @param position Pointer to the current position - * @param pseudo_rands Pointer to the array of 64-bit values - * @pre pseudo_rands must point to @a instance->segment_length allocated values - */ -void generate_addresses(const argon2_instance_t *instance, - const argon2_position_t *position, - uint64_t *pseudo_rands); - -/* - * Function that fills the segment using previous segments also from other - * threads. - * Identical to the reference code except that it calls optimized FillBlock() - * @param instance Pointer to the current instance - * @param position Current position - * @pre all block pointers must be valid - */ -void fill_segment(const argon2_instance_t *instance, - argon2_position_t position); - -#endif /* ARGON2_OPT_H */ diff --git a/stratum/algos/ar2/ref.c b/stratum/algos/ar2/ref.c deleted file mode 100644 index 98ae07c..0000000 --- a/stratum/algos/ar2/ref.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Argon2 source code package - * - * Written by Daniel Dinu and Dmitry Khovratovich, 2015 - * - * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. - * - * You should have received a copy of the CC0 Public Domain Dedication along - * with - * this software. If not, see - * . - */ - -#include -#include -#include - -#include "argon2.h" -#include "cores.h" -#include "ref.h" - -#include "blake2/blamka-round-ref.h" -#include "blake2/blake2-impl.h" -#include "blake2/blake2.h" - -void fill_block(const block *prev_block, const block *ref_block, - block *next_block) { - block blockR, block_tmp; - unsigned i; - - copy_block(&blockR, ref_block); - xor_block(&blockR, prev_block); - copy_block(&block_tmp, &blockR); - - /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then - (16,17,..31)... finally (112,113,...127) */ - for (i = 0; i < 8; ++i) { - BLAKE2_ROUND_NOMSG( - blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2], - blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5], - blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8], - blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11], - blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14], - blockR.v[16 * i + 15]); - } - - /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then - (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */ - for (i = 0; i < 8; i++) { - BLAKE2_ROUND_NOMSG( - blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16], - blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33], - blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64], - blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81], - blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112], - blockR.v[2 * i + 113]); - } - - copy_block(next_block, &block_tmp); - xor_block(next_block, &blockR); -} - -void generate_addresses(const argon2_instance_t *instance, - const argon2_position_t *position, - uint64_t *pseudo_rands) { - block zero_block, input_block, address_block; - uint32_t i; - - init_block_value(&zero_block, 0); - init_block_value(&input_block, 0); - init_block_value(&address_block, 0); - - if (instance != NULL && position != NULL) { - input_block.v[0] = position->pass; - input_block.v[1] = position->lane; - input_block.v[2] = position->slice; - input_block.v[3] = 16; - input_block.v[4] = 2; - input_block.v[5] = instance->type; - - for (i = 0; i < 4; ++i) { - if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { - input_block.v[6]++; - fill_block(&zero_block, &input_block, &address_block); - fill_block(&zero_block, &address_block, &address_block); - } - - pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK]; - } - } -} - -void fill_segment(const argon2_instance_t *instance, - argon2_position_t position) { - block *ref_block = NULL, *curr_block = NULL; - uint64_t pseudo_rand, ref_index, ref_lane; - uint32_t prev_offset, curr_offset; - uint32_t starting_index; - uint32_t i; - int data_independent_addressing = (instance->type == Argon2_i); - /* Pseudo-random values that determine the reference block position */ - uint64_t *pseudo_rands = NULL; - - if (instance == NULL) { - return; - } - - pseudo_rands = - (uint64_t *)malloc(sizeof(uint64_t) * 4); - - if (pseudo_rands == NULL) { - return; - } - - if (data_independent_addressing) { - generate_addresses(instance, &position, pseudo_rands); - } - - starting_index = 0; - - if ((0 == position.pass) && (0 == position.slice)) { - starting_index = 2; /* we have already generated the first two blocks */ - } - - /* Offset of the current block */ - curr_offset = position.lane * 16 + - position.slice * 4 + starting_index; - - if (0 == curr_offset % 16) { - /* Last block in this lane */ - prev_offset = curr_offset + 16 - 1; - } else { - /* Previous block */ - prev_offset = curr_offset - 1; - } - - for (i = starting_index; i < 4; ++i, ++curr_offset, ++prev_offset) { - /*1.1 Rotating prev_offset if needed */ - if (curr_offset % 16 == 1) { - prev_offset = curr_offset - 1; - } - - /* 1.2 Computing the index of the reference block */ - /* 1.2.1 Taking pseudo-random value from the previous block */ - if (data_independent_addressing) { - pseudo_rand = pseudo_rands[i]; - } else { - pseudo_rand = instance->memory[prev_offset].v[0]; - } - - /* 1.2.2 Computing the lane of the reference block */ - ref_lane = ((pseudo_rand >> 32)) % 1; - - if ((position.pass == 0) && (position.slice == 0)) { - /* Can not reference other lanes yet */ - ref_lane = position.lane; - } - - /* 1.2.3 Computing the number of possible reference block within the - * lane. - */ - position.index = i; - ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF, - ref_lane == position.lane); - - /* 2 Creating a new block */ - ref_block = - instance->memory + 16 * ref_lane + ref_index; - curr_block = instance->memory + curr_offset; - fill_block(instance->memory + prev_offset, ref_block, curr_block); - } - - free(pseudo_rands); -} diff --git a/stratum/algos/ar2/ref.h b/stratum/algos/ar2/ref.h deleted file mode 100644 index 7ee22ee..0000000 --- a/stratum/algos/ar2/ref.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Argon2 source code package - * - * Written by Daniel Dinu and Dmitry Khovratovich, 2015 - * - * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. - * - * You should have received a copy of the CC0 Public Domain Dedication along - * with - * this software. If not, see - * . - */ - -#ifndef ARGON2_REF_H -#define ARGON2_REF_H - -/* - * Function fills a new memory block - * @param prev_block Pointer to the previous block - * @param ref_block Pointer to the reference block - * @param next_block Pointer to the block to be constructed - * @pre all block pointers must be valid - */ -void fill_block(const block *prev_block, const block *ref_block, - block *next_block); - -/* - * Generate pseudo-random values to reference blocks in the segment and puts - * them into the array - * @param instance Pointer to the current instance - * @param position Pointer to the current position - * @param pseudo_rands Pointer to the array of 64-bit values - * @pre pseudo_rands must point to @a instance->segment_length allocated values - */ -void generate_addresses(const argon2_instance_t *instance, - const argon2_position_t *position, - uint64_t *pseudo_rands); - -/* - * Function that fills the segment using previous segments also from other - * threads - * @param instance Pointer to the current instance - * @param position Current position - * @pre all block pointers must be valid - */ -void fill_segment(const argon2_instance_t *instance, - argon2_position_t position); - -#endif /* ARGON2_REF_H */ diff --git a/stratum/algos/ar2/run.c b/stratum/algos/ar2/run.c deleted file mode 100644 index 2b1b30a..0000000 --- a/stratum/algos/ar2/run.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Argon2 source code package - * - * Written by Daniel Dinu and Dmitry Khovratovich, 2015 - * - * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. - * - * You should have received a copy of the CC0 Public Domain Dedication along - * with - * this software. If not, see - * . - */ - -#include -#include -#include -#include -#include -#include - -#include "argon2.h" -#include "cores.h" - -#define T_COST_DEF 3 -#define LOG_M_COST_DEF 12 /* 2^12 = 4 MiB */ -#define LANES_DEF 1 -#define THREADS_DEF 1 -#define OUT_LEN 32 -#define SALT_LEN 16 - -#define UNUSED_PARAMETER(x) (void)(x) - -static void usage(const char *cmd) { - printf("Usage: %s pwd salt [-y version] [-t iterations] [-m memory] [-p " - "parallelism]\n", - cmd); - - printf("Parameters:\n"); - printf("\tpwd\t\tThe password to hash\n"); - printf("\tsalt\t\tThe salt to use, at most 16 characters\n"); - printf("\t-d\t\tUse Argon2d instead of Argon2i (which is the default)\n"); - printf("\t-t N\t\tSets the number of iterations to N (default = %d)\n", - T_COST_DEF); - printf("\t-m N\t\tSets the memory usage of 2^N KiB (default %d)\n", - LOG_M_COST_DEF); - printf("\t-p N\t\tSets parallelism to N threads (default %d)\n", - THREADS_DEF); -} - -static void fatal(const char *error) { - fprintf(stderr, "Error: %s\n", error); - exit(1); -} - -/* -Runs Argon2 with certain inputs and parameters, inputs not cleared. Prints the -Base64-encoded hash string -@out output array with at least 32 bytes allocated -@pwd NULL-terminated string, presumably from argv[] -@salt salt array with at least SALTLEN_DEF bytes allocated -@t_cost number of iterations -@m_cost amount of requested memory in KB -@lanes amount of requested parallelism -@threads actual parallelism -@type String, only "d" and "i" are accepted -*/ -static void run(uint8_t *out, char *pwd, uint8_t *salt, uint32_t t_cost, - uint32_t m_cost, uint32_t lanes, uint32_t threads, - const char *type) { - clock_t start_time, stop_time; - unsigned pwd_length; - argon2_context context; - int i; - - start_time = clock(); - - if (!pwd) { - fatal("password missing"); - } - - if (!salt) { - secure_wipe_memory(pwd, strlen(pwd)); - fatal("salt missing"); - } - - pwd_length = strlen(pwd); - - UNUSED_PARAMETER(threads); - - context.out = out; - context.outlen = OUT_LEN; - context.pwd = (uint8_t *)pwd; - context.pwdlen = pwd_length; - context.salt = salt; - context.saltlen = SALT_LEN; - context.secret = NULL; - context.secretlen = 0; - context.ad = NULL; - context.adlen = 0; - context.t_cost = t_cost; - context.m_cost = m_cost; - context.lanes = lanes; - context.threads = lanes; - context.allocate_cbk = NULL; - context.free_cbk = NULL; - context.flags = ARGON2_FLAG_CLEAR_PASSWORD; - - if (!strcmp(type, "d")) { - int result = argon2d(&context); - if (result != ARGON2_OK) - fatal(error_message(result)); - } else if (!strcmp(type, "i")) { - int result = argon2i(&context); - if (result != ARGON2_OK) - fatal(error_message(result)); - } else { - secure_wipe_memory(pwd, strlen(pwd)); - fatal("wrong Argon2 type"); - } - - stop_time = clock(); - - /* add back when proper decoding */ - /* - char encoded[300]; - encode_string(encoded, sizeof encoded, &context); - printf("%s\n", encoded); - */ - printf("Hash:\t\t"); - for (i = 0; i < context.outlen; ++i) { - printf("%02x", context.out[i]); - } - printf("\n"); - - printf("%2.3f seconds\n", - ((double)stop_time - start_time) / (CLOCKS_PER_SEC)); -} - -int main(int argc, char *argv[]) { - unsigned char out[OUT_LEN]; - uint32_t m_cost = 1 << LOG_M_COST_DEF; - uint32_t t_cost = T_COST_DEF; - uint32_t lanes = LANES_DEF; - uint32_t threads = THREADS_DEF; - char *pwd = NULL; - uint8_t salt[SALT_LEN]; - const char *type = "i"; - int i; - - if (argc < 3) { - usage(argv[0]); - return ARGON2_MISSING_ARGS; - } - - /* get password and salt from command line */ - pwd = argv[1]; - if (strlen(argv[2]) > SALT_LEN) { - fatal("salt too long"); - } - memset(salt, 0x00, SALT_LEN); /* pad with null bytes */ - memcpy(salt, argv[2], strlen(argv[2])); - - /* parse options */ - for (i = 3; i < argc; i++) { - const char *a = argv[i]; - unsigned long input = 0; - if (!strcmp(a, "-m")) { - if (i < argc - 1) { - i++; - input = strtoul(argv[i], NULL, 10); - if (input == 0 || input == ULONG_MAX || - input > ARGON2_MAX_MEMORY_BITS) { - fatal("bad numeric input for -m"); - } - m_cost = ARGON2_MIN(UINT64_C(1) << input, UINT32_C(0xFFFFFFFF)); - if (m_cost > ARGON2_MAX_MEMORY) { - fatal("m_cost overflow"); - } - continue; - } else { - fatal("missing -m argument"); - } - } else if (!strcmp(a, "-t")) { - if (i < argc - 1) { - i++; - input = strtoul(argv[i], NULL, 10); - if (input == 0 || input == ULONG_MAX || - input > ARGON2_MAX_TIME) { - fatal("bad numeric input for -t"); - } - t_cost = input; - continue; - } else { - fatal("missing -t argument"); - } - } else if (!strcmp(a, "-p")) { - if (i < argc - 1) { - i++; - input = strtoul(argv[i], NULL, 10); - if (input == 0 || input == ULONG_MAX || - input > ARGON2_MAX_THREADS || input > ARGON2_MAX_LANES) { - fatal("bad numeric input for -p"); - } - threads = input; - lanes = threads; - continue; - } else { - fatal("missing -p argument"); - } - } else if (!strcmp(a, "-d")) { - type = "d"; - } else { - fatal("unknown argument"); - } - } - printf("Type:\t\tArgon2%c\n", type[0]); - printf("Iterations:\t%" PRIu32 " \n", t_cost); - printf("Memory:\t\t%" PRIu32 " KiB\n", m_cost); - printf("Parallelism:\t%" PRIu32 " \n", lanes); - run(out, pwd, salt, t_cost, m_cost, lanes, threads, type); - - return ARGON2_OK; -} diff --git a/stratum/algos/ar2/thread.c b/stratum/algos/ar2/thread.c new file mode 100644 index 0000000..75d71db --- /dev/null +++ b/stratum/algos/ar2/thread.c @@ -0,0 +1,57 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#if !defined(ARGON2_NO_THREADS) + +#include "thread.h" +#if defined(_WIN32) +#include +#endif + +int argon2_thread_create(argon2_thread_handle_t *handle, + argon2_thread_func_t func, void *args) { + if (NULL == handle || func == NULL) { + return -1; + } +#if defined(_WIN32) + *handle = _beginthreadex(NULL, 0, func, args, 0, NULL); + return *handle != 0 ? 0 : -1; +#else + return pthread_create(handle, NULL, func, args); +#endif +} + +int argon2_thread_join(argon2_thread_handle_t handle) { +#if defined(_WIN32) + if (WaitForSingleObject((HANDLE)handle, INFINITE) == WAIT_OBJECT_0) { + return CloseHandle((HANDLE)handle) != 0 ? 0 : -1; + } + return -1; +#else + return pthread_join(handle, NULL); +#endif +} + +void argon2_thread_exit(void) { +#if defined(_WIN32) + _endthreadex(0); +#else + pthread_exit(NULL); +#endif +} + +#endif /* ARGON2_NO_THREADS */ \ No newline at end of file diff --git a/stratum/algos/ar2/thread.h b/stratum/algos/ar2/thread.h new file mode 100644 index 0000000..098ba64 --- /dev/null +++ b/stratum/algos/ar2/thread.h @@ -0,0 +1,67 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef ARGON2_THREAD_H +#define ARGON2_THREAD_H + +#if !defined(ARGON2_NO_THREADS) + +/* + Here we implement an abstraction layer for the simpĺe requirements + of the Argon2 code. We only require 3 primitives---thread creation, + joining, and termination---so full emulation of the pthreads API + is unwarranted. Currently we wrap pthreads and Win32 threads. + + The API defines 2 types: the function pointer type, + argon2_thread_func_t, + and the type of the thread handle---argon2_thread_handle_t. +*/ +#if defined(_WIN32) +#include +typedef unsigned(__stdcall *argon2_thread_func_t)(void *); +typedef uintptr_t argon2_thread_handle_t; +#else +#include +typedef void *(*argon2_thread_func_t)(void *); +typedef pthread_t argon2_thread_handle_t; +#endif + +/* Creates a thread + * @param handle pointer to a thread handle, which is the output of this + * function. Must not be NULL. + * @param func A function pointer for the thread's entry point. Must not be + * NULL. + * @param args Pointer that is passed as an argument to @func. May be NULL. + * @return 0 if @handle and @func are valid pointers and a thread is successfuly + * created. + */ +int argon2_thread_create(argon2_thread_handle_t *handle, + argon2_thread_func_t func, void *args); + +/* Waits for a thread to terminate + * @param handle Handle to a thread created with argon2_thread_create. + * @return 0 if @handle is a valid handle, and joining completed successfully. +*/ +int argon2_thread_join(argon2_thread_handle_t handle); + +/* Terminate the current thread. Must be run inside a thread created by + * argon2_thread_create. +*/ +void argon2_thread_exit(void); + +#endif /* ARGON2_NO_THREADS */ +#endif \ No newline at end of file diff --git a/stratum/algos/argon2a.c b/stratum/algos/argon2a.c index eab0d81..e32b0b8 100644 --- a/stratum/algos/argon2a.c +++ b/stratum/algos/argon2a.c @@ -5,8 +5,9 @@ #include "sysendian.h" +#include "argon2a.h" #include "ar2/argon2.h" -#include "ar2/cores.h" +#include "ar2/core.h" #include "ar2/ar2-scrypt-jane.h" #define _ALIGN(x) __attribute__ ((aligned(x))) @@ -24,10 +25,10 @@ inline void argon_call(void *out, void *in, void *salt, int type) context.pwd = (uint8_t *)in; context.salt = (uint8_t *)salt; - argon2_core(&context, type); + argon2_ctx(&context, type); } -void argon2_hash(const char* input, char* output, uint32_t len) +void argon2a_hash(const char* input, char* output, uint32_t len) { uint32_t _ALIGN(32) hashA[8], hashB[8]; diff --git a/stratum/algos/argon2a.h b/stratum/algos/argon2a.h index 05238ff..2cfe3f0 100644 --- a/stratum/algos/argon2a.h +++ b/stratum/algos/argon2a.h @@ -7,7 +7,7 @@ extern "C" { #include -void argon2_hash(const char* input, char* output, uint32_t len); +void argon2a_hash(const char* input, char* output, uint32_t len); #ifdef __cplusplus } diff --git a/stratum/algos/argon2d-dyn.c b/stratum/algos/argon2d-dyn.c new file mode 100644 index 0000000..c9c6a56 --- /dev/null +++ b/stratum/algos/argon2d-dyn.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +#include "sysendian.h" + +#include "ar2/argon2.h" +#include "ar2/core.h" + +static const size_t INPUT_BYTES = 80; // Lenth of a block header in bytes. Input Length = Salt Length (salt = input) +static const size_t OUTPUT_BYTES = 32; // Length of output needed for a 256-bit hash +static const unsigned int DEFAULT_ARGON2_FLAG = 2; //Same as ARGON2_DEFAULT_FLAGS + +void argon2d_call(const void *input, void *output) +{ + argon2_context context; + context.out = (uint8_t *)output; + context.outlen = (uint32_t)OUTPUT_BYTES; + context.pwd = (uint8_t *)input; + context.pwdlen = (uint32_t)INPUT_BYTES; + context.salt = (uint8_t *)input; //salt = input + context.saltlen = (uint32_t)INPUT_BYTES; + context.secret = NULL; + context.secretlen = 0; + context.ad = NULL; + context.adlen = 0; + context.allocate_cbk = NULL; + context.free_cbk = NULL; + context.flags = DEFAULT_ARGON2_FLAG; // = ARGON2_DEFAULT_FLAGS + // main configurable Argon2 hash parameters + context.m_cost = 500; // Memory in KiB (512KB) + context.lanes = 8; // Degree of Parallelism + context.threads = 1; // Threads + context.t_cost = 2; // Iterations + + argon2_ctx(&context, Argon2_d); +} + +void argon2d_dyn_hash(const unsigned char* input, unsigned char* output, unsigned int len) +{ + argon2d_call(input, output); +} \ No newline at end of file diff --git a/stratum/algos/argon2d-dyn.h b/stratum/algos/argon2d-dyn.h new file mode 100644 index 0000000..1d5f99c --- /dev/null +++ b/stratum/algos/argon2d-dyn.h @@ -0,0 +1,16 @@ +#ifndef ARGON2D_H +#define ARGON2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void argon2d_dyn_hash(const char* input, char* output, unsigned int len); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/stratum/algos/ar2/blake2/blake2-impl.h b/stratum/algos/blake2/blake2-impl.h similarity index 82% rename from stratum/algos/ar2/blake2/blake2-impl.h rename to stratum/algos/blake2/blake2-impl.h index 115a192..241f0be 100644 --- a/stratum/algos/ar2/blake2/blake2-impl.h +++ b/stratum/algos/blake2/blake2-impl.h @@ -1,3 +1,20 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + #ifndef PORTABLE_BLAKE2_IMPL_H #define PORTABLE_BLAKE2_IMPL_H @@ -134,10 +151,6 @@ static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) { return (w >> c) | (w << (64 - c)); } -/* prevents compiler optimizing out memset() */ -static BLAKE2_INLINE void burn(void *v, size_t n) { - static void *(*const volatile memset_v)(void *, int, size_t) = &memset; - memset_v(v, 0, n); -} +void clear_internal_memory(void *v, size_t n); #endif diff --git a/stratum/algos/ar2/blake2/blake2.h b/stratum/algos/blake2/blake2.h similarity index 70% rename from stratum/algos/ar2/blake2/blake2.h rename to stratum/algos/blake2/blake2.h index 7d8d5eb..12533d1 100644 --- a/stratum/algos/ar2/blake2/blake2.h +++ b/stratum/algos/blake2/blake2.h @@ -1,3 +1,20 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + #ifndef PORTABLE_BLAKE2_H #define PORTABLE_BLAKE2_H @@ -37,10 +54,10 @@ typedef struct __blake2b_state { uint64_t h[8]; uint64_t t[2]; uint64_t f[2]; + uint8_t buf[BLAKE2B_BLOCKBYTES]; unsigned buflen; unsigned outlen; uint8_t last_node; - uint8_t buf[BLAKE2B_BLOCKBYTES]; } blake2b_state; /* Ensure param structs have not been wrongly padded */ @@ -57,17 +74,15 @@ int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen); int blake2b_init_param(blake2b_state *S, const blake2b_param *P); int blake2b_update(blake2b_state *S, const void *in, size_t inlen); -void my_blake2b_update(blake2b_state *S, const void *in, size_t inlen); int blake2b_final(blake2b_state *S, void *out, size_t outlen); /* Simple API */ -int blake2b(void *out, const void *in, const void *key, size_t keylen); +int blake2b(void *out, size_t outlen, const void *in, size_t inlen, + const void *key, size_t keylen); /* Argon2 Team - Begin Code */ -int blake2b_long(void *out, const void *in); +int blake2b_long(void *out, size_t outlen, const void *in, size_t inlen); /* Argon2 Team - End Code */ -/* Miouyouyou */ -void blake2b_too(void *out, const void *in); #if defined(__cplusplus) } diff --git a/stratum/algos/blake2/blake2b.c b/stratum/algos/blake2/blake2b.c new file mode 100644 index 0000000..ca05df5 --- /dev/null +++ b/stratum/algos/blake2/blake2b.c @@ -0,0 +1,390 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#include +#include +#include + +#include "blake2.h" +#include "blake2-impl.h" + +static const uint64_t blake2b_IV[8] = { + UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b), + UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1), + UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f), + UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179)}; + +static const unsigned int blake2b_sigma[12][16] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, + {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, + {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, + {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, + {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, + {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, + {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, + {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, + {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, +}; + +static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) { + S->f[1] = (uint64_t)-1; +} + +static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) { + if (S->last_node) { + blake2b_set_lastnode(S); + } + S->f[0] = (uint64_t)-1; +} + +static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S, + uint64_t inc) { + S->t[0] += inc; + S->t[1] += (S->t[0] < inc); +} + +static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) { + clear_internal_memory(S, sizeof(*S)); /* wipe */ + blake2b_set_lastblock(S); /* invalidate for further use */ +} + +static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) { + memset(S, 0, sizeof(*S)); + memcpy(S->h, blake2b_IV, sizeof(S->h)); +} + +int blake2b_init_param(blake2b_state *S, const blake2b_param *P) { + const unsigned char *p = (const unsigned char *)P; + unsigned int i; + + if (NULL == P || NULL == S) { + return -1; + } + + blake2b_init0(S); + /* IV XOR Parameter Block */ + for (i = 0; i < 8; ++i) { + S->h[i] ^= load64(&p[i * sizeof(S->h[i])]); + } + S->outlen = P->digest_length; + return 0; +} + +/* Sequential blake2b initialization */ +int blake2b_init(blake2b_state *S, size_t outlen) { + blake2b_param P; + + if (S == NULL) { + return -1; + } + + if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) { + blake2b_invalidate_state(S); + return -1; + } + + /* Setup Parameter Block for unkeyed BLAKE2 */ + P.digest_length = (uint8_t)outlen; + P.key_length = 0; + P.fanout = 1; + P.depth = 1; + P.leaf_length = 0; + P.node_offset = 0; + P.node_depth = 0; + P.inner_length = 0; + memset(P.reserved, 0, sizeof(P.reserved)); + memset(P.salt, 0, sizeof(P.salt)); + memset(P.personal, 0, sizeof(P.personal)); + + return blake2b_init_param(S, &P); +} + +int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, + size_t keylen) { + blake2b_param P; + + if (S == NULL) { + return -1; + } + + if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) { + blake2b_invalidate_state(S); + return -1; + } + + if ((key == 0) || (keylen == 0) || (keylen > BLAKE2B_KEYBYTES)) { + blake2b_invalidate_state(S); + return -1; + } + + /* Setup Parameter Block for keyed BLAKE2 */ + P.digest_length = (uint8_t)outlen; + P.key_length = (uint8_t)keylen; + P.fanout = 1; + P.depth = 1; + P.leaf_length = 0; + P.node_offset = 0; + P.node_depth = 0; + P.inner_length = 0; + memset(P.reserved, 0, sizeof(P.reserved)); + memset(P.salt, 0, sizeof(P.salt)); + memset(P.personal, 0, sizeof(P.personal)); + + if (blake2b_init_param(S, &P) < 0) { + blake2b_invalidate_state(S); + return -1; + } + + { + uint8_t block[BLAKE2B_BLOCKBYTES]; + memset(block, 0, BLAKE2B_BLOCKBYTES); + memcpy(block, key, keylen); + blake2b_update(S, block, BLAKE2B_BLOCKBYTES); + /* Burn the key from stack */ + clear_internal_memory(block, BLAKE2B_BLOCKBYTES); + } + return 0; +} + +static void blake2b_compress(blake2b_state *S, const uint8_t *block) { + uint64_t m[16]; + uint64_t v[16]; + unsigned int i, r; + + for (i = 0; i < 16; ++i) { + m[i] = load64(block + i * sizeof(m[i])); + } + + for (i = 0; i < 8; ++i) { + v[i] = S->h[i]; + } + + v[8] = blake2b_IV[0]; + v[9] = blake2b_IV[1]; + v[10] = blake2b_IV[2]; + v[11] = blake2b_IV[3]; + v[12] = blake2b_IV[4] ^ S->t[0]; + v[13] = blake2b_IV[5] ^ S->t[1]; + v[14] = blake2b_IV[6] ^ S->f[0]; + v[15] = blake2b_IV[7] ^ S->f[1]; + +#define G(r, i, a, b, c, d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ + d = rotr64(d ^ a, 32); \ + c = c + d; \ + b = rotr64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ + d = rotr64(d ^ a, 16); \ + c = c + d; \ + b = rotr64(b ^ c, 63); \ + } while ((void)0, 0) + +#define ROUND(r) \ + do { \ + G(r, 0, v[0], v[4], v[8], v[12]); \ + G(r, 1, v[1], v[5], v[9], v[13]); \ + G(r, 2, v[2], v[6], v[10], v[14]); \ + G(r, 3, v[3], v[7], v[11], v[15]); \ + G(r, 4, v[0], v[5], v[10], v[15]); \ + G(r, 5, v[1], v[6], v[11], v[12]); \ + G(r, 6, v[2], v[7], v[8], v[13]); \ + G(r, 7, v[3], v[4], v[9], v[14]); \ + } while ((void)0, 0) + + for (r = 0; r < 12; ++r) { + ROUND(r); + } + + for (i = 0; i < 8; ++i) { + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + } + +#undef G +#undef ROUND +} + +int blake2b_update(blake2b_state *S, const void *in, size_t inlen) { + const uint8_t *pin = (const uint8_t *)in; + + if (inlen == 0) { + return 0; + } + + /* Sanity check */ + if (S == NULL || in == NULL) { + return -1; + } + + /* Is this a reused state? */ + if (S->f[0] != 0) { + return -1; + } + + if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) { + /* Complete current block */ + size_t left = S->buflen; + size_t fill = BLAKE2B_BLOCKBYTES - left; + memcpy(&S->buf[left], pin, fill); + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); + blake2b_compress(S, S->buf); + S->buflen = 0; + inlen -= fill; + pin += fill; + /* Avoid buffer copies when possible */ + while (inlen > BLAKE2B_BLOCKBYTES) { + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); + blake2b_compress(S, pin); + inlen -= BLAKE2B_BLOCKBYTES; + pin += BLAKE2B_BLOCKBYTES; + } + } + memcpy(&S->buf[S->buflen], pin, inlen); + S->buflen += (unsigned int)inlen; + return 0; +} + +int blake2b_final(blake2b_state *S, void *out, size_t outlen) { + uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; + unsigned int i; + + /* Sanity checks */ + if (S == NULL || out == NULL || outlen < S->outlen) { + return -1; + } + + /* Is this a reused state? */ + if (S->f[0] != 0) { + return -1; + } + + blake2b_increment_counter(S, S->buflen); + blake2b_set_lastblock(S); + memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */ + blake2b_compress(S, S->buf); + + for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ + store64(buffer + sizeof(S->h[i]) * i, S->h[i]); + } + + memcpy(out, buffer, S->outlen); + clear_internal_memory(buffer, sizeof(buffer)); + clear_internal_memory(S->buf, sizeof(S->buf)); + clear_internal_memory(S->h, sizeof(S->h)); + return 0; +} + +int blake2b(void *out, size_t outlen, const void *in, size_t inlen, + const void *key, size_t keylen) { + blake2b_state S; + int ret = -1; + + /* Verify parameters */ + if (NULL == in && inlen > 0) { + goto fail; + } + + if (NULL == out || outlen == 0 || outlen > BLAKE2B_OUTBYTES) { + goto fail; + } + + if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) { + goto fail; + } + + if (keylen > 0) { + if (blake2b_init_key(&S, outlen, key, keylen) < 0) { + goto fail; + } + } else { + if (blake2b_init(&S, outlen) < 0) { + goto fail; + } + } + + if (blake2b_update(&S, in, inlen) < 0) { + goto fail; + } + ret = blake2b_final(&S, out, outlen); + +fail: + clear_internal_memory(&S, sizeof(S)); + return ret; +} + +/* Argon2 Team - Begin Code */ +int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) { + uint8_t *out = (uint8_t *)pout; + blake2b_state blake_state; + uint8_t outlen_bytes[sizeof(uint32_t)] = {0}; + int ret = -1; + + if (outlen > UINT32_MAX) { + goto fail; + } + + /* Ensure little-endian byte order! */ + store32(outlen_bytes, (uint32_t)outlen); + +#define TRY(statement) \ + do { \ + ret = statement; \ + if (ret < 0) { \ + goto fail; \ + } \ + } while ((void)0, 0) + + if (outlen <= BLAKE2B_OUTBYTES) { + TRY(blake2b_init(&blake_state, outlen)); + TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes))); + TRY(blake2b_update(&blake_state, in, inlen)); + TRY(blake2b_final(&blake_state, out, outlen)); + } else { + uint32_t toproduce; + uint8_t out_buffer[BLAKE2B_OUTBYTES]; + uint8_t in_buffer[BLAKE2B_OUTBYTES]; + TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES)); + TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes))); + TRY(blake2b_update(&blake_state, in, inlen)); + TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES)); + memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2); + out += BLAKE2B_OUTBYTES / 2; + toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2; + + while (toproduce > BLAKE2B_OUTBYTES) { + memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES); + TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer, + BLAKE2B_OUTBYTES, NULL, 0)); + memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2); + out += BLAKE2B_OUTBYTES / 2; + toproduce -= BLAKE2B_OUTBYTES / 2; + } + + memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES); + TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL, + 0)); + memcpy(out, out_buffer, toproduce); + } +fail: + clear_internal_memory(&blake_state, sizeof(blake_state)); + return ret; +#undef TRY +} +/* Argon2 Team - End Code */ diff --git a/stratum/algos/blake2/blamka-round-opt.h b/stratum/algos/blake2/blamka-round-opt.h new file mode 100644 index 0000000..faf9666 --- /dev/null +++ b/stratum/algos/blake2/blamka-round-opt.h @@ -0,0 +1,476 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef BLAKE_ROUND_MKA_OPT_H +#define BLAKE_ROUND_MKA_OPT_H + +#if defined(HAVE_CONFIG_H) +#include "config/dynamic-config.h" +#endif + +#include "blake2-impl.h" + +#include +#if defined(__SSSE3__) +#include /* for _mm_shuffle_epi8 and _mm_alignr_epi8 */ +#endif + +#if defined(__XOP__) && (defined(__GNUC__) || defined(__clang__)) +#include +#endif + +#if !defined(__AVX512F__) +#if !defined(__AVX2__) +#if !defined(__XOP__) +#if defined(__SSSE3__) +#define r16 \ + (_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9)) +#define r24 \ + (_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10)) +#define _mm_roti_epi64(x, c) \ + (-(c) == 32) \ + ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \ + : (-(c) == 24) \ + ? _mm_shuffle_epi8((x), r24) \ + : (-(c) == 16) \ + ? _mm_shuffle_epi8((x), r16) \ + : (-(c) == 63) \ + ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \ + _mm_add_epi64((x), (x))) \ + : _mm_xor_si128(_mm_srli_epi64((x), -(c)), \ + _mm_slli_epi64((x), 64 - (-(c)))) +#else /* defined(__SSE2__) */ +#define _mm_roti_epi64(r, c) \ + _mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-(c)))) +#endif +#else +#endif + +static BLAKE2_INLINE __m128i fBlaMka(__m128i x, __m128i y) { + const __m128i z = _mm_mul_epu32(x, y); + return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z)); +} + +#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + A0 = fBlaMka(A0, B0); \ + A1 = fBlaMka(A1, B1); \ + \ + D0 = _mm_xor_si128(D0, A0); \ + D1 = _mm_xor_si128(D1, A1); \ + \ + D0 = _mm_roti_epi64(D0, -32); \ + D1 = _mm_roti_epi64(D1, -32); \ + \ + C0 = fBlaMka(C0, D0); \ + C1 = fBlaMka(C1, D1); \ + \ + B0 = _mm_xor_si128(B0, C0); \ + B1 = _mm_xor_si128(B1, C1); \ + \ + B0 = _mm_roti_epi64(B0, -24); \ + B1 = _mm_roti_epi64(B1, -24); \ + } while ((void)0, 0) + +#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + A0 = fBlaMka(A0, B0); \ + A1 = fBlaMka(A1, B1); \ + \ + D0 = _mm_xor_si128(D0, A0); \ + D1 = _mm_xor_si128(D1, A1); \ + \ + D0 = _mm_roti_epi64(D0, -16); \ + D1 = _mm_roti_epi64(D1, -16); \ + \ + C0 = fBlaMka(C0, D0); \ + C1 = fBlaMka(C1, D1); \ + \ + B0 = _mm_xor_si128(B0, C0); \ + B1 = _mm_xor_si128(B1, C1); \ + \ + B0 = _mm_roti_epi64(B0, -63); \ + B1 = _mm_roti_epi64(B1, -63); \ + } while ((void)0, 0) + +#if defined(__SSSE3__) +#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + __m128i t0 = _mm_alignr_epi8(B1, B0, 8); \ + __m128i t1 = _mm_alignr_epi8(B0, B1, 8); \ + B0 = t0; \ + B1 = t1; \ + \ + t0 = C0; \ + C0 = C1; \ + C1 = t0; \ + \ + t0 = _mm_alignr_epi8(D1, D0, 8); \ + t1 = _mm_alignr_epi8(D0, D1, 8); \ + D0 = t1; \ + D1 = t0; \ + } while ((void)0, 0) + +#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + __m128i t0 = _mm_alignr_epi8(B0, B1, 8); \ + __m128i t1 = _mm_alignr_epi8(B1, B0, 8); \ + B0 = t0; \ + B1 = t1; \ + \ + t0 = C0; \ + C0 = C1; \ + C1 = t0; \ + \ + t0 = _mm_alignr_epi8(D0, D1, 8); \ + t1 = _mm_alignr_epi8(D1, D0, 8); \ + D0 = t1; \ + D1 = t0; \ + } while ((void)0, 0) +#else /* SSE2 */ +#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + __m128i t0 = D0; \ + __m128i t1 = B0; \ + D0 = C0; \ + C0 = C1; \ + C1 = D0; \ + D0 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t0, t0)); \ + D1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(D1, D1)); \ + B0 = _mm_unpackhi_epi64(B0, _mm_unpacklo_epi64(B1, B1)); \ + B1 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(t1, t1)); \ + } while ((void)0, 0) + +#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + __m128i t0, t1; \ + t0 = C0; \ + C0 = C1; \ + C1 = t0; \ + t0 = B0; \ + t1 = D0; \ + B0 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(B0, B0)); \ + B1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(B1, B1)); \ + D0 = _mm_unpackhi_epi64(D0, _mm_unpacklo_epi64(D1, D1)); \ + D1 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t1, t1)); \ + } while ((void)0, 0) +#endif + +#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + G1(A0, B0, C0, D0, A1, B1, C1, D1); \ + G2(A0, B0, C0, D0, A1, B1, C1, D1); \ + \ + DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \ + \ + G1(A0, B0, C0, D0, A1, B1, C1, D1); \ + G2(A0, B0, C0, D0, A1, B1, C1, D1); \ + \ + UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \ + } while ((void)0, 0) + +#else /* __AVX2__ */ + +#include + +#define rotr32(x) _mm256_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1)) +#define rotr24(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10)) +#define rotr16(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9)) +#define rotr63(x) _mm256_xor_si256(_mm256_srli_epi64((x), 63), _mm256_add_epi64((x), (x))) + +#define G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + __m256i ml = _mm256_mul_epu32(A0, B0); \ + ml = _mm256_add_epi64(ml, ml); \ + A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \ + D0 = _mm256_xor_si256(D0, A0); \ + D0 = rotr32(D0); \ + \ + ml = _mm256_mul_epu32(C0, D0); \ + ml = _mm256_add_epi64(ml, ml); \ + C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \ + \ + B0 = _mm256_xor_si256(B0, C0); \ + B0 = rotr24(B0); \ + \ + ml = _mm256_mul_epu32(A1, B1); \ + ml = _mm256_add_epi64(ml, ml); \ + A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \ + D1 = _mm256_xor_si256(D1, A1); \ + D1 = rotr32(D1); \ + \ + ml = _mm256_mul_epu32(C1, D1); \ + ml = _mm256_add_epi64(ml, ml); \ + C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \ + \ + B1 = _mm256_xor_si256(B1, C1); \ + B1 = rotr24(B1); \ + } while((void)0, 0); + +#define G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + __m256i ml = _mm256_mul_epu32(A0, B0); \ + ml = _mm256_add_epi64(ml, ml); \ + A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \ + D0 = _mm256_xor_si256(D0, A0); \ + D0 = rotr16(D0); \ + \ + ml = _mm256_mul_epu32(C0, D0); \ + ml = _mm256_add_epi64(ml, ml); \ + C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \ + B0 = _mm256_xor_si256(B0, C0); \ + B0 = rotr63(B0); \ + \ + ml = _mm256_mul_epu32(A1, B1); \ + ml = _mm256_add_epi64(ml, ml); \ + A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \ + D1 = _mm256_xor_si256(D1, A1); \ + D1 = rotr16(D1); \ + \ + ml = _mm256_mul_epu32(C1, D1); \ + ml = _mm256_add_epi64(ml, ml); \ + C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \ + B1 = _mm256_xor_si256(B1, C1); \ + B1 = rotr63(B1); \ + } while((void)0, 0); + +#define DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \ + C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \ + D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \ + \ + B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \ + C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \ + D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \ + } while((void)0, 0); + +#define DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \ + __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \ + B1 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \ + B0 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \ + \ + tmp1 = C0; \ + C0 = C1; \ + C1 = tmp1; \ + \ + tmp1 = _mm256_blend_epi32(D0, D1, 0xCC); \ + tmp2 = _mm256_blend_epi32(D0, D1, 0x33); \ + D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \ + D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \ + } while(0); + +#define UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \ + C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \ + D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \ + \ + B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \ + C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \ + D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \ + } while((void)0, 0); + +#define UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \ + __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \ + B0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \ + B1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \ + \ + tmp1 = C0; \ + C0 = C1; \ + C1 = tmp1; \ + \ + tmp1 = _mm256_blend_epi32(D0, D1, 0x33); \ + tmp2 = _mm256_blend_epi32(D0, D1, 0xCC); \ + D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \ + D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \ + } while((void)0, 0); + +#define BLAKE2_ROUND_1(A0, A1, B0, B1, C0, C1, D0, D1) \ + do{ \ + G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + \ + DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \ + \ + G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + \ + UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \ + } while((void)0, 0); + +#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do{ \ + G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + \ + DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + \ + G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + \ + UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + } while((void)0, 0); + +#endif /* __AVX2__ */ + +#else /* __AVX512F__ */ + +#include + +#define ror64(x, n) _mm512_ror_epi64((x), (n)) + +static __m512i muladd(__m512i x, __m512i y) +{ + __m512i z = _mm512_mul_epu32(x, y); + return _mm512_add_epi64(_mm512_add_epi64(x, y), _mm512_add_epi64(z, z)); +} + +#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + A0 = muladd(A0, B0); \ + A1 = muladd(A1, B1); \ +\ + D0 = _mm512_xor_si512(D0, A0); \ + D1 = _mm512_xor_si512(D1, A1); \ +\ + D0 = ror64(D0, 32); \ + D1 = ror64(D1, 32); \ +\ + C0 = muladd(C0, D0); \ + C1 = muladd(C1, D1); \ +\ + B0 = _mm512_xor_si512(B0, C0); \ + B1 = _mm512_xor_si512(B1, C1); \ +\ + B0 = ror64(B0, 24); \ + B1 = ror64(B1, 24); \ + } while ((void)0, 0) + +#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + A0 = muladd(A0, B0); \ + A1 = muladd(A1, B1); \ +\ + D0 = _mm512_xor_si512(D0, A0); \ + D1 = _mm512_xor_si512(D1, A1); \ +\ + D0 = ror64(D0, 16); \ + D1 = ror64(D1, 16); \ +\ + C0 = muladd(C0, D0); \ + C1 = muladd(C1, D1); \ +\ + B0 = _mm512_xor_si512(B0, C0); \ + B1 = _mm512_xor_si512(B1, C1); \ +\ + B0 = ror64(B0, 63); \ + B1 = ror64(B1, 63); \ + } while ((void)0, 0) + +#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \ + B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \ +\ + C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \ + C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \ +\ + D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \ + D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \ + } while ((void)0, 0) + +#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \ + B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \ +\ + C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \ + C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \ +\ + D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \ + D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \ + } while ((void)0, 0) + +#define BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + G1(A0, B0, C0, D0, A1, B1, C1, D1); \ + G2(A0, B0, C0, D0, A1, B1, C1, D1); \ +\ + DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \ +\ + G1(A0, B0, C0, D0, A1, B1, C1, D1); \ + G2(A0, B0, C0, D0, A1, B1, C1, D1); \ +\ + UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \ + } while ((void)0, 0) + +#define SWAP_HALVES(A0, A1) \ + do { \ + __m512i t0, t1; \ + t0 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(1, 0, 1, 0)); \ + t1 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(3, 2, 3, 2)); \ + A0 = t0; \ + A1 = t1; \ + } while((void)0, 0) + +#define SWAP_QUARTERS(A0, A1) \ + do { \ + SWAP_HALVES(A0, A1); \ + A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \ + A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \ + } while((void)0, 0) + +#define UNSWAP_QUARTERS(A0, A1) \ + do { \ + A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \ + A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \ + SWAP_HALVES(A0, A1); \ + } while((void)0, 0) + +#define BLAKE2_ROUND_1(A0, C0, B0, D0, A1, C1, B1, D1) \ + do { \ + SWAP_HALVES(A0, B0); \ + SWAP_HALVES(C0, D0); \ + SWAP_HALVES(A1, B1); \ + SWAP_HALVES(C1, D1); \ + BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \ + SWAP_HALVES(A0, B0); \ + SWAP_HALVES(C0, D0); \ + SWAP_HALVES(A1, B1); \ + SWAP_HALVES(C1, D1); \ + } while ((void)0, 0) + +#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + SWAP_QUARTERS(A0, A1); \ + SWAP_QUARTERS(B0, B1); \ + SWAP_QUARTERS(C0, C1); \ + SWAP_QUARTERS(D0, D1); \ + BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \ + UNSWAP_QUARTERS(A0, A1); \ + UNSWAP_QUARTERS(B0, B1); \ + UNSWAP_QUARTERS(C0, C1); \ + UNSWAP_QUARTERS(D0, D1); \ + } while ((void)0, 0) + +#endif /* __AVX512F__ */ +#endif /* BLAKE_ROUND_MKA_OPT_H */ \ No newline at end of file diff --git a/stratum/algos/ar2/blake2/blamka-round-ref.h b/stratum/algos/blake2/blamka-round-ref.h similarity index 75% rename from stratum/algos/ar2/blake2/blamka-round-ref.h rename to stratum/algos/blake2/blamka-round-ref.h index f497e10..2238959 100644 --- a/stratum/algos/ar2/blake2/blamka-round-ref.h +++ b/stratum/algos/blake2/blamka-round-ref.h @@ -1,3 +1,20 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + #ifndef BLAKE_ROUND_MKA_H #define BLAKE_ROUND_MKA_H @@ -36,4 +53,4 @@ static BLAKE2_INLINE uint64_t fBlaMka(uint64_t x, uint64_t y) { G(v3, v4, v9, v14); \ } while ((void)0, 0) -#endif +#endif \ No newline at end of file diff --git a/stratum/algos/blake2b.c b/stratum/algos/blake2b.c new file mode 100644 index 0000000..e65d2d1 --- /dev/null +++ b/stratum/algos/blake2b.c @@ -0,0 +1,23 @@ +/** + * Blake2-B Implementation + * tpruvot@github 2016-2018 + */ + +#include +#include + +#include +#include + +void blake2b_hash(const char* input, char* output, uint32_t len) +{ + uint32_t ALIGN(64) hash[8]; + blake2b_ctx ctx; + + blake2b_init(&ctx, 32, NULL, 0); + blake2b_update(&ctx, input, len); + blake2b_final(&ctx, hash); + + memcpy(output, hash, 32); +} + diff --git a/stratum/algos/blake2b.h b/stratum/algos/blake2b.h new file mode 100644 index 0000000..eeda45c --- /dev/null +++ b/stratum/algos/blake2b.h @@ -0,0 +1,16 @@ +#ifndef BLAKE2B_H +#define BLAKE2B_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void blake2b_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/blake2.c b/stratum/algos/blake2s.c similarity index 100% rename from stratum/algos/blake2.c rename to stratum/algos/blake2s.c diff --git a/stratum/algos/blake2.h b/stratum/algos/blake2s.h similarity index 100% rename from stratum/algos/blake2.h rename to stratum/algos/blake2s.h diff --git a/stratum/algos/exosis.c b/stratum/algos/exosis.c new file mode 100644 index 0000000..48a5477 --- /dev/null +++ b/stratum/algos/exosis.c @@ -0,0 +1,157 @@ +#include +#include +#include + +#define HASH_FUNC_BASE_TIMESTAMP 1538556426 // Exosis: Genesis Timestamp +#define HASH_FUNC_COUNT 8 +#define HASH_FUNC_COUNT_PERMUTATIONS 40320 + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define _ALIGN(x) __attribute__ ((aligned(x))) + +// helpers +inline void swap(int *a, int *b) { + int c = *a; + *a = *b; + *b = c; +} + +static void reverse(int *pbegin, int *pend) { + while ( (pbegin != pend) && (pbegin != --pend) ) + swap(pbegin++, pend); +} + +static void next_permutation(int *pbegin, int *pend) { + if (pbegin == pend) + return; + + int *i = pbegin; + ++i; + if (i == pend) + return; + + i = pend; + --i; + + while (1) { + int *j = i; + --i; + + if (*i < *j) { + int *k = pend; + + while (!(*i < *--k)) + /* pass */; + + swap(i, k); + reverse(j, pend); + return; // true + } + + if (i == pbegin) { + reverse(pbegin, pend); + return; // false + } + } +} +// helpers + +void exosis_hash(const char* input, char* output, uint32_t len) +{ + uint32_t _ALIGN(64) hash[16 * HASH_FUNC_COUNT]; + uint32_t *hashA, *hashB; + uint32_t dataLen = 64; + uint32_t *work_data = (uint32_t *)input; + const uint32_t timestamp = work_data[17]; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + + // We want to permute algorithms. To get started we + // initialize an array with a sorted sequence of unique + // integers where every integer represents its own algorithm. + uint32_t permutation[HASH_FUNC_COUNT]; + for (uint32_t i = 0; i < HASH_FUNC_COUNT; i++) { + permutation[i]=i; + } + + // Compute the next permuation + uint32_t steps = (timestamp - HASH_FUNC_BASE_TIMESTAMP) % HASH_FUNC_COUNT_PERMUTATIONS; + for (uint32_t i = 0; i < steps; i++) { + next_permutation(permutation, permutation + HASH_FUNC_COUNT); + } + + for (uint32_t i = 0; i < HASH_FUNC_COUNT; i++) { + if (i == 0) { + dataLen = len; + hashA = work_data; + } else { + dataLen = 64; + hashA = &hash[16 * (i - 1)]; + } + hashB = &hash[16 * i]; + + switch(permutation[i]) { + case 0: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, hashA, dataLen); + sph_blake512_close(&ctx_blake, hashB); + break; + case 1: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hashA, dataLen); + sph_bmw512_close(&ctx_bmw, hashB); + break; + case 2: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, hashA, dataLen); + sph_groestl512_close(&ctx_groestl, hashB); + break; + case 3: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, hashA, dataLen); + sph_skein512_close(&ctx_skein, hashB); + break; + case 4: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, hashA, dataLen); + sph_jh512_close(&ctx_jh, hashB); + break; + case 5: + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hashA, dataLen); + sph_keccak512_close(&ctx_keccak, hashB); + break; + case 6: + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hashA, dataLen); + sph_luffa512_close(&ctx_luffa, hashB); + break; + case 7: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, hashA, dataLen); + sph_cubehash512_close(&ctx_cubehash, hashB); + break; + default: + break; + } + } + + memcpy(output, &hash[16 * (HASH_FUNC_COUNT - 1)], 32); +} + diff --git a/stratum/algos/exosis.h b/stratum/algos/exosis.h new file mode 100644 index 0000000..fcda523 --- /dev/null +++ b/stratum/algos/exosis.h @@ -0,0 +1,16 @@ +#ifndef EXOSIS_H +#define EXOSIS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void exosis_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/hex.c b/stratum/algos/hex.c new file mode 100644 index 0000000..9a294d1 --- /dev/null +++ b/stratum/algos/hex.c @@ -0,0 +1,180 @@ +// Copyright (c) 2018 The XDNA Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include + +#include "hex.h" + +#include "../sha3/sph_blake.h" +#include "../sha3/sph_bmw.h" +#include "../sha3/sph_groestl.h" +#include "../sha3/sph_skein.h" +#include "../sha3/sph_jh.h" +#include "../sha3/sph_keccak.h" + +#include "../sha3/sph_luffa.h" +#include "../sha3/sph_cubehash.h" +#include "../sha3/sph_shavite.h" +#include "../sha3/sph_simd.h" +#include "../sha3/sph_echo.h" + +#include "../sha3/sph_hamsi.h" +#include "../sha3/sph_fugue.h" +#include "../sha3/sph_shabal.h" +#include "../sha3/sph_whirlpool.h" +#include "../sha3/sph_sha2.h" + +enum Algo { + BLAKE = 0, + BMW, + GROESTL, + JH, + KECCAK, + SKEIN, + LUFFA, + CUBEHASH, + SHAVITE, + SIMD, + ECHO, + HAMSI, + FUGUE, + SHABAL, + WHIRLPOOL, + SHA512, + HASH_FUNC_COUNT +}; + +static const int TOTAL_CYCLES = 16; + +static uint8_t get_first_algo(const uint32_t* prevblock) { + uint8_t* data = (uint8_t*)prevblock; + return data[7] >> 4; +} + +void hex_hash(const char* input, char* output, uint32_t len) +{ + unsigned char hash[128]; + uint8_t curr_algo; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_skein512_context ctx_skein; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + + const void *in = input; + int size = len; + + uint32_t *in32 = (uint32_t*) input; + + // initial algo = first digit of prev block hashorder (cheers, x16r) + curr_algo = get_first_algo(&in32[1]); + + for (int i = 0; i < TOTAL_CYCLES; i++) + { + // Only 4 test algos yet + switch (curr_algo) { + case BLAKE: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case BMW: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case GROESTL: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + case JH: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case KECCAK: + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, in, size); + sph_keccak512_close(&ctx_keccak, hash); + break; + case SKEIN: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case LUFFA: + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, in, size); + sph_luffa512_close(&ctx_luffa, hash); + break; + case CUBEHASH: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case SHAVITE: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case SIMD: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + + case ECHO: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case HAMSI: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case FUGUE: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case SHABAL: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case WHIRLPOOL: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case SHA512: + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) in, size); + sph_sha512_close(&ctx_sha512,(void*) hash); + break; + } + // next algos = first digit on prev hash + curr_algo = (uint8_t)hash[0] % HASH_FUNC_COUNT; + in = (void*)hash; + size = 64; + } + + memcpy(output, hash, 32); +} diff --git a/stratum/algos/hex.h b/stratum/algos/hex.h new file mode 100644 index 0000000..101f1a1 --- /dev/null +++ b/stratum/algos/hex.h @@ -0,0 +1,20 @@ +// Copyright (c) 2018 The XDNA Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef HEXHASH_H +#define HEXHASH_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void hex_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif // HEXHASH_H diff --git a/stratum/algos/lbk3.c b/stratum/algos/lbk3.c new file mode 100644 index 0000000..fbedd75 --- /dev/null +++ b/stratum/algos/lbk3.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +#include +#include +#include + +#define _ALIGN(x) __attribute__ ((aligned(x))) + +extern uint64_t lbk3_height; + +void lbk3_hash(const char* input, char* output, uint32_t len) +{ + sph_bmw256_context ctx_bmw; + sph_blake256_context ctx_blake; + sph_keccak256_context ctx_keccak; + + uint8_t _ALIGN(128) hash[96]; + memset(&hash[32], 0, 64); + + sph_bmw256_init(&ctx_bmw); + sph_bmw256 (&ctx_bmw, input, 80); + sph_bmw256_close(&ctx_bmw, &hash[0]); + + sph_blake256_init(&ctx_blake); + sph_blake256 (&ctx_blake, &hash[0], 64); + sph_blake256_close(&ctx_blake, &hash[32]); + + sph_keccak256_init(&ctx_keccak); + sph_keccak256 (&ctx_keccak, &hash[32], 64); + sph_keccak256_close(&ctx_keccak, &hash[64]); + + memcpy(output, &hash[64], 32); +} diff --git a/stratum/algos/lbk3.h b/stratum/algos/lbk3.h new file mode 100644 index 0000000..7d42722 --- /dev/null +++ b/stratum/algos/lbk3.h @@ -0,0 +1,16 @@ +#ifndef LBK3_H +#define LBK3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void lbk3_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/lyra2v3.c b/stratum/algos/lyra2v3.c new file mode 100644 index 0000000..ece25e7 --- /dev/null +++ b/stratum/algos/lyra2v3.c @@ -0,0 +1,68 @@ +/*- + * Copyright(or left) 2019 YiiMP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + */ + +#include +#include +#include +#include + +#include "../sha3/sph_blake.h" +#include "../sha3/sph_cubehash.h" +#include "../sha3/sph_bmw.h" + +#include "Lyra2.h" + +void lyra2v3_hash(const char* input, char* output, uint32_t len) +{ + uint32_t hash[8], hashB[8]; + + sph_blake256_context ctx_blake; + sph_cubehash256_context ctx_cubehash; + sph_bmw256_context ctx_bmw; + + sph_blake256_set_rounds(14); + + sph_blake256_init(&ctx_blake); + sph_blake256(&ctx_blake, input, len); /* 80 */ + sph_blake256_close(&ctx_blake, hash); + + LYRA2_3(hashB, 32, hash, 32, hash, 32, 1, 4, 4); + + sph_cubehash256_init(&ctx_cubehash); + sph_cubehash256(&ctx_cubehash, hashB, 32); + sph_cubehash256_close(&ctx_cubehash, hash); + + LYRA2_3(hashB, 32, hash, 32, hash, 32, 1, 4, 4); + + sph_bmw256_init(&ctx_bmw); + sph_bmw256(&ctx_bmw, hashB, 32); + sph_bmw256_close(&ctx_bmw, hash); + + memcpy(output, hash, 32); +} + diff --git a/stratum/algos/lyra2v3.h b/stratum/algos/lyra2v3.h new file mode 100644 index 0000000..8cb341d --- /dev/null +++ b/stratum/algos/lyra2v3.h @@ -0,0 +1,16 @@ +#ifndef LYRA2V3_H +#define LYRA2V3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void lyra2v3_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/lyra2z.c b/stratum/algos/lyra2z.c index b83b838..0d946de 100644 --- a/stratum/algos/lyra2z.c +++ b/stratum/algos/lyra2z.c @@ -3,7 +3,7 @@ #include #include -#include "Lyra2z.h" +#include "Lyra2-z.h" #include diff --git a/stratum/algos/lyra2zz.c b/stratum/algos/lyra2zz.c new file mode 100644 index 0000000..f1b1441 --- /dev/null +++ b/stratum/algos/lyra2zz.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +#include "Lyra2-zz.h" + +#include + +#define _ALIGN(x) __attribute__ ((aligned(x))) + +extern uint64_t lyra2z_height; + +void lyra2zz_hash(const char* input, char* output, uint32_t len) +{ + uint32_t _ALIGN(64) hashB[8], hash[8]; + sph_blake256_context ctx_blake; + + sph_blake256_set_rounds(14); + + sph_blake256_init(&ctx_blake); + sph_blake256(&ctx_blake, input, 112); + sph_blake256_close(&ctx_blake, hashB); + + LYRA2ZZ(hash, 32, hashB, 32, hashB, 32, 8, 8, 8); + + memcpy(output, hash, 32); +} diff --git a/stratum/algos/lyra2zz.h b/stratum/algos/lyra2zz.h new file mode 100644 index 0000000..ad524ec --- /dev/null +++ b/stratum/algos/lyra2zz.h @@ -0,0 +1,16 @@ +#ifndef LYRA2ZZ_H +#define LYRA2ZZ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void lyra2zz_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/makefile b/stratum/algos/makefile index 950ec2b..c48a54d 100644 --- a/stratum/algos/makefile +++ b/stratum/algos/makefile @@ -8,18 +8,19 @@ CXXFLAGS = -O2 -I.. -march=native CFLAGS= $(CXXFLAGS) -std=gnu99 LDFLAGS=-O2 -lgmp -SOURCES=lyra2re.c lyra2v2.c Lyra2.c lyra2z.c Lyra2z.c Sponge.c \ - blake.c scrypt.c c11.c x11.c x13.c sha256.c sha256t.c jha.c keccak.c deep.c tribus.c \ - hsr14.c sm3.c \ - x14.c x15.c x17.c nist5.c fresh.c quark.c neoscrypt.c scryptn.c qubit.c skein.c groestl.c \ - bitcore.c timetravel.c xevan.c bastion.c hmq17.c \ - skein2.c zr5.c bmw.c luffa.c pentablake.c whirlpool.c whirlpoolx.c blakecoin.c \ - blake2.c \ - yescrypt.c yescrypt-opt.c sha256_Y.c lbry.c \ - m7m.c magimath.cpp velvet.c \ - argon2a.c ar2/blake2b.c ar2/argon2.c ar2/ref.c ar2/cores.c ar2/ar2-scrypt-jane.c \ - hive.c pomelo.c \ - phi.c polytimos.c skunk.c sib.c veltor.c gost.c x11evo.c +SOURCES=lyra2re.c lyra2v2.c lyra2v3.c Lyra2.c lyra2z.c Lyra2-z.c lyra2zz.c Lyra2-zz.c Sponge.c allium.c \ + c11.c x11.c x12.c x13.c hsr14.c sm3.c x14.c x15.c x17.c \ + x22i.c SWIFFTX/SWIFFTX.c \ + blake.c blakecoin.c blake2b.c blake2s.c jha.c keccak.c lbry.c tribus.c exosis.c \ + deep.c fresh.c groestl.c neoscrypt.c nist5.c quark.c qubit.c skein.c skein2.c \ + bitcore.c timetravel.c x11evo.c x16r.c x16rv2.c x16s.c xevan.c bastion.c hmq17.c sonoa.c \ + bmw.c luffa.c pentablake.c vitalium.c whirlpool.c whirlpoolx.c zr5.c \ + scrypt.c scryptn.c sha256.c sha256t.c sha256q.c \ + yescrypt.c yescrypt-opt.c sha256_Y.c \ + a5a.c a5amath.c m7m.c magimath.cpp velvet.c \ + argon2a.c blake2/blake2b.c ar2/argon2.c ar2/core.c ar2/encoding.c ar2/opt.c ar2/thread.c ar2/ar2-scrypt-jane.c \ + hive.c pomelo.c hex.c argon2d-dyn.c \ + phi.c phi2.c polytimos.c rainforest.c skunk.c sib.c veltor.c gost.c aergo.c lbk3.c OBJECTS=$(SOURCES:%.c=%.o) $(SOURCES:%.cpp=%.o) OUTPUT=libalgos.a @@ -41,4 +42,5 @@ $(OUTPUT): $(OBJECTS) clean: rm -f *.o rm -f ar2/*.o - + rm -f blake2/*.o + rm -f SWIFFTX/*.o diff --git a/stratum/algos/phi2.c b/stratum/algos/phi2.c new file mode 100644 index 0000000..1aad372 --- /dev/null +++ b/stratum/algos/phi2.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "gost.h" + +#include "Lyra2.h" + +#include "common.h" + +void phi2_hash(const char* input, char* output, uint32_t len) +{ + unsigned char _ALIGN(128) hash[64]; + unsigned char _ALIGN(128) hashA[64]; + unsigned char _ALIGN(128) hashB[64]; + + sph_cubehash512_context ctx_cubehash; + sph_jh512_context ctx_jh; + sph_gost512_context ctx_gost; + sph_echo512_context ctx_echo; + sph_skein512_context ctx_skein; + + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, input, len); + sph_cubehash512_close(&ctx_cubehash, (void*)hashB); + + LYRA2(&hashA[ 0], 32, &hashB[ 0], 32, &hashB[ 0], 32, 1, 8, 8); + LYRA2(&hashA[32], 32, &hashB[32], 32, &hashB[32], 32, 1, 8, 8); + + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, (const void*)hashA, 64); + sph_jh512_close(&ctx_jh, (void*)hash); + + if (hash[0] & 1) { + sph_gost512_init(&ctx_gost); + sph_gost512(&ctx_gost, (const void*)hash, 64); + sph_gost512_close(&ctx_gost, (void*)hash); + } else { + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, (const void*)hash, 64); + sph_echo512_close(&ctx_echo, (void*)hash); + + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, (const void*)hash, 64); + sph_echo512_close(&ctx_echo, (void*)hash); + } + + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, (const void*)hash, 64); + sph_skein512_close(&ctx_skein, (void*)hash); + + for (int i=0; i<32; i++) + hash[i] ^= hash[i+32]; + + memcpy(output, hash, 32); +} diff --git a/stratum/algos/phi2.h b/stratum/algos/phi2.h new file mode 100644 index 0000000..d551d28 --- /dev/null +++ b/stratum/algos/phi2.h @@ -0,0 +1,16 @@ +#ifndef PHI2_H +#define PHI2_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void phi2_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/rainforest.c b/stratum/algos/rainforest.c new file mode 100644 index 0000000..685c363 --- /dev/null +++ b/stratum/algos/rainforest.c @@ -0,0 +1,802 @@ +// RainForest hash algorithm +// Author: Bill Schneider +// Date: Feb 13th, 2018 +// +// RainForest uses native integer operations which are extremely fast on +// modern 64-bit processors, significantly slower on 32-bit processors such +// as GPUs, and extremely slow if at all implementable on FPGAs and ASICs. +// It makes an intensive use of the L1 cache to maintain a heavy intermediary +// state favoring modern CPUs compared to GPUs (small L1 cache shared by many +// shaders) or FPGAs (very hard to implement the required low-latency cache) +// when scanning ranges for nonces. The purpose is to create a fair balance +// between all mining equipments, from mobile phones to extreme performance +// GPUs and to rule out farming factories relying on ASICs and FPGAs. The +// CRC32 instruction is used a lot as it is extremely fast on low-power ARM +// chips and allows such devices to rival high-end PCs mining performance. +// +// Tests on various devices have shown the following performance : +// +--------------------------------------------------------------------------+ +// | CPU/GPU Clock Threads Full hash Nonce scan Watts Cost | +// | (MHz) (80 bytes) (4 bytes) total | +// | Core i7-6700k 4000 8 390 kH/s 1642 kH/s 200 ~$350+PC | +// | Radeon RX560 1300 1024 1100 kH/s 1650 kH/s 300 ~$180+PC | +// | RK3368 (8*A53) 1416 8 534 kH/s 1582 kH/s 6 $60 (Geekbox) | +// +--------------------------------------------------------------------------+ +// +// Build instructions on Ubuntu 16.04 : +// - on x86: use gcc -march=native or -maes to enable AES-NI +// - on ARMv8: use gcc -march=native or -march=armv8-a+crypto+crc to enable +// CRC32 and AES extensions. +// +// Note: always use the same options to build all files! + +#include +#include +#include +#include + +//#define DEBUG_ALGO + +/* Rijndael's substitution box for sub_bytes step */ +static uint8_t SBOX[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +/*--- The parts below are not used when crypto extensions are available ---*/ +/* Use -march=armv8-a+crypto on ARMv8 to use crypto extensions */ +/* Use -maes on x86_64 to use AES-NI */ +#if defined(RF_NOASM) || (!defined(__aarch64__) || !defined(__ARM_FEATURE_CRYPTO)) && (!defined(__x86_64__) || !defined(__AES__)) + +/* shifts to do for shift_rows step */ +static uint8_t shifts[16] = { + 0, 5, 10, 15, + 4, 9, 14, 3, + 8, 13, 2, 7, + 12, 1, 6, 11 +}; + +/* add the round key to the state with simple XOR operation */ +static void add_round_key(uint8_t * state, uint8_t * rkey) { + uint8_t i; + for (i = 0; i < 16; i++) + state[i] ^= rkey[i]; +} + +/* substitute all bytes using Rijndael's substitution box */ +static void sub_bytes(uint8_t * state) { + uint8_t i; + for (i = 0; i < 16; i++) + state[i] = SBOX[state[i]]; +} + +/* imagine the state not as 1-dimensional, but a 4x4 grid; + * this step shifts the rows of this grid around */ +static void shift_rows(uint8_t * state) { + uint8_t temp[16]; + uint8_t i; + + for (i = 0; i < 16; i++) { + temp[i] = state[shifts[i]]; + } + + for (i = 0; i < 16; i++) { + state[i] = temp[i]; + } +} + +/* mix columns */ +static void mix_columns(uint8_t * state) { + uint8_t a[4]; + uint8_t b[4]; + uint8_t h, i, k; + + for (k = 0; k < 4; k++) { + for (i = 0; i < 4; i++) { + a[i] = state[i + 4 * k]; + h = state[i + 4 * k] & 0x80; /* hi bit */ + b[i] = state[i + 4 * k] << 1; + + if (h == 0x80) { + b[i] ^= 0x1b; /* Rijndael's Galois field */ + } + } + + state[4 * k] = b[0] ^ a[3] ^ a[2] ^ b[1] ^ a[1]; + state[1 + 4 * k] = b[1] ^ a[0] ^ a[3] ^ b[2] ^ a[2]; + state[2 + 4 * k] = b[2] ^ a[1] ^ a[0] ^ b[3] ^ a[3]; + state[3 + 4 * k] = b[3] ^ a[2] ^ a[1] ^ b[0] ^ a[0]; + } +} +#endif // (!defined(__aarch64__) || !defined(__ARM_FEATURE_CRYPTO)) && (!defined(__x86_64__) || !defined(__AES__)) + + +/* key schedule stuff */ + +/* simple function to rotate 4 byte array */ +static inline uint32_t rotate32(uint32_t in) { +#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + in = (in >> 8) | (in << 24); +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + in = (in << 8) | (in >> 24); +#else + uint8_t *b = (uint8_t *)&in, temp = b[0]; + b[0] = b[1]; b[1] = b[2]; b[2] = b[3]; b[3] = temp; +#endif + return in; +} + +/* key schedule core operation */ +static inline uint32_t sbox(uint32_t in, uint8_t n) { + in = (SBOX[in & 255]) | (SBOX[(in >> 8) & 255] << 8) | (SBOX[(in >> 16) & 255] << 16) | (SBOX[(in >> 24) & 255] << 24); +#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + in ^= n; +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + in ^= n << 24; +#else + *(uint8_t *)&in ^= n; +#endif + return in; +} + +// this version is optimized for exactly two rounds. +// _state_ must be 16-byte aligned. +static void aes2r_encrypt(uint8_t * state, uint8_t * key) { + uint32_t key_schedule[12] __attribute__((aligned(16))); + uint32_t t; + + /* initialize key schedule; its first 16 bytes are the key */ + key_schedule[0] = ((uint32_t *)key)[0]; + key_schedule[1] = ((uint32_t *)key)[1]; + key_schedule[2] = ((uint32_t *)key)[2]; + key_schedule[3] = ((uint32_t *)key)[3]; + t = key_schedule[3]; + + t = rotate32(t); + t = sbox(t, 1); + t = key_schedule[4] = key_schedule[0] ^ t; + t = key_schedule[5] = key_schedule[1] ^ t; + t = key_schedule[6] = key_schedule[2] ^ t; + t = key_schedule[7] = key_schedule[3] ^ t; + + t = rotate32(t); + t = sbox(t, 2); + t = key_schedule[8] = key_schedule[4] ^ t; + t = key_schedule[9] = key_schedule[5] ^ t; + t = key_schedule[10] = key_schedule[6] ^ t; + t = key_schedule[11] = key_schedule[7] ^ t; + +// Use -march=armv8-a+crypto+crc to get this one +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRYPTO) + asm volatile( + "ld1 {v0.16b},[%0] \n" + "ld1 {v1.16b,v2.16b,v3.16b},[%1] \n" + "aese v0.16b,v1.16b \n" // round1: add_round_key,sub_bytes,shift_rows + "aesmc v0.16b,v0.16b \n" // round1: mix_columns + "aese v0.16b,v2.16b \n" // round2: add_round_key,sub_bytes,shift_rows + "eor v0.16b,v0.16b,v3.16b \n" // finish: add_round_key + "st1 {v0.16b},[%0] \n" + : /* only output is in *state */ + : "r"(state), "r"(key_schedule) + : "v0", "v1", "v2", "v3", "cc", "memory"); + +// Use -maes to get this one +#elif defined(__x86_64__) && defined(__AES__) + asm volatile( + "movups (%0), %%xmm0 \n" + "movups (%1), %%xmm1 \n" + "pxor %%xmm1,%%xmm0 \n" // add_round_key(state, key_schedule) + "movups 16(%1),%%xmm2 \n" + "movups 32(%1),%%xmm1 \n" + "aesenc %%xmm2,%%xmm0 \n" // first round + "aesenclast %%xmm1,%%xmm0 \n" // final round + "movups %%xmm0, (%0) \n" + : /* only output is in *state */ + : "r"(state), "r" (key_schedule) + : "xmm0", "xmm1", "xmm2", "cc", "memory"); + +#else + /* first round of the algorithm */ + add_round_key(state, (void*)&key_schedule[0]); + sub_bytes(state); + shift_rows(state); + mix_columns(state); + add_round_key(state, (void*)&key_schedule[4]); + + /* final round of the algorithm */ + sub_bytes(state); + shift_rows(state); + add_round_key(state, (void*)&key_schedule[8]); + +#endif +} + +// this seems necessary only for gcc, otherwise hash is bogus +typedef __attribute__((may_alias)) uint8_t rf_u8; +typedef __attribute__((may_alias)) uint16_t rf_u16; +typedef __attribute__((may_alias)) uint32_t rf_u32; +typedef __attribute__((may_alias)) uint64_t rf_u64; + +// 2048 entries for the rambox => 16kB +#define RAMBOX_SIZE 2048 +#define RAMBOX_LOOPS 4 + +typedef union { + rf_u8 b[32]; + rf_u16 w[16]; + rf_u32 d[8]; + rf_u64 q[4]; +} hash256_t; + +typedef struct __attribute__((aligned(16))) rf_ctx { + uint64_t rambox[RAMBOX_SIZE]; + hash256_t hash; + uint32_t crc; + uint32_t word; // LE pending message + uint32_t len; // total message length +} rf256_ctx_t; + +// these archs are fine with unaligned reads +#if defined(__x86_64__)||defined(__aarch64__) +#define RF_UNALIGNED_LE64 +#define RF_UNALIGNED_LE32 +#elif defined(__i386__)||defined(__ARM_ARCH_7A__) +#define RF_UNALIGNED_LE32 +#endif + +#define RF256_INIT_CRC 20180213 + +// the table is used as an 8 bit-aligned array of uint64_t for the first word, +// and as a 16 bit-aligned array of uint64_t for the second word. It is filled +// with the sha256 of "RainForestProCpuAntiAsic", iterated over and over until +// the table is filled. The highest offset being ((uint16_t *)table)[255] we +// need to add 6 extra bytes at the end to read an uint64_t. Maybe calculated +// on a UNIX system with this loop : +// +// ref="RainForestProCpuAntiAsic" +// for ((i=0;i<18;i++)); do +// set $(echo -n $ref|sha256sum) +// echo $1|sed 's/\(..\)/0x\1,/g' +// ref=$(printf $(echo $1|sed 's/\(..\)/\\x\1/g')) +// done + +const uint8_t rf_table[256*2+6] = { + 0x8e,0xc1,0xa8,0x04,0x38,0x78,0x7c,0x54,0x29,0x23,0x1b,0x78,0x9f,0xf9,0x27,0x54, + 0x11,0x78,0x95,0xb6,0xaf,0x78,0x45,0x16,0x2b,0x9e,0x91,0xe8,0x97,0x25,0xf8,0x63, + 0x82,0x56,0xcf,0x48,0x6f,0x82,0x14,0x0d,0x61,0xbe,0x47,0xd1,0x37,0xee,0x30,0xa9, + 0x28,0x1e,0x4b,0xbf,0x07,0xcd,0x41,0xdf,0x23,0x21,0x12,0xb8,0x81,0x99,0x1d,0xe6, + 0x68,0xcf,0xfa,0x2d,0x8e,0xb9,0x88,0xa7,0x15,0xce,0x9e,0x2f,0xeb,0x1b,0x0f,0x67, + 0x20,0x68,0x6c,0xa9,0x5d,0xc1,0x7c,0x76,0xdf,0xbd,0x98,0x61,0xb4,0x14,0x65,0x40, + 0x1e,0x72,0x51,0x74,0x93,0xd3,0xad,0xbe,0x46,0x0a,0x25,0xfb,0x6a,0x5e,0x1e,0x8a, + 0x5a,0x03,0x3c,0xab,0x12,0xc2,0xd4,0x07,0x91,0xab,0xc9,0xdf,0x92,0x2c,0x85,0x6a, + 0xa6,0x25,0x1e,0x66,0x50,0x26,0x4e,0xa8,0xbd,0xda,0x88,0x1b,0x95,0xd4,0x00,0xeb, + 0x0d,0x1c,0x9b,0x3c,0x86,0xc7,0xb2,0xdf,0xb4,0x5a,0x36,0x15,0x8e,0x04,0xd2,0x54, + 0x79,0xd2,0x3e,0x3d,0x99,0x50,0xa6,0x12,0x4c,0x32,0xc8,0x51,0x14,0x4d,0x4b,0x0e, + 0xbb,0x17,0x80,0x8f,0xa4,0xc4,0x99,0x72,0xd7,0x14,0x4b,0xef,0xed,0x14,0xe9,0x17, + 0xfa,0x9b,0x5d,0x37,0xd6,0x2f,0xef,0x02,0xd6,0x71,0x0a,0xbd,0xc5,0x40,0x11,0x90, + 0x90,0x4e,0xb4,0x4c,0x72,0x51,0x7a,0xd8,0xba,0x30,0x4d,0x8c,0xe2,0x11,0xbb,0x6d, + 0x4b,0xbc,0x6f,0x14,0x0c,0x9f,0xfa,0x5e,0x66,0x40,0x45,0xcb,0x7d,0x1b,0x3a,0xc5, + 0x5e,0x9c,0x1e,0xcc,0xbd,0x16,0x3b,0xcf,0xfb,0x2a,0xd2,0x08,0x2a,0xf8,0x3d,0x46, + 0x93,0x90,0xb3,0x66,0x81,0x34,0x7f,0x6d,0x9b,0x8c,0x99,0x03,0xc5,0x27,0xa3,0xd9, + 0xce,0x90,0x88,0x0f,0x55,0xc3,0xa1,0x60,0x53,0xc8,0x0d,0x25,0xae,0x61,0xd9,0x72, + 0x48,0x1d,0x6c,0x61,0xd2,0x87,0xdd,0x3d,0x23,0xf5,0xde,0x93,0x39,0x4c,0x43,0x9a, + 0xf9,0x37,0xf2,0x61,0xd7,0xf8,0xea,0x65,0xf0,0xf1,0xde,0x3f,0x05,0x57,0x83,0x81, + 0xde,0x02,0x62,0x49,0xd4,0x32,0x7e,0x4a,0xd4,0x9f,0x40,0x7e,0xb9,0x91,0xb1,0x35, + 0xf7,0x62,0x3f,0x65,0x9e,0x4d,0x2b,0x10,0xde,0xd4,0x77,0x64,0x0f,0x84,0xad,0x92, + 0xe7,0xa3,0x8a,0x10,0xc1,0x14,0xeb,0x57,0xc4,0xad,0x8e,0xc2,0xc7,0x32,0xa3,0x7e, + 0x50,0x1f,0x7c,0xbb,0x2e,0x5f,0xf5,0x18,0x22,0xea,0xec,0x9d,0xa4,0x77,0xcd,0x85, + 0x04,0x2f,0x20,0x61,0x72,0xa7,0x0c,0x92,0x06,0x4d,0x01,0x70,0x9b,0x35,0xa1,0x27, + 0x32,0x6e,0xb9,0x78,0xe0,0xaa,0x5f,0x91,0xa6,0x51,0xe3,0x63,0xf8,0x97,0x2f,0x60, + 0xd9,0xfb,0x15,0xe5,0x59,0xcf,0x31,0x3c,0x61,0xc7,0xb5,0x61,0x2a,0x6b,0xdd,0xd1, + 0x09,0x70,0xc0,0xcf,0x94,0x7a,0xcc,0x31,0x94,0xb1,0xa2,0xf6,0x95,0xc0,0x38,0x3d, + 0xef,0x19,0x30,0x70,0xdd,0x62,0x32,0x8f,0x7c,0x30,0xb9,0x18,0xf8,0xe7,0x8f,0x0a, + 0xaa,0xb6,0x00,0x86,0xf2,0xe0,0x30,0x5f,0xa2,0xe8,0x00,0x8e,0x05,0xa0,0x22,0x18, + 0x9f,0x83,0xd4,0x3a,0x85,0x10,0xb9,0x51,0x8d,0x07,0xf0,0xb3,0xcd,0x9b,0x55,0xa1, + 0x14,0xce,0x0f,0xb2,0xcf,0xb8,0xce,0x2d,0xe6,0xe8,0x35,0x32,0x1f,0x22,0xb5,0xec, + 0xd0,0xb9,0x72,0xa8,0xb4,0x97 + //,0x6e,0x0a,0x47,0xcd,0x5a,0xf0,0xdc,0xeb,0xfd,0x46, + //0xe5,0x6e,0x83,0xe6,0x1a,0xcc,0x4a,0x8b,0xa5,0x28,0x9e,0x50,0x48,0xa9,0xa2,0x6b, +}; + +// this is made of the last iteration of the rf_table (18th transformation) +const uint8_t rf256_iv[32] = { + 0x78,0xe9,0x90,0xd3,0xb3,0xc8,0x9b,0x7b,0x0a,0xc4,0x86,0x6e,0x4e,0x38,0xb3,0x6b, + 0x33,0x68,0x7c,0xed,0x73,0x35,0x4b,0x0a,0x97,0x25,0x4c,0x77,0x7a,0xaa,0x61,0x1b +}; + +// crc32 lookup tables +const uint32_t rf_crc32_table[256] = { + /* 0x00 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + /* 0x04 */ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + /* 0x08 */ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + /* 0x0c */ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + /* 0x10 */ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + /* 0x14 */ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + /* 0x18 */ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + /* 0x1c */ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + /* 0x20 */ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + /* 0x24 */ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + /* 0x28 */ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + /* 0x2c */ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + /* 0x30 */ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + /* 0x34 */ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + /* 0x38 */ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + /* 0x3c */ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + /* 0x40 */ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + /* 0x44 */ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + /* 0x48 */ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + /* 0x4c */ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + /* 0x50 */ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + /* 0x54 */ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + /* 0x58 */ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + /* 0x5c */ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + /* 0x60 */ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + /* 0x64 */ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + /* 0x68 */ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + /* 0x6c */ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + /* 0x70 */ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + /* 0x74 */ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + /* 0x78 */ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + /* 0x7c */ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + /* 0x80 */ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + /* 0x84 */ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + /* 0x88 */ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + /* 0x8c */ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + /* 0x90 */ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + /* 0x94 */ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + /* 0x98 */ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + /* 0x9c */ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + /* 0xa0 */ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + /* 0xa4 */ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + /* 0xa8 */ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + /* 0xac */ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + /* 0xb0 */ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + /* 0xb4 */ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + /* 0xb8 */ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + /* 0xbc */ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + /* 0xc0 */ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + /* 0xc4 */ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + /* 0xc8 */ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + /* 0xcc */ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + /* 0xd0 */ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + /* 0xd4 */ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + /* 0xd8 */ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + /* 0xdc */ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + /* 0xe0 */ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + /* 0xe4 */ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + /* 0xe8 */ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + /* 0xec */ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + /* 0xf0 */ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + /* 0xf4 */ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + /* 0xf8 */ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + /* 0xfc */ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; + +// compute the crc32 of 32-bit message _msg_ from previous crc _crc_. +// build with -mcpu=cortex-a53+crc to enable native CRC instruction on ARM +static inline uint32_t rf_crc32_32(uint32_t crc, uint32_t msg) { +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) + asm("crc32w %w0,%w0,%w1\n":"+r"(crc):"r"(msg)); +#else + crc=crc^msg; + crc=rf_crc32_table[crc&0xff]^(crc>>8); + crc=rf_crc32_table[crc&0xff]^(crc>>8); + crc=rf_crc32_table[crc&0xff]^(crc>>8); + crc=rf_crc32_table[crc&0xff]^(crc>>8); +#endif + return crc; +} + +//static inline uint32_t rf_crc32_24(uint32_t crc, uint32_t msg) { +//#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) +// asm("crc32b %w0,%w0,%w1\n":"+r"(crc):"r"(msg)); +// asm("crc32h %w0,%w0,%w1\n":"+r"(crc):"r"(msg>>8)); +//#else +// crc=crc^msg; +// crc=rf_crc32_table[crc&0xff]^(crc>>8); +// crc=rf_crc32_table[crc&0xff]^(crc>>8); +// crc=rf_crc32_table[crc&0xff]^(crc>>8); +//#endif +// return crc; +//} +// +//static inline uint32_t rf_crc32_16(uint32_t crc, uint32_t msg) { +//#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) +// asm("crc32h %w0,%w0,%w1\n":"+r"(crc):"r"(msg)); +//#else +// crc=crc^msg; +// crc=rf_crc32_table[crc&0xff]^(crc>>8); +// crc=rf_crc32_table[crc&0xff]^(crc>>8); +//#endif +// return crc; +//} +// +//static inline uint32_t rf_crc32_8(uint32_t crc, uint32_t msg) { +//#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) +// asm("crc32b %w0,%w0,%w1\n":"+r"(crc):"r"(msg)); +//#else +// crc=crc^msg; +// crc=rf_crc32_table[crc&0xff]^(crc>>8); +//#endif +// return crc; +//} + +// add to _msg_ its own crc32. use -mcpu=cortex-a53+crc to enable native CRC +// instruction on ARM. +static inline uint64_t rf_add64_crc32(uint64_t msg) { + uint64_t crc=0; +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) + asm("crc32x %w0,%w0,%x1\n":"+r"(crc):"r"(msg)); +#else + crc^=(uint32_t)msg; + crc=rf_crc32_table[crc&0xff]^(crc>>8); + crc=rf_crc32_table[crc&0xff]^(crc>>8); + crc=rf_crc32_table[crc&0xff]^(crc>>8); + crc=rf_crc32_table[crc&0xff]^(crc>>8); + + crc^=msg>>32; + crc=rf_crc32_table[crc&0xff]^(crc>>8); + crc=rf_crc32_table[crc&0xff]^(crc>>8); + crc=rf_crc32_table[crc&0xff]^(crc>>8); + crc=rf_crc32_table[crc&0xff]^(crc>>8); +#endif + return msg+crc; +} + +// mix the current state with the crc and return the new crc +static inline uint32_t rf_crc32x4(rf_u32 *state, uint32_t crc) { + crc=state[0]=rf_crc32_32(crc, state[0]); + crc=state[1]=rf_crc32_32(crc, state[1]); + crc=state[2]=rf_crc32_32(crc, state[2]); + crc=state[3]=rf_crc32_32(crc, state[3]); + return crc; +} + +// read 64 bit from possibly unaligned memory address _p_ in little endian mode +static inline uint64_t rf_memr64(const uint8_t *p) { +#ifdef RF_UNALIGNED_LE64 + return *(uint64_t *)p; +#else + uint64_t ret; + int byte; + for (ret=byte=0; byte<8; byte++) + ret+=(uint64_t)p[byte]<<(byte*8); + return ret; +#endif +} + +// return rainforest lower word entry for index +static inline uint64_t rf_wltable(uint8_t index) { + return rf_memr64(&rf_table[index]); +} + +// return rainforest upper word entry for _index_ +static inline uint64_t rf_whtable(uint8_t index) { + return rf_memr64(&rf_table[index*2]); +} + +// rotate left vector _v_ by _bits_ bits +static inline uint64_t rf_rotl64(uint64_t v, uint8_t bits) { +#if !defined(__ARM_ARCH_8A) && !defined(__AARCH64EL__) && !defined(x86_64) + bits&=63; +#endif + return (v<>(64-bits)); +} + +// rotate right vector _v_ by _bits_ bits +static inline uint64_t rf_rotr64(uint64_t v, uint8_t bits) { +#if !defined(__ARM_ARCH_8A) && !defined(__AARCH64EL__) && !defined(x86_64) + bits&=63; +#endif + return (v>>bits)|(v<<(64-bits)); +} + +// reverse all bytes in the word _v_ +static inline uint64_t rf_bswap64(uint64_t v) { +#if defined(__x86_64__) + asm("bswap %0":"+r"(v)); +#elif defined(__aarch64__) + asm("rev %0,%0\n":"+r"(v)); +#else + v=((v&0xff00ff00ff00ff00ULL)>>8)|((v&0x00ff00ff00ff00ffULL)<<8); + v=((v&0xffff0000ffff0000ULL)>>16)|((v&0x0000ffff0000ffffULL)<<16); + v=(v>>32)|(v<<32); +#endif + return v; +} + +// lookup _old_ in _rambox_, update it and perform a substitution if a matching +// value is found. +static inline uint32_t rf_rambox(uint64_t *rambox, uint64_t old) { + uint64_t *p; + int loops; + + for (loops=0; loops>56)<0x80) + *p = old; + } + return old; +} + +// write (_x_,_y_) at cell _cell_ for offset _ofs_ +static inline void rf_w128(uint64_t *cell, ulong ofs, uint64_t x, uint64_t y) { +#if defined(__ARM_ARCH_8A) || defined(__AARCH64EL__) + // 128 bit at once is faster when exactly two parallelizable instructions are + // used between two calls to keep the pipe full. + asm volatile("stp %0, %1, [%2,#%3]\n\t" + : /* no output */ + : "r"(x), "r"(y), "r" (cell), "I" (ofs*8)); +#else + cell[ofs+0] = x; + cell[ofs+1] = y; +#endif +} + +// initialize the ram box +static __attribute__((noinline)) void rf_raminit(uint64_t *rambox) { + uint64_t pat1 = 0x0123456789ABCDEFULL; + uint64_t pat2 = 0xFEDCBA9876543210ULL; + uint64_t pat3; + uint32_t pos; + + // Note: no need to mask the higher bits on armv8 nor x86 : + // + // From ARMv8's ref manual : + // The register that is specified for a shift can be 32-bit or + // 64-bit. The amount to be shifted can be specified either as + // an immediate, that is up to register size minus one, or by + // a register where the value is taken only from the bottom five + // (modulo-32) or six (modulo-64) bits. + // + // Here we rotate pat2 by pat1's bits and put it into pat1, and in + // parallel we rotate pat1 by pat2's bits and put it into pat2. Thus + // the two data blocks are exchanged in addition to being rotated. + // What is stored each time is the previous and the rotated blocks, + // which only requires one rotate and a register rename. + + for (pos = 0; pos < RAMBOX_SIZE; pos += 16) { + pat3 = pat1; + pat1 = rf_rotr64(pat2, pat3) + 0x111; + rf_w128(rambox + pos, 0, pat1, pat3); + + pat3 = pat2; + pat2 = rf_rotr64(pat1, pat3) + 0x222; + rf_w128(rambox + pos, 2, pat2, pat3); + + pat3 = pat1; + pat1 = rf_rotr64(pat2, pat3) + 0x333; + rf_w128(rambox + pos, 4, pat1, pat3); + + pat3 = pat2; + pat2 = rf_rotr64(pat1, pat3) + 0x444; + rf_w128(rambox + pos, 6, pat2, pat3); + + pat3 = pat1; + pat1 = rf_rotr64(pat2, pat3) + 0x555; + rf_w128(rambox + pos, 8, pat1, pat3); + + pat3 = pat2; + pat2 = rf_rotr64(pat1, pat3) + 0x666; + rf_w128(rambox + pos, 10, pat2, pat3); + + pat3 = pat1; + pat1 = rf_rotr64(pat2, pat3) + 0x777; + rf_w128(rambox + pos, 12, pat1, pat3); + + pat3 = pat2; + pat2 = rf_rotr64(pat1, pat3) + 0x888; + rf_w128(rambox + pos, 14, pat2, pat3); + } +} + +// exec the div/mod box. _v0_ and _v1_ must be aligned. +static inline void rf256_divbox(rf_u64 *v0, rf_u64 *v1) { + uint64_t pl, ql, ph, qh; + + //---- low word ---- ---- high word ---- + pl=~*v0; ph=~*v1; + ql=rf_bswap64(*v0); qh=rf_bswap64(*v1); + + if (!pl||!ql) { pl=ql=0; } + else if (pl>ql) { uint64_t p=pl; pl=p/ql; ql=p%ql; } + else { uint64_t p=pl; pl=ql/p; ql=ql%p; } + + if (!ph||!qh) { ph=qh=0; } + else if (ph>qh) { uint64_t p=ph; ph=p/qh; qh=p%qh; } + else { uint64_t p=ph; ph=qh/p; qh=qh%p; } + + pl+=qh; ph+=ql; + *v0-=pl; *v1-=ph; +} + +// exec the rotation/add box. _v0_ and _v1_ must be aligned. +static inline void rf256_rotbox(rf_u64 *v0, rf_u64 *v1, uint8_t b0, uint8_t b1) { + uint64_t l, h; + + //---- low word ---- ---- high word ---- + l=*v0; h=*v1; + l=rf_rotr64(l,b0); h=rf_rotl64(h,b1); + l+=rf_wltable(b0); h+=rf_whtable(b1); + b0=l; b1=h; + l=rf_rotl64(l,b1); h=rf_rotr64(h,b0); + b0=l; b1=h; + l=rf_rotr64(l,b1); h=rf_rotl64(h,b0); + *v0=l; *v1=h; +} + +// mix the current state with the current crc +static inline uint32_t rf256_scramble(rf256_ctx_t *ctx) { + return ctx->crc=rf_crc32x4(ctx->hash.d, ctx->crc); +} + +// mix the state with the crc and the pending text, and update the crc +static inline void rf256_inject(rf256_ctx_t *ctx) { + // BS: never <4 bytes with 80 input bytes + //ctx->crc= + // (ctx->bytes&3)==0?rf_crc32_32(rf256_scramble(ctx), ctx->word): + // (ctx->bytes&3)==3?rf_crc32_24(rf256_scramble(ctx), ctx->word): + // (ctx->bytes&3)==2?rf_crc32_16(rf256_scramble(ctx), ctx->word): + // rf_crc32_8(rf256_scramble(ctx), ctx->word); + ctx->crc=rf_crc32_32(rf256_scramble(ctx), ctx->word); + ctx->word=0; +} + +// rotate the hash by 32 bits. Not using streaming instructions (SSE/NEON) is +// faster because the compiler can follow moves an use register renames. +static inline void rf256_rot32x256(hash256_t *hash) { +#if defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_ARCH_7A__) + uint32_t t0, t1, t2; + + t0=hash->d[0]; + t1=hash->d[1]; + t2=hash->d[2]; + hash->d[1]=t0; + hash->d[2]=t1; + + t0=hash->d[3]; + t1=hash->d[4]; + hash->d[3]=t2; + hash->d[4]=t0; + + t2=hash->d[5]; + t0=hash->d[6]; + hash->d[5]=t1; + hash->d[6]=t2; + + t1=hash->d[7]; + hash->d[7]=t0; + hash->d[0]=t1; +#else + uint32_t tmp=hash->d[7]; + + memmove(&hash->d[1], &hash->d[0], 28); + hash->d[0]=tmp; +#endif +} + +// encrypt the first 128 bits of the hash using the last 128 bits as the key +static inline void rf256_aesenc(rf256_ctx_t *ctx) { + aes2r_encrypt((uint8_t *)ctx->hash.b, (uint8_t *)ctx->hash.b+16); +} + +// each new round consumes exactly 32 bits of text at once and perturbates +// 128 bits of output, 96 of which overlap with the previous round, and 32 +// of which are new. With 5 rounds or more each output bit depends on every +// input bit. +static inline void rf256_one_round(rf256_ctx_t *ctx) { + uint64_t carry; + + rf256_rot32x256(&ctx->hash); + + carry=((uint64_t)ctx->len << 32) + ctx->crc; + rf256_scramble(ctx); + rf256_divbox(ctx->hash.q, ctx->hash.q+1); + rf256_scramble(ctx); + + carry=rf_rambox(ctx->rambox, carry); + rf256_rotbox(ctx->hash.q, ctx->hash.q+1, carry, carry>>56); + rf256_scramble(ctx); + rf256_divbox(ctx->hash.q, ctx->hash.q+1); + rf256_scramble(ctx); + rf256_divbox(ctx->hash.q, ctx->hash.q+1); + rf256_scramble(ctx); + + carry=rf_rambox(ctx->rambox, carry); + rf256_rotbox(ctx->hash.q, ctx->hash.q+1, carry>>8, carry>>48); + rf256_scramble(ctx); + rf256_divbox(ctx->hash.q, ctx->hash.q+1); + rf256_scramble(ctx); + rf256_divbox(ctx->hash.q, ctx->hash.q+1); + rf256_scramble(ctx); + + carry=rf_rambox(ctx->rambox, carry); + rf256_rotbox(ctx->hash.q, ctx->hash.q+1, carry>>16, carry>>40); + rf256_scramble(ctx); + rf256_divbox(ctx->hash.q, ctx->hash.q+1); + rf256_scramble(ctx); + rf256_divbox(ctx->hash.q, ctx->hash.q+1); + rf256_scramble(ctx); + + carry=rf_rambox(ctx->rambox,carry); + rf256_rotbox(ctx->hash.q, ctx->hash.q+1, carry>>24, carry>>32); + rf256_scramble(ctx); + rf256_divbox(ctx->hash.q, ctx->hash.q+1); + rf256_inject(ctx); + rf256_aesenc(ctx); + rf256_scramble(ctx); +} + +// initialize the hash state +static void rf256_init(rf256_ctx_t *ctx) { + rf_raminit(ctx->rambox); + memcpy(ctx->hash.b, rf256_iv, sizeof(ctx->hash.b)); + ctx->crc=RF256_INIT_CRC; + ctx->word=ctx->len=0; +} + +// update the hash context _ctx_ with _len_ bytes from message _msg_ +static void rf256_update(rf256_ctx_t *ctx, const void *msg, size_t len) { + while (len > 0) { +#ifdef RF_UNALIGNED_LE32 + if (!(ctx->len&3) && len>=4) { + ctx->word=*(uint32_t *)msg; + ctx->len+=4; + rf256_one_round(ctx); + msg+=4; + len-=4; + continue; + } +#endif + ctx->word|=((uint32_t)*(uint8_t *)msg++)<<(8*(ctx->len++&3)); + len--; + if (!(ctx->len&3)) + rf256_one_round(ctx); + } +} + +// finalize the hash and copy the result into _out_ if not null (256 bits) +static void rf256_final(void *out, rf256_ctx_t *ctx) { + // BS: never happens with 80 input bytes + //uint32_t pad; + + //if (ctx->len&3) + // rf256_one_round(ctx); + + // always work on at least 256 bits of input + //for (pad=0; pad+ctx->len < 32;pad+=4) + // rf256_one_round(ctx); + + // always run 4 extra rounds to complete the last 128 bits + rf256_one_round(ctx); + rf256_one_round(ctx); + rf256_one_round(ctx); + rf256_one_round(ctx); + //if (out) + memcpy(out, ctx->hash.b, 32); +} + +// hash _len_ bytes from _in_ into _out_ +void rf256_hash(void *out, const void *in, size_t len) { + rf256_ctx_t ctx; + rf256_init(&ctx); + rf256_update(&ctx, in, len); + rf256_final(out, &ctx); +} diff --git a/stratum/algos/rainforest.h b/stratum/algos/rainforest.h new file mode 100644 index 0000000..2f5b494 --- /dev/null +++ b/stratum/algos/rainforest.h @@ -0,0 +1,19 @@ +#ifndef RAINFOREST_H +#define RAINFOREST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void rf256_hash(void *out, const void *in, size_t len); +static inline void rainforest_hash(const char* input, char* output, uint32_t len) { + rf256_hash(output, input, len); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sha256q.c b/stratum/algos/sha256q.c new file mode 100644 index 0000000..1cd7f4d --- /dev/null +++ b/stratum/algos/sha256q.c @@ -0,0 +1,32 @@ + +#include +#include +#include +#include + +#include "sha256.h" + +#include + +void sha256q_hash(const char* input, char* output, uint32_t len) +{ + unsigned char hash[64]; + + SHA256_CTX ctx_sha256; + SHA256_Init(&ctx_sha256); + SHA256_Update(&ctx_sha256, input, len); + SHA256_Final(hash, &ctx_sha256); + + SHA256_Init(&ctx_sha256); + SHA256_Update(&ctx_sha256, hash, 32); + SHA256_Final(hash, &ctx_sha256); + + SHA256_Init(&ctx_sha256); + SHA256_Update(&ctx_sha256, hash, 32); + SHA256_Final(hash, &ctx_sha256); + + SHA256_Init(&ctx_sha256); + SHA256_Update(&ctx_sha256, hash, 32); + SHA256_Final((unsigned char*)output, &ctx_sha256); +} + diff --git a/stratum/algos/sha256q.h b/stratum/algos/sha256q.h new file mode 100644 index 0000000..23fd6c1 --- /dev/null +++ b/stratum/algos/sha256q.h @@ -0,0 +1,16 @@ +#ifndef SHA256Q_H +#define SHA256Q_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void sha256q_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sm3.c b/stratum/algos/sm3.c index 295ba15..b627cb8 100644 --- a/stratum/algos/sm3.c +++ b/stratum/algos/sm3.c @@ -153,17 +153,17 @@ void sm3_compress(uint32_t digest[8], const unsigned char block[64]) uint32_t H = digest[7]; uint32_t SS1,SS2,TT1,TT2,T[64]; - for (j = 0; j < 16; j++) { + for(j = 0; j < 16; j++) { W[j] = cpu_to_be32(pblock[j]); } - for (j = 16; j < 68; j++) { + for(j = 16; j < 68; j++) { W[j] = P1( W[j-16] ^ W[j-9] ^ ROTATELEFT(W[j-3],15)) ^ ROTATELEFT(W[j - 13],7 ) ^ W[j-6];; } - for( j = 0; j < 64; j++) { + for(j = 0; j < 64; j++) { W1[j] = W[j] ^ W[j+4]; } - for(j =0; j < 16; j++) { + for(j = 0; j < 16; j++) { T[j] = 0x79CC4519; SS1 = ROTATELEFT((ROTATELEFT(A,12) + E + ROTATELEFT(T[j],j)), 7); @@ -180,10 +180,10 @@ void sm3_compress(uint32_t digest[8], const unsigned char block[64]) E = P0(TT2); } - for(j =16; j < 64; j++) { + for(j = 16; j < 64; j++) { T[j] = 0x7A879D8A; - SS1 = ROTATELEFT((ROTATELEFT(A,12) + E + ROTATELEFT(T[j],j)), 7); + SS1 = ROTATELEFT((ROTATELEFT(A,12) + E + ROTATELEFT(T[j],j&31)), 7); SS2 = SS1 ^ ROTATELEFT(A,12); TT1 = FF1(A,B,C) + D + SS2 + W1[j]; TT2 = GG1(E,F,G) + H + SS1 + W[j]; diff --git a/stratum/algos/sonoa.c b/stratum/algos/sonoa.c new file mode 100644 index 0000000..ade6ef9 --- /dev/null +++ b/stratum/algos/sonoa.c @@ -0,0 +1,369 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +void sonoa_hash(const char* input, char* output, uint32_t len) +{ + uint8_t _ALIGN(128) hash[64]; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_skein512_context ctx_skein; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + sph_haval256_5_context ctx_haval; + + + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, input, 80); + sph_blake512_close(&ctx_blake, hash); + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, hash, 64); + sph_fugue512_close(&ctx_fugue, hash); + + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + + sph_fugue512(&ctx_fugue, hash, 64); + sph_fugue512_close(&ctx_fugue, hash); + + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, hash, 64); + sph_shabal512_close(&ctx_shabal, hash); + + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_shabal512(&ctx_shabal, hash, 64); + sph_shabal512_close(&ctx_shabal, hash); + + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + + sph_fugue512(&ctx_fugue, hash, 64); + sph_fugue512_close(&ctx_fugue, hash); + + sph_shabal512(&ctx_shabal, hash, 64); + sph_shabal512_close(&ctx_shabal, hash); + + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, hash, 64); + sph_whirlpool_close(&ctx_whirlpool, hash); + + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + + sph_fugue512(&ctx_fugue, hash, 64); + sph_fugue512_close(&ctx_fugue, hash); + + sph_shabal512(&ctx_shabal, hash, 64); + sph_shabal512_close(&ctx_shabal, hash); + + sph_whirlpool(&ctx_whirlpool, hash, 64); + sph_whirlpool_close(&ctx_whirlpool, hash); + + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) hash, 64); + sph_sha512_close(&ctx_sha512,(void*) hash); + + sph_whirlpool(&ctx_whirlpool, hash, 64); + sph_whirlpool_close(&ctx_whirlpool, hash); + + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + + sph_fugue512(&ctx_fugue, hash, 64); + sph_fugue512_close(&ctx_fugue, hash); + + sph_shabal512(&ctx_shabal, hash, 64); + sph_shabal512_close(&ctx_shabal, hash); + + sph_whirlpool(&ctx_whirlpool, hash, 64); + sph_whirlpool_close(&ctx_whirlpool, hash); + + sph_sha512(&ctx_sha512,(const void*) hash, 64); + sph_sha512_close(&ctx_sha512,(void*) hash); + + sph_haval256_5_init(&ctx_haval); + sph_haval256_5(&ctx_haval,(const void*) hash, 64); + sph_haval256_5_close(&ctx_haval, hash); + + memcpy(output, hash, 32); +} + diff --git a/stratum/algos/sonoa.h b/stratum/algos/sonoa.h new file mode 100644 index 0000000..c4b6b88 --- /dev/null +++ b/stratum/algos/sonoa.h @@ -0,0 +1,16 @@ +#ifndef SONOA_H +#define SONOA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void sonoa_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/vitalium.c b/stratum/algos/vitalium.c new file mode 100644 index 0000000..2a3b27c --- /dev/null +++ b/stratum/algos/vitalium.c @@ -0,0 +1,87 @@ +#include "vitalium.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "gost.h" + +#include "common.h" + +void vitalium_hash(const char* input, char* output, uint32_t len) +{ + sph_skein512_context ctx_skein; + sph_cubehash512_context ctx_cubehash; + sph_fugue512_context ctx_fugue; + sph_gost512_context ctx_gost; + sph_echo512_context ctx_echo; + sph_shavite512_context ctx_shavite; + sph_luffa512_context ctx_luffa; + + //these uint512 in the c++ source of the client are backed by an array of uint32 + uint32_t hashA[16], hashB[16]; + + sph_skein512_init(&ctx_skein); + sph_skein512 (&ctx_skein, input, len); + sph_skein512_close (&ctx_skein, hashA); + + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512 (&ctx_cubehash, hashA, 64); + sph_cubehash512_close(&ctx_cubehash, hashB); + + sph_fugue512_init(&ctx_fugue); + sph_fugue512 (&ctx_fugue, hashB, 64); + sph_fugue512_close(&ctx_fugue, hashA); + + sph_gost512_init(&ctx_gost); + sph_gost512 (&ctx_gost, hashA, 64); + sph_gost512_close (&ctx_gost, hashB); + + sph_echo512_init(&ctx_echo); + sph_echo512 (&ctx_echo, hashB, 64); + sph_echo512_close(&ctx_echo, hashA); + + sph_shavite512_init(&ctx_shavite); + sph_shavite512 (&ctx_shavite, hashA, 64); + sph_shavite512_close(&ctx_shavite, hashB); + + sph_luffa512_init (&ctx_luffa); + sph_luffa512 (&ctx_luffa, hashB, 64); + sph_luffa512_close (&ctx_luffa, hashA); + + sph_gost512_init(&ctx_gost); + sph_gost512 (&ctx_gost, hashA, 64); + sph_gost512_close (&ctx_gost, hashB); + + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512 (&ctx_cubehash, hashB, 64); + sph_cubehash512_close(&ctx_cubehash, hashA); + + sph_fugue512_init(&ctx_fugue); + sph_fugue512 (&ctx_fugue, hashA, 64); + sph_fugue512_close(&ctx_fugue, hashB); + + sph_gost512_init(&ctx_gost); + sph_gost512 (&ctx_gost, hashB, 64); + sph_gost512_close (&ctx_gost, hashA); + + sph_echo512_init(&ctx_echo); + sph_echo512 (&ctx_echo, hashA, 64); + sph_echo512_close(&ctx_echo, hashB); + + sph_shavite512_init(&ctx_shavite); + sph_shavite512 (&ctx_shavite, hashB, 64); + sph_shavite512_close(&ctx_shavite, hashA); + + sph_luffa512_init (&ctx_luffa); + sph_luffa512 (&ctx_luffa, hashA, 64); + sph_luffa512_close (&ctx_luffa, hashB); + + memcpy(output, hashB, 32); +} diff --git a/stratum/algos/vitalium.h b/stratum/algos/vitalium.h new file mode 100644 index 0000000..e29b3bc --- /dev/null +++ b/stratum/algos/vitalium.h @@ -0,0 +1,16 @@ +#ifndef VITALITY_H +#define VITALITY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void vitalium_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/x12.c b/stratum/algos/x12.c new file mode 100644 index 0000000..07346a1 --- /dev/null +++ b/stratum/algos/x12.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void x12_hash(const char* input, char* output, uint32_t len) +{ + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_hamsi512_context ctx_hamsi; + + uint32_t hash[16]; + + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, input, len); + sph_blake512_close(&ctx_blake, hash); + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + + memcpy(output, hash, 32); +} diff --git a/stratum/algos/x12.h b/stratum/algos/x12.h new file mode 100644 index 0000000..1b7ee98 --- /dev/null +++ b/stratum/algos/x12.h @@ -0,0 +1,16 @@ +#ifndef X12_H +#define X12_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void x12_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/x16r.c b/stratum/algos/x16r.c new file mode 100644 index 0000000..2b7a44f --- /dev/null +++ b/stratum/algos/x16r.c @@ -0,0 +1,178 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +enum Algo { + BLAKE = 0, + BMW, + GROESTL, + JH, + KECCAK, + SKEIN, + LUFFA, + CUBEHASH, + SHAVITE, + SIMD, + ECHO, + HAMSI, + FUGUE, + SHABAL, + WHIRLPOOL, + SHA512, + HASH_FUNC_COUNT +}; + +static void getAlgoString(const uint8_t* prevblock, char *output) +{ + char *sptr = output; + + for (int j = 0; j < HASH_FUNC_COUNT; j++) { + char b = (15 - j) >> 1; // 16 ascii hex chars, reversed + uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4; + if (algoDigit >= 10) + sprintf(sptr, "%c", 'A' + (algoDigit - 10)); + else + sprintf(sptr, "%u", (uint32_t) algoDigit); + sptr++; + } + *sptr = '\0'; +} + +void x16r_hash(const char* input, char* output, uint32_t len) +{ + uint32_t hash[64/4]; + char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + + void *in = (void*) input; + int size = len; + + getAlgoString(&input[4], hashOrder); + + for (int i = 0; i < 16; i++) + { + const char elem = hashOrder[i]; + const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; + + switch (algo) { + case BLAKE: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case BMW: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case GROESTL: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + case SKEIN: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case JH: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case KECCAK: + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, in, size); + sph_keccak512_close(&ctx_keccak, hash); + break; + case LUFFA: + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, in, size); + sph_luffa512_close(&ctx_luffa, hash); + break; + case CUBEHASH: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case SHAVITE: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case SIMD: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + case ECHO: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case HAMSI: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case FUGUE: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case SHABAL: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case WHIRLPOOL: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case SHA512: + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) in, size); + sph_sha512_close(&ctx_sha512,(void*) hash); + break; + } + in = (void*) hash; + size = 64; + } + memcpy(output, hash, 32); +} diff --git a/stratum/algos/x16r.h b/stratum/algos/x16r.h new file mode 100644 index 0000000..4a41ec8 --- /dev/null +++ b/stratum/algos/x16r.h @@ -0,0 +1,16 @@ +#ifndef X16R_H +#define X16R_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void x16r_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/x16rv2.c b/stratum/algos/x16rv2.c new file mode 100644 index 0000000..788bd7f --- /dev/null +++ b/stratum/algos/x16rv2.c @@ -0,0 +1,199 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +enum Algo { + BLAKE = 0, + BMW, + GROESTL, + JH, + KECCAK, + SKEIN, + LUFFA, + CUBEHASH, + SHAVITE, + SIMD, + ECHO, + HAMSI, + FUGUE, + SHABAL, + WHIRLPOOL, + SHA512, + HASH_FUNC_COUNT +}; + +static void getAlgoString(const uint8_t* prevblock, char *output) +{ + char *sptr = output; + + for (int j = 0; j < HASH_FUNC_COUNT; j++) { + char b = (15 - j) >> 1; // 16 ascii hex chars, reversed + uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4; + if (algoDigit >= 10) + sprintf(sptr, "%c", 'A' + (algoDigit - 10)); + else + sprintf(sptr, "%u", (uint32_t) algoDigit); + sptr++; + } + *sptr = '\0'; +} + +inline void padtiger512(uint32_t* hash) { + for (int i = (24/4); i < (64/4); i++) hash[i] = 0; +} + +void x16rv2_hash(const char* input, char* output, uint32_t len) +{ + uint32_t hash[64/4]; + char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + sph_tiger_context ctx_tiger; + + void *in = (void*) input; + int size = len; + + getAlgoString(&input[4], hashOrder); + + for (int i = 0; i < 16; i++) + { + const char elem = hashOrder[i]; + const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; + + switch (algo) { + case BLAKE: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case BMW: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case GROESTL: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + case SKEIN: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case JH: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case KECCAK: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + padtiger512(hash); + + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + break; + case LUFFA: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + padtiger512(hash); + + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + break; + case CUBEHASH: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case SHAVITE: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case SIMD: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + case ECHO: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case HAMSI: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case FUGUE: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case SHABAL: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case WHIRLPOOL: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case SHA512: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + padtiger512(hash); + + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) hash, 64); + sph_sha512_close(&ctx_sha512,(void*) hash); + break; + } + in = (void*) hash; + size = 64; + } + memcpy(output, hash, 32); +} diff --git a/stratum/algos/x16rv2.h b/stratum/algos/x16rv2.h new file mode 100644 index 0000000..9ff2bf4 --- /dev/null +++ b/stratum/algos/x16rv2.h @@ -0,0 +1,16 @@ +#ifndef X16RV2_H +#define X16RV2_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void x16rv2_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/x16s.c b/stratum/algos/x16s.c new file mode 100644 index 0000000..d3f3291 --- /dev/null +++ b/stratum/algos/x16s.c @@ -0,0 +1,180 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +enum Algo { + BLAKE = 0, + BMW, + GROESTL, + JH, + KECCAK, + SKEIN, + LUFFA, + CUBEHASH, + SHAVITE, + SIMD, + ECHO, + HAMSI, + FUGUE, + SHABAL, + WHIRLPOOL, + SHA512, + HASH_FUNC_COUNT +}; + +static void getAlgoString(const uint8_t* prevblock, char *output) +{ + strcpy(output, "0123456789ABCDEF"); + + for(int i = 0; i < 16; i++){ + uint8_t b = (15 - i) >> 1; // 16 ascii hex chars, reversed + uint8_t algoDigit = (i & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4; + + int offset = algoDigit; + // insert the nth character at the front + char oldVal = output[offset]; + for(int j=offset; j-->0;) { + output[j+1] = output[j]; + } + output[0] = oldVal; + } +} + +void x16s_hash(const char* input, char* output, uint32_t len) +{ + uint32_t hash[64/4]; + char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + + void *in = (void*) input; + int size = len; + + getAlgoString(&input[4], hashOrder); + + for (int i = 0; i < 16; i++) + { + const char elem = hashOrder[i]; + const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; + + switch (algo) { + case BLAKE: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case BMW: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case GROESTL: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + case SKEIN: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case JH: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case KECCAK: + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, in, size); + sph_keccak512_close(&ctx_keccak, hash); + break; + case LUFFA: + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, in, size); + sph_luffa512_close(&ctx_luffa, hash); + break; + case CUBEHASH: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case SHAVITE: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case SIMD: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + case ECHO: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case HAMSI: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case FUGUE: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case SHABAL: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case WHIRLPOOL: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case SHA512: + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) in, size); + sph_sha512_close(&ctx_sha512,(void*) hash); + break; + } + in = (void*) hash; + size = 64; + } + memcpy(output, hash, 32); +} diff --git a/stratum/algos/x16s.h b/stratum/algos/x16s.h new file mode 100644 index 0000000..ec9201c --- /dev/null +++ b/stratum/algos/x16s.h @@ -0,0 +1,16 @@ +#ifndef X16S_H +#define X16S_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void x16s_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/x22i.c b/stratum/algos/x22i.c new file mode 100644 index 0000000..02a1aa3 --- /dev/null +++ b/stratum/algos/x22i.c @@ -0,0 +1,146 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SWIFFTX/SWIFFTX.h" +#include "gost.h" +#include "Lyra2.h" + +#include "common.h" + + +void x22i_hash(const char* input, char* output, uint32_t len) +{ + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + sph_haval256_5_context ctx_haval; + sph_tiger_context ctx_tiger; + sph_gost512_context ctx_gost; + sph_sha256_context ctx_sha; + + unsigned char _ALIGN(128) hash[64 * 4] = {0}; + unsigned char _ALIGN(128) hash2[64]; + + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, input, len); + sph_blake512_close (&ctx_blake, hash); + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close (&ctx_luffa, hash); + + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, hash, 64); + sph_fugue512_close(&ctx_fugue, hash); + + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, (const void*) hash, 64); + sph_shabal512_close(&ctx_shabal, &hash[64]); + + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool (&ctx_whirlpool, (const void*) &hash[64], 64); + sph_whirlpool_close(&ctx_whirlpool, &hash[128]); + + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) &hash[128], 64); + sph_sha512_close(&ctx_sha512,(void*) &hash[192]); + + InitializeSWIFFTX(); + ComputeSingleSWIFFTX((unsigned char*)hash, (unsigned char*)hash2, false); + + memset(hash, 0, 64); + sph_haval256_5_init(&ctx_haval); + sph_haval256_5(&ctx_haval,(const void*) hash2, 64); + sph_haval256_5_close(&ctx_haval,hash); + + memset(hash2, 0, 64); + sph_tiger_init(&ctx_tiger); + sph_tiger (&ctx_tiger, (const void*) hash, 64); + sph_tiger_close(&ctx_tiger, (void*) hash2); + + memset(hash, 0, 64); + LYRA2((void*) hash, 32, (const void*) hash2, 32, (const void*) hash2, 32, 1, 4, 4); + + sph_gost512_init(&ctx_gost); + sph_gost512 (&ctx_gost, (const void*) hash, 64); + sph_gost512_close(&ctx_gost, (void*) hash); + + sph_sha256_init(&ctx_sha); + sph_sha256 (&ctx_sha, (const void*) hash, 64); + sph_sha256_close(&ctx_sha, (void*) hash); + + memcpy(output, hash, 32); +} diff --git a/stratum/algos/x22i.h b/stratum/algos/x22i.h new file mode 100644 index 0000000..502b894 --- /dev/null +++ b/stratum/algos/x22i.h @@ -0,0 +1,16 @@ +#ifndef X22I_H +#define X22I_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void x22i_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/yescrypt-opt.c b/stratum/algos/yescrypt-opt.c index 4b42e85..c96190b 100644 --- a/stratum/algos/yescrypt-opt.c +++ b/stratum/algos/yescrypt-opt.c @@ -942,7 +942,15 @@ yescrypt_kdf(const yescrypt_shared_t * shared, yescrypt_local_t * local, { HMAC_SHA256_CTX_Y ctx; HMAC_SHA256_Init_Y(&ctx, buf, buflen); - HMAC_SHA256_Update_Y(&ctx, salt, saltlen); + if (r == 32) { // yescryptR32 + HMAC_SHA256_Update_Y(&ctx, "WaviBanana", 10); + } else + if (r == 16) { // yescryptR16 + HMAC_SHA256_Update_Y(&ctx, "Client Key", 10); + } + else { // yescrypt + HMAC_SHA256_Update_Y(&ctx, salt, saltlen); + } HMAC_SHA256_Final_Y((uint8_t *)sha256, &ctx); } /* Compute StoredKey */ diff --git a/stratum/algos/yescrypt.c b/stratum/algos/yescrypt.c index da070d6..2959dfa 100644 --- a/stratum/algos/yescrypt.c +++ b/stratum/algos/yescrypt.c @@ -327,35 +327,25 @@ 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; + yescrypt_shared_t shared; + 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, + if (yescrypt_init_shared(&shared, NULL, 0, 0, 0, 0, YESCRYPT_SHARED_DEFAULTS, 0, NULL, 0)) return -1; - if (yescrypt_init_local(&local)) { + 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 + + yescrypt_free_local(&local); + yescrypt_free_shared(&shared); + return retval; } @@ -364,3 +354,13 @@ void yescrypt_hash(const char *input, char *output, uint32_t len) { yescrypt_bsty((uint8_t*)input, len, (uint8_t*)input, len, 2048, 8, 1, (uint8_t*)output, 32); } + +void yescryptR16_hash(const char *input, char *output, uint32_t len) +{ + yescrypt_bsty((uint8_t*)input, len, (uint8_t*)input, len, 4096, 16, 1, (uint8_t*)output, 32); +} + +void yescryptR32_hash(const char *input, char *output, uint32_t len) +{ + yescrypt_bsty((uint8_t*)input, len, (uint8_t*)input, len, 4096, 32, 1, (uint8_t*)output, 32); +} diff --git a/stratum/algos/yescrypt.h b/stratum/algos/yescrypt.h index db72217..8e87c7b 100644 --- a/stratum/algos/yescrypt.h +++ b/stratum/algos/yescrypt.h @@ -39,6 +39,8 @@ extern "C" { #include /* for size_t */ void yescrypt_hash(const char* input, char* output, uint32_t len); +void yescryptR16_hash(const char* input, char* output, uint32_t len); +void yescryptR32_hash(const char* input, char* output, uint32_t len); /** * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): diff --git a/stratum/base58.cpp b/stratum/base58.cpp index 856683e..631fde0 100644 --- a/stratum/base58.cpp +++ b/stratum/base58.cpp @@ -96,3 +96,19 @@ bool base58_decode(const char *input, char *output) return true; } + +bool is_base58(char *input) +{ + // All alphanumeric characters except "0", "O", "I" and "l" + size_t i=0, len = strlen(input); + char *c = input; + while (i < len) { + bool isdigit = (c[i] >= '1' && c[i] <= '9'); + bool isalpha = (c[i] >= 'a' && c[i] <= 'z') || (c[i] >= 'A' && c[i] <= 'Z'); + if (!isdigit && !isalpha) return false; + if (c[i] == 'I' || c[i] == 'O' || c[i] == 'l') return false; + i++; + } + return true; +} + diff --git a/stratum/client.cpp b/stratum/client.cpp index e0bf1fb..3c2bd94 100644 --- a/stratum/client.cpp +++ b/stratum/client.cpp @@ -1,8 +1,6 @@ #include "stratum.h" -//#define CLIENT_DEBUGLOG_ - bool client_suggest_difficulty(YAAMP_CLIENT *client, json_value *json_params) { if(json_params->u.array.length>0) @@ -47,8 +45,8 @@ bool client_subscribe(YAAMP_CLIENT *client, json_value *json_params) if(json_params->u.array.length>0) { - strncpy(client->version, json_params->u.array.values[0]->u.string.ptr, 1023); - // if(!strcmp(client->version, "stratum-proxy/0.0.1")) return false; + if (json_params->u.array.values[0]->u.string.ptr) + strncpy(client->version, json_params->u.array.values[0]->u.string.ptr, 1023); if(strstr(client->version, "NiceHash") || strstr(client->version, "proxy") || strstr(client->version, "/3.")) client->reconnectable = false; @@ -88,9 +86,9 @@ bool client_subscribe(YAAMP_CLIENT *client, json_value *json_params) memcpy(client->job_history, client1->job_history, sizeof(client->job_history)); client1->lock_count = 0; -#ifdef CLIENT_DEBUGLOG_ - debuglog("reconnecting client locked to %x\n", client->jobid_next); -#endif + if (g_debuglog_client) { + debuglog("reconnecting client locked to %x\n", client->jobid_next); + } } else @@ -106,9 +104,9 @@ bool client_subscribe(YAAMP_CLIENT *client, json_value *json_params) memcpy(client->job_history, client1->job_history, sizeof(client->job_history)); client1->lock_count = 0; -#ifdef CLIENT_DEBUGLOG_ - debuglog("reconnecting2 client\n"); -#endif + if (g_debuglog_client) { + debuglog("reconnecting2 client\n"); + } } } } @@ -116,9 +114,9 @@ bool client_subscribe(YAAMP_CLIENT *client, json_value *json_params) strcpy(client->extranonce1_last, client->extranonce1); client->extranonce2size_last = client->extranonce2size; -#ifdef CLIENT_DEBUGLOG_ - debuglog("new client with nonce %s\n", client->extranonce1); -#endif + if (g_debuglog_client) { + debuglog("new client with nonce %s\n", client->extranonce1); + } client_send_result(client, "[[[\"mining.set_difficulty\",\"%.3g\"],[\"mining.notify\",\"%s\"]],\"%s\",%d]", client->difficulty_actual, client->notify_id, client->extranonce1, client->extranonce2size); @@ -197,7 +195,14 @@ bool client_validate_user_address(YAAMP_CLIENT *client) bool client_authorize(YAAMP_CLIENT *client, json_value *json_params) { - if(json_params->u.array.length>1) + + if(g_list_client.Find(client)) { + clientlog(client, "Already logged"); + client_send_error(client, 21, "Already logged"); + return false; + } + + if(json_params->u.array.length>1 && json_params->u.array.values[1]->u.string.ptr) strncpy(client->password, json_params->u.array.values[1]->u.string.ptr, 1023); if (g_list_client.count >= g_stratum_max_cons) { @@ -205,7 +210,7 @@ bool client_authorize(YAAMP_CLIENT *client, json_value *json_params) return false; } - if(json_params->u.array.length>0) + if(json_params->u.array.length>0 && json_params->u.array.values[0]->u.string.ptr) { strncpy(client->username, json_params->u.array.values[0]->u.string.ptr, 1023); @@ -224,14 +229,19 @@ bool client_authorize(YAAMP_CLIENT *client, json_value *json_params) } } + if (!is_base58(client->username)) { + clientlog(client, "bad mining address %s", client->username); + return false; + } + bool reset = client_initialize_multialgo(client); if(reset) return false; client_initialize_difficulty(client); -#ifdef CLIENT_DEBUGLOG_ - debuglog("new client %s, %s, %s\n", client->username, client->password, client->version); -#endif + if (g_debuglog_client) { + debuglog("new client %s, %s, %s\n", client->username, client->password, client->version); + } if(!client->userid || !client->workerid) { @@ -281,7 +291,7 @@ bool client_authorize(YAAMP_CLIENT *client, json_value *json_params) bool client_update_block(YAAMP_CLIENT *client, json_value *json_params) { // password, id, block hash - if(json_params->u.array.length < 3) + if(json_params->u.array.length < 3 || !json_params->u.array.values[0]->u.string.ptr) { clientlog(client, "update block, bad params"); return false; @@ -293,14 +303,18 @@ bool client_update_block(YAAMP_CLIENT *client, json_value *json_params) return false; } - YAAMP_COIND *coind = (YAAMP_COIND *)object_find(&g_list_coind, json_params->u.array.values[1]->u.integer, true); + int coinid = json_params->u.array.values[1]->u.integer; + if(!coinid) return false; + YAAMP_COIND *coind = (YAAMP_COIND *)object_find(&g_list_coind, coinid, true); if(!coind) return false; const char* hash = json_params->u.array.values[2]->u.string.ptr; -#ifdef CLIENT_DEBUGLOG_ - debuglog("notify: new %s block %s\n", coind->symbol, hash); -#endif + if (g_debuglog_client) { + debuglog("notify: new %s block %s\n", coind->symbol, hash); + } + + snprintf(coind->lastnotifyhash, 161, "%s", hash); coind->newblock = true; coind->notreportingcounter = 0; @@ -541,6 +555,10 @@ void *client_thread(void *p) client->id_int = json_get_int(json, "id"); client->id_str = json_get_string(json, "id"); + if (client->id_str && strlen(client->id_str) > 32) { + clientlog(client, "bad id"); + break; + } const char *method = json_get_string(json, "method"); @@ -567,9 +585,9 @@ void *client_thread(void *p) break; } -#ifdef CLIENT_DEBUGLOG_ - debuglog("client %s %d %s\n", method, client->id_int, client->id_str? client->id_str: "null"); -#endif + if (g_debuglog_client) { + debuglog("client %s %d %s\n", method, client->id_int, client->id_str? client->id_str: "null"); + } bool b = false; if(!strcmp(method, "mining.subscribe")) @@ -608,9 +626,7 @@ void *client_thread(void *p) else if(!strcmp(method, "getwork")) { clientlog(client, "using getwork"); // client using http:// url - break; } - else { b = client_send_error(client, 20, "Not supported"); @@ -625,10 +641,10 @@ void *client_thread(void *p) // source_close(client->source); -#ifdef CLIENT_DEBUGLOG_ - debuglog("client terminate\n"); -#endif - if(!client || client->deleted) { + if (g_debuglog_client) { + debuglog("client terminate\n"); + } + if(!client) { pthread_exit(NULL); } @@ -646,10 +662,13 @@ void *client_thread(void *p) db_clear_worker(g_db, client); CommonUnlock(&g_db_mutex); } + object_delete(client); + } else { + // only clients sockets in g_list_client are purged (if marked deleted) + socket_close(client->sock); + delete client; } - object_delete(client); - pthread_exit(NULL); } diff --git a/stratum/client_difficulty.cpp b/stratum/client_difficulty.cpp index 59ee751..e3d34cb 100644 --- a/stratum/client_difficulty.cpp +++ b/stratum/client_difficulty.cpp @@ -3,10 +3,10 @@ double client_normalize_difficulty(double difficulty) { - if(difficulty <= 0.001) difficulty = 0.001; + if(difficulty < g_stratum_min_diff) difficulty = g_stratum_min_diff; else if(difficulty < 1) difficulty = floor(difficulty*1000/2)/1000*2; else if(difficulty > 1) difficulty = floor(difficulty/2)*2; - + if(difficulty > g_stratum_max_diff) difficulty = g_stratum_max_diff; return difficulty; } @@ -48,13 +48,12 @@ void client_change_difficulty(YAAMP_CLIENT *client, double difficulty) void client_adjust_difficulty(YAAMP_CLIENT *client) { - if(client->difficulty_remote) - { + if(client->difficulty_remote) { client_change_difficulty(client, client->difficulty_remote); return; } - if(client->shares_per_minute > 600) + if(client->shares_per_minute > 100) client_change_difficulty(client, client->difficulty_actual*4); else if(client->difficulty_fixed) @@ -79,6 +78,7 @@ int client_send_difficulty(YAAMP_CLIENT *client, double difficulty) client_call(client, "mining.set_difficulty", "[%.0f]", difficulty); else client_call(client, "mining.set_difficulty", "[%.3f]", difficulty); + return 0; } void client_initialize_difficulty(YAAMP_CLIENT *client) diff --git a/stratum/client_submit.cpp b/stratum/client_submit.cpp index 993b726..055c349 100644 --- a/stratum/client_submit.cpp +++ b/stratum/client_submit.cpp @@ -4,7 +4,6 @@ uint64_t lyra2z_height = 0; //#define MERKLE_DEBUGLOG -//#define HASH_DEBUGLOG_ //#define DONTSUBMIT void build_submit_values(YAAMP_JOB_VALUES *submitvalues, YAAMP_JOB_TEMPLATE *templ, @@ -32,10 +31,14 @@ void build_submit_values(YAAMP_JOB_VALUES *submitvalues, YAAMP_JOB_TEMPLATE *tem #ifdef MERKLE_DEBUGLOG printf("merkle root %s\n", merkleroot.c_str()); #endif - if (!strcmp(g_current_algo->name, "lbry")) { + if (!strcmp(g_stratum_algo, "lbry")) { sprintf(submitvalues->header, "%s%s%s%s%s%s%s", templ->version, templ->prevhash_be, submitvalues->merkleroot_be, templ->claim_be, ntime, templ->nbits, nonce); - ser_string_be(submitvalues->header, submitvalues->header_be, 32 + 20); + ser_string_be(submitvalues->header, submitvalues->header_be, 112/4); + } else if (strlen(templ->extradata_be) == 128) { // LUX SC + sprintf(submitvalues->header, "%s%s%s%s%s%s%s", templ->version, templ->prevhash_be, submitvalues->merkleroot_be, + ntime, templ->nbits, nonce, templ->extradata_be); + ser_string_be(submitvalues->header, submitvalues->header_be, 36); // 80+64 / sizeof(u32) } else { sprintf(submitvalues->header, "%s%s%s%s%s%s", templ->version, templ->prevhash_be, submitvalues->merkleroot_be, ntime, templ->nbits, nonce); @@ -215,12 +218,18 @@ static void client_do_submit(YAAMP_CLIENT *client, YAAMP_JOB *job, YAAMP_JOB_VAL if(hash_int <= coin_target) { + char count_hex[8] = { 0 }; + if (templ->txcount <= 252) + sprintf(count_hex, "%02x", templ->txcount & 0xFF); + else + sprintf(count_hex, "fd%02x%02x", templ->txcount & 0xFF, templ->txcount >> 8); + memset(block_hex, 0, block_size); - sprintf(block_hex, "%s%02x%s", submitvalues->header_be, (unsigned char)templ->txcount, submitvalues->coinbase); + sprintf(block_hex, "%s%s%s", submitvalues->header_be, count_hex, submitvalues->coinbase); if (g_current_algo->name && !strcmp("jha", g_current_algo->name)) { // block header of 88 bytes - sprintf(block_hex, "%s8400000008000000%02x%s", submitvalues->header_be, (unsigned char)templ->txcount, submitvalues->coinbase); + sprintf(block_hex, "%s8400000008000000%s%s", submitvalues->header_be, count_hex, submitvalues->coinbase); } vector::const_iterator i; @@ -272,27 +281,29 @@ static void client_do_submit(YAAMP_CLIENT *client, YAAMP_JOB *job, YAAMP_JOB_VAL target_to_diff(coin_target), target_to_diff(hash_int), hash1, submitvalues->hash_be, templ->has_segwit_txs); - if(coind->noblocknotify) { - // DCR go wallet doesnt handle blocknotify= config (yet) - // required to store the user id and the user diff + if(!strcmp("DCR", coind->rpcencoding)) { + // delay between dcrd and dcrwallet sleep(1); + } + + if(!strcmp(coind->lastnotifyhash,submitvalues->hash_be)) { block_confirm(coind->id, submitvalues->hash_be); } -#ifdef HASH_DEBUGLOG_ - debuglog("--------------------------------------------------------------\n"); - debuglog("hash1 %s\n", hash1); - debuglog("hash2 %s\n", submitvalues->hash_be); -#endif + if (g_debuglog_hash) { + debuglog("--------------------------------------------------------------\n"); + debuglog("hash1 %s\n", hash1); + debuglog("hash2 %s\n", submitvalues->hash_be); + } } else { debuglog("*** REJECTED :( %s block %d %d txs\n", coind->name, templ->height, templ->txcount); rejectlog("REJECTED %s block %d\n", coind->symbol, templ->height); -#ifdef HASH_DEBUGLOG_ - //debuglog("block %s\n", block_hex); - debuglog("--------------------------------------------------------------\n"); -#endif + if (g_debuglog_hash) { + //debuglog("block %s\n", block_hex); + debuglog("--------------------------------------------------------------\n"); + } } } @@ -318,9 +329,9 @@ void client_submit_error(YAAMP_CLIENT *client, YAAMP_JOB *job, int id, const cha share_add(client, job, false, extranonce2, ntime, nonce, 0, id); client->submit_bad++; -#ifdef HASH_DEBUGLOG_ - dump_submit_debug(message, client, job, extranonce2, ntime, nonce); -#endif + if (g_debuglog_hash) { + dump_submit_debug(message, client, job, extranonce2, ntime, nonce); + } } object_unlock(job); @@ -332,33 +343,37 @@ static bool ntime_valid_range(const char ntimehex[]) uint32_t ntime = 0; if (strlen(ntimehex) != 8) return false; sscanf(ntimehex, "%8x", &ntime); - if (ntime < 0x57000000 || ntime > 0x60000000) // 14 Jan 2021 - ntime = bswap32(ntime); // just in case... + if (ntime < 0x5b000000 || ntime > 0x60000000) // 14 Jan 2021 + return false; time(&rawtime); - return ((rawtime - ntime) < (23 * 60 * 60)); + return (abs(rawtime - ntime) < (30 * 60)); +} + +static bool valid_string_params(json_value *json_params) +{ + for(int p=0; p < json_params->u.array.length; p++) { + if (!json_is_string(json_params->u.array.values[p])) + return false; + } + return true; } bool client_submit(YAAMP_CLIENT *client, json_value *json_params) { // submit(worker_name, jobid, extranonce2, ntime, nonce): - if(json_params->u.array.length<5) - { + if(json_params->u.array.length<5 || !valid_string_params(json_params)) { debuglog("%s - %s bad message\n", client->username, client->sock->ip); client->submit_bad++; return false; } - char extranonce2[32]; - char ntime[32]; - char nonce[32]; - char vote[8]; + char extranonce2[32] = { 0 }; + char extra[160] = { 0 }; + char nonce[80] = { 0 }; + char ntime[32] = { 0 }; + char vote[8] = { 0 }; - memset(extranonce2, 0, 32); - memset(ntime, 0, 32); - memset(nonce, 0, 32); - memset(vote, 0, 8); - - if (!json_params->u.array.values[1]->u.string.ptr || strlen(json_params->u.array.values[1]->u.string.ptr) > 32) { + if (strlen(json_params->u.array.values[1]->u.string.ptr) > 32) { clientlog(client, "bad json, wrong jobid len"); client->submit_bad++; return false; @@ -368,17 +383,27 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params) strncpy(extranonce2, json_params->u.array.values[2]->u.string.ptr, 31); strncpy(ntime, json_params->u.array.values[3]->u.string.ptr, 31); strncpy(nonce, json_params->u.array.values[4]->u.string.ptr, 31); - if (json_params->u.array.length == 6) - strncpy(vote, json_params->u.array.values[5]->u.string.ptr, 7); - -#ifdef HASH_DEBUGLOG_ - debuglog("submit %s (uid %d) %d, %s, %s, %s\n", client->sock->ip, client->userid, jobid, extranonce2, ntime, nonce); -#endif string_lower(extranonce2); string_lower(ntime); string_lower(nonce); - string_lower(vote); + + if (json_params->u.array.length == 6) { + if (strstr(g_stratum_algo, "phi")) { + // lux optional field, smart contral root hashes (not mandatory on shares submit) + strncpy(extra, json_params->u.array.values[5]->u.string.ptr, 128); + string_lower(extra); + } else { + // heavycoin vote + strncpy(vote, json_params->u.array.values[5]->u.string.ptr, 7); + string_lower(vote); + } + } + + if (g_debuglog_hash) { + debuglog("submit %s (uid %d) %d, %s, t=%s, n=%s, extra=%s\n", client->sock->ip, client->userid, + jobid, extranonce2, ntime, nonce, extra); + } YAAMP_JOB *job = (YAAMP_JOB *)object_find(&g_list_job, jobid, true); if(!job) @@ -399,15 +424,14 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params) YAAMP_JOB_TEMPLATE *templ = job->templ; - if(strlen(nonce) != YAAMP_NONCE_SIZE*2) - { + if(strlen(nonce) != YAAMP_NONCE_SIZE*2 || !ishexa(nonce, YAAMP_NONCE_SIZE*2)) { client_submit_error(client, job, 20, "Invalid nonce size", extranonce2, ntime, nonce); return true; } if(strcmp(ntime, templ->ntime)) { - if (!ntime_valid_range(ntime)) { + if (!ishexa(ntime, 8) || !ntime_valid_range(ntime)) { client_submit_error(client, job, 23, "Invalid time rolling", extranonce2, ntime, nonce); return true; } @@ -444,18 +468,20 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params) if (extranull) { debuglog("extranonce %s is empty!, should be %s - %s\n", extranonce2, extra1_id, client->sock->ip); client_submit_error(client, job, 27, "Invalid extranonce2 suffix", extranonce2, ntime, nonce); - client->submit_bad++; return true; } if (extradiff) { // some ccminer pre-release doesn't fill correctly the extranonce client_submit_error(client, job, 27, "Invalid extranonce2 suffix", extranonce2, ntime, nonce); - client->submit_bad++; socket_send(client->sock, "{\"id\":null,\"method\":\"mining.set_extranonce\",\"params\":[\"%s\",%d]}\n", client->extranonce1, client->extranonce2size); return true; } } + else if(!ishexa(extranonce2, client->extranonce2size*2)) { + client_submit_error(client, job, 27, "Invalid nonce2", extranonce2, ntime, nonce); + return true; + } /////////////////////////////////////////////////////////////////////////////////////////// @@ -474,11 +500,11 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params) // minimum hash diff begins with 0000, for all... uint8_t pfx = submitvalues.hash_bin[30] | submitvalues.hash_bin[31]; if(pfx) { -#ifdef HASH_DEBUGLOG_ - debuglog("Possible %s error, hash starts with %02x%02x%02x%02x\n", g_current_algo->name, - (int) submitvalues.hash_bin[31], (int) submitvalues.hash_bin[30], - (int) submitvalues.hash_bin[29], (int) submitvalues.hash_bin[28]); -#endif + if (g_debuglog_hash) { + debuglog("Possible %s error, hash starts with %02x%02x%02x%02x\n", g_current_algo->name, + (int) submitvalues.hash_bin[31], (int) submitvalues.hash_bin[30], + (int) submitvalues.hash_bin[29], (int) submitvalues.hash_bin[28]); + } client_submit_error(client, job, 25, "Invalid share", extranonce2, ntime, nonce); return true; } @@ -488,11 +514,11 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params) uint64_t coin_target = decode_compact(templ->nbits); if (templ->nbits && !coin_target) coin_target = 0xFFFF000000000000ULL; -#ifdef HASH_DEBUGLOG_ - debuglog("%016llx actual\n", hash_int); - debuglog("%016llx target\n", user_target); - debuglog("%016llx coin\n", coin_target); -#endif + if (g_debuglog_hash) { + debuglog("%016llx actual\n", hash_int); + debuglog("%016llx target\n", user_target); + debuglog("%016llx coin\n", coin_target); + } if(hash_int > user_target && hash_int > coin_target) { client_submit_error(client, job, 26, "Low difficulty share", extranonce2, ntime, nonce); @@ -518,12 +544,12 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params) // share_diff = share_diff / g_current_algo->diff_multiplier; // } -#ifndef HASH_DEBUGLOG_ - // only log a few... - if (share_diff > (client->difficulty_actual * 16)) - debuglog("submit %s (uid %d) %d, %s, %s, %s, %.3f/%.3f\n", client->sock->ip, client->userid, - jobid, extranonce2, ntime, nonce, share_diff, client->difficulty_actual); -#endif + if (g_debuglog_hash) { + // only log a few... + if (share_diff > (client->difficulty_actual * 16)) + debuglog("submit %s (uid %d) %d, %s, %s, %s, %.3f/%.3f\n", client->sock->ip, client->userid, + jobid, extranonce2, ntime, nonce, share_diff, client->difficulty_actual); + } share_add(client, job, true, extranonce2, ntime, nonce, share_diff, 0); object_unlock(job); diff --git a/stratum/coinbase.cpp b/stratum/coinbase.cpp index b37bca8..86b31eb 100644 --- a/stratum/coinbase.cpp +++ b/stratum/coinbase.cpp @@ -14,12 +14,30 @@ static void encode_tx_value(char *encoded, json_int_t value) TX_VALUE(value, 32), TX_VALUE(value, 40), TX_VALUE(value, 48), TX_VALUE(value, 56)); } +static void p2sh_pack_tx(YAAMP_COIND *coind, char *data, json_int_t amount, char *payee) +{ + char evalue[32]; + char coinb2_part[256]; + char coinb2_len[4]; + sprintf(coinb2_part, "a9%02x%s87", (unsigned int)(strlen(payee) >> 1) & 0xFF, payee); + sprintf(coinb2_len, "%02x", (unsigned int)(strlen(coinb2_part) >> 1) & 0xFF); + encode_tx_value(evalue, amount); + strcat(data, evalue); + strcat(data, coinb2_len); + strcat(data, coinb2_part); +} + static void job_pack_tx(YAAMP_COIND *coind, char *data, json_int_t amount, char *key) { int ol = strlen(data); char evalue[32]; - encode_tx_value(evalue, amount); + if(coind->p2sh_address && !key) { + p2sh_pack_tx(coind, data, amount, coind->script_pubkey); + return; + } + + encode_tx_value(evalue, amount); sprintf(data+strlen(data), "%s", evalue); if(coind->pos && !key) @@ -104,6 +122,69 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value * if (strlen(coind->charity_address) == 0) sprintf(coind->charity_address, "EdFwYw4Mo2Zq6CFM2yNJgXvE2DTJxgdBRX"); } + else if(strcmp(coind->symbol, "DYN") == 0) + { + char script_dests[2048] = { 0 }; + char script_payee[128] = { 0 }; + char payees[3]; + int npayees = (templ->has_segwit_txs) ? 2 : 1; + bool dynode_enabled; + dynode_enabled = json_get_bool(json_result, "dynode_payments_enforced"); + bool superblocks_enabled = json_get_bool(json_result, "superblocks_enabled"); + json_value* superblock = json_get_array(json_result, "superblock"); + json_value* dynode; + dynode = json_get_object(json_result, "dynode"); + if(!dynode && json_get_bool(json_result, "dynode_payments")) { + coind->oldmasternodes = true; + debuglog("%s is using old dynodes rpc keys\n", coind->symbol); + return; + } + + if(superblocks_enabled && superblock) { + for(int i = 0; i < superblock->u.array.length; i++) { + const char *payee = json_get_string(superblock->u.array.values[i], "payee"); + json_int_t amount = json_get_int(superblock->u.array.values[i], "amount"); + if (payee && amount) { + npayees++; + available -= amount; + base58_decode(payee, script_payee); + job_pack_tx(coind, script_dests, amount, script_payee); + //debuglog("%s superblock found %s %u\n", coind->symbol, payee, amount); + } + } + } + if (dynode_enabled && dynode) { + bool started; + started = json_get_bool(json_result, "dynode_payments_started"); + const char *payee = json_get_string(dynode, "payee"); + json_int_t amount = json_get_int(dynode, "amount"); + if (!payee) + debuglog("coinbase_create failed to get Dynode payee\n"); + + if (!amount) + debuglog("coinbase_create failed to get Dynode amount\n"); + + if (!started) + debuglog("coinbase_create failed to get Dynode started\n"); + + if (payee && amount && started) { + npayees++; + available -= amount; + base58_decode(payee, script_payee); + job_pack_tx(coind, script_dests, amount, script_payee); + //debuglog("%s dynode found %s %u\n", coind->symbol, payee, amount); + } + } + sprintf(payees, "%02x", npayees); + strcat(templ->coinb2, payees); + if (templ->has_segwit_txs) strcat(templ->coinb2, commitment); + strcat(templ->coinb2, script_dests); + job_pack_tx(coind, templ->coinb2, available, NULL); + strcat(templ->coinb2, "00000000"); // locktime + coind->reward = (double)available/100000000*coind->reward_mul; + //debuglog("%s %d dests %s\n", coind->symbol, npayees, script_dests); + return; + } else if(strcmp(coind->symbol, "LTCR") == 0) { if (coind->charity_percent <= 0) coind->charity_percent = 10; @@ -145,9 +226,155 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value * if (strlen(coind->charity_address) == 0 && !strcmp(coind->symbol, "DCR")) sprintf(coind->charity_address, "Dcur2mcGjmENx4DhNqDctW5wJCVyT3Qeqkx"); } + else if(strcmp(coind->symbol, "STAK") == 0) { + char script_payee[512] = { 0 }; + char payees[4]; + int npayees = (templ->has_segwit_txs) ? 2 : 1; + bool masternode_payments = json_get_bool(json_result, "masternode_payments"); + bool masternodes_enabled = json_get_bool(json_result, "enforce_masternode_payments"); + + if (masternodes_enabled && masternode_payments) { + const char *payee = json_get_string(json_result, "payee"); + json_int_t amount = json_get_int(json_result, "payee_amount"); + if (payee && amount) + ++npayees; + } + + //treasury 5% @ 10 STAK per block + json_int_t charity_amount = 50000000; + //testnet + //sprintf(coind->charity_address, "93ASJtDuVYVdKXemH9BrtSMscznvsp9stD"); + switch (templ->height % 4) { + case 0: sprintf(coind->charity_address, "3K3bPrW5h7DYEMp2RcXawTCXajcm4ZU9Zh"); + break; + case 1: sprintf(coind->charity_address, "33Ssxmn3ehVMgyxgegXhpLGSBpubPjLZQ6"); + break; + case 2: sprintf(coind->charity_address, "3HFPNAjesiBY5sSVUmuBFnMEGut69R49ca"); + break; + case 3: sprintf(coind->charity_address, "37jLjjfUXQU4bdqVzvpUXyzAqPQSmxyByi"); + break; + } + ++npayees; + available -= charity_amount; + base58_decode(coind->charity_address, script_payee); + sprintf(payees, "%02x", npayees); + strcat(templ->coinb2, payees); + if (templ->has_segwit_txs) strcat(templ->coinb2, commitment); + char echarity_amount[32]; + encode_tx_value(echarity_amount, charity_amount); + strcat(templ->coinb2, echarity_amount); + char coinb2_part[1024] = { 0 }; + char coinb2_len[3] = { 0 }; + sprintf(coinb2_part, "a9%02x%s87", (unsigned int)(strlen(script_payee) >> 1) & 0xFF, script_payee); + sprintf(coinb2_len, "%02x", (unsigned int)(strlen(coinb2_part) >> 1) & 0xFF); + strcat(templ->coinb2, coinb2_len); + strcat(templ->coinb2, coinb2_part); + if (masternodes_enabled && masternode_payments) { + //duplicated: revisit ++todo + const char *payee = json_get_string(json_result, "payee"); + json_int_t amount = json_get_int(json_result, "payee_amount"); + if (payee && amount) { + available -= amount; + base58_decode(payee, script_payee); + job_pack_tx(coind, templ->coinb2, amount, script_payee); + } + } + job_pack_tx(coind, templ->coinb2, available, NULL); + strcat(templ->coinb2, "00000000"); // locktime + + coind->reward = (double)available / 100000000 * coind->reward_mul; + return; + } + else if(strcmp(coind->symbol, "TUX") == 0) { + char script_payee[1024]; + char charity_payee[256] = { 0 }; + const char *payee = json_get_string(json_result, "donation_payee"); + if(payee != NULL){ + sprintf(coind->charity_address, "%s", payee); + } else { + sprintf(coind->charity_address, "%s", ""); + } + + if(strlen(coind->charity_address) > 0){ + char script_payee[1024]; + char charity_payee[256] = { 0 }; + sprintf(charity_payee, "%s", coind->charity_address); + if (strlen(charity_payee) == 0) + stratumlog("ERROR %s has no charity_address set!\n", coind->name); + + base58_decode(charity_payee, script_payee); + + json_int_t charity_amount = json_get_int(json_result, "donation_amount"); + coind->charity_amount = charity_amount; + + if (templ->has_segwit_txs) { + strcat(templ->coinb2, "03"); // 3 outputs (nulldata + fees + miner) + strcat(templ->coinb2, commitment); + } else { + strcat(templ->coinb2, "02"); + } + job_pack_tx(coind, templ->coinb2, available, NULL); + + char echarity_amount[32]; + encode_tx_value(echarity_amount, charity_amount); + strcat(templ->coinb2, echarity_amount); + char coinb2_part[1024] = { 0 }; + char coinb2_len[3] = { 0 }; + sprintf(coinb2_part, "a9%02x%s87", (unsigned int)(strlen(script_payee) >> 1) & 0xFF, script_payee); + sprintf(coinb2_len, "%02x", (unsigned int)(strlen(coinb2_part) >> 1) & 0xFF); + strcat(templ->coinb2, coinb2_len); + strcat(templ->coinb2, coinb2_part); + debuglog("pack tx %s\n", coinb2_part); + strcat(templ->coinb2, "00000000"); // locktime + + coind->reward = (double)available/100000000*coind->reward_mul; + //debuglog("INFO %s block available %f, charity %f miner %f\n", coind->symbol, + // (double) available/1e8, (double) charity_amount/1e8, coind->reward); + return; + } + } + + bool founder_enabled = json_get_bool(json_result, "founder_payments_started"); + json_value* founder = json_get_object(json_result, "founder"); + + if (!coind->hasmasternodes && founder_enabled && founder) { + char founder_payee[256] = { 0 }; + char founder_script[1024] = { 0}; + const char *payee = json_get_string(founder, "payee"); + bool founder_use_p2sh = (strcmp(coind->symbol, "PGN") == 0); + json_int_t amount = json_get_int(founder, "amount"); + if(payee && amount) { + if (payee) snprintf(founder_payee, 255, "%s", payee); + if (strlen(founder_payee) == 0) + stratumlog("ERROR %s has no charity_address set!\n", coind->name); + base58_decode(founder_payee, founder_script); + available -= amount; + + if (templ->has_segwit_txs) { + strcat(templ->coinb2, "03"); // 3 outputs (nulldata + fees + miner) + strcat(templ->coinb2, commitment); + } else { + strcat(templ->coinb2, "02"); + } + job_pack_tx(coind, templ->coinb2, available, NULL); + if(founder_use_p2sh) { + p2sh_pack_tx(coind, templ->coinb2, amount, founder_script); + } else { + job_pack_tx(coind, templ->coinb2, amount, founder_script); + } + strcat(templ->coinb2, "00000000"); // locktime + + coind->reward = (double)available/100000000*coind->reward_mul; + debuglog("%s founder address %s, amount %lld\n", coind->symbol,founder_payee, amount); + debuglog("%s founder script %s\n", coind->symbol,founder_script); + debuglog("%s scripts %s\n", coind->symbol, templ->coinb2); + + return; + } + } // 2 txs are required on these coins, one for foundation (dev fees) - if(coind->charity_percent) + if(coind->charity_percent && !coind->hasmasternodes) { char script_payee[1024]; char charity_payee[256] = { 0 }; @@ -159,7 +386,10 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value * base58_decode(charity_payee, script_payee); - json_int_t charity_amount = (available * coind->charity_percent) / 100; + json_int_t charity_amount = json_get_int(json_result, "payee_amount"); + if (charity_amount <= 0) + charity_amount = (available * coind->charity_percent) / 100; + available -= charity_amount; coind->charity_amount = charity_amount; @@ -174,6 +404,8 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value * strcat(templ->coinb2, "00000000"); // locktime coind->reward = (double)available/100000000*coind->reward_mul; + //debuglog("INFO %s block available %f, charity %f miner %f\n", coind->symbol, + // (double) available/1e8, (double) charity_amount/1e8, coind->reward); return; } @@ -213,24 +445,42 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value * } } - if(strcmp(coind->symbol, "SIB") == 0 || - strcmp(coind->symbol, "MUE") == 0 || // MUEcore-x11 - strcmp(coind->symbol, "VIVO") == 0 || // VIVO coin - strcmp(coind->symbol, "INN") == 0 || // Innova coin - strcmp(coind->symbol, "DSR") == 0 || // Desire coin - strcmp(coind->symbol, "ONEX") == 0 || // ONEX Cash - strcmp(coind->symbol, "GBX") == 0 || // GoByte - strcmp(coind->symbol, "KZC") == 0 || // KZ Cash - strcmp(coind->symbol, "DASH") == 0 || strcmp(coind->symbol, "DASH-TESTNET") == 0) // Dash 12.1 + // most recent masternodes rpc (DASH, SIB, MUE, DSR, GBX...) + if(coind->hasmasternodes && !coind->oldmasternodes) { char script_dests[2048] = { 0 }; char script_payee[128] = { 0 }; char payees[4]; // addresses count - int npayees = 1; + int npayees = (templ->has_segwit_txs) ? 2 : 1; bool masternode_enabled = json_get_bool(json_result, "masternode_payments_enforced"); bool superblocks_enabled = json_get_bool(json_result, "superblocks_enabled"); json_value* superblock = json_get_array(json_result, "superblock"); json_value* masternode = json_get_object(json_result, "masternode"); + if(!masternode && json_get_bool(json_result, "masternode_payments")) { + coind->oldmasternodes = true; + debuglog("%s is using old masternodes rpc keys\n", coind->symbol); + return; + } + if(coind->charity_percent) { + char charity_payee[256] = { 0 }; + const char *payee = json_get_string(json_result, "payee"); + if (payee) snprintf(charity_payee, 255, "%s", payee); + else sprintf(charity_payee, "%s", coind->charity_address); + if (strlen(charity_payee) == 0) + stratumlog("ERROR %s has no charity_address set!\n", coind->name); + json_int_t charity_amount = (available * coind->charity_percent) / 100; + npayees++; + available -= charity_amount; + coind->charity_amount = charity_amount; + base58_decode(charity_payee, script_payee); + job_pack_tx(coind, script_dests, charity_amount, script_payee); + } + // smart contracts balance refund, same format as DASH superblocks + json_value* screfund = json_get_array(json_result, "screfund"); + if(screfund && screfund->u.array.length) { + superblocks_enabled = true; + superblock = screfund; + } if(superblocks_enabled && superblock) { for(int i = 0; i < superblock->u.array.length; i++) { const char *payee = json_get_string(superblock->u.array.values[i], "payee"); @@ -239,27 +489,38 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value * npayees++; available -= amount; base58_decode(payee, script_payee); - job_pack_tx(coind, script_dests, amount, script_payee); + bool superblock_use_p2sh = (strcmp(coind->symbol, "MAC") == 0); + if(superblock_use_p2sh) + p2sh_pack_tx(coind, script_dests, amount, script_payee); + else + job_pack_tx(coind, script_dests, amount, script_payee); //debuglog("%s superblock %s %u\n", coind->symbol, payee, amount); } } } if (masternode_enabled && masternode) { + bool started = json_get_bool(json_result, "masternode_payments_started"); const char *payee = json_get_string(masternode, "payee"); json_int_t amount = json_get_int(masternode, "amount"); - if (payee && amount) { + if (payee && amount && started) { npayees++; available -= amount; base58_decode(payee, script_payee); - job_pack_tx(coind, script_dests, amount, script_payee); + bool masternode_use_p2sh = (strcmp(coind->symbol, "MAC") == 0); + if(masternode_use_p2sh) + p2sh_pack_tx(coind, script_dests, amount, script_payee); + else + job_pack_tx(coind, script_dests, amount, script_payee); } } sprintf(payees, "%02x", npayees); strcat(templ->coinb2, payees); + if (templ->has_segwit_txs) strcat(templ->coinb2, commitment); strcat(templ->coinb2, script_dests); job_pack_tx(coind, templ->coinb2, available, NULL); strcat(templ->coinb2, "00000000"); // locktime coind->reward = (double)available/100000000*coind->reward_mul; + //debuglog("%s total %u available %u\n", coind->symbol, templ->value, available); //debuglog("%s %d dests %s\n", coind->symbol, npayees, script_dests); return; } @@ -351,7 +612,7 @@ void coinbase_create(YAAMP_COIND *coind, YAAMP_JOB_TEMPLATE *templ, json_value * } - else if(coind->hasmasternodes) /* OLD DASH style */ + else if(coind->hasmasternodes && coind->oldmasternodes) /* OLD DASH style */ { char charity_payee[256] = { 0 }; const char *payee = json_get_string(json_result, "payee"); diff --git a/stratum/coind.cpp b/stratum/coind.cpp index 8e33540..1eb83a3 100644 --- a/stratum/coind.cpp +++ b/stratum/coind.cpp @@ -98,7 +98,7 @@ bool coind_validate_user_address(YAAMP_COIND *coind, char* const address) } bool isvalid = json_get_bool(json_result, "isvalid"); - if(!isvalid) stratumlog("%s user address %s is not valid.\n", coind->name, address); + if(!isvalid) stratumlog("%s: %s user address %s is not valid.\n", g_stratum_algo, coind->symbol, address); json_value_free(json); @@ -114,7 +114,12 @@ bool coind_validate_address(YAAMP_COIND *coind) char params[YAAMP_SMALLBUFSIZE]; sprintf(params, "[\"%s\"]", coind->wallet); - json_value *json = rpc_call(&coind->rpc, "validateaddress", params); + json_value *json; + bool getaddressinfo = ((strcmp(coind->symbol,"DGB") == 0) || (strcmp(coind->symbol2, "DGB") == 0)); + if(getaddressinfo) + json = rpc_call(&coind->rpc, "getaddressinfo", params); + else + json = rpc_call(&coind->rpc, "validateaddress", params); if(!json) return false; json_value *json_result = json_get_object(json, "result"); @@ -124,11 +129,12 @@ bool coind_validate_address(YAAMP_COIND *coind) return false; } - bool isvalid = json_get_bool(json_result, "isvalid"); + bool isvalid = getaddressinfo || json_get_bool(json_result, "isvalid"); if(!isvalid) stratumlog("%s wallet %s is not valid.\n", coind->name, coind->wallet); bool ismine = json_get_bool(json_result, "ismine"); if(!ismine) stratumlog("%s wallet %s is not mine.\n", coind->name, coind->wallet); + else isvalid = ismine; const char *p = json_get_string(json_result, "pubkey"); strcpy(coind->pubkey, p ? p : ""); @@ -139,6 +145,8 @@ bool coind_validate_address(YAAMP_COIND *coind) if (!base58_decode(coind->wallet, coind->script_pubkey)) stratumlog("Warning: unable to decode %s %s script pubkey\n", coind->symbol, coind->wallet); + coind->p2sh_address = json_get_bool(json_result, "isscript"); + // if base58 decode fails if (!strlen(coind->script_pubkey)) { const char *pk = json_get_string(json_result, "scriptPubKey"); @@ -165,7 +173,6 @@ void coind_init(YAAMP_COIND *coind) strcpy(account, coind->account); if(!strcmp(coind->rpcencoding, "DCR")) { coind->usegetwork = true; - //coind->noblocknotify = true; //sprintf(account, "default"); } @@ -247,8 +254,6 @@ void coind_terminate(YAAMP_COIND *coind) // CommonLock(&coind->mutex); // while(!coind->deleted) // { -// debuglog("calling coind_getinfo %s\n", coind->symbol); - // job_create_last(coind, true); // pthread_cond_wait(&coind->cond, &coind->mutex); // } diff --git a/stratum/coind.h b/stratum/coind.h index aae8eb3..f58f091 100644 --- a/stratum/coind.h +++ b/stratum/coind.h @@ -35,6 +35,7 @@ public: char pubkey[1024]; char script_pubkey[1024]; + bool p2sh_address; bool pos; bool hassubmitblock; @@ -47,6 +48,7 @@ public: bool enable; bool auto_ready; bool newblock; + char lastnotifyhash[192]; int height; double difficulty; @@ -65,7 +67,7 @@ public: bool usegetwork; bool usememorypool; bool hasmasternodes; - bool noblocknotify; + bool oldmasternodes; bool multialgos; // pow_hash field (or mined_hash) bool usesegwit; diff --git a/stratum/coind_submit.cpp b/stratum/coind_submit.cpp index f1f8b6f..6089494 100644 --- a/stratum/coind_submit.cpp +++ b/stratum/coind_submit.cpp @@ -140,6 +140,9 @@ bool coind_submitgetauxblock(YAAMP_COIND *coind, const char *hash, const char *b json_value *json_result = json_get_object(json, "result"); bool b = json_result && json_result->type == json_boolean && json_result->u.boolean; + // some auxpow coins return error:null, result: null on success + if(!b) + b=json_result && json_result->type == json_null; json_value_free(json); return b; diff --git a/stratum/coind_template.cpp b/stratum/coind_template.cpp index 82bd4f6..33ecc62 100644 --- a/stratum/coind_template.cpp +++ b/stratum/coind_template.cpp @@ -68,17 +68,17 @@ YAAMP_JOB_TEMPLATE *coind_create_template_memorypool(YAAMP_COIND *coind) json_value_free(json); - json = rpc_call(&coind->rpc, "getinfo", "[]"); + json = rpc_call(&coind->rpc, "getmininginfo", "[]"); if(!json || json->type == json_null) { - coind_error(coind, "coind_getinfo"); + coind_error(coind, "coind getmininginfo"); return NULL; } json_result = json_get_object(json, "result"); if(!json_result || json_result->type == json_null) { - coind_error(coind, "coind_getinfo"); + coind_error(coind, "coind getmininginfo"); json_value_free(json); return NULL; @@ -333,6 +333,18 @@ YAAMP_JOB_TEMPLATE *coind_create_template(YAAMP_COIND *coind) } } + const char *sc_root = json_get_string(json_result, "stateroot"); + const char *sc_utxo = json_get_string(json_result, "utxoroot"); + if (sc_root && sc_utxo) { + // LUX Smart Contracts, 144-bytes block headers + strcpy(&templ->extradata_hex[ 0], sc_root); // 32-bytes hash (64 in hexa) + strcpy(&templ->extradata_hex[64], sc_utxo); // 32-bytes hash too + + // same weird byte order as previousblockhash field + ser_string_be2(sc_root, &templ->extradata_be[ 0], 8); + ser_string_be2(sc_utxo, &templ->extradata_be[64], 8); + } + if (strcmp(coind->rpcencoding, "DCR") == 0) { decred_fix_template(coind, templ, json_result); } @@ -381,12 +393,20 @@ YAAMP_JOB_TEMPLATE *coind_create_template(YAAMP_COIND *coind) txids.push_back(""); templ->has_segwit_txs = false; - // to force/test - // templ->has_segwit_txs = coind->usesegwit = (coind->usesegwit || g_stratum_segwit); + + templ->has_filtered_txs = false; + templ->filtered_txs_fee = 0; + for(int i = 0; i < json_tx->u.array.length; i++) { const char *p = json_get_string(json_tx->u.array.values[i], "hash"); char hash_be[256] = { 0 }; + + if (templ->has_filtered_txs) { + templ->filtered_txs_fee += json_get_int(json_tx->u.array.values[i], "fee"); + continue; + } + string_be(p, hash_be); txhashes.push_back(hash_be); @@ -396,7 +416,6 @@ YAAMP_JOB_TEMPLATE *coind_create_template(YAAMP_COIND *coind) string_be(txid, txid_be); txids.push_back(txid_be); if (strcmp(hash_be, txid_be)) { - //debuglog("%s segwit tx found, height %d\n", coind->symbol, templ->height); templ->has_segwit_txs = true; // if not, its useless to generate a segwit block, bigger } } else { @@ -405,6 +424,17 @@ YAAMP_JOB_TEMPLATE *coind_create_template(YAAMP_COIND *coind) const char *d = json_get_string(json_tx->u.array.values[i], "data"); templ->txdata.push_back(d); + + // if wanted, we can limit the count of txs to include + if (g_limit_txs_per_block && i >= g_limit_txs_per_block-2) { + debuglog("limiting block to %d first txs (of %d)\n", g_limit_txs_per_block, json_tx->u.array.length); + templ->has_filtered_txs = true; + } + } + + if (templ->has_filtered_txs) { + // coinbasevalue is a total with all tx fees, need to reduce it if some are skipped + templ->value -= templ->filtered_txs_fee; } templ->txmerkles[0] = '\0'; diff --git a/stratum/config.sample/a5a.conf b/stratum/config.sample/a5a.conf new file mode 100644 index 0000000..25bdc96 --- /dev/null +++ b/stratum/config.sample/a5a.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 8633 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = a5a +difficulty = 8 +max_ttf = 4000000 diff --git a/stratum/config.sample/aergo.conf b/stratum/config.sample/aergo.conf new file mode 100644 index 0000000..c7488e3 --- /dev/null +++ b/stratum/config.sample/aergo.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 3691 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = aergo +difficulty = 0.001 +max_ttf = 400000000 \ No newline at end of file diff --git a/stratum/config.sample/allium.conf b/stratum/config.sample/allium.conf new file mode 100644 index 0000000..1f8f192 --- /dev/null +++ b/stratum/config.sample/allium.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 4443 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = allium +difficulty = 1 +max_ttf = 4000000 diff --git a/stratum/config.sample/argon2d-dyn.conf b/stratum/config.sample/argon2d-dyn.conf new file mode 100644 index 0000000..fc53112 --- /dev/null +++ b/stratum/config.sample/argon2d-dyn.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 4239 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = argon2d-dyn +difficulty = 2.0 +max_ttf = 400000000 \ No newline at end of file diff --git a/stratum/config.sample/blake2b.conf b/stratum/config.sample/blake2b.conf new file mode 100644 index 0000000..91a8e04 --- /dev/null +++ b/stratum/config.sample/blake2b.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 5777 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = blake2b +difficulty = 0.25 +max_ttf = 4000000 + diff --git a/stratum/config.sample/exosis.conf b/stratum/config.sample/exosis.conf new file mode 100644 index 0000000..3d54269 --- /dev/null +++ b/stratum/config.sample/exosis.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 3557 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = exosis +difficulty = 0.125 +max_ttf = 50000 diff --git a/stratum/config.sample/keccakc.conf b/stratum/config.sample/keccakc.conf new file mode 100644 index 0000000..0be446a --- /dev/null +++ b/stratum/config.sample/keccakc.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 5134 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = keccakc +difficulty = 2 +max_ttf = 4000000 + diff --git a/stratum/config.sample/lbk3.conf b/stratum/config.sample/lbk3.conf new file mode 100644 index 0000000..4e82314 --- /dev/null +++ b/stratum/config.sample/lbk3.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 5522 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = lbk3 +difficulty = 8 +max_ttf = 40000 diff --git a/stratum/config.sample/lyra2.conf b/stratum/config.sample/lyra2.conf index d2f7361..0faa798 100644 --- a/stratum/config.sample/lyra2.conf +++ b/stratum/config.sample/lyra2.conf @@ -1,6 +1,6 @@ [TCP] server = yaamp.com -port = 4433 +port = 4432 password = tu8tu5 [SQL] diff --git a/stratum/config.sample/lyra2v3.conf b/stratum/config.sample/lyra2v3.conf new file mode 100644 index 0000000..04c9dad --- /dev/null +++ b/stratum/config.sample/lyra2v3.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 4433 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = lyra2v3 +difficulty = 1 +max_ttf = 40000 + diff --git a/stratum/config.sample/lyra2zz.conf b/stratum/config.sample/lyra2zz.conf new file mode 100644 index 0000000..85cd1a4 --- /dev/null +++ b/stratum/config.sample/lyra2zz.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 4555 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = lyra2zz +difficulty = 1 +max_ttf = 40000 diff --git a/stratum/config.sample/phi2.conf b/stratum/config.sample/phi2.conf new file mode 100644 index 0000000..f961112 --- /dev/null +++ b/stratum/config.sample/phi2.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 8332 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = phi2 +difficulty = 1 +max_ttf = 40000 + diff --git a/stratum/config.sample/rainforest.conf b/stratum/config.sample/rainforest.conf new file mode 100644 index 0000000..37455e7 --- /dev/null +++ b/stratum/config.sample/rainforest.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 7443 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = rainforest +difficulty = 1 +max_ttf = 400000000 diff --git a/stratum/config.sample/sha256q.conf b/stratum/config.sample/sha256q.conf new file mode 100644 index 0000000..8b4c0d1 --- /dev/null +++ b/stratum/config.sample/sha256q.conf @@ -0,0 +1,17 @@ +[TCP] +server = yaamp.com +port = 3337 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = sha256q +difficulty = 1 +max_ttf = 40000 +reconnect = 1 + diff --git a/stratum/config.sample/skein.conf b/stratum/config.sample/skein.conf index f4957e5..b6d7536 100644 --- a/stratum/config.sample/skein.conf +++ b/stratum/config.sample/skein.conf @@ -14,3 +14,11 @@ algo = skein difficulty = 0.1 max_ttf = 200000000000000 +[DEBUGLOG] +client = 0 +hash = 0 +socket = 0 +rpc = 0 +list = 0 +remote = 0 + diff --git a/stratum/config.sample/vitalium.conf b/stratum/config.sample/vitalium.conf new file mode 100644 index 0000000..ff522cb --- /dev/null +++ b/stratum/config.sample/vitalium.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 3233 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = vitalium +difficulty = 0.001 +max_ttf = 400000000 + diff --git a/stratum/config.sample/x12.conf b/stratum/config.sample/x12.conf new file mode 100644 index 0000000..6bce44a --- /dev/null +++ b/stratum/config.sample/x12.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 3233 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = x12 +difficulty = 0.008 +max_ttf = 50000 + diff --git a/stratum/config.sample/x16r.conf b/stratum/config.sample/x16r.conf new file mode 100644 index 0000000..a2329a8 --- /dev/null +++ b/stratum/config.sample/x16r.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 3636 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = x16r +difficulty = 0.25 +max_ttf = 50000 + diff --git a/stratum/config.sample/x16rv2.conf b/stratum/config.sample/x16rv2.conf new file mode 100644 index 0000000..2779358 --- /dev/null +++ b/stratum/config.sample/x16rv2.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 3637 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = x16rv2 +difficulty = 0.25 +max_ttf = 50000 diff --git a/stratum/config.sample/x16s.conf b/stratum/config.sample/x16s.conf new file mode 100644 index 0000000..d71d25e --- /dev/null +++ b/stratum/config.sample/x16s.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 3663 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = x16s +difficulty = 0.25 +max_ttf = 50000 + diff --git a/stratum/config.sample/x22i.conf b/stratum/config.sample/x22i.conf new file mode 100644 index 0000000..156b2fb --- /dev/null +++ b/stratum/config.sample/x22i.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 3223 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = x22i +difficulty = 0.008 +max_ttf = 50000 + diff --git a/stratum/config.sample/yescryptR16.conf b/stratum/config.sample/yescryptR16.conf new file mode 100644 index 0000000..7c24aed --- /dev/null +++ b/stratum/config.sample/yescryptR16.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 6333 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = yescryptR16 +difficulty = 2 +max_ttf = 400000000 diff --git a/stratum/config.sample/yescryptR32.conf b/stratum/config.sample/yescryptR32.conf new file mode 100644 index 0000000..7494625 --- /dev/null +++ b/stratum/config.sample/yescryptR32.conf @@ -0,0 +1,15 @@ +[TCP] +server = yaamp.com +port = 6343 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = yescryptR32 +difficulty = 1 +max_ttf = 400000000 diff --git a/stratum/db.cpp b/stratum/db.cpp index 765a7dc..55cb062 100644 --- a/stratum/db.cpp +++ b/stratum/db.cpp @@ -1,5 +1,6 @@ #include "stratum.h" +#include #include void db_reconnect(YAAMP_DB *db) @@ -12,7 +13,7 @@ void db_reconnect(YAAMP_DB *db) mysql_init(&db->mysql); for(int i=0; i<6; i++) { - MYSQL *p = mysql_real_connect(&db->mysql, g_sql_host, g_sql_username, g_sql_password, g_sql_database, 0, 0, 0); + MYSQL *p = mysql_real_connect(&db->mysql, g_sql_host, g_sql_username, g_sql_password, g_sql_database, g_sql_port, 0, 0); if(p) break; stratumlog("%d, %s\n", i, mysql_error(&db->mysql)); @@ -42,15 +43,31 @@ void db_close(YAAMP_DB *db) char *db_clean_string(YAAMP_DB *db, char *string) { - string[1000] = 0; - char tmp[1024]; - - unsigned long ret = mysql_real_escape_string(&db->mysql, tmp, string, strlen(string)); - strcpy(string, tmp); - + char *c = string; + size_t i, len = strlen(string) & 0x1FF; + for (i = 0; i < len; i++) { + bool isdigit = (c[i] >= '0' && c[i] <= '9'); + bool isalpha = (c[i] >= 'a' && c[i] <= 'z') || (c[i] >= 'A' && c[i] <= 'Z'); + bool issepch = (c[i] == '=' || c[i] == ',' || c[i] == ';' || c[i] == '.'); + bool isextra = (c[i] == '/' || c[i] == '-' || c[i] == '_'); + if (!isdigit && !isalpha && !issepch && !isextra) { c[i] = '\0'; break; } + } return string; } +// allow more chars without the most hurting ones (bench device names) +static void clean_html(char* string) +{ + char *c = string; + size_t i, len = strlen(string) & 0x1FF; + for (i = 0; i < len; i++) { + if (c[i] == '<' || c[i] == '>' || c[i] == '%' || c[i] == '\\' || c[i] == '"' || c[i] == '\'') { + c[i] = '\0'; break; + } + } + if (strstr(string, "script")) strcpy(string, ""); +} + void db_query(YAAMP_DB *db, const char *format, ...) { va_list arglist; @@ -70,6 +87,7 @@ void db_query(YAAMP_DB *db, const char *format, ...) res = mysql_errno(&db->mysql); stratumlog("SQL ERROR: %d, %s\n", res, mysql_error(&db->mysql)); + if(res == ER_DUP_ENTRY) break; // rarely seen on new user creation if(res != CR_SERVER_GONE_ERROR && res != CR_SERVER_LOST) exit(1); usleep(100*YAAMP_MS); @@ -87,17 +105,17 @@ void db_register_stratum(YAAMP_DB *db) int t = time(NULL); if(!db) return; - db_query(db, "INSERT INTO stratums (pid, time, started, algo, port) VALUES (%d, %d, %d, '%s', %d) " - " ON DUPLICATE KEY UPDATE time=%d, algo='%s', port=%d", - pid, t, t, g_stratum_algo, g_tcp_port, - t, g_stratum_algo, g_tcp_port + db_query(db, "INSERT INTO stratums (pid, time, started, algo, url, port) VALUES (%d,%d,%d,'%s','%s',%d) " + " ON DUPLICATE KEY UPDATE time=%d, algo='%s', url='%s', port=%d", + pid, t, t, g_stratum_algo, g_tcp_server, g_tcp_port, + t, g_stratum_algo, g_tcp_server, g_tcp_port ); } void db_update_algos(YAAMP_DB *db) { int pid = getpid(); - //int fds = 0; // todo, sample: ls -l /proc/$PID/fd | grep socket | grep -c . + int fds = opened_files(); if(!db) return; if(g_current_algo->overflow) @@ -117,7 +135,8 @@ void db_update_algos(YAAMP_DB *db) } } - db_query(db, "UPDATE stratums SET workers=%d, symbol=%s WHERE pid=%d", g_list_client.count, symbol, pid); + db_query(db, "UPDATE stratums SET workers=%d, fds=%d, symbol=%s WHERE pid=%d", + g_list_client.count, fds, symbol, pid); /////////////////////////////////////////////////////////////////////////////////////////// @@ -200,6 +219,17 @@ void db_update_coinds(YAAMP_DB *db) coind->newcoind = false; strcpy(coind->name, row[1]); + strcpy(coind->symbol, row[20]); + // optional coin filters + if(coind->newcoind) { + bool ignore = false; + if (strlen(g_stratum_coin_include) && !strstr(g_stratum_coin_include, coind->symbol)) ignore = true; + if (strlen(g_stratum_coin_exclude) && strstr(g_stratum_coin_exclude, coind->symbol)) ignore = true; + if (ignore) { + object_delete(coind); + continue; + } + } if(row[7]) strcpy(coind->wallet, row[7]); if(row[6]) strcpy(coind->rpcencoding, row[6]); @@ -252,7 +282,6 @@ void db_update_coinds(YAAMP_DB *db) if(row[18]) coind->charity_percent = atof(row[18]); if(row[19]) coind->reward_mul = atof(row[19]); - strcpy(coind->symbol, row[20]); if(row[21]) coind->isaux = atoi(row[21]); if(row[22] && row[23]) coind->actual_ttf = min(atoi(row[22]), atoi(row[23])); @@ -282,20 +311,30 @@ void db_update_coinds(YAAMP_DB *db) if(!strcmp(coind->symbol, "DCR") && strcmp(coind->rpcencoding, "DCR")) strcpy(coind->rpcencoding, "DCR"); + // old dash masternodes coins.. + if(coind->hasmasternodes) { + if (strcmp(coind->symbol, "ALQO") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "BSD") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "BWK") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "CHC") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "CRW") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "DNR") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "FLAX") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "ITZ") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "J") == 0 || strcmp(coind->symbol2, "J") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "LAX") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "MAG") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "PBS") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "URALS") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "VSX") == 0) coind->oldmasternodes = true; + if (strcmp(coind->symbol, "XLR") == 0) coind->oldmasternodes = true; + } + //////////////////////////////////////////////////////////////////////////////////////////////////// //coind->touch = true; if(coind->newcoind) { - // optional coin filter - bool ignore = false; - if (strlen(g_stratum_coin_include) && !strstr(g_stratum_coin_include, coind->symbol)) ignore = true; - if (strlen(g_stratum_coin_exclude) && strstr(g_stratum_coin_exclude, coind->symbol)) ignore = true; - if (ignore) { - object_delete(coind); - continue; - } - debuglog("connecting to coind %s\n", coind->symbol); bool b = rpc_connect(&coind->rpc); @@ -507,9 +546,14 @@ static void _json_str_safe(YAAMP_DB *db, json_value *json, const char *key, size json_value *val = json_get_val(json, key); out[0] = '\0'; if (db && val && json_is_string(val)) { - strncpy(out, json_string_value(val), maxlen); + char str[128] = { 0 }; + char escaped[256] = { 0 }; + snprintf(str, sizeof(str)-1, "%s", json_string_value(val)); + str[maxlen-1] = '\0'; // truncate to dest len + clean_html(str); + mysql_real_escape_string(&db->mysql, escaped, str, strlen(str)); + snprintf(out, maxlen, "%s", escaped); out[maxlen-1] = '\0'; - db_clean_string(db, out); } } #define json_str_safe(stats, k, out) _json_str_safe(db, stats, k, sizeof(out), out) diff --git a/stratum/job.h b/stratum/job.h index f876fd7..aef4bdb 100644 --- a/stratum/job.h +++ b/stratum/job.h @@ -24,9 +24,13 @@ struct YAAMP_JOB_TEMPLATE int created; char flags[64]; - char prevhash_hex[1024]; - char prevhash_be[1024]; + char prevhash_hex[512]; + char prevhash_be[512]; + char extradata_hex[512]; + char extradata_be[512]; + + // todo: can use extra field char claim_hex[128]; char claim_be[128]; @@ -52,6 +56,9 @@ struct YAAMP_JOB_TEMPLATE bool has_segwit_txs; + bool has_filtered_txs; + int filtered_txs_fee; + int auxs_size; YAAMP_COIND_AUX *auxs[MAX_AUXS]; }; diff --git a/stratum/job_send.cpp b/stratum/job_send.cpp index d1d8567..5af3c72 100644 --- a/stratum/job_send.cpp +++ b/stratum/job_send.cpp @@ -16,14 +16,22 @@ static void job_mining_notify_buffer(YAAMP_JOB *job, char *buffer) { YAAMP_JOB_TEMPLATE *templ = job->templ; - if (!strcmp(g_current_algo->name, "lbry")) { + if (!strcmp(g_stratum_algo, "lbry")) { sprintf(buffer, "{\"id\":null,\"method\":\"mining.notify\",\"params\":[" "\"%x\",\"%s\",\"%s\",\"%s\",\"%s\",[%s],\"%s\",\"%s\",\"%s\",true]}\n", job->id, templ->prevhash_be, templ->claim_be, templ->coinb1, templ->coinb2, templ->txmerkles, templ->version, templ->nbits, templ->ntime); return; + } else if (strlen(templ->extradata_hex) == 128) { + // LUX smart contract state hashes (like lbry extra field, here the 2 root hashes in one) + sprintf(buffer, "{\"id\":null,\"method\":\"mining.notify\",\"params\":[" + "\"%x\",\"%s\",\"%s\",\"%s\",\"%s\",[%s],\"%s\",\"%s\",\"%s\",true]}\n", + job->id, templ->prevhash_be, templ->extradata_be, templ->coinb1, templ->coinb2, + templ->txmerkles, templ->version, templ->nbits, templ->ntime); + return; } + // standard stratum sprintf(buffer, "{\"id\":null,\"method\":\"mining.notify\",\"params\":[\"%x\",\"%s\",\"%s\",\"%s\",[%s],\"%s\",\"%s\",\"%s\",true]}\n", job->id, templ->prevhash_be, templ->coinb1, templ->coinb2, templ->txmerkles, templ->version, templ->nbits, templ->ntime); } @@ -107,6 +115,7 @@ void job_broadcast(YAAMP_JOB *job) { YAAMP_CLIENT *client = (YAAMP_CLIENT *)li->data; if(client->deleted) continue; + if(!client->sock) continue; // if(client->reconnecting && client->locked) continue; if(client->jobid_next != job->id) continue; diff --git a/stratum/json.cpp b/stratum/json.cpp index ca70ef7..3ceba40 100644 --- a/stratum/json.cpp +++ b/stratum/json.cpp @@ -503,7 +503,7 @@ json_value * json_parse_ex (json_settings * settings, case ']': - if (top->type == json_array) + if (top && top->type == json_array) flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next; else { sprintf (error, "%d:%d: Unexpected ]", cur_line, e_off); diff --git a/stratum/list.cpp b/stratum/list.cpp index 2942f43..ea18d7f 100644 --- a/stratum/list.cpp +++ b/stratum/list.cpp @@ -5,21 +5,21 @@ void CommonLock(pthread_mutex_t *mutex) { -#ifdef _LIST_DEBUG_ - int i=0; - for(; i<10; i++) - { - int res = pthread_mutex_trylock(mutex); - if(res == 0) break; + if (g_debuglog_list) { + int i=0; + for(; i<10; i++) + { + int res = pthread_mutex_trylock(mutex); + if(res == 0) break; - usleep(100*YAAMP_MS); + usleep(100*YAAMP_MS); + } + + if(i == 10) + debuglog("failed mutex2 %x <<----------------\n", mutex); + } else { + pthread_mutex_lock(mutex); } - - if(i == 10) - debuglog("failed mutex2 %x <<----------------\n", mutex); -#else - pthread_mutex_lock(mutex); -#endif } void CommonUnlock(pthread_mutex_t *mutex) @@ -43,21 +43,21 @@ CommonList::~CommonList() void CommonList::Enter() { -#ifdef _LIST_DEBUG_ - int i=0; - for(; i<10; i++) - { - int res = pthread_mutex_trylock(&mutex); - if(res == 0) break; + if (g_debuglog_list) { + int i=0; + for(; i<10; i++) + { + int res = pthread_mutex_trylock(&mutex); + if(res == 0) break; - usleep(100*YAAMP_MS); + usleep(100*YAAMP_MS); + } + + if(i == 10) + debuglog("failed mutex1 %x <<----------------\n", &mutex); + } else { + pthread_mutex_lock(&mutex); } - - if(i == 10) - debuglog("failed mutex1 %x <<----------------\n", &mutex); -#else - pthread_mutex_lock(&mutex); -#endif } void CommonList::Leave() diff --git a/stratum/remote.cpp b/stratum/remote.cpp index 70e8793..b3e4ef1 100644 --- a/stratum/remote.cpp +++ b/stratum/remote.cpp @@ -1,8 +1,6 @@ #include "stratum.h" -//#define REMOTE_DEBUGLOG_ - bool remote_can_mine(YAAMP_REMOTE *remote) { if(!remote) return false; @@ -40,9 +38,9 @@ bool remote_connected(YAAMP_REMOTE *remote) void remote_close(YAAMP_REMOTE *remote) { -#ifdef REMOTE_DEBUGLOG_ - debuglog("remote_close JOB%d\n", remote->id); -#endif + if (g_debuglog_remote) { + debuglog("remote_close JOB%d\n", remote->id); + } remote->difficulty_actual = 0; @@ -65,11 +63,11 @@ bool remote_connect(YAAMP_REMOTE *remote) if(remote_connected(remote)) remote_close(remote); -#ifdef REMOTE_DEBUGLOG_ - debuglog("connecting to %s:%d JOB%d\n", remote->host, remote->port, remote->id); -#endif + if (g_debuglog_remote) { + debuglog("connecting to %s:%d JOB%d\n", remote->host, remote->port, remote->id); + } - int sock = socket(AF_INET, SOCK_STREAM, 0); + int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock <= 0) return false; struct hostent *ent = gethostbyname(remote->host); @@ -85,9 +83,9 @@ bool remote_connect(YAAMP_REMOTE *remote) int res = connect(sock, (struct sockaddr*)&serv, sizeof(serv)); if(res < 0) { -#ifdef REMOTE_DEBUGLOG_ - debuglog("cant connect to %s:%d JOB%d\n", remote->host, remote->port, remote->id); -#endif + if (g_debuglog_remote) { + debuglog("cant connect to %s:%d JOB%d\n", remote->host, remote->port, remote->id); + } return false; } diff --git a/stratum/remote_template.cpp b/stratum/remote_template.cpp index 84fadc5..6235b70 100644 --- a/stratum/remote_template.cpp +++ b/stratum/remote_template.cpp @@ -62,7 +62,7 @@ void remote_create_job(YAAMP_REMOTE *remote, json_value *json_params) YAAMP_JOB_TEMPLATE *templ = new YAAMP_JOB_TEMPLATE; memset(templ, 0, sizeof(YAAMP_JOB_TEMPLATE)); - strncpy(templ->prevhash_be, json_params->u.array.values[1]->u.string.ptr, 1023); + strncpy(templ->prevhash_be, json_params->u.array.values[1]->u.string.ptr, sizeof(templ->prevhash_be)-1); strncpy(templ->coinb1, json_params->u.array.values[2]->u.string.ptr, 1023); strncpy(templ->coinb2, json_params->u.array.values[3]->u.string.ptr, 1023); diff --git a/stratum/rpc.cpp b/stratum/rpc.cpp index 66f857d..219b619 100644 --- a/stratum/rpc.cpp +++ b/stratum/rpc.cpp @@ -37,9 +37,9 @@ bool rpc_connect(YAAMP_RPC *rpc) rpc->id = 0; rpc->bufpos = 0; -#ifdef RPC_DEBUGLOG_ - debuglog("connected to %s:%d\n", rpc->host, rpc->port); -#endif + if (g_debuglog_rpc) { + debuglog("connected to %s:%d\n", rpc->host, rpc->port); + } return true; } @@ -52,9 +52,9 @@ void rpc_close(YAAMP_RPC *rpc) close(rpc->sock); rpc->sock = 0; -#ifdef RPC_DEBUGLOG_ - debuglog("disconnected from %s:%d\n", rpc->host, rpc->port); -#endif + if (g_debuglog_rpc) { + debuglog("disconnected from %s:%d\n", rpc->host, rpc->port); + } } /////////////////////////////////////////////////////////////////// @@ -66,9 +66,9 @@ int rpc_send_raw(YAAMP_RPC *rpc, const char *buffer, int bytes) int res = send(rpc->sock, buffer, bytes, MSG_NOSIGNAL); if(res <= 0) return res; -#ifdef RPC_DEBUGLOG_ - debuglog("sending >%s<\n", buffer); -#endif + if (g_debuglog_rpc) { + debuglog("sending >%s<\n", buffer); + } return res; } @@ -148,9 +148,9 @@ char *rpc_do_call(YAAMP_RPC *rpc, char const *data) while(!g_exiting) { int bytes = recv(rpc->sock, buffer+bufpos, YAAMP_SMALLBUFSIZE-bufpos-1, 0); -#ifdef RPC_DEBUGLOG_ - debuglog("got %s\n", buffer+bufpos); -#endif + if (g_debuglog_rpc) { + debuglog("got %s\n", buffer+bufpos); + } if(bytes <= 0) { debuglog("ERROR: recv1, %d, %d, %s, %s\n", bytes, errno, data, buffer); diff --git a/stratum/sha3/blake2b.c b/stratum/sha3/blake2b.c new file mode 100644 index 0000000..f85c977 --- /dev/null +++ b/stratum/sha3/blake2b.c @@ -0,0 +1,196 @@ +/* + * Copyright 2009 Colin Percival, 2014 savale + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + */ + +#include +#include +#include + +#include "sph_types.h" +#include "blake2b.h" + +// Cyclic right rotation. + +#ifndef ROTR64 +#define ROTR64(x, y) (((x) >> (y)) ^ ((x) << (64 - (y)))) +#endif + +// Little-endian byte access. + +#define B2B_GET64(p) \ + (((uint64_t) ((uint8_t *) (p))[0]) ^ \ + (((uint64_t) ((uint8_t *) (p))[1]) << 8) ^ \ + (((uint64_t) ((uint8_t *) (p))[2]) << 16) ^ \ + (((uint64_t) ((uint8_t *) (p))[3]) << 24) ^ \ + (((uint64_t) ((uint8_t *) (p))[4]) << 32) ^ \ + (((uint64_t) ((uint8_t *) (p))[5]) << 40) ^ \ + (((uint64_t) ((uint8_t *) (p))[6]) << 48) ^ \ + (((uint64_t) ((uint8_t *) (p))[7]) << 56)) + +// G Mixing function. + +#define B2B_G(a, b, c, d, x, y) { \ + v[a] = v[a] + v[b] + x; \ + v[d] = ROTR64(v[d] ^ v[a], 32); \ + v[c] = v[c] + v[d]; \ + v[b] = ROTR64(v[b] ^ v[c], 24); \ + v[a] = v[a] + v[b] + y; \ + v[d] = ROTR64(v[d] ^ v[a], 16); \ + v[c] = v[c] + v[d]; \ + v[b] = ROTR64(v[b] ^ v[c], 63); } + +// Initialization Vector. + +static const uint64_t blake2b_iv[8] = { + 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, + 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, + 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, + 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 +}; + +// Compression function. "last" flag indicates last block. + +static void blake2b_compress(blake2b_ctx *ctx, int last) +{ + const uint8_t sigma[12][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } + }; + int i; + uint64_t v[16], m[16]; + + for (i = 0; i < 8; i++) { // init work variables + v[i] = ctx->h[i]; + v[i + 8] = blake2b_iv[i]; + } + + v[12] ^= ctx->t[0]; // low 64 bits of offset + v[13] ^= ctx->t[1]; // high 64 bits + if (last) // last block flag set ? + v[14] = ~v[14]; + + for (i = 0; i < 16; i++) // get little-endian words + m[i] = B2B_GET64(&ctx->b[8 * i]); + + for (i = 0; i < 12; i++) { // twelve rounds + B2B_G( 0, 4, 8, 12, m[sigma[i][ 0]], m[sigma[i][ 1]]); + B2B_G( 1, 5, 9, 13, m[sigma[i][ 2]], m[sigma[i][ 3]]); + B2B_G( 2, 6, 10, 14, m[sigma[i][ 4]], m[sigma[i][ 5]]); + B2B_G( 3, 7, 11, 15, m[sigma[i][ 6]], m[sigma[i][ 7]]); + B2B_G( 0, 5, 10, 15, m[sigma[i][ 8]], m[sigma[i][ 9]]); + B2B_G( 1, 6, 11, 12, m[sigma[i][10]], m[sigma[i][11]]); + B2B_G( 2, 7, 8, 13, m[sigma[i][12]], m[sigma[i][13]]); + B2B_G( 3, 4, 9, 14, m[sigma[i][14]], m[sigma[i][15]]); + } + + for( i = 0; i < 8; ++i ) + ctx->h[i] ^= v[i] ^ v[i + 8]; +} + +// Initialize the hashing context "ctx" with optional key "key". +// 1 <= outlen <= 64 gives the digest size in bytes. +// Secret key (also <= 64 bytes) is optional (keylen = 0). + +int blake2b_init(blake2b_ctx *ctx, size_t outlen, + const void *key, size_t keylen) // (keylen=0: no key) +{ + size_t i; + + if (outlen == 0 || outlen > 64 || keylen > 64) + return -1; // illegal parameters + + for (i = 0; i < 8; i++) // state, "param block" + ctx->h[i] = blake2b_iv[i]; + ctx->h[0] ^= 0x01010000 ^ (keylen << 8) ^ outlen; + + ctx->t[0] = 0; // input count low word + ctx->t[1] = 0; // input count high word + ctx->c = 0; // pointer within buffer + ctx->outlen = outlen; + + for (i = keylen; i < 128; i++) // zero input block + ctx->b[i] = 0; + if (keylen > 0) { + blake2b_update(ctx, key, keylen); + ctx->c = 128; // at the end + } + + return 0; +} + +// Add "inlen" bytes from "in" into the hash. + +void blake2b_update(blake2b_ctx *ctx, + const void *in, size_t inlen) // data bytes +{ + size_t i; + + for (i = 0; i < inlen; i++) { + if (ctx->c == 128) { // buffer full ? + ctx->t[0] += ctx->c; // add counters + if (ctx->t[0] < ctx->c) // carry overflow ? + ctx->t[1]++; // high word + blake2b_compress(ctx, 0); // compress (not last) + ctx->c = 0; // counter to zero + } + ctx->b[ctx->c++] = ((const uint8_t *) in)[i]; + } +} + +// Generate the message digest (size given in init). +// Result placed in "out". + +void blake2b_final(blake2b_ctx *ctx, void *out) +{ + size_t i; + + ctx->t[0] += ctx->c; // mark last block offset + if (ctx->t[0] < ctx->c) // carry overflow + ctx->t[1]++; // high word + + while (ctx->c < 128) // fill up with zeros + ctx->b[ctx->c++] = 0; + blake2b_compress(ctx, 1); // final block flag = 1 + + // little endian convert and store + for (i = 0; i < ctx->outlen; i++) { + ((uint8_t *) out)[i] = + (ctx->h[i >> 3] >> (8 * (i & 7))) & 0xFF; + } +} + diff --git a/stratum/sha3/blake2b.h b/stratum/sha3/blake2b.h new file mode 100644 index 0000000..f8652c1 --- /dev/null +++ b/stratum/sha3/blake2b.h @@ -0,0 +1,41 @@ +#pragma once +#ifndef __BLAKE2B_H__ +#define __BLAKE2B_H__ + +#include +#include + +#if defined(_MSC_VER) +#include +#define inline __inline +#define ALIGN(x) __declspec(align(x)) +#else +#define ALIGN(x) __attribute__((aligned(x))) +#endif + +#if defined(_MSC_VER) || defined(__x86_64__) || defined(__x86__) +#define NATIVE_LITTLE_ENDIAN +#endif + +// state context +ALIGN(64) typedef struct { + uint8_t b[128]; // input buffer + uint64_t h[8]; // chained state + uint64_t t[2]; // total number of bytes + size_t c; // pointer for b[] + size_t outlen; // digest size +} blake2b_ctx; + +#if defined(__cplusplus) +extern "C" { +#endif + +int blake2b_init(blake2b_ctx *ctx, size_t outlen, const void *key, size_t keylen); +void blake2b_update(blake2b_ctx *ctx, const void *in, size_t inlen); +void blake2b_final(blake2b_ctx *ctx, void *out); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/stratum/sha3/makefile b/stratum/sha3/makefile index ab83f61..6c91799 100644 --- a/stratum/sha3/makefile +++ b/stratum/sha3/makefile @@ -7,7 +7,7 @@ LDFLAGS=-O2 SOURCES=sph_jh.c sph_blake.c sph_bmw.c sph_groestl.c sph_skein.c sph_keccak.c sph_luffa.c sph_cubehash.c sph_shavite.c \ sph_simd.c sph_echo.c sph_fugue.c sph_hamsi.c sph_shabal.c sph_whirlpool.c \ sph_haval.c sph_hefty1.c sph_ripemd.c sph_sha2.c sph_sha2big.c sph_tiger.c \ - blake2s.c + blake2s.c blake2b.c OBJECTS=$(SOURCES:.c=.o) OUTPUT=libhash.a diff --git a/stratum/share.cpp b/stratum/share.cpp index c7106da..14c4332 100644 --- a/stratum/share.cpp +++ b/stratum/share.cpp @@ -232,10 +232,10 @@ void block_add(int userid, int workerid, int coinid, int height, double diff, do } // called from blocknotify tool -void block_confirm(int coinid, const char *blockhash) +bool block_confirm(int coinid, const char *blockhash) { char hash[192]; - if(strlen(blockhash) < 64) return; + if(strlen(blockhash) < 64) return false; snprintf(hash, 161, "%s", blockhash); @@ -261,8 +261,10 @@ void block_confirm(int coinid, const char *blockhash) } const char *h1 = json_get_string(json_res, "pow_hash"); // DGB, MYR, J const char *h2 = json_get_string(json_res, "mined_hash"); // XVG + const char *h3 = json_get_string(json_res, "phash"); // XSH if (h1) snprintf(hash, 161, "%s", h1); else if (h2) snprintf(hash, 161, "%s", h2); + else if (h3) snprintf(hash, 161, "%s", h3); //debuglog("%s: getblock %s -> pow %s\n", __func__, blockhash, hash); json_value_free(json); break; @@ -290,17 +292,18 @@ void block_confirm(int coinid, const char *blockhash) for(CLI li = g_list_block.first; li; li = li->next) { YAAMP_BLOCK *block = (YAAMP_BLOCK *)li->data; - if(block->coinid == coinid && !block->confirmed && !block->deleted) + if(block->coinid == coinid && !block->deleted) { if(strcmp(block->hash1, hash) && strcmp(block->hash2, hash)) continue; - debuglog("*** CONFIRMED %d : %s\n", block->height, block->hash2); - - strncpy(block->hash, blockhash, 65); - block->confirmed = true; - - return; + if (!block->confirmed) { + debuglog("*** CONFIRMED %d : %s\n", block->height, block->hash2); + strncpy(block->hash, blockhash, 65); + block->confirmed = true; + } + return true; } } + return false; } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/stratum/share.h b/stratum/share.h index 1decef9..dd90eca 100644 --- a/stratum/share.h +++ b/stratum/share.h @@ -100,7 +100,7 @@ inline void submit_delete(YAAMP_OBJECT *object) void block_prune(YAAMP_DB *db); void block_add(int userid, int workerid, int coinid, int height, double diff, double diff_user, const char *hash1, const char *h2, int segwit); -void block_confirm(int coinid, const char *hash); +bool block_confirm(int coinid, const char *hash); YAAMP_SUBMIT *submit_add(int remoteid, double difficulty); void submit_prune(YAAMP_DB *db); diff --git a/stratum/socket.cpp b/stratum/socket.cpp index b708f96..a9796fc 100644 --- a/stratum/socket.cpp +++ b/stratum/socket.cpp @@ -1,42 +1,91 @@ #include "stratum.h" -//#define SOCKET_DEBUGLOG_ - bool socket_connected(YAAMP_SOCKET *s) { return s->sock > 0; } +void socket_real_ip(YAAMP_SOCKET *s) +{ + // get real ip if we are using haproxy or similar that use PROXY protocol + // https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt + int size, ret; + const char v2sig[] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"; + + do { + ret = recv(s->sock, &hdr, sizeof(hdr), MSG_PEEK); + } while (ret == -1 && errno == EINTR); + + if (ret >= (16 + ntohs(hdr.v2.len)) && + memcmp(&hdr.v2, v2sig, 12) == 0 && + ((hdr.v2.ver_cmd & 0xF0) == 0x20) && + hdr.v2.fam == 0x11) { + // we received a proxy v2 header + inet_ntop(AF_INET, &hdr.v2.addr.ip4.src_addr, s->ip, 64); + s->port = ntohs(hdr.v2.addr.ip4.src_port); + + // we need to consume the appropriate amount of data from the socket + // read the buffer without PEEK'ing so that we begin at the real data later in socket_nextjson + size = 16 + ntohs(hdr.v2.len); + do { + ret = recv(s->sock, &hdr, size, 0); + } while (ret == -1 && errno == EINTR); + return; + } + else { + // not received any proxy header + struct sockaddr_in name; + socklen_t len = sizeof(name); + memset(&name, 0, len); + + int res = getpeername(s->sock, (struct sockaddr *)&name, &len); + inet_ntop(AF_INET, &name.sin_addr, s->ip, 64); + + res = getsockname(s->sock, (struct sockaddr *)&name, &len); + s->port = ntohs(name.sin_port); + return; + } +} + YAAMP_SOCKET *socket_initialize(int sock) { + struct timeval timeout; + timeout.tv_sec = g_socket_recv_timeout; + timeout.tv_usec = 0; YAAMP_SOCKET *s = new YAAMP_SOCKET; memset(s, 0, sizeof(YAAMP_SOCKET)); s->buflen = 0; s->sock = sock; + setsockopt(s->sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + // yaamp_create_mutex(&s->mutex); // pthread_mutex_lock(&s->mutex); + if (!g_handle_haproxy_ips) { + int res = 0; + struct sockaddr_in name; + socklen_t len = sizeof(name); + memset(&name, 0, len); - struct sockaddr_in name; - socklen_t len = sizeof(name); - memset(&name, 0, len); + res = getpeername(s->sock, (struct sockaddr *)&name, &len); + inet_ntop(AF_INET, &name.sin_addr, s->ip, 64); - int res = getpeername(s->sock, (struct sockaddr *)&name, &len); - inet_ntop(AF_INET, &name.sin_addr, s->ip, 64); - - res = getsockname(s->sock, (struct sockaddr *)&name, &len); - s->port = ntohs(name.sin_port); + res = getsockname(s->sock, (struct sockaddr *)&name, &len); + s->port = ntohs(name.sin_port); + } else { + socket_real_ip(s); + } return s; } void socket_close(YAAMP_SOCKET *s) { -#ifdef SOCKET_DEBUGLOG_ - debuglog("socket_close\n"); -#endif + if (g_debuglog_socket) { + debuglog("socket_close\n"); + } if(!s) return; if(s->sock) close(s->sock); @@ -140,9 +189,9 @@ json_value *socket_nextjson(YAAMP_SOCKET *s, YAAMP_CLIENT *client) int socket_send_raw(YAAMP_SOCKET *s, const char *buffer, int size) { -#ifdef SOCKET_DEBUGLOG_ - debuglog("socket send: %s", buffer); -#endif + if (g_debuglog_socket) { + debuglog("socket send: %s", buffer); + } int res = send(s->sock, buffer, size, MSG_NOSIGNAL); return res; @@ -170,7 +219,6 @@ int socket_send(YAAMP_SOCKET *s, const char *format, ...) // pthread_mutex_lock(&s->mutex); int res = socket_send_raw(s, buffer, strlen(buffer)); - // pthread_mutex_unlock(&s->mutex); return res; } diff --git a/stratum/socket.h b/stratum/socket.h index c169e33..f992fa5 100644 --- a/stratum/socket.h +++ b/stratum/socket.h @@ -18,6 +18,8 @@ struct YAAMP_SOCKET bool socket_connected(YAAMP_SOCKET *s); +void socket_real_ip(YAAMP_SOCKET *s); + YAAMP_SOCKET *socket_initialize(int sock); void socket_close(YAAMP_SOCKET *s); @@ -26,3 +28,32 @@ int socket_send(YAAMP_SOCKET *s, const char *format, ...); int socket_send_raw(YAAMP_SOCKET *s, const char *buffer, int size); +static union { + struct { + char line[108]; + } v1; + struct { + uint8_t sig[12]; + uint8_t ver_cmd; + uint8_t fam; + uint16_t len; + union { + struct { /* for TCP/UDP over IPv4, len = 12 */ + uint32_t src_addr; + uint32_t dst_addr; + uint16_t src_port; + uint16_t dst_port; + } ip4; + struct { /* for TCP/UDP over IPv6, len = 36 */ + uint8_t src_addr[16]; + uint8_t dst_addr[16]; + uint16_t src_port; + uint16_t dst_port; + } ip6; + struct { /* for AF_UNIX sockets, len = 216 */ + uint8_t src_addr[108]; + uint8_t dst_addr[108]; + } unx; + } addr; + } v2; +} hdr; diff --git a/stratum/stratum.cpp b/stratum/stratum.cpp index 6758eea..e352fab 100644 --- a/stratum/stratum.cpp +++ b/stratum/stratum.cpp @@ -23,18 +23,34 @@ char g_sql_host[1024]; char g_sql_database[1024]; char g_sql_username[1024]; char g_sql_password[1024]; +int g_sql_port = 3306; char g_stratum_coin_include[256]; char g_stratum_coin_exclude[256]; char g_stratum_algo[256]; double g_stratum_difficulty; +double g_stratum_min_diff; +double g_stratum_max_diff; int g_stratum_max_ttf; int g_stratum_max_cons = 5000; bool g_stratum_reconnect; bool g_stratum_renting; -bool g_stratum_segwit; +bool g_stratum_segwit = false; + +int g_limit_txs_per_block = 0; + +bool g_handle_haproxy_ips = false; +int g_socket_recv_timeout = 600; + +bool g_debuglog_client; +bool g_debuglog_hash; +bool g_debuglog_socket; +bool g_debuglog_rpc; +bool g_debuglog_list; +bool g_debuglog_remote; + bool g_autoexchange = true; uint64_t g_max_shares = 0; @@ -101,28 +117,38 @@ YAAMP_ALGO g_algos[] = {"c11", c11_hash, 1, 0, 0}, {"x11", x11_hash, 1, 0, 0}, + {"x12", x12_hash, 1, 0, 0}, {"x13", x13_hash, 1, 0, 0}, {"x14", x14_hash, 1, 0, 0}, {"x15", x15_hash, 1, 0, 0}, {"x17", x17_hash, 1, 0, 0}, + {"x22i", x22i_hash, 1, 0, 0}, {"x11evo", x11evo_hash, 1, 0, 0}, {"xevan", xevan_hash, 0x100, 0, 0}, + {"x16r", x16r_hash, 0x100, 0, 0}, + {"x16rv2", x16rv2_hash, 0x100, 0, 0}, + {"x16s", x16s_hash, 0x100, 0, 0}, {"timetravel", timetravel_hash, 0x100, 0, 0}, {"bitcore", timetravel10_hash, 0x100, 0, 0}, + {"exosis", exosis_hash, 0x100, 0, 0}, {"hsr", hsr_hash, 1, 0, 0}, {"hmq1725", hmq17_hash, 0x10000, 0, 0}, {"jha", jha_hash, 0x10000, 0}, + {"allium", allium_hash, 0x100, 0, 0}, {"lyra2", lyra2re_hash, 0x80, 0, 0}, {"lyra2v2", lyra2v2_hash, 0x100, 0, 0}, + {"lyra2v3", lyra2v3_hash, 0x100, 0, 0}, {"lyra2z", lyra2z_hash, 0x100, 0, 0}, + {"lyra2zz", lyra2zz_hash, 0x100, 0, 0}, {"bastion", bastion_hash, 1, 0 }, {"blake", blake_hash, 1, 0 }, {"blakecoin", blakecoin_hash, 1 /*0x100*/, 0, sha256_hash_hex }, + {"blake2b", blake2b_hash, 1, 0 }, {"blake2s", blake2s_hash, 1, 0 }, {"vanilla", blakecoin_hash, 1, 0 }, {"decred", decred_hash, 1, 0 }, @@ -136,28 +162,44 @@ YAAMP_ALGO g_algos[] = {"dmd-gr", groestl_hash, 0x100, 0, 0}, /* diamond (double groestl) */ {"myr-gr", groestlmyriad_hash, 1, 0, 0}, /* groestl + sha 64 */ {"skein", skein_hash, 1, 0, 0}, + {"sonoa", sonoa_hash, 1, 0, 0}, {"tribus", tribus_hash, 1, 0, 0}, {"keccak", keccak256_hash, 0x80, 0, sha256_hash_hex }, + {"keccakc", keccak256_hash, 0x100, 0, 0}, + {"hex", hex_hash, 0x100, 0, sha256_hash_hex }, + {"phi", phi_hash, 1, 0, 0}, + {"phi2", phi2_hash, 0x100, 0, 0}, + {"polytimos", polytimos_hash, 1, 0, 0}, {"skunk", skunk_hash, 1, 0, 0}, {"bmw", bmw_hash, 1, 0, 0}, + {"lbk3", lbk3_hash, 0x100, 0, 0}, {"lbry", lbry_hash, 0x100, 0, 0}, {"luffa", luffa_hash, 1, 0, 0}, {"penta", penta_hash, 1, 0, 0}, + {"rainforest", rainforest_hash, 0x100, 0, 0}, {"skein2", skein2_hash, 1, 0, 0}, {"yescrypt", yescrypt_hash, 0x10000, 0, 0}, + {"yescryptR16", yescryptR16_hash, 0x10000, 0, 0 }, + {"yescryptR32", yescryptR32_hash, 0x10000, 0, 0 }, {"zr5", zr5_hash, 1, 0, 0}, + {"a5a", a5a_hash, 0x10000, 0, 0}, {"hive", hive_hash, 0x10000, 0, 0}, {"m7m", m7m_hash, 0x10000, 0, 0}, {"veltor", veltor_hash, 1, 0, 0}, {"velvet", velvet_hash, 0x10000, 0, 0}, - {"argon2", argon2_hash, 0x10000, 0, sha256_hash_hex }, + {"argon2", argon2a_hash, 0x10000, 0, sha256_hash_hex }, + {"argon2d-dyn", argon2d_dyn_hash, 0x10000, 0, 0 }, // Dynamic Argon2d Implementation + {"vitalium", vitalium_hash, 1, 0, 0}, + {"aergo", aergo_hash, 1, 0, 0}, {"sha256t", sha256t_hash, 1, 0, 0}, // sha256 3x + {"sha256q", sha256q_hash, 1, 0, 0}, // sha256 4x + {"sib", sib_hash, 1, 0, 0}, {"whirlcoin", whirlpool_hash, 1, 0, sha256_hash_hex }, /* old sha merkleroot */ @@ -180,8 +222,6 @@ YAAMP_ALGO *stratum_find_algo(const char *name) //////////////////////////////////////////////////////////////////////////////////////// -#include - int main(int argc, char **argv) { if(argc < 2) @@ -218,6 +258,7 @@ int main(int argc, char **argv) strcpy(g_sql_database, iniparser_getstring(ini, "SQL:database", NULL)); strcpy(g_sql_username, iniparser_getstring(ini, "SQL:username", NULL)); strcpy(g_sql_password, iniparser_getstring(ini, "SQL:password", NULL)); + g_sql_port = iniparser_getint(ini, "SQL:port", 3306); // optional coin filters (to mine only one on a special port or a test instance) char *coin_filter = iniparser_getstring(ini, "WALLETS:include", NULL); @@ -227,10 +268,25 @@ int main(int argc, char **argv) strcpy(g_stratum_algo, iniparser_getstring(ini, "STRATUM:algo", NULL)); g_stratum_difficulty = iniparser_getdouble(ini, "STRATUM:difficulty", 16); + g_stratum_min_diff = iniparser_getdouble(ini, "STRATUM:diff_min", g_stratum_difficulty/2); + g_stratum_max_diff = iniparser_getdouble(ini, "STRATUM:diff_max", g_stratum_difficulty*8192); + g_stratum_max_cons = iniparser_getint(ini, "STRATUM:max_cons", 5000); g_stratum_max_ttf = iniparser_getint(ini, "STRATUM:max_ttf", 0x70000000); g_stratum_reconnect = iniparser_getint(ini, "STRATUM:reconnect", true); g_stratum_renting = iniparser_getint(ini, "STRATUM:renting", true); + g_handle_haproxy_ips = iniparser_getint(ini, "STRATUM:haproxy_ips", g_handle_haproxy_ips); + g_socket_recv_timeout = iniparser_getint(ini, "STRATUM:recv_timeout", 600); + + g_max_shares = iniparser_getint(ini, "STRATUM:max_shares", g_max_shares); + g_limit_txs_per_block = iniparser_getint(ini, "STRATUM:max_txs_per_block", 0); + + g_debuglog_client = iniparser_getint(ini, "DEBUGLOG:client", false); + g_debuglog_hash = iniparser_getint(ini, "DEBUGLOG:hash", false); + g_debuglog_socket = iniparser_getint(ini, "DEBUGLOG:socket", false); + g_debuglog_rpc = iniparser_getint(ini, "DEBUGLOG:rpc", false); + g_debuglog_list = iniparser_getint(ini, "DEBUGLOG:list", false); + g_debuglog_remote = iniparser_getint(ini, "DEBUGLOG:remote", false); iniparser_freedict(ini); @@ -249,9 +305,10 @@ int main(int argc, char **argv) g_current_algo->name, g_tcp_server, g_tcp_port); // ntime should not be changed by miners for these algos - g_allow_rolltime = strcmp(g_current_algo->name,"x11evo"); - g_allow_rolltime = g_allow_rolltime && strcmp(g_current_algo->name,"timetravel"); - g_allow_rolltime = g_allow_rolltime && strcmp(g_current_algo->name,"bitcore"); + g_allow_rolltime = strcmp(g_stratum_algo,"x11evo"); + g_allow_rolltime = g_allow_rolltime && strcmp(g_stratum_algo,"timetravel"); + g_allow_rolltime = g_allow_rolltime && strcmp(g_stratum_algo,"bitcore"); + g_allow_rolltime = g_allow_rolltime && strcmp(g_stratum_algo,"exosis"); if (!g_allow_rolltime) stratumlog("note: time roll disallowed for %s algo\n", g_current_algo->name); @@ -400,8 +457,8 @@ void *stratum_thread(void *p) stratumlog("%s socket accept() error %d\n", g_stratum_algo, error); failcount++; usleep(50000); - if (error == 24 && failcount > 16) { - g_exiting = true; + if (error == 24 && failcount > 5) { + g_exiting = true; // happen when max open files is reached (see ulimit) stratumlogdate("%s too much socket failure, exiting...\n", g_stratum_algo); exit(error); } diff --git a/stratum/stratum.h b/stratum/stratum.h index e338e6b..d938e1b 100644 --- a/stratum/stratum.h +++ b/stratum/stratum.h @@ -1,4 +1,3 @@ - #include #include #include @@ -19,6 +18,7 @@ #include #include #include +#include #include #include @@ -74,18 +74,32 @@ extern char g_sql_host[1024]; extern char g_sql_database[1024]; extern char g_sql_username[1024]; extern char g_sql_password[1024]; +extern int g_sql_port; extern char g_stratum_coin_include[256]; extern char g_stratum_coin_exclude[256]; extern char g_stratum_algo[256]; extern double g_stratum_difficulty; +extern double g_stratum_min_diff; +extern double g_stratum_max_diff; extern int g_stratum_max_cons; extern int g_stratum_max_ttf; extern bool g_stratum_reconnect; extern bool g_stratum_renting; extern bool g_stratum_segwit; +extern int g_limit_txs_per_block; + +extern bool g_handle_haproxy_ips; +extern int g_socket_recv_timeout; + +extern bool g_debuglog_client; +extern bool g_debuglog_hash; +extern bool g_debuglog_socket; +extern bool g_debuglog_rpc; +extern bool g_debuglog_list; +extern bool g_debuglog_remote; extern uint64_t g_max_shares; extern uint64_t g_shares_counter; @@ -133,13 +147,19 @@ void scrypt_N_R_1_256(const char* input, char* output, uint32_t N, uint32_t R, u void sha256_hash_hex(const char *input, char *output, unsigned int len); void sha256_double_hash_hex(const char *input, char *output, unsigned int len); +#include "algos/a5a.h" #include "algos/c11.h" #include "algos/x11.h" #include "algos/x11evo.h" +#include "algos/x12.h" #include "algos/x13.h" #include "algos/x14.h" #include "algos/x15.h" +#include "algos/x16r.h" +#include "algos/x16rv2.h" +#include "algos/x16s.h" #include "algos/x17.h" +#include "algos/x22i.h" #include "algos/xevan.h" #include "algos/hmq17.h" #include "algos/nist5.h" @@ -147,18 +167,23 @@ void sha256_double_hash_hex(const char *input, char *output, unsigned int len); #include "algos/hsr14.h" #include "algos/quark.h" #include "algos/neoscrypt.h" +#include "algos/allium.h" #include "algos/lyra2re.h" #include "algos/lyra2v2.h" +#include "algos/lyra2v3.h" #include "algos/lyra2z.h" +#include "algos/lyra2zz.h" #include "algos/blake.h" #include "algos/blakecoin.h" -#include "algos/blake2.h" +#include "algos/blake2b.h" +#include "algos/blake2s.h" #include "algos/qubit.h" #include "algos/groestl.h" #include "algos/jha.h" #include "algos/skein.h" #include "algos/keccak.h" #include "algos/sha256t.h" +#include "algos/sha256q.h" #include "algos/skunk.h" #include "algos/timetravel.h" #include "algos/bitcore.h" @@ -166,9 +191,11 @@ void sha256_double_hash_hex(const char *input, char *output, unsigned int len); #include "algos/bastion.h" #include "algos/bmw.h" #include "algos/deep.h" +#include "algos/lbk3.h" #include "algos/lbry.h" #include "algos/luffa.h" #include "algos/pentablake.h" +#include "algos/rainforest.h" #include "algos/whirlpool.h" #include "algos/whirlpoolx.h" #include "algos/skein2.h" @@ -178,9 +205,15 @@ void sha256_double_hash_hex(const char *input, char *output, unsigned int len); #include "algos/sib.h" #include "algos/m7m.h" #include "algos/phi.h" +#include "algos/phi2.h" #include "algos/polytimos.h" +#include "algos/sonoa.h" #include "algos/tribus.h" #include "algos/veltor.h" #include "algos/velvet.h" #include "algos/argon2a.h" - +#include "algos/vitalium.h" +#include "algos/aergo.h" +#include "algos/hex.h" +#include "algos/argon2d-dyn.h" +#include "algos/exosis.h" diff --git a/stratum/user.cpp b/stratum/user.cpp index 29bf045..1e2ec6c 100644 --- a/stratum/user.cpp +++ b/stratum/user.cpp @@ -108,8 +108,8 @@ void db_add_user(YAAMP_DB *db, YAAMP_CLIENT *client) else if(client->userid == 0 && strlen(client->username) >= MIN_ADDRESS_LEN) { - db_query(db, "INSERT INTO accounts (username, coinsymbol, balance, donation) values ('%s', '%s', 0, %d)", - client->username, symbol, gift); + db_query(db, "INSERT INTO accounts (username, coinsymbol, balance, donation, hostaddr) values ('%s', '%s', 0, %d, '%s')", + client->username, symbol, gift, client->sock->ip); client->userid = (int)mysql_insert_id(&db->mysql); } diff --git a/stratum/util.cpp b/stratum/util.cpp index ef928c4..92f284a 100644 --- a/stratum/util.cpp +++ b/stratum/util.cpp @@ -149,7 +149,11 @@ void clientlog(YAAMP_CLIENT *client, const char *format, ...) if(g_clientlog) { fprintf(g_clientlog, "%s", buffer3); - fflush(g_clientlog); + if (fflush(g_clientlog) == EOF) { + // reopen if wiped + fclose(g_clientlog); + g_clientlog = fopen("client.log", "a"); + } } } @@ -219,7 +223,10 @@ void stratumlog(const char *format, ...) if(g_stratumlog) { fprintf(g_stratumlog, "%s: %s", buffer2, buffer); - fflush(g_stratumlog); + if (fflush(g_stratumlog) == EOF) { + fclose(g_stratumlog); + g_stratumlog = fopen("stratum.log", "a"); + } } } @@ -264,7 +271,10 @@ void rejectlog(const char *format, ...) if(g_rejectlog) { fprintf(g_rejectlog, "%s: %s", buffer2, buffer); - fflush(g_rejectlog); + if (fflush(g_rejectlog) == EOF) { + fclose(g_rejectlog); + g_rejectlog = fopen("reject.log", "a"); + } } } @@ -407,6 +417,14 @@ void hexlify(char *hex, const unsigned char *bin, int len) sprintf(hex+strlen(hex), "%02x", bin[i]); } +bool ishexa(char *hex, int len) +{ + for(int i=0; i= '0' && v <= '9') @@ -664,6 +682,29 @@ long long current_timestamp_dms() // allow 0.1 ms time return dms; } +int opened_files() +{ + int fds = 0; + DIR *d = opendir("/proc/self/fd"); + if (d) { + while (readdir(d)) fds++; + closedir(d); + } + return fds; +} + +int resident_size() +{ + int sz, res = 0; + FILE *fp = fopen("/proc/self/statm", "r"); + if (fp) { + int p = fscanf(fp, "%d", &sz); + if (p) p += fscanf(fp, "%d", &res); + fclose(fp); + } + return res; +} + void string_lower(char *s) { for(int i = 0; s[i]; i++) diff --git a/stratum/util.h b/stratum/util.h index 1a39be2..bf57bfd 100644 --- a/stratum/util.h +++ b/stratum/util.h @@ -74,6 +74,7 @@ string merkle_with_first(vector steps, string f); ////////////////////////////////////////////////////////////////////////// bool base58_decode(const char *input, char *output); +bool is_base58(char *input); void base64_encode(char *base64, const char *normal); void base64_decode(char *normal, const char *base64); @@ -86,6 +87,8 @@ void ser_string_be2(const char *input, char *output, int len); void string_be(const char *input, char *output); void string_be1(char *s); +bool ishexa(char *hex, int len); + void hexlify(char *hex, const unsigned char *bin, int len); void binlify(unsigned char *bin, const char *hex); @@ -102,6 +105,9 @@ uint64_t get_hash_difficulty(unsigned char *input); long long current_timestamp(); long long current_timestamp_dms(); +int opened_files(); +int resident_size(); + void string_lower(char *s); void string_upper(char *s); diff --git a/tests/.gitkeep b/tests/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/.gitkeep @@ -0,0 +1 @@ + diff --git a/web/keys.sample.php b/web/keys.sample.php index da2034f..cd9b7ca 100644 --- a/web/keys.sample.php +++ b/web/keys.sample.php @@ -3,10 +3,12 @@ define('YIIMP_MYSQLDUMP_USER', 'root'); define('YIIMP_MYSQLDUMP_PASS', ''); +define('YIIMP_MYSQLDUMP_PATH', '/root/backup'); /* Keys required to create/cancel orders and access your balances/deposit addresses */ define('EXCH_BITTREX_SECRET', ''); define('EXCH_BITSTAMP_SECRET',''); +define('EXCH_BINANCE_SECRET', ''); define('EXCH_BLEUTRADE_SECRET', ''); define('EXCH_BTER_SECRET', ''); define('EXCH_CCEX_SECRET', ''); @@ -16,6 +18,7 @@ define('EXCH_CRYPTOPIA_SECRET', ''); define('EXCH_EMPOEX_SECKEY', ''); define('EXCH_HITBTC_SECRET', ''); define('EXCH_KRAKEN_SECRET',''); +define('EXCH_KUCOIN_SECRET', ''); define('EXCH_LIVECOIN_SECRET', ''); define('EXCH_NOVA_SECRET',''); define('EXCH_POLONIEX_SECRET', ''); diff --git a/web/serverconfig.sample.php b/web/serverconfig.sample.php index efe8032..b5baf75 100644 --- a/web/serverconfig.sample.php +++ b/web/serverconfig.sample.php @@ -36,8 +36,11 @@ define('YAAMP_SITE_NAME', 'YiiMP'); define('YAAMP_ADMIN_EMAIL', 'yiimp@spam.la'); define('YAAMP_ADMIN_IP', ''); // samples: "80.236.118.26,90.234.221.11" or "10.0.0.1/8" define('YAAMP_ADMIN_WEBCONSOLE', true); +<<<<<<< HEAD define('YAAMP_NOTIFY_NEW_COINS', true); define('YAAMP_DEFAULT_ALGO', 'lbry'); +define('YAAMP_CREATE_NEW_COINS', false); + define('YAAMP_USE_NGINX', false); @@ -46,15 +49,19 @@ define('EXCH_CRYPTOPIA_KEY', ''); define('EXCH_POLONIEX_KEY', ''); define('EXCH_BITTREX_KEY', ''); define('EXCH_BLEUTRADE_KEY', ''); -define('EXCH_BTER_KEY', ''); define('EXCH_YOBIT_KEY', ''); define('EXCH_CCEX_KEY', ''); +define('EXCH_CEXIO_ID', ''); +define('EXCH_CEXIO_KEY', ''); define('EXCH_COINMARKETS_USER', ''); define('EXCH_COINMARKETS_PIN', ''); +define('EXCH_CREX24_KEY', ''); +define('EXCH_BINANCE_KEY', ''); define('EXCH_BITSTAMP_ID',''); define('EXCH_BITSTAMP_KEY',''); define('EXCH_HITBTC_KEY',''); define('EXCH_KRAKEN_KEY', ''); +define('EXCH_KUCOIN_KEY', ''); define('EXCH_LIVECOIN_KEY', ''); define('EXCH_NOVA_KEY', ''); define('EXCH_STOCKSEXCHANGE_KEY', ''); diff --git a/web/yaamp/commands/CheckupCommand.php b/web/yaamp/commands/CheckupCommand.php index b4da2ba..87f72b4 100644 --- a/web/yaamp/commands/CheckupCommand.php +++ b/web/yaamp/commands/CheckupCommand.php @@ -186,8 +186,15 @@ class CheckupCommand extends CConsoleCommand $nbUpdated = 0; $nbDropped = 0; foreach ($coins->findAll() as $coin) { if (!empty($coin->image)) { - if (file_exists($this->basePath.$coin->image)) + if (file_exists($this->basePath.$coin->image)) { + $data = file_get_contents($this->basePath.$coin->image); + if (strstr($data, "basePath.$coin->image); + $coin->image = NULL; + $nbDropped += $coin->save(); + } continue; + } if (file_exists($this->basePath."/images/coin-$coin->symbol.png")) { $coin->image = "/images/coin-$coin->symbol.png"; $nbUpdated += $coin->save(); diff --git a/web/yaamp/commands/CoindbCommand.php b/web/yaamp/commands/CoindbCommand.php index 41892a4..619ddcd 100644 --- a/web/yaamp/commands/CoindbCommand.php +++ b/web/yaamp/commands/CoindbCommand.php @@ -50,12 +50,12 @@ class CoindbCommand extends CConsoleCommand } elseif ($args[0] == 'icons') { - $nbUpdated = $this->grabBterIcons(); - $nbUpdated += $this->grabCcexIcons(); + $nbUpdated = $this->grabCcexIcons(); $nbUpdated += $this->grabCryptopiaIcons(); $nbUpdated += $this->grabBittrexIcons(); // can be huge ones $nbUpdated += $this->grabCoinExchangeIcons(); $nbUpdated += $this->grabAlcurexIcons(); + $nbUpdated += $this->grabKuCoinIcons(); $nbUpdated += $this->grabNovaIcons(); echo "total updated: $nbUpdated\n"; @@ -294,41 +294,6 @@ class CoindbCommand extends CConsoleCommand return $nbUpdated; } - /** - * Icon grabber - Bter - */ - public function grabBterIcons() - { - $url = 'http://bter.com/images/coin_icon/64/'; - $nbUpdated = 0; - $sql = "SELECT DISTINCT coins.id FROM coins INNER JOIN markets M ON M.coinid = coins.id WHERE M.name='bter' AND IFNULL(coins.image,'') = ''"; - $coins = dbolist($sql); - if (empty($coins)) - return 0; - echo "bter: try to download new icons...\n"; - foreach ($coins as $coin) { - $coin = getdbo('db_coins', $coin["id"]); - $symbol = $coin->symbol; - if (!empty($coin->symbol2)) $symbol = $coin->symbol2; - $local = $this->basePath."/images/coin-{$symbol}.png"; - try { - $data = @ file_get_contents($url.strtolower($symbol).'.png'); - } catch (Exception $e) { - continue; - } - if (strlen($data) < 2048) continue; - echo $coin->symbol." icon found\n"; - file_put_contents($local, $data); - if (filesize($local) > 0) { - $coin->image = "/images/coin-{$symbol}.png"; - $nbUpdated += $coin->save(); - } - } - if ($nbUpdated) - echo "$nbUpdated icons downloaded from bter\n"; - return $nbUpdated; - } - /** * Icon grabber - Bittrex */ @@ -440,7 +405,7 @@ class CoindbCommand extends CConsoleCommand } catch (Exception $e) { continue; } - if (strlen($data) < 2048) continue; + if (strlen($data) < 3000 || strstr($data, ' 0) { @@ -504,8 +469,7 @@ class CoindbCommand extends CConsoleCommand echo "alcurex: try to download new icons...\n"; foreach ($coins as $coin) { $coin = getdbo('db_coins', $coin["id"]); - $symbol = $coin->symbol; - if (!empty($coin->symbol2)) $symbol = $coin->symbol2; + $symbol = $coin->getOfficialSymbol(); $local = $this->basePath."/images/coin-{$symbol}.png"; try { $data = @ file_get_contents($url.strtoupper($symbol).'.png'); @@ -525,6 +489,41 @@ class CoindbCommand extends CConsoleCommand return $nbUpdated; } + /** + * Icon grabber - KuCoin + */ + public function grabKuCoinIcons() + { + $url = 'https://assets.kucoin.com/www/coin/pc/';//GRIN.png + $nbUpdated = 0; + $sql = "SELECT DISTINCT coins.id FROM coins INNER JOIN markets M ON M.coinid = coins.id ". + "WHERE M.name='kucoin' AND IFNULL(coins.image,'') = ''"; + $coins = dbolist($sql); + if (empty($coins)) + return 0; + echo "kucoin: try to download new icons...\n"; + foreach ($coins as $coin) { + $coin = getdbo('db_coins', $coin["id"]); + $symbol = $coin->getOfficialSymbol(); + $local = $this->basePath."/images/coin-{$symbol}.png"; + try { + $data = @ file_get_contents($url.$symbol.'.png'); + } catch (Exception $e) { + continue; + } + if (strlen($data) < 2048) continue; + echo $symbol." icon found\n"; + file_put_contents($local, $data); + if (filesize($local) > 0) { + $coin->image = "/images/coin-{$symbol}.png"; + $nbUpdated += $coin->save(); + } + } + if ($nbUpdated) + echo "$nbUpdated icons downloaded from kucoin\n"; + return $nbUpdated; + } + /** * Icon grabber - NovaExchange */ @@ -540,8 +539,7 @@ class CoindbCommand extends CConsoleCommand echo "nova: try to download new icons...\n"; foreach ($coins as $coin) { $coin = getdbo('db_coins', $coin["id"]); - $symbol = $coin->symbol; - if (!empty($coin->symbol2)) $symbol = $coin->symbol2; + $symbol = $coin->getOfficialSymbol(); $local = $this->basePath."/images/coin-{$symbol}.png"; try { $data = @ file_get_contents($url.strtolower($symbol).'.png'); diff --git a/web/yaamp/commands/ExchangeCommand.php b/web/yaamp/commands/ExchangeCommand.php index 15f143f..e659917 100644 --- a/web/yaamp/commands/ExchangeCommand.php +++ b/web/yaamp/commands/ExchangeCommand.php @@ -122,6 +122,16 @@ class ExchangeCommand extends CConsoleCommand public function testApiKeys() { + if (!empty(EXCH_BINANCE_KEY)) { + $balance = binance_api_user('account'); + if (!is_object($balance)) echo "binance error ".json_encode($balance)."\n"; + else { + $assets = $balance->balances; + foreach ($assets as $asset) { + if ($asset->asset == 'BTC') echo("binance: ".json_encode($asset)."\n"); + } + } + } if (!empty(EXCH_BITSTAMP_KEY)) { $balance = bitstamp_api_user('balance'); if (!is_array($balance)) echo "bitstamp error ".json_encode($balance)."\n"; @@ -143,11 +153,6 @@ class ExchangeCommand extends CConsoleCommand if (!is_object($balance)) echo "bleutrade error\n"; else echo("bleutrade btc: ".json_encode($balance->result)."\n"); } - if (!empty(EXCH_BTER_KEY)) { - $info = bter_api_user('getfunds'); - if (!$info || arraySafeVal($info,'result') != 'true' || !isset($info['available_funds'])) echo "bter error\n"; - else echo("bter available: ".json_encode($info['available_funds'])."\n"); - } if (!empty(EXCH_CCEX_KEY)) { $ccex = new CcexAPI; $balances = $ccex->getBalances(); @@ -164,6 +169,11 @@ class ExchangeCommand extends CConsoleCommand if (!is_array($balances)) echo "coinsmarkets error ".json_encode($balances)."\n"; else echo("coinsmarkets: ".json_encode($balances['return'])."\n"); } + if (!empty(EXCH_CREX24_KEY)) { + $balance = crex24_api_user('account/balance',array('currency'=>'BTC')); + if (!is_array($balance)) echo "crex24 error ".json_encode($balance)."\n"; + else echo("crex24: ".json_encode($balance)."\n"); + } if (!empty(EXCH_CRYPTOPIA_KEY)) { $balance = cryptopia_api_user('GetBalance',array("Currency"=>"BTC")); if (!is_object($balance)) echo("cryptopia error ".json_encode($balance)."\n"); @@ -181,6 +191,11 @@ class ExchangeCommand extends CConsoleCommand $balance = kraken_api_user('Balance'); echo("kraken btc: ".json_encode($balance)."\n"); } + if (!empty(EXCH_KUCOIN_KEY) && !empty(EXCH_KUCOIN_PASSPHRASE)) { + $balance = kucoin_api_user('accounts',array('currency'=>'BTC')); + if (!is_object($balance) || !isset($balance->data)) echo "kucoin error ".json_encode($balance)."\n"; + else echo("kucoin: ".json_encode($balance->data)."\n"); + } if (!empty(EXCH_LIVECOIN_KEY)) { $livecoin = new LiveCoinApi; $balance = $livecoin->getBalances('BTC'); diff --git a/web/yaamp/commands/PayoutCommand.php b/web/yaamp/commands/PayoutCommand.php index 128e2ef..84fbad6 100644 --- a/web/yaamp/commands/PayoutCommand.php +++ b/web/yaamp/commands/PayoutCommand.php @@ -35,6 +35,10 @@ class PayoutCommand extends CConsoleCommand echo "Yiimp payout command\n"; echo "Usage: yiimp payout check [fixit]\n"; echo "Usage: payout coinswaps\n"; + echo "Usage: payout confirmations \n"; + if (YIIMP_CLI_ALLOW_TXS) + echo "Usage: payout redotx \n"; + return 1; } elseif ($command == 'check') { @@ -52,6 +56,14 @@ class PayoutCommand extends CConsoleCommand } elseif ($command == 'coinswaps') { $this->checkCoinSwaps($args); return 0; + + } elseif ($command == 'confirmations') { + $this->checkPayoutsConfirmations($args); + return 0; + + } elseif ($command == 'redotx' && YIIMP_CLI_ALLOW_TXS) { + $this->redoTransaction($args); + return 0; } } @@ -121,9 +133,12 @@ class PayoutCommand extends CConsoleCommand if (empty($payouts) || empty($ids)) return 0; + $DCR = ($coin->rpcencoding == 'DCR' || $coin->getOfficialSymbol() == 'DCR'); + $DGB = ($coin->rpcencoding == 'DGB' || $coin->getOfficialSymbol() == 'DGB'); + $remote = new WalletRPC($coin); $account = ''; - if ($coin->rpcencoding == 'DCR') $account = '*'; + if ($DCR || $DGB) $account = '*'; $rawtxs = $remote->listtransactions($account, 25000); foreach ($ids as $uid => $user_addr) @@ -263,4 +278,93 @@ class PayoutCommand extends CConsoleCommand echo "earnings: all fine\n"; } } + + /** + * Can be used to redo a payment made on a bad fork... + */ + protected function redoTransaction($args) + { + $txid = arraySafeVal($args, 1); + if (empty($txid)) + die("Usage..\n"); + + $payouts = getdbolist('db_payouts', "tx=:txid", array(':txid'=>$txid)); + if (empty($payouts)) + die("Invalid payout txid\n"); + echo "users to pay: ".count($payouts)."\n"; + + $payout = $payouts[0]; + $coin = getdbo('db_coins', $payout->idcoin); + if (!$coin || !$coin->installed) + die("Invalid payout coin id\n"); + + $relayfee = 0.0001; + + $dests = array(); $total = 0.; + foreach ($payouts as $payout) { + $user = getdbo('db_accounts', $payout->account_id); + if (!$user || $user->coinid != $coin->id) continue; + if (doubleval($payout->amount) < $relayfee) continue; // dust if < relayfee + $dests[$user->username] = doubleval($payout->amount); + $total += doubleval($payout->amount); + } + + echo "$total {$coin->symbol} to pay...\n"; + + $nbnew = 0; + $remote = new WalletRPC($coin); + $res = $remote->sendmany((string) $coin->account, $dests); + if (!$res) var_dump($remote->error); + else { + $new_txid = $res; + echo "txid: $new_txid\n"; + foreach ($payouts as $payout) { + if (doubleval($payout->amount) < $relayfee) continue; + $p = new db_payouts; + $p->time = time(); + $p->idcoin = $coin->id; + $p->amount = doubleval($payout->amount); + $p->account_id = $payout->account_id; + $p->completed = 1; + $p->fee = 0; + $p->tx = $new_txid; + $nbnew += $p->insert(); + } + echo "payouts rows added: $nbnew\n"; + if ($nbnew == count($payouts)) { + $res = dborun("UPDATE payouts SET completed=0, tx='orphaned', memoid='redo' WHERE tx=:txid", array(':txid'=>$txid)); + echo "payouts marked as 'orphaned': $res\n"; + } + } + return $nbnew; + } + + /** + * List the last payouts made for a wallet and check if the tx have confirmations + */ + protected function checkPayoutsConfirmations($args) + { + $symbol = arraySafeVal($args, 1); + if (empty($symbol)) + die("payout confirmations \n"); + + $coin = getdbosql('db_coins', "symbol=:symbol", array(':symbol'=>$symbol)); + if (!$coin) { + echo "wallet $symbol not found!\n"; + return 0; + } + $since = time() - (72 * 3600); + $data = dbolist("SELECT P.tx, MAX(P.time) as time, SUM(P.amount) as amount FROM payouts P ". + "WHERE P.time>$since AND P.idcoin=".$coin->id." ". + "GROUP BY P.tx ORDER BY time DESC" + ); + + $remote = new WalletRPC($coin); + foreach ($data as $row) { + $txid = $row['tx']; + $tx = $remote->gettransaction($txid); + echo strftime('%Y-%m-%d %H:%M', $row['time'])." $txid ".$tx['confirmations']. + " confs (".altcoinvaluetoa($row['amount'],4)." $symbol, fees: ".bitcoinvaluetoa($tx['fee']).")\n"; + } + } } diff --git a/web/yaamp/commands/UserCommand.php b/web/yaamp/commands/UserCommand.php index 4d3e9d5..eb11139 100644 --- a/web/yaamp/commands/UserCommand.php +++ b/web/yaamp/commands/UserCommand.php @@ -26,6 +26,7 @@ class UserCommand extends CConsoleCommand echo "YiiMP user command(s)\n"; echo "Usage: yiimp user delete \n"; echo " yiimp user swap
- assign symbol\n"; + echo " yiimp user search \n"; echo " yiimp user purge [days] (default 180)\n"; return 1; @@ -48,12 +49,19 @@ class UserCommand extends CConsoleCommand echo "$nb user(s) deleted\n"; return 0; + } else if ($args[0] == 'search') { + if (!isset($args[1])) + die("usage: yiimp user search \n"); + $addr = $args[1]; + $this->searchUserByIP($addr); + } else if ($args[0] == 'swap') { if (!isset($args[2])) - die("usage: yiimp user swap
- assign symbol"); + die("usage: yiimp user swap
[force] - assign symbol\n"); $addr = $args[1]; $symbol = $args[2]; - $this->swapUserCoin($addr, $symbol); + $force = arraySafeVal($args, 3, false); + $this->swapUserCoin($addr, $symbol, $force); return 0; } } @@ -124,6 +132,34 @@ class UserCommand extends CConsoleCommand return $nbDeleted; } + /** + * Search users by worker ip + */ + public function searchUserByIP($ip) + { + $workers = new db_workers; + $rows = $workers->findAll(array( + 'condition'=>'ip LIKE :ip', + 'params'=>array(':ip'=>"%$ip%"), + 'limit'=>25, + 'order'=>'id DESC', + )); + + if (empty($rows)) { + echo "no user(s) found with this ip\n"; + return 0; + } + + foreach ($rows as $worker) { + $user = getdbo('db_accounts', $worker->userid); + if (!$user) continue; + $time = strftime("%Y-%m-%d %H:%M:%S", $worker->time); + echo "$time\t{$user->username}\t{$worker->ip}\t{$worker->algo}\n"; + } + + return 0; + } + /** * Manually assign the right currency symbol to an user (for yiimp mode without exchange) */ diff --git a/web/yaamp/core/backend/backend.php b/web/yaamp/core/backend/backend.php index 4f0c177..b2940d3 100644 --- a/web/yaamp/core/backend/backend.php +++ b/web/yaamp/core/backend/backend.php @@ -1,5 +1,6 @@ vendorid) || empty($bench->device)) continue; + if ($bench->algo == 'x16r') { // not constant, inaccurate + $bench->delete(); + continue; + } + + $rawdata = json_encode($bench->attributes); + if (strpos($rawdata,"script")) { + debuglog("bench record deleted : $rawdata"); + $bench->delete(); + continue; + } + $dups = getdbocount('db_benchmarks', "vendorid=:vid AND client=:client AND os=:os AND driver=:drv AND throughput=:thr AND userid=:uid", array(':vid'=>$bench->vendorid, ':client'=>$bench->client, ':os'=>$bench->os, ':drv'=>$bench->driver,':thr'=>$bench->throughput,':uid'=>$bench->userid) ); @@ -48,6 +62,10 @@ function BenchUpdateChips() $bench->delete(); continue; } + if ($bench->chip == 'GPU' || $bench->chip == 'Graphics Device') { + $bench->delete(); + continue; + } debuglog("bench: {$bench->device} ($chip)..."); $bench->save(); } diff --git a/web/yaamp/core/backend/blocks.php b/web/yaamp/core/backend/blocks.php index 7625e1a..5854f15 100644 --- a/web/yaamp/core/backend/blocks.php +++ b/web/yaamp/core/backend/blocks.php @@ -98,6 +98,16 @@ function BackendBlockFind1($coinid = NULL) } if(!$coin->enable) continue; if($coin->rpcencoding == 'DCR' && !$coin->auto_ready) continue; + + $dblock = getdbosql('db_blocks', "coin_id=:coinid AND blockhash=:hash AND height=:height AND id!=:blockid", + array(':coinid'=>$coin->id, ':hash'=>$db_block->blockhash, ':height'=>$db_block->height, ':blockid'=>$db_block->id) + ); + + if($dblock) { + debuglog("warning: Doubled {$coin->symbol} block found for block height {$db_block->height}!"); + $db_block->delete(); + continue; + } $db_block->category = 'orphan'; $remote = new WalletRPC($coin); @@ -180,6 +190,10 @@ function BackendBlocksUpdate($coinid = NULL) continue; } + if (!$coin->auto_ready || ($coin->target_height && $coin->target_height > $coin->block_height)) { + continue; + } + $remote = new WalletRPC($coin); if(empty($block->txhash)) { @@ -271,6 +285,7 @@ function BackendBlocksUpdate($coinid = NULL) // auto update mature_blocks if ($block->confirmations > 0 && $block->confirmations < $coin->mature_blocks || empty($coin->mature_blocks)) { + $coin = getdbo('db_coins', $block->coin_id); // refresh coin data debuglog("{$coin->symbol} mature_blocks updated to {$block->confirmations}"); $coin->mature_blocks = $block->confirmations; $coin->save(); @@ -285,7 +300,7 @@ function BackendBlocksUpdate($coinid = NULL) } //////////////////////////////////////////////////////////////////////////////////////////// -// Search new block transactions +// Search new block transactions (main thread) function BackendBlockFind2($coinid = NULL) { @@ -299,23 +314,20 @@ function BackendBlockFind2($coinid = NULL) if($coin->symbol == 'BTC') continue; $remote = new WalletRPC($coin); + $timerpc = microtime(true); $mostrecent = 0; if(empty($coin->lastblock)) $coin->lastblock = ''; $list = $remote->listsinceblock($coin->lastblock); + $rpcdelay = microtime(true) - $timerpc; + if ($rpcdelay > 0.5) + screenlog(__FUNCTION__.": {$coin->symbol} listsinceblock took ".round($rpcdelay,3)." sec, ". + (is_array($list) ? count($list) : 0). "txs"); if(!$list) continue; -// debuglog("find2 $coin->symbol"); foreach($list['transactions'] as $transaction) { if(!isset($transaction['blockhash'])) continue; if($transaction['time'] > time() - 5*60) continue; - - if($transaction['time'] > $mostrecent) - { - $coin->lastblock = $transaction['blockhash']; - $mostrecent = $transaction['time']; - } - if($transaction['time'] < time() - 60*60) continue; if($transaction['category'] != 'generate' && $transaction['category'] != 'immature') continue; @@ -330,6 +342,13 @@ function BackendBlockFind2($coinid = NULL) if ($coin->rpcencoding == 'DCR') debuglog("{$coin->name} generated block {$blockext['height']} detected!"); + if($transaction['time'] > $mostrecent) { + $coin = getdbo('db_coins', $coin->id); // refresh coin data + $coin->lastblock = $transaction['blockhash']; + $coin->save(); + $mostrecent = $transaction['time']; + } + $db_block = new db_blocks; $db_block->blockhash = $transaction['blockhash']; $db_block->coin_id = $coin->id; @@ -357,6 +376,7 @@ function BackendBlockFind2($coinid = NULL) } if (!$coin->hasmasternodes) { + $coin = getdbo('db_coins', $coin->id); // refresh coin data $coin->hasmasternodes = true; $coin->save(); } @@ -370,14 +390,12 @@ function BackendBlockFind2($coinid = NULL) debuglog(__FUNCTION__.": unable to insert block!"); BackendBlockNew($coin, $db_block); - } - - $coin->save(); + } // tx } $d1 = microtime(true) - $t1; controller()->memcache->add_monitoring_function(__FUNCTION__, $d1); - //debuglog(__FUNCTION__." took ".round($d1,3)." sec"); + if ($d1 > 3.0) screenlog(__FUNCTION__.": took ".round($d1,3)." sec"); } //////////////////////////////////////////////////////////////////////////////////////////// diff --git a/web/yaamp/core/backend/coins.php b/web/yaamp/core/backend/coins.php index 51c0e80..1112671 100644 --- a/web/yaamp/core/backend/coins.php +++ b/web/yaamp/core/backend/coins.php @@ -140,12 +140,13 @@ function BackendCoinsUpdate() $coin->charity_amount = $template['_V2']/100000000; if(isset($template['payee_amount']) && $coin->symbol != 'LIMX') { - $coin->charity_amount = $template['payee_amount']/100000000; + $coin->charity_amount = doubleval($template['payee_amount'])/100000000; $coin->reward -= $coin->charity_amount; } else if(isset($template['masternode']) && arraySafeVal($template,'masternode_payments_enforced')) { - $coin->reward -= arraySafeVal($template['masternode'],'amount',0)/100000000; + if (arraySafeVal($template,'masternode_payments_started')) + $coin->reward -= arraySafeVal($template['masternode'],'amount',0)/100000000; $coin->hasmasternodes = true; } diff --git a/web/yaamp/core/backend/functions.php b/web/yaamp/core/backend/functions.php new file mode 100644 index 0000000..0c680c7 --- /dev/null +++ b/web/yaamp/core/backend/functions.php @@ -0,0 +1,12 @@ + $ticker) + { + $pairs = explode('_', $c); + $symbol = strtoupper(reset($pairs)); $base = end($pairs); + if($symbol == 'BTC' || $base != 'btc') continue; + + if (market_get($exchange, $symbol, "disabled")) { + $market->disabled = 1; + $market->message = 'disabled from settings'; + } + $coin = getdbosql('db_coins', "symbol='{$symbol}'"); + if(!$coin) continue; + if(!$coin->installed && !$coin->watch) continue; + $market = getdbosql('db_markets', "coinid={$coin->id} and name='{$exchange}'"); + + if(!$market) continue; + $price2 = ($ticker->bidPrice + $ticker->askPrice)/2; + $market->price2 = AverageIncrement($market->price2, $price2); + $market->price = AverageIncrement($market->price, $ticker->bidPrice); + $market->pricetime = time(); + $market->priority = -1; + $market->txfee = 0.2; // trade pct + $market->save(); + // debuglog("$exchange: update $symbol: {$market->price} {$market->price2}"); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// + +function updateCryptoBridgeMarkets($force = false) +{ + $exchange = 'cryptobridge'; + if (exchange_get($exchange, 'disabled')) return; + + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + + $result = cryptobridge_api_query('ticker'); + if(!is_array($result)) return; + + foreach($result as $ticker) + { + if (is_null(objSafeVal($ticker,'id'))) continue; + $pairs = explode('_', $ticker->id); + $symbol = reset($pairs); $base = end($pairs); + if($symbol == 'BTC' || $base != 'BTC') continue; + + if (market_get($exchange, $symbol, "disabled")) { + $market->disabled = 1; + $market->message = 'disabled from settings'; + } + + $coin = getdbosql('db_coins', "symbol='{$symbol}'"); + if(!$coin) continue; + if(!$coin->installed && !$coin->watch) continue; + + $market = getdbosql('db_markets', "coinid={$coin->id} and name='{$exchange}'"); + if(!$market) continue; + + $price2 = ($ticker->bid + $ticker->ask)/2; + $market->price2 = AverageIncrement($market->price2, $price2); + $market->price = AverageIncrement($market->price, $ticker->bid); + $market->pricetime = time(); + $market->priority = -1; + $market->txfee = 0.2; // trade pct + $market->save(); + + //debuglog("$exchange: update $symbol: {$market->price} {$market->price2}"); + } +} + +function updateEscoDexMarkets($force = false) +{ + $exchange = 'escodex'; + if (exchange_get($exchange, 'disabled')) return; + + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + $result = escodex_api_query('ticker'); + if(!is_array($result)) return; + foreach($result as $ticker) + { + if (is_null(objSafeVal($ticker,'id'))) continue; + #$pairs = explode('_', $ticker->id); + $symbol = $ticker->quote; $base = $ticker->base; + if($symbol == 'BTC' || $base != 'BTC') continue; + if (market_get($exchange, $symbol, "disabled")) { + $market->disabled = 1; + $market->message = 'disabled from settings'; + } + + $coin = getdbosql('db_coins', "symbol='{$symbol}'"); + if(!$coin) continue; + if(!$coin->installed && !$coin->watch) continue; + $market = getdbosql('db_markets', "coinid={$coin->id} and name='{$exchange}'"); + if(!$market) continue; + + $price2 = ($ticker->highest_bid + $ticker->lowest_ask)/2; + $market->price2 = AverageIncrement($market->price2, $price2); + $market->price = AverageIncrement($market->price, $ticker->highest_bid); + $market->pricetime = time(); + $market->priority = -1; + $market->txfee = 0.2; // trade pct + $market->save(); + //debuglog("$exchange: update $symbol: {$market->price} {$market->price2}"); + if ((empty($coin->price))||(empty($coin->price2))) { + $coin->price = $market->price; + $coin->price2 = $market->price2; + $coin->market = $exchange; + $coin->save(); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// + +function updateGateioMarkets($force = false) +{ + $exchange = 'gateio'; + if (exchange_get($exchange, 'disabled')) return; + + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + + $markets = gateio_api_query('tickers'); + if(!is_array($markets)) return; + + foreach($list as $market) + { + $coin = getdbo('db_coins', $market->coinid); + if(!$coin) continue; + + $symbol = $coin->getOfficialSymbol(); + if (market_get($exchange, $symbol, "disabled")) { + $market->disabled = 1; + $market->message = 'disabled from settings'; + $market->save(); + continue; + } + + $dbpair = strtolower($symbol).'_btc'; + foreach ($markets as $pair => $ticker) { + if ($pair != $dbpair) continue; + $price2 = (doubleval($ticker['highestBid']) + doubleval($ticker['lowestAsk'])) / 2; + $market->price = AverageIncrement($market->price, doubleval($ticker['highestBid'])); + $market->price2 = AverageIncrement($market->price2, $price2); + $market->pricetime = time(); + $market->priority = -1; + $market->txfee = 0.2; // trade pct + $market->save(); + + if (empty($coin->price2)) { + $coin->price = $market->price; + $coin->price2 = $market->price2; + $coin->market = $exchange; + $coin->save(); + } + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// + +function updateGraviexMarkets($force = false) +{ + $exchange = 'graviex'; + if (exchange_get($exchange, 'disabled')) return; + + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + + $markets = graviex_api_query('tickers'); + if(!is_array($markets)) return; + + foreach($list as $market) + { + $coin = getdbo('db_coins', $market->coinid); + if(!$coin) continue; + + $symbol = $coin->getOfficialSymbol(); + if (market_get($exchange, $symbol, "disabled")) { + $market->disabled = 1; + $market->message = 'disabled from settings'; + $market->save(); + continue; + } + + $symbol = strtolower($symbol); + $dbpair = $symbol.'btc'; + foreach ($markets as $pair => $ticker) { + if ($pair != $dbpair) continue; + $price2 = ($ticker['ticker']['buy']+$ticker['ticker']['sell'])/2; + $market->price = AverageIncrement($market->price, $ticker['ticker']['buy']); + $market->price2 = AverageIncrement($market->price2, $price2); + $market->pricetime = time(); + $market->save(); + + if (empty($coin->price2)) { + $coin->price = $market->price; + $coin->price2 = $market->price2; + $coin->market = $exchange; + $coin->save(); + } + } + } +} + ///////////////////////////////////////////////////////////////////////////////////////////// function updateKrakenMarkets($force = false) @@ -287,6 +512,9 @@ function updateKrakenMarkets($force = false) $exchange = 'kraken'; if (exchange_get($exchange, 'disabled')) return; + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + $result = kraken_api_query('AssetPairs'); if(!is_array($result)) return; @@ -351,6 +579,9 @@ function updateBittrexMarkets($force = false) $exchange = 'bittrex'; if (exchange_get($exchange, 'disabled')) return; + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + $list = bittrex_api_query('public/getcurrencies'); if(!is_object($list)) return; foreach($list->result as $currency) @@ -431,6 +662,9 @@ function updateCCexMarkets() $exchange = 'c-cex'; if (exchange_get($exchange, 'disabled')) return; + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + $ccex = new CcexAPI; $list = $ccex->getMarketSummaries(); if (!is_array($list)) return; @@ -518,6 +752,9 @@ function updatePoloniexMarkets() $exchange = 'poloniex'; if (exchange_get($exchange, 'disabled')) return; + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + $poloniex = new poloniex; $tickers = $poloniex->get_ticker(); @@ -603,6 +840,9 @@ function updateYobitMarkets() $exchange = 'yobit'; if (exchange_get($exchange, 'disabled')) return; + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + $res = yobit_api_query('info'); if(!is_object($res)) return; @@ -688,10 +928,12 @@ function updateJubiMarkets() $exchange = 'jubi'; if (exchange_get($exchange, 'disabled')) return; + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + $btc = jubi_api_query('ticker', "?coin=btc"); if(!is_object($btc)) return; - $list = getdbolist('db_markets', "name='jubi'"); foreach($list as $market) { $coin = getdbo('db_coins', $market->coinid); @@ -733,10 +975,12 @@ function updateAlcurexMarkets() $exchange = 'alcurex'; if (exchange_get($exchange, 'disabled')) return; + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + $data = alcurex_api_query('market', "?info=on"); if(!is_object($data)) return; - $list = getdbolist('db_markets', "name='$exchange'"); foreach($list as $market) { $coin = getdbo('db_coins', $market->coinid); @@ -774,7 +1018,105 @@ function updateAlcurexMarkets() $coin->price2 = $market->price2; $coin->save(); } -// debuglog("alcurex: $pair $market->price ".bitcoinvaluetoa($market->price2)); + //debuglog("$exchange: $pair price updated to {$market->price}"); + break; + } + } + } +} + +function updateCoinbeneMarkets() +{ + $exchange = 'coinbene'; + if (exchange_get($exchange, 'disabled')) return; + + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + + $data = coinbene_api_query('market/ticker', 'symbol=all'); + $data = objSafeVal($data,'ticker'); + if(!is_array($data)) return; + + foreach($list as $market) { + $coin = getdbo('db_coins', $market->coinid); + if(!$coin) continue; + if(!$coin->installed && !$coin->watch) continue; + + $symbol = $coin->getOfficialSymbol(); + if (market_get($exchange, $symbol, "disabled")) { + $market->disabled = 1; + $market->message = 'disabled from settings'; + $market->save(); + continue; + } + + $pair = $symbol.'BTC'; + foreach($data as $ticker) { + if ($ticker->symbol != $pair) continue; + + $price2 = ($ticker->bid+$ticker->ask)/2; + $market->price2 = AverageIncrement($market->price2, $price2); + $market->price = AverageIncrement($market->price, $ticker->bid); + $market->pricetime = time(); + $market->save(); + + break; + } + } +} + +function updateCrex24Markets() +{ + $exchange = 'crex24'; + if (exchange_get($exchange, 'disabled')) return; + + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + + $data = crex24_api_query('tickers'); + if(!is_array($data)) return; + + foreach($list as $market) + { + $coin = getdbo('db_coins', $market->coinid); + if(!$coin) continue; + + $symbol = $coin->getOfficialSymbol(); + $pair = strtoupper($symbol).'-BTC'; + + $sqlFilter = ''; + if (!empty($market->base_coin)) { + $pair = strtoupper($symbol.'-'.$market->base_coin); + $sqlFilter = "AND base_coin='{$market->base_coin}'"; + } + + if (market_get($exchange, $symbol, "disabled")) { + $market->disabled = 1; + $market->message = 'disabled from settings'; + $market->save(); + continue; + } + + foreach ($data as $ticker) { + if ($ticker->instrument === $pair) { + if ($market->disabled < 9) { + $nbm = (int) dboscalar("SELECT COUNT(id) FROM markets WHERE coinid={$coin->id} $sqlFilter"); + $market->disabled = ($ticker->bid < $ticker->ask/2) && ($nbm > 1); + } + + $price2 = ($ticker->bid+$ticker->ask)/2; + $market->price2 = AverageIncrement($market->price2, $price2); + $market->price = AverageIncrement($market->price, $ticker->bid); + $market->pricetime = time(); // $ticker->timestamp "2018-08-31T12:48:56Z" + $market->save(); + + if (empty($coin->price) && $ticker->ask) { + $coin->price = $market->price; + $coin->price2 = $price2; + $coin->save(); + } + //debuglog("$exchange: $pair price updated to {$market->price}"); + break; } } } @@ -785,10 +1127,12 @@ function updateCryptopiaMarkets() $exchange = 'cryptopia'; if (exchange_get($exchange, 'disabled')) return; + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + $data = cryptopia_api_query('GetMarkets', 24); if(!is_object($data)) return; - $list = getdbolist('db_markets', "name LIKE('$exchange%')"); foreach($list as $market) { $coin = getdbo('db_coins', $market->coinid); @@ -1045,10 +1389,12 @@ function updateBinanceMarkets() $exchange = 'binance'; if (exchange_get($exchange, 'disabled')) return; + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + $tickers = binance_api_query('ticker/allBookTickers'); if(!is_array($tickers)) return; - $list = getdbolist('db_markets', "name='$exchange'"); foreach($list as $market) { $coin = getdbo('db_coins', $market->coinid); @@ -1082,56 +1428,17 @@ function updateBinanceMarkets() } } -function updateBterMarkets() -{ - $exchange = 'bter'; - if (exchange_get($exchange, 'disabled')) return; - - $markets = bter_api_query('tickers'); - if(!is_array($markets)) return; - - $list = getdbolist('db_markets', "name='$exchange'"); - foreach($list as $market) - { - $coin = getdbo('db_coins', $market->coinid); - if(!$coin) continue; - - $symbol = $coin->getOfficialSymbol(); - if (market_get($exchange, $symbol, "disabled")) { - $market->disabled = 1; - $market->message = 'disabled from settings'; - $market->save(); - continue; - } - - $dbpair = strtolower($symbol).'_btc'; - foreach ($markets as $pair => $ticker) { - if ($pair != $dbpair) continue; - - $market->price = AverageIncrement($market->price, $ticker['buy']); - $market->price2 = AverageIncrement($market->price2, $ticker['avg']); - $market->pricetime = time(); - if ($market->disabled < 9) $market->disabled = (floatval($ticker['vol_btc']) < 0.01); - $market->save(); - - if (empty($coin->price2)) { - $coin->price = $market->price; - $coin->price2 = $market->price2; - $coin->save(); - } - } - } -} - function updateEmpoexMarkets() { $exchange = 'empoex'; if (exchange_get($exchange, 'disabled')) return; + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + $markets = empoex_api_query('marketinfo'); if(!is_array($markets)) return; - $list = getdbolist('db_markets', "name='$exchange'"); foreach($list as $market) { $coin = getdbo('db_coins', $market->coinid); @@ -1167,15 +1474,83 @@ function updateEmpoexMarkets() } } +function updateKuCoinMarkets() +{ + $exchange = 'kucoin'; + if (exchange_get($exchange, 'disabled')) return; + + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + + $symbols = kucoin_api_query('symbols','market=BTC'); + if(!kucoin_result_valid($symbols) || empty($symbols->data)) return; + + usleep(500); + $markets = kucoin_api_query('market/allTickers'); + if(!kucoin_result_valid($markets) || empty($markets->data)) return; + if(!isset($markets->data->ticker) || !is_array($markets->data->ticker)) return; + $tickers = $markets->data->ticker; + + foreach($list as $market) + { + $coin = getdbo('db_coins', $market->coinid); + if(!$coin) continue; + + $symbol = $coin->getOfficialSymbol(); + if (market_get($exchange, $symbol, "disabled")) { + $market->disabled = 1; + $market->message = 'disabled from settings'; + $market->save(); + continue; + } + + $pair = strtoupper($symbol).'-BTC'; + + $enableTrading = false; + foreach ($symbols->data as $sym) { + if (objSafeVal($sym,'symbol') != $pair) continue; + $enableTrading = objSafeVal($sym,'enableTrading',false); + break; + } + + if ($market->disabled == $enableTrading) { + $market->disabled = (int) (!$enableTrading); + $market->save(); + if ($market->disabled) continue; + } + + foreach ($tickers as $ticker) { + if ($ticker->symbol != $pair) continue; + if (objSafeVal($ticker,'buy',-1) == -1) continue; + + $market->price = AverageIncrement($market->price, $ticker->buy); + $market->price2 = AverageIncrement($market->price2, objSafeVal($ticker,'sell',$ticker->buy)); + $market->priority = -1; + $market->pricetime = time(); + + if (floatval($ticker->vol) > 0.01) + $market->save(); + + if (empty($coin->price2)) { + $coin->price = $market->price; + $coin->price2 = $market->price2; + $coin->save(); + } + } + } +} + function updateLiveCoinMarkets() { $exchange = 'livecoin'; if (exchange_get($exchange, 'disabled')) return; + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + $markets = livecoin_api_query('exchange/ticker'); if(!is_array($markets)) return; - $list = getdbolist('db_markets', "name='$exchange'"); foreach($list as $market) { $coin = getdbo('db_coins', $market->coinid); @@ -1241,6 +1616,9 @@ function updateCoinExchangeMarkets() $exchange = 'coinexchange'; if (exchange_get($exchange, 'disabled')) return; + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + $list = coinexchange_api_query('getmarkets'); if(!is_object($list)) return; $markets = coinexchange_api_query('getmarketsummaries'); @@ -1312,6 +1690,9 @@ function updateCoinsMarketsMarkets() $exchange = 'coinsmarkets'; if (exchange_get($exchange, 'disabled')) return; + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + $list = coinsmarkets_api_query('apicoin'); if(empty($list) || !is_array($list)) return; foreach($list as $pair=>$data) @@ -1369,6 +1750,9 @@ function updateStocksExchangeMarkets() $exchange = 'stocksexchange'; if (exchange_get($exchange, 'disabled')) return; + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + $list = stocksexchange_api_query('ticker'); if(empty($list) || !is_array($list)) return; foreach($list as $m) @@ -1416,6 +1800,9 @@ function updateTradeSatoshiMarkets() $exchange = 'tradesatoshi'; if (exchange_get($exchange, 'disabled')) return; + $count = (int) dboscalar("SELECT count(id) FROM markets WHERE name LIKE '$exchange%'"); + if ($count == 0) return; + $data = tradesatoshi_api_query('getmarketsummaries'); if(!is_object($data) || !$data->success || !is_array($data->result)) return; foreach($data->result as $m) @@ -1463,10 +1850,12 @@ function updateShapeShiftMarkets() $exchange = 'shapeshift'; if (exchange_get($exchange, 'disabled')) return; + $list = getdbolist('db_markets', "name LIKE '$exchange%'"); + if (empty($list)) return; + $markets = shapeshift_api_query('marketinfo'); if(!is_array($markets) || empty($markets)) return; - $list = getdbolist('db_markets', "name='$exchange'"); foreach($list as $market) { $coin = getdbo('db_coins', $market->coinid); @@ -1489,7 +1878,7 @@ function updateShapeShiftMarkets() $market->price = AverageIncrement($market->price, $ticker['rate']); $market->price2 = AverageIncrement($market->price2, $ticker['rate']); - $market->txfee = $ticker['minerFee']; + $market->txfee = $ticker['minerFee'] * 100; $market->pricetime = time(); $market->priority = -1; // not ready for trading $market->save(); diff --git a/web/yaamp/core/backend/payment.php b/web/yaamp/core/backend/payment.php index 7a5eaa5..b3704ea 100644 --- a/web/yaamp/core/backend/payment.php +++ b/web/yaamp/core/backend/payment.php @@ -171,17 +171,19 @@ function BackendCoinPayments($coin) if(!$user) continue; if(!isset($addresses[$user->username])) continue; + $payment_amount = bitcoinvaluetoa($addresses[$user->username]); + $payout = new db_payouts; $payout->account_id = $user->id; $payout->time = time(); - $payout->amount = bitcoinvaluetoa($user->balance*$coef); + $payout->amount = $payment_amount; $payout->fee = 0; $payout->idcoin = $coin->id; if ($payout->save()) { $payouts[$payout->id] = $user->id; - $user->balance = bitcoinvaluetoa(floatval($user->balance) - (floatval($user->balance)*$coef)); + $user->balance = bitcoinvaluetoa(floatval($user->balance) - $payment_amount); $user->save(); } } diff --git a/web/yaamp/core/backend/rawcoins.php b/web/yaamp/core/backend/rawcoins.php index 8e7bdf9..34d9768 100644 --- a/web/yaamp/core/backend/rawcoins.php +++ b/web/yaamp/core/backend/rawcoins.php @@ -9,10 +9,12 @@ function updateRawcoins() exchange_set_default('alcurex', 'disabled', true); exchange_set_default('binance', 'disabled', true); - exchange_set_default('bter', 'disabled', true); exchange_set_default('empoex', 'disabled', true); + exchange_set_default('coinbene', 'disabled', true); exchange_set_default('coinexchange', 'disabled', true); exchange_set_default('coinsmarkets', 'disabled', true); + exchange_set_default('escodex', 'disabled', true); + exchange_set_default('gateio', 'disabled', true); exchange_set_default('jubi', 'disabled', true); exchange_set_default('nova', 'disabled', true); exchange_set_default('stocksexchange', 'disabled', true); @@ -22,21 +24,71 @@ function updateRawcoins() if (!exchange_get('bittrex', 'disabled')) { $list = bittrex_api_query('public/getcurrencies'); - if(isset($list->result)) + if(isset($list->result) && !empty($list->result)) { dborun("UPDATE markets SET deleted=true WHERE name='bittrex'"); - foreach($list->result as $currency) + foreach($list->result as $currency) { + if ($currency->Currency == 'BTC') { + exchange_set('bittrex', 'withdraw_fee_btc', $currency->TxFee); + continue; + } updateRawCoin('bittrex', $currency->Currency, $currency->CurrencyLong); + } + } + } + + if (!exchange_get('bitz', 'disabled')) { + $list = bitz_api_query('tickerall'); + if (!empty($list)) { + dborun("UPDATE markets SET deleted=true WHERE name='bitz'"); + foreach($list as $c => $ticker) { + $e = explode('_', $c); + if (strtoupper($e[1]) !== 'BTC') + continue; + $symbol = strtoupper($e[0]); + updateRawCoin('bitz', $symbol); + } } } if (!exchange_get('bleutrade', 'disabled')) { $list = bleutrade_api_query('public/getcurrencies'); - if(isset($list->result)) + if(isset($list->result) && !empty($list->result)) { dborun("UPDATE markets SET deleted=true WHERE name='bleutrade'"); - foreach($list->result as $currency) + foreach($list->result as $currency) { + if ($currency->Currency == 'BTC') { + exchange_set('bleutrade', 'withdraw_fee_btc', $currency->TxFee); + continue; + } updateRawCoin('bleutrade', $currency->Currency, $currency->CurrencyLong); + } + } + } + + if (!exchange_get('coinbene', 'disabled')) { + $data = coinbene_api_query('market/symbol'); + $list = objSafeVal($data, 'symbol'); + if(is_array($list) && !empty($list)) { + dborun("UPDATE markets SET deleted=true WHERE name='coinbene'"); + foreach($list as $ticker) { + if ($ticker->quoteAsset != 'BTC') continue; + $symbol = $ticker->baseAsset; + updateRawCoin('coinbene', $symbol); + } + } + } + + if (!exchange_get('crex24', 'disabled')) { + $list = crex24_api_query('currencies'); + if(is_array($list) && !empty($list)) { + dborun("UPDATE markets SET deleted=true WHERE name='crex24'"); + foreach ($list as $currency) { + $symbol = objSafeVal($currency, 'symbol'); + $name = objSafeVal($currency, 'name'); + if ($currency->isFiat || $currency->isDelisted) continue; + updateRawCoin('crex24', $symbol, $name); + } } } @@ -74,26 +126,6 @@ function updateRawcoins() } } - if (!exchange_get('bter', 'disabled')) { - $list = bter_api_query('marketlist'); - if(is_object($list) && is_array($list->data)) - { - dborun("UPDATE markets SET deleted=true WHERE name='bter'"); - foreach($list->data as $item) { - if (strtoupper($item->curr_b) !== 'BTC') - continue; - if (strpos($item->name, 'Asset') !== false) - continue; - if (strpos($item->name, 'BitShares') !== false && $item->symbol != 'BTS') - continue; - // ignore some dead coins and assets - if (in_array($item->symbol, array('BITGLD','DICE','ROX','TOKEN'))) - continue; - updateRawCoin('bter', $item->symbol, $item->name); - } - } - } - if (!exchange_get('yobit', 'disabled')) { $res = yobit_api_query('info'); if($res) @@ -152,6 +184,36 @@ function updateRawcoins() } } + if (!exchange_get('cryptobridge', 'disabled')) { + $list = cryptobridge_api_query('ticker'); + if(is_array($list) && !empty($list)) + { + dborun("UPDATE markets SET deleted=true WHERE name='cryptobridge'"); + foreach($list as $ticker) { + $e = explode('_', $ticker->id); + if (strtoupper($e[1]) !== 'BTC') + continue; + $symbol = strtoupper($e[0]); + updateRawCoin('cryptobridge', $symbol); + } + } + } + + if (!exchange_get('escodex', 'disabled')) { + $list = escodex_api_query('ticker'); + if(is_array($list) && !empty($list)) + { + dborun("UPDATE markets SET deleted=true WHERE name='escodex'"); + foreach($list as $ticker) { + #debuglog (json_encode($ticker)); + if (strtoupper($ticker->base) !== 'BTC') + continue; + $symbol = strtoupper($ticker->quote); + updateRawCoin('escodex', $symbol); + } + } + } + if (!exchange_get('hitbtc', 'disabled')) { $list = hitbtc_api_query('symbols'); if(is_object($list) && isset($list->symbols) && is_array($list->symbols)) @@ -211,6 +273,22 @@ function updateRawcoins() } } + if (!exchange_get('gateio', 'disabled')) { + $json = gateio_api_query('marketlist'); + $list = arraySafeVal($json,'data'); + if(!empty($list)) + { + dborun("UPDATE markets SET deleted=true WHERE name='gateio'"); + foreach($list as $item) { + if ($item['curr_b'] != 'BTC') + continue; + $symbol = trim(strtoupper($item['symbol'])); + $name = trim($item['name']); + updateRawCoin('gateio', $symbol, $name); + } + } + } + if (!exchange_get('nova', 'disabled')) { $list = nova_api_query('markets'); if(is_object($list) && !empty($list->markets)) @@ -259,6 +337,19 @@ function updateRawcoins() } } + if (!exchange_get('kucoin', 'disabled')) { + $list = kucoin_api_query('currencies'); + if(kucoin_result_valid($list) && !empty($list->data)) + { + dborun("UPDATE markets SET deleted=true WHERE name='kucoin'"); + foreach($list->data as $item) { + $symbol = $item->name; + $name = $item->fullName; + updateRawCoin('kucoin', $symbol, $name); + } + } + } + if (!exchange_get('livecoin', 'disabled')) { $list = livecoin_api_query('exchange/ticker'); if(is_array($list)) @@ -343,7 +434,7 @@ function updateRawCoin($marketname, $symbol, $name='unknown') if($symbol == 'BTC') return; $coin = getdbosql('db_coins', "symbol=:symbol", array(':symbol'=>$symbol)); - if(!$coin && $marketname != 'yobit') + if(!$coin && YAAMP_CREATE_NEW_COINS) { $algo = ''; if ($marketname == 'cryptopia') { @@ -361,11 +452,15 @@ function updateRawCoin($marketname, $symbol, $name='unknown') } } - if (in_array($marketname, array('nova','askcoin','binance','coinexchange','coinsmarkets','hitbtc'))) { + if (in_array($marketname, array('nova','askcoin','binance','bitz','coinexchange','coinsmarkets','cryptobridge','hitbtc'))) { // don't polute too much the db with new coins, its better from exchanges with labels return; } + // some other to ignore... + if (in_array($marketname, array('crex24','escodex','yobit','coinbene','kucoin','tradesatoshi'))) + return; + if (market_get($marketname, $symbol, "disabled")) { return; } diff --git a/web/yaamp/core/backend/sell.php b/web/yaamp/core/backend/sell.php index 5b25a2c..7fba09b 100644 --- a/web/yaamp/core/backend/sell.php +++ b/web/yaamp/core/backend/sell.php @@ -38,7 +38,7 @@ function sellCoinToExchange($coin) $market = getBestMarket($coin); if(!$market) return; - if(!$coin->sellonbid && $market->lastsent != null && $market->lastsent > $market->lasttraded) + if($market->lastsent != null && $market->lastsent > $market->lasttraded) { // debuglog("*** not sending $coin->name to $market->name. last tx is late ***"); return; @@ -77,9 +77,6 @@ function sellCoinToExchange($coin) $amount = round($amount, 8); // debuglog("sending $amount $coin->symbol to $marketname, $deposit_address"); - $market->lastsent = time(); - $market->save(); - // sleep(1); $tx = $remote->sendtoaddress($deposit_address, $amount); @@ -107,6 +104,12 @@ function sellCoinToExchange($coin) return; } } + + if($tx) + { + $market->lastsent = time(); + $market->save(); + } $exchange = new db_exchange; $exchange->market = $marketname; diff --git a/web/yaamp/core/backend/services.php b/web/yaamp/core/backend/services.php index e398698..60dfbd3 100644 --- a/web/yaamp/core/backend/services.php +++ b/web/yaamp/core/backend/services.php @@ -22,6 +22,23 @@ function BackendUpdateServices() 10=>'whirlx', 11=>'qubit', 12=>'quark', + // 13=>'Axiom', + 14=>'lyra2v2', // 14 = Lyra2REv2 + // 15=>'ScryptJaneNf16', // 15 = ScryptJaneNf16 + 16=>'blakecoin', // 16 = Blake256r8 + // 17=>'Blake256r14', + // 18=>'Blake256r8vnl', + // 19=>'Hodl', + // 20=>'DaggerHashimoto', + // 21=>'Decred', + // 22=>'CryptoNight', + 23=>'lbry', + 24=>'equihash', + // 25=>'Pascal', + 26=>'sib', // X11Gost + // 27=>'Sia', + 28=>'blake2s', + 29=>'skunk', ); $res = fetch_url('https://api.nicehash.com/api?method=stats.global.current'); diff --git a/web/yaamp/core/backend/system.php b/web/yaamp/core/backend/system.php index 99c9117..7b2e169 100644 --- a/web/yaamp/core/backend/system.php +++ b/web/yaamp/core/backend/system.php @@ -2,9 +2,6 @@ function BackendDoBackup() { - $d = date('Y-m-d-H', time()); - $filename = "/root/backup/yaamp-$d.sql"; - if (is_readable("/usr/bin/xz")) { $ziptool = "xz --threads=4"; $ext = ".xz"; } else { @@ -19,6 +16,9 @@ function BackendDoBackup() $user = YIIMP_MYSQLDUMP_USER; $pass = YIIMP_MYSQLDUMP_PASS; + $d = date('Y-m-d-H', time()); + $filename = YIIMP_MYSQLDUMP_PATH.DIRECTORY_SEPARATOR."$db-$d.sql"; + if (1) { // faster on huge databases if the disk is fast (nvme), reduce the db lock time system("mysqldump -h $host -u$user -p$pass --skip-extended-insert $db > $filename"); @@ -35,8 +35,7 @@ function BackendQuickClean() foreach($coins as $coin) { - $delay = time() - 24*60*60; - if ($coin->symbol=='DCR') $delay = time() - 7*24*60*60; + $delay = time() - 7*24*60*60; $id = dboscalar("select id from blocks where coin_id=$coin->id and time<$delay and id not in (select blockid from earnings where coinid=$coin->id) @@ -135,7 +134,7 @@ function BackendCleanDatabase() marketHistoryPrune(); $delay = time() - 60*24*60*60; -// dborun("delete from blocks where time<$delay"); + dborun("DELETE from blocks where time<$delay"); dborun("delete from hashstats where time<$delay"); dborun("delete from payouts where time<$delay"); dborun("delete from rentertxs where time<$delay"); diff --git a/web/yaamp/core/backend/users.php b/web/yaamp/core/backend/users.php index 35bc8bb..443443d 100644 --- a/web/yaamp/core/backend/users.php +++ b/web/yaamp/core/backend/users.php @@ -70,7 +70,7 @@ function BackendUsersUpdate() } if (empty($user->coinid)) { - debuglog("{$user->username} is an unknown address!"); + debuglog("{$user->hostaddr} - {$user->username} is an unknown address!"); } $user->save(); diff --git a/web/yaamp/core/common/system.php b/web/yaamp/core/common/system.php index b8eff20..a666673 100644 --- a/web/yaamp/core/common/system.php +++ b/web/yaamp/core/common/system.php @@ -4,7 +4,7 @@ function send_email_alert($name, $title, $message, $t=10) { // debuglog(__FUNCTION__); - $last = memcache_get(controller()->memcache->memcache, "last_email_sent_$name"); + $last = controller()->memcache->get("last_email_sent_$name"); if($last + $t*60 > time()) return; debuglog("mail('".YAAMP_ADMIN_EMAIL."', $title, ...)"); @@ -12,7 +12,7 @@ function send_email_alert($name, $title, $message, $t=10) $b = mail(YAAMP_ADMIN_EMAIL, $title, $message); if(!$b) debuglog('error sending email'); - memcache_set(controller()->memcache->memcache, "last_email_sent_$name", time()); + controller()->memcache->set("last_email_sent_$name", time()); } function dos_filesize($fn) diff --git a/web/yaamp/core/common/util.php b/web/yaamp/core/common/util.php index d494035..999d897 100644 --- a/web/yaamp/core/common/util.php +++ b/web/yaamp/core/common/util.php @@ -40,6 +40,13 @@ function getparam($p,$default='') return isset($_REQUEST[$p]) ? $_REQUEST[$p] : $default; } +function gethexparam($p,$default='') +{ + $str = getparam($p, NULL); + $hex = (is_string($str) && ctype_xdigit($str)) ? $str : $default; + return $hex; +} + function getiparam($p,$default=0) { // workaround for yii default /route/ .... @@ -54,6 +61,12 @@ function getiparam($p,$default=0) return isset($_REQUEST[$p]) ? intval($_REQUEST[$p]) : $default; } +function getalgoparam() +{ + $algo = strip_tags(substr(getparam('algo'), 0, 32)); + return $algo; +} + ////////////////////////////////////////////////////// function downloadFile($url, &$size) diff --git a/web/yaamp/core/exchange/binance.php b/web/yaamp/core/exchange/binance.php index a83b44c..456d09d 100644 --- a/web/yaamp/core/exchange/binance.php +++ b/web/yaamp/core/exchange/binance.php @@ -4,19 +4,91 @@ function binance_api_query($method) { + $exchange = 'binance'; $uri = "https://www.binance.com/api/v1/$method"; $ch = curl_init($uri); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; Binance API PHP client; '.php_uname('s').'; PHP/'.PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION.')'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_TIMEOUT, 30); $res = curl_exec($ch); $obj = json_decode($res); + if(!is_object($obj) && !is_array($obj)) { + $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + debuglog("$exchange: $method failed ($status) ".strip_data($res)); + } return $obj; } +// https://api.binance.com/api/v3/account + +function binance_api_user($method, $params=NULL) +{ + $exchange = 'binance'; + require_once('/etc/yiimp/keys.php'); + if (!defined('EXCH_BINANCE_SECRET')) define('EXCH_BINANCE_SECRET', ''); + + if (empty(EXCH_BINANCE_KEY) || empty(EXCH_BINANCE_SECRET)) return false; + + $mt = explode(' ', microtime()); + $nonce = $mt[1].substr($mt[0], 2, 3); + $url = "https://api.binance.com/api/v3/$method"; + + if (empty($params)) $params = array(); + $params['timestamp'] = $nonce; + $query = http_build_query($params, '', '&'); + + $hmac = strtolower(hash_hmac('sha256', $query, EXCH_BINANCE_SECRET)); + $isPostMethod = ($method == 'order'); + if ($isPostMethod) + $query .= '&signature='.$hmac; + else + $url .= '?'.$query.'&signature='.$hmac; + + $headers = array( + 'Content-Type: application/json;charset=UTF-8', + 'X-MBX-APIKEY: '.EXCH_BINANCE_KEY, + ); + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + if ($isPostMethod) { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $query); + } + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; Binance API PHP client; '.php_uname('s').'; PHP/'.PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION.')'); + curl_setopt($ch, CURLOPT_ENCODING , ''); + //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + //curl_setopt($ch, CURLOPT_VERBOSE, 1); + + $res = curl_exec($ch); + if($res === false) { + $e = curl_error($ch); + debuglog("$exchange: $method $e"); + curl_close($ch); + return false; + } + + $result = json_decode($res); + if(!is_object($result) && !is_array($result)) { + $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + debuglog("$exchange: $method failed ($status) ".strip_data($res)); + } + + curl_close($ch); + + return $result; +} + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // manual update of one market diff --git a/web/yaamp/core/exchange/bitstamp.php b/web/yaamp/core/exchange/bitstamp.php index 2b86158..0431129 100644 --- a/web/yaamp/core/exchange/bitstamp.php +++ b/web/yaamp/core/exchange/bitstamp.php @@ -86,7 +86,8 @@ function getBitstampBalances() if (is_object($savebalance)) { $balances = bitstamp_api_user('balance'); if (is_array($balances)) { - $savebalance->balance = arraySafeVal($balances, 'btc_balance'); + $savebalance->balance = arraySafeVal($balances, 'btc_balance',0.) - arraySafeVal($balances, 'btc_reserved'); + $savebalance->onsell = arraySafeVal($balances, 'btc_reserved'); $savebalance->save(); } } diff --git a/web/yaamp/core/exchange/bitz.php b/web/yaamp/core/exchange/bitz.php new file mode 100644 index 0000000..cd654e2 --- /dev/null +++ b/web/yaamp/core/exchange/bitz.php @@ -0,0 +1,27 @@ +balance = arraySafeVal($b, 'available'); + $savebalance->balance = arraySafeVal($b, 'available',0.); + $savebalance->onsell = arraySafeVal($b, 'orders',0.); $savebalance->save(); } } diff --git a/web/yaamp/core/exchange/coinbene.php b/web/yaamp/core/exchange/coinbene.php new file mode 100644 index 0000000..0cc8f76 --- /dev/null +++ b/web/yaamp/core/exchange/coinbene.php @@ -0,0 +1,21 @@ +data)) return false; + return true; +} + +// https://openapi-v2.kucoin.com/api/v1/symbols?market=BTC +// https://openapi-v2.kucoin.com/api/v1/currencies for labels + +function kucoin_api_query($method, $params='', $returnType='object') +{ + $exchange = 'kucoin'; + $url = "https://openapi-v2.kucoin.com/api/v1/$method"; + if (!empty($params)) $url .= "?$params"; + + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; KuCoin API PHP client; '.php_uname('s').'; PHP/'.phpversion().')'); + curl_setopt($ch, CURLOPT_ENCODING , ''); + //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + + $res = curl_exec($ch); + if($res === false) { + $e = curl_error($ch); + debuglog("$exchange: $method $e"); + curl_close($ch); + return false; + } + + if ($returnType == 'object') + $ret = json_decode($res); + else + $ret = json_decode($res,true); + + if(!is_object($ret) && !is_array($ret)) { + $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + debuglog("$exchange: $method failed ($status) ".strip_data($res)); + } + curl_close($ch); + return $ret; +} + +// https://openapi-v2.kucoin.com/api/v1/deposit-addresses?currency= + +function kucoin_api_user($method, $params=NULL, $isPostMethod=false) +{ + $exchange = 'kucoin'; + require_once('/etc/yiimp/keys.php'); + if (!defined('EXCH_KUCOIN_SECRET')) define('EXCH_KUCOIN_SECRET', ''); + + if (empty(EXCH_KUCOIN_KEY) || empty(EXCH_KUCOIN_SECRET)) return false; + if (empty(EXCH_KUCOIN_PASSPHRASE)) return false; + + $api_host = 'https://openapi-v2.kucoin.com'; + $mt = explode(' ', microtime()); + $nonce = $mt[1].substr($mt[0], 2, 3); + $url = $endpoint = "/api/v1/$method"; + + if (empty($params)) $params = array(); + $query = http_build_query($params); + $body = ""; + if ($isPostMethod) + $body = json_encode($params); + else if (strlen($query)) { + $body = '?'.$query; + $url .= $body; + } + + $req = $isPostMethod ? "POST" : "GET"; + $tosign = "{$nonce}{$req}{$endpoint}{$body}"; + $hmac = hash_hmac('sha256', $tosign, EXCH_KUCOIN_SECRET, true); + + $headers = array( + 'Content-Type: application/json;charset=UTF-8', + 'KC-API-KEY: '.EXCH_KUCOIN_KEY, + 'KC-API-PASSPHRASE: '.EXCH_KUCOIN_PASSPHRASE, + 'KC-API-TIMESTAMP: '.$nonce, + 'KC-API-SIGN: '.base64_encode($hmac), + ); + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $api_host.$url); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + if ($isPostMethod) { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + } + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; KuCoin API PHP client; '.php_uname('s').'; PHP/'.phpversion().')'); + curl_setopt($ch, CURLOPT_ENCODING , ''); + //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + //curl_setopt($ch, CURLOPT_VERBOSE, 1); + + $res = curl_exec($ch); + if($res === false) { + $e = curl_error($ch); + debuglog("$exchange: $method $e"); + curl_close($ch); + return false; + } + + $result = json_decode($res); + if(!is_object($result) && !is_array($result)) { + $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + debuglog("$exchange: $method failed ($status) ".strip_data($res)); + } + + curl_close($ch); + + return $result; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// manual update of one market +function kucoin_update_market($market) +{ + $exchange = 'kucoin'; + if (is_string($market)) + { + $symbol = $market; + $coin = getdbosql('db_coins', "symbol=:sym", array(':sym'=>$symbol)); + if(!$coin) return false; + $pair = $symbol.'-BTC'; + $market = getdbosql('db_markets', "coinid={$coin->id} AND name='$exchange'"); + if(!$market) return false; + + } else if (is_object($market)) { + + $coin = getdbo('db_coins', $market->coinid); + if(!$coin) return false; + $symbol = $coin->getOfficialSymbol(); + $pair = $symbol.'-BTC'; + if (!empty($market->base_coin)) $pair = $symbol.'-'.$market->base_coin; + } + + $t1 = microtime(true); + $query = kucoin_api_query('market/orderbook/level1','symbol='.$pair); + if(!kucoin_result_valid($query)) return false; + $ticker = $query->data; + + $price2 = ((double) $ticker->bestBid + (double)$ticker->bestAsk)/2; + $market->price2 = AverageIncrement($market->price2, $price2); + $market->price = AverageIncrement($market->price, $ticker->bestBid); + $market->pricetime = min(time(), 0 + $ticker->sequence); + $market->save(); + + $apims = round((microtime(true) - $t1)*1000,3); + user()->setFlash('message', "$exchange $symbol price updated in $apims ms"); + + return true; +} diff --git a/web/yaamp/core/exchange/stocksexchange.php b/web/yaamp/core/exchange/stocksexchange.php index 868ce06..35e01b1 100644 --- a/web/yaamp/core/exchange/stocksexchange.php +++ b/web/yaamp/core/exchange/stocksexchange.php @@ -1,12 +1,11 @@ 1.0, 'x13' => 1.0, 'argon2' => 1.0, + 'argon2d-dyn' => 1.0, 'lyra2' => 1.0, 'lyra2v2' => 1.0, 'myr-gr' => 1.0, @@ -107,6 +133,8 @@ function yaamp_get_algo_norm($algo) 'velvet' => 1.0, 'whirlpool' => 1.0, 'yescrypt' => 1.0, + 'yescryptR16' => 1.0, + 'yescryptR32' => 1.0, 'zr5' => 1.0, ); @@ -121,6 +149,7 @@ function getAlgoColors($algo) $a = array( 'sha256' => '#d0d0a0', 'sha256t' => '#d0d0f0', + 'sha256q' => '#9696dd', 'scrypt' => '#c0c0e0', 'neoscrypt' => '#a0d0f0', 'scryptn' => '#d0d0d0', @@ -129,15 +158,25 @@ function getAlgoColors($algo) 'deep' => '#e0ffff', 'x11' => '#f0f0a0', 'x11evo' => '#c0f0c0', + 'x12' => '#ffe090', 'x13' => '#ffd880', 'x14' => '#f0c080', 'x15' => '#f0b080', + 'x16r' => '#f0b080', + 'x16rv2' => '#f0b080', + 'x16s' => '#f0b080', 'x17' => '#f0b0a0', - 'xevan' => '#f0b0a0', + 'x22i' => '#f0a090', + 'xevan' => '#f0b0a0', + 'allium' => '#80a0d0', 'argon2' => '#e0d0e0', + 'argon2d-dyn' => '#e0d0e0', + 'aergo' => '#e0d0e0', 'bastion' => '#e0b0b0', 'blake' => '#f0f0f0', 'blakecoin' => '#f0f0f0', + 'blake2b' => '#f2c81f', + 'exosis' => '#49CCFE', 'groestl' => '#d0a0a0', 'jha' => '#a0d0c0', 'dmd-gr' => '#a0c0f0', @@ -145,6 +184,8 @@ function getAlgoColors($algo) 'hmq1725' => '#ffa0a0', 'hsr' => '#aa70ff', 'keccak' => '#c0f0c0', + 'keccakc' => '#c0f0c0', + 'hex' => '#c0f0c0', 'lbry' => '#b0d0e0', 'luffa' => '#a0c0c0', 'm7m' => '#d0a0a0', @@ -152,10 +193,15 @@ function getAlgoColors($algo) 'nist5' => '#c0e0e0', 'quark' => '#c0c0c0', 'qubit' => '#d0a0f0', + 'rainforest' => '#d0f0a0', + 'lbk3' => '#809aef', 'lyra2' => '#80a0f0', 'lyra2v2' => '#80c0f0', + 'lyra2v3' => '#80a0f0', 'lyra2z' => '#80b0f0', + 'lyra2zz' => '#80b0f0', 'phi' => '#a0a0e0', + 'phi2' => '#a0a0e0', 'polytimos' => '#dedefe', 'sib' => '#a0a0c0', 'skein' => '#80a0a0', @@ -164,10 +210,14 @@ function getAlgoColors($algo) 'bitcore' => '#f790c0', 'skunk' => '#dedefe', 'tribus' => '#c0d0d0', + 'a5a' => '#f0f0f0', 'vanilla' => '#f0f0f0', 'velvet' => '#aac0cc', + 'vitalium' => '#f0b0a0', 'whirlpool' => '#d0e0e0', 'yescrypt' => '#e0d0e0', + 'yescryptR16' => '#e2d0e2', + 'yescryptR32' => '#e2d0d2', 'zr5' => '#d0b0d0', 'MN' => '#ffffff', // MasterNode Earnings @@ -185,17 +235,25 @@ function getAlgoPort($algo) $a = array( 'sha256' => 3333, 'sha256t' => 3339, + 'sha256q' => 3337, 'lbry' => 3334, 'scrypt' => 3433, 'timetravel' => 3555, 'bitcore' => 3556, + 'exosis' => 3557, 'c11' => 3573, 'deep' => 3535, 'x11' => 3533, 'x11evo' => 3553, + 'x12' => 3233, 'x13' => 3633, 'x15' => 3733, + 'x16r' => 3636, + 'x16rv2' => 3637, + 'x16s' => 3663, 'x17' => 3737, + 'x22i' => 3223, + 'aergo' => 3691, 'xevan' => 3739, 'hmq1725' => 3747, 'nist5' => 3833, @@ -204,16 +262,23 @@ function getAlgoPort($algo) 'whirlpool' => 4133, 'neoscrypt' => 4233, 'argon2' => 4234, + 'argon2d-dyn' => 4239, 'scryptn' => 4333, - 'lyra2' => 4433, + 'allium' => 4443, + 'lbk3' => 5522, + 'lyra2' => 4432, 'lyra2v2' => 4533, + 'lyra2v3' => 4433, 'lyra2z' => 4553, + 'lyra2zz' => 4555, 'jha' => 4633, 'qubit' => 4733, 'zr5' => 4833, 'skein' => 4933, 'sib' => 5033, 'keccak' => 5133, + 'keccakc' => 5134, + 'hex' => 5135, 'skein2' => 5233, //'groestl' => 5333, 'dmd-gr' => 5333, @@ -225,18 +290,25 @@ function getAlgoPort($algo) 'decred' => 3252, 'vanilla' => 5755, 'blake2s' => 5766, + 'blake2b' => 5777, 'penta' => 5833, + 'rainforest' => 7443, 'luffa' => 5933, 'm7m' => 6033, 'veltor' => 5034, 'velvet' => 6133, + 'vitalium' => 3233, 'yescrypt' => 6233, + 'yescryptR16' => 6333, + 'yescryptR32' => 6343, 'bastion' => 6433, 'hsr' => 7433, 'phi' => 8333, + 'phi2' => 8332, 'polytimos' => 8463, 'skunk' => 8433, 'tribus' => 8533, + 'a5a' => 8633, ); global $configCustomPorts; @@ -254,7 +326,7 @@ function getAlgoPort($algo) function yaamp_fee($algo) { $fee = controller()->memcache->get("yaamp_fee-$algo"); - if($fee) return $fee; + if($fee && is_numeric($fee)) return (float) $fee; /* $norm = yaamp_get_algo_norm($algo); if($norm == 0) $norm = 1; diff --git a/web/yaamp/core/rpc/easybitcoin.php b/web/yaamp/core/rpc/easybitcoin.php index 59d8342..ad3401a 100644 --- a/web/yaamp/core/rpc/easybitcoin.php +++ b/web/yaamp/core/rpc/easybitcoin.php @@ -135,6 +135,11 @@ class Bitcoin { // The ID should be unique for each call $this->id++; + if (stripos($method, 'dump') !== false || stripos($method, 'backupwallet') !== false) { + $this->error = "$method method is not authorized!"; + return FALSE; + } + // If no parameters are passed, this will be an empty array if($method == 'getblocktemplate') { diff --git a/web/yaamp/core/rpc/wallet-rpc.php b/web/yaamp/core/rpc/wallet-rpc.php index f5b77c4..78750db 100644 --- a/web/yaamp/core/rpc/wallet-rpc.php +++ b/web/yaamp/core/rpc/wallet-rpc.php @@ -7,6 +7,7 @@ class WalletRPC { public $type = 'Bitcoin'; protected $rpc; protected $rpc_wallet; + protected $hasGetInfo = false; // cache protected $account; @@ -42,6 +43,7 @@ class WalletRPC { default: $this->type = 'Bitcoin'; $this->rpc = new Bitcoin($coin->rpcuser, $coin->rpcpasswd, $coin->rpchost, $coin->rpcport, $url); + $this->hasGetInfo = $coin->hasgetinfo; } } else { @@ -53,6 +55,12 @@ class WalletRPC { function __call($method, $params) { + if (stripos($method, "dump") !== false || stripos($method, "backupwallet") !== false) { + $this->error = "$method not authorized!"; + debuglog("$method rpc method is not authorized!"); + return false; + } + if ($this->type == 'Ethereum') { if (!isset($this->accounts)) { $this->accounts = $this->rpc->eth_accounts(); @@ -62,11 +70,6 @@ class WalletRPC { // if wallet is stopped return false; } - if (stripos($method, "key") !== false) { - $this->error = "$method not authorized!"; - debuglog("$method not authorized (key)!"); - return false; - } // convert common methods used by yiimp switch ($method) { case 'getaccountaddress': @@ -377,7 +380,34 @@ class WalletRPC { } // Bitcoin RPC - $res = $this->rpc->__call($method,$params); + switch ($method) { + case 'getinfo': + if ($this->hasGetInfo) { + $res = $this->rpc->__call($method,$params); + } else { + $miningInfo = $this->rpc->getmininginfo(); + $res["blocks"] = arraySafeVal($miningInfo,"blocks"); + $res["difficulty"] = arraySafeVal($miningInfo,"difficulty"); + $res["testnet"] = "main" != arraySafeVal($miningInfo,"chain"); + $walletInfo = $this->rpc->getwalletinfo(); + $res["walletversion"] = arraySafeVal($walletInfo,"walletversion"); + $res["balance"] = arraySafeVal($walletInfo,"balance"); + $res["keypoololdest"] = arraySafeVal($walletInfo,"keypoololdest"); + $res["keypoolsize"] = arraySafeVal($walletInfo,"keypoolsize"); + $res["paytxfee"] = arraySafeVal($walletInfo,"paytxfee"); + $networkInfo = $this->rpc->getnetworkinfo(); + $res["version"] = arraySafeVal($networkInfo,"version"); + $res["protocolversion"] = arraySafeVal($networkInfo,"protocolversion"); + $res["timeoffset"] = arraySafeVal($networkInfo,"timeoffset"); + $res["connections"] = arraySafeVal($networkInfo,"connections"); +// $res["proxy"] = arraySafeVal($networkInfo,"networks")[0]["proxy"]; + $res["relayfee"] = arraySafeVal($networkInfo,"relayfee"); + } + break; + default: + $res = $this->rpc->__call($method,$params); + } + $this->error = $this->rpc->error; return $res; } diff --git a/web/yaamp/core/trading/binance_trading.php b/web/yaamp/core/trading/binance_trading.php new file mode 100644 index 0000000..3cad356 --- /dev/null +++ b/web/yaamp/core/trading/binance_trading.php @@ -0,0 +1,57 @@ +balances)) return; + + $savebalance = getdbosql('db_balances', "name='$exchange'"); + + if (is_array($data->balances)) + foreach($data->balances as $balance) + { + if ($balance->asset == 'BTC') { + if (is_object($savebalance)) { + $savebalance->balance = $balance->free; + $savebalance->onsell = $balance->locked; + $savebalance->save(); + } + continue; + } + + if ($updatebalances) { + // store available balance in market table + $coins = getdbolist('db_coins', "symbol=:symbol OR symbol2=:symbol", + array(':symbol'=>$balance->asset) + ); + if (empty($coins)) continue; + foreach ($coins as $coin) { + $market = getdbosql('db_markets', + "coinid=:coinid AND name='$exchange' ORDER BY balance" + , array(':coinid'=>$coin->id) + ); + if (!$market) continue; + $market->balance = $balance->free; + $market->ontrade = $balance->locked; + $market->balancetime = time(); + $market->save(); + } + } + } + + if (!YAAMP_ALLOW_EXCHANGE) return; + + // real trading, todo.. +} diff --git a/web/yaamp/core/trading/bittrex_trading.php b/web/yaamp/core/trading/bittrex_trading.php index a3bbe64..2ce73f2 100644 --- a/web/yaamp/core/trading/bittrex_trading.php +++ b/web/yaamp/core/trading/bittrex_trading.php @@ -27,7 +27,8 @@ function doBittrexTrading($quick=false) $savebalance = getdbosql('db_balances', "name='$exchange'"); if (is_object($savebalance)) { - $savebalance->balance = 0; + $savebalance->balance = 0.; + $savebalance->onsell = 0.; $savebalance->save(); } @@ -36,6 +37,7 @@ function doBittrexTrading($quick=false) if ($balance->Currency == 'BTC') { if (is_object($savebalance)) { $savebalance->balance = $balance->Available; + $savebalance->onsell = (double) $balance->Balance - (double) $balance->Available; $savebalance->save(); } continue; @@ -66,7 +68,7 @@ function doBittrexTrading($quick=false) if($quick) $flushall = false; // minimum order allowed by the exchange - $min_btc_trade = exchange_get($exchange, 'trade_min_btc', 0.00050000); + $min_btc_trade = exchange_get($exchange, 'trade_min_btc', 0.00100000); // sell on ask price + 5% $sell_ask_pct = exchange_get($exchange, 'trade_sell_ask_pct', 1.05); // cancel order if our price is more than ask price + 20% @@ -234,7 +236,7 @@ function doBittrexTrading($quick=false) } $withdraw_min = exchange_get($exchange, 'withdraw_min_btc', EXCH_AUTO_WITHDRAW); - $withdraw_fee = exchange_get($exchange, 'withdraw_fee_btc', 0.001); + $withdraw_fee = exchange_get($exchange, 'withdraw_fee_btc', 0.0005); if($withdraw_min > 0 && $savebalance->balance >= ($withdraw_min + $withdraw_fee)) { // $btcaddr = exchange_get($exchange, 'withdraw_btc_address', YAAMP_BTCADDRESS); diff --git a/web/yaamp/core/trading/bleutrade_trading.php b/web/yaamp/core/trading/bleutrade_trading.php index b5a31f5..6d800e3 100644 --- a/web/yaamp/core/trading/bleutrade_trading.php +++ b/web/yaamp/core/trading/bleutrade_trading.php @@ -28,6 +28,7 @@ function doBleutradeTrading($quick=false) $savebalance = getdbosql('db_balances', "name='$exchange'"); if (is_object($savebalance)) { $savebalance->balance = 0; + $savebalance->onsell = 0; $savebalance->save(); } @@ -36,6 +37,7 @@ function doBleutradeTrading($quick=false) if ($balance->Currency == 'BTC') { if (is_object($savebalance)) { $savebalance->balance = $balance->Available; + $savebalance->onsell = (double) $balance->Balance - (double) $balance->Available; $savebalance->save(); } continue; diff --git a/web/yaamp/core/trading/bter_trading.php b/web/yaamp/core/trading/bter_trading.php deleted file mode 100644 index 7736905..0000000 --- a/web/yaamp/core/trading/bter_trading.php +++ /dev/null @@ -1,56 +0,0 @@ -balance = 0; - $savebalance->save(); - } - - // bter only returns non-zero balances - if ($updatebalances) dborun("UPDATE markets SET balance=0 WHERE name='{$exchange}'"); - - foreach($balances['available_funds'] as $symbol => $available) - { - if ($symbol == 'BTC') { - if (is_object($savebalance)) { - $savebalance->balance = $balance->available; - $savebalance->save(); - } - continue; - } - - if ($updatebalances) { - // store available balance in market table - $coins = getdbolist('db_coins', "symbol=:symbol OR symbol2=:symbol", - array(':symbol'=>$symbol) - ); - if (empty($coins)) continue; - foreach ($coins as $coin) { - $market = getdbosql('db_markets', "coinid=:coinid AND name='{$exchange}'", array(':coinid'=>$coin->id)); - if (!$market) continue; - $market->balance = $available; - $market->ontrade = arraySafeVal($balances['locked_funds'],$symbol,0); - $market->balancetime = time(); - $market->save(); - } - } - } - - if (!YAAMP_ALLOW_EXCHANGE) return; - - $flushall = rand(0, 8) == 0; - if($quick) $flushall = false; -} diff --git a/web/yaamp/core/trading/c-cex_trading.php b/web/yaamp/core/trading/c-cex_trading.php index f91c8ce..a9d4351 100644 --- a/web/yaamp/core/trading/c-cex_trading.php +++ b/web/yaamp/core/trading/c-cex_trading.php @@ -39,6 +39,7 @@ function doCCexTrading($quick=false) if ($symbol == 'BTC') { if (!is_object($savebalance)) continue; $savebalance->balance = arraySafeVal($balance,'Available'); + $savebalance->onsell = arraySafeVal($balance,'Balance',0.) - arraySafeVal($balance,'Available'); $savebalance->save(); continue; } diff --git a/web/yaamp/core/trading/crex24_trading.php b/web/yaamp/core/trading/crex24_trading.php new file mode 100644 index 0000000..a01ab4a --- /dev/null +++ b/web/yaamp/core/trading/crex24_trading.php @@ -0,0 +1,53 @@ +currency == 'BTC') { + if (is_object($savebalance)) { + $savebalance->balance = $balance->available; + $savebalance->onsell = $balance->reserved; + $savebalance->save(); + } + continue; + } + + if ($updatebalances) { + // store available balance in market table + $coins = getdbolist('db_coins', "symbol=:symbol OR symbol2=:symbol", + array(':symbol'=>$balance->currency) + ); + if (empty($coins)) continue; + foreach ($coins as $coin) { + $market = getdbosql('db_markets', "coinid=:coinid AND name='$exchange'", array(':coinid'=>$coin->id)); + if (!$market) continue; + $market->balance = $balance->available; + $market->ontrade = $balance->reserved; + $market->balancetime = time(); + $market->save(); + } + } + } + + if (!YAAMP_ALLOW_EXCHANGE) return; + + // real trading, todo.. +} diff --git a/web/yaamp/core/trading/cryptopia_trading.php b/web/yaamp/core/trading/cryptopia_trading.php index 7956c6f..19aaf90 100644 --- a/web/yaamp/core/trading/cryptopia_trading.php +++ b/web/yaamp/core/trading/cryptopia_trading.php @@ -27,6 +27,7 @@ function doCryptopiaTrading($quick=false) $savebalance = getdbosql('db_balances', "name='$exchange'"); if (is_object($savebalance)) { $savebalance->balance = 0; + $savebalance->onsell = 0; $savebalance->save(); } @@ -36,6 +37,7 @@ function doCryptopiaTrading($quick=false) if ($balance->Symbol == 'BTC') { if (is_object($savebalance)) { $savebalance->balance = $balance->Available; + $savebalance->onsell = $balance->HeldForTrades; $savebalance->save(); } continue; @@ -86,7 +88,8 @@ function doCryptopiaTrading($quick=false) $market = getdbosql('db_markets', "coinid=:coinid AND name='cryptopia'", array(':coinid'=>$coin->id)); if(!$market) continue; - $market->balance = $balance->HeldForTrades; + $market->balance = $balance->Available; + $market->ontrade = $balance->HeldForTrades; $market->message = $balance->StatusMessage; $orders = NULL; diff --git a/web/yaamp/core/trading/hitbtc_trading.php b/web/yaamp/core/trading/hitbtc_trading.php index ba6a38d..db380ea 100644 --- a/web/yaamp/core/trading/hitbtc_trading.php +++ b/web/yaamp/core/trading/hitbtc_trading.php @@ -25,6 +25,7 @@ function doHitBTCTrading($quick=false) if ($balance->currency_code == 'BTC') { if (is_object($savebalance)) { $savebalance->balance = $balance->cash; + $savebalance->onsell = $balance->reserved; $savebalance->save(); } continue; diff --git a/web/yaamp/core/trading/kraken_trading.php b/web/yaamp/core/trading/kraken_trading.php index d8a7c0f..580bcff 100644 --- a/web/yaamp/core/trading/kraken_trading.php +++ b/web/yaamp/core/trading/kraken_trading.php @@ -10,12 +10,16 @@ function doKrakenTrading($quick=false) $balances = kraken_api_user('Balance'); if(!$balances || !is_array($balances)) return; + //$total = kraken_api_user('TradeBalance', array('asset'=>'XXBT')); + //if(!$total || !is_array($total)) return; + foreach($balances as $symbol => $balance) { if ($symbol == 'BTC') { $db_balance = getdbosql('db_balances', "name='$exchange'"); if ($db_balance) { $db_balance->balance = $balance; + //$db_balance->onsell = (double) $total['result']['tb'] - $balance; $db_balance->save(); } continue; diff --git a/web/yaamp/core/trading/kucoin_trading.php b/web/yaamp/core/trading/kucoin_trading.php new file mode 100644 index 0000000..6b03896 --- /dev/null +++ b/web/yaamp/core/trading/kucoin_trading.php @@ -0,0 +1,71 @@ +data)) + foreach($data->data as $balance) + { + if ($balance->currency == 'BTC' && $balance->type == 'main') { + if (is_object($savebalance)) { + $savebalance->balance = $balance->balance; + $savebalance->onsell = $balance->holds; + $savebalance->save(); + } + continue; + } + + if ($updatebalances && $balance->type == 'main') { + // store available balance in market table + $coins = getdbolist('db_coins', "symbol=:symbol OR symbol2=:symbol", + array(':symbol'=>$balance->currency) + ); + if (empty($coins)) continue; + foreach ($coins as $coin) { + $market = getdbosql('db_markets', + "coinid=:coinid AND name='$exchange' ORDER BY balance" + , array(':coinid'=>$coin->id) + ); + if (!$market) continue; + $market->balance = $balance->balance; + $market->ontrade = $balance->holds; + $market->balancetime = time(); + $market->save(); + + $checked_today = cache()->get($exchange.'-deposit_address-check-'.$coin->symbol); + if ($coin->installed && !$checked_today) { + sleep(1); + $obj = kucoin_api_user('deposit-addresses',array('currency'=>$coin->symbol)); + if (!kucoin_result_valid($obj)) continue; + $result = $obj->data; + $deposit_address = objSafeVal($result,'address'); + if (!empty($deposit_address) && $deposit_address != $market->deposit_address) { + debuglog("$exchange: updated {$coin->symbol} deposit address $deposit_address"); + $market->save(); + } + cache()->set($exchange.'-deposit_address-check-'.$coin->symbol, time(), 24*3600); + } + } + } + } + + if (!YAAMP_ALLOW_EXCHANGE) return; + + // real trading, todo.. +} diff --git a/web/yaamp/core/trading/livecoin_trading.php b/web/yaamp/core/trading/livecoin_trading.php index a014fdd..40676d2 100644 --- a/web/yaamp/core/trading/livecoin_trading.php +++ b/web/yaamp/core/trading/livecoin_trading.php @@ -52,13 +52,17 @@ function doLiveCoinTrading($quick = false) foreach ($balances as $balance) { if ($balance->currency == 'BTC' && $balance->type == "available") { - if (!is_object($savebalance)) { - continue; - } + if (!is_object($savebalance)) continue; $savebalance->balance = $balance->value; $savebalance->save(); continue; } + if ($balance->currency == 'BTC' && $balance->type == "trade") { + if (!is_object($savebalance)) continue; + $savebalance->onsell = $balance->value; + $savebalance->save(); + continue; + } if ($updatebalances) { // store available balance in market table diff --git a/web/yaamp/core/trading/nova_trading.php b/web/yaamp/core/trading/nova_trading.php index ca32216..4e7b268 100644 --- a/web/yaamp/core/trading/nova_trading.php +++ b/web/yaamp/core/trading/nova_trading.php @@ -38,6 +38,7 @@ function doNovaTrading($quick=false) $savebalance = getdbosql('db_balances', "name='{$exchange}'"); if (is_object($savebalance)) { $savebalance->balance = 0; + $savebalance->onsell = 0; $savebalance->save(); } else { dborun("INSERT INTO balances (name,balance) VALUES ('$exchange',0)"); @@ -49,6 +50,7 @@ function doNovaTrading($quick=false) if ($balance->currency == 'BTC') { if (is_object($savebalance)) { $savebalance->balance = $balance->amount; + $savebalance->onsell = $balance->amount_trades; $savebalance->save(); } continue; diff --git a/web/yaamp/core/trading/poloniex_trading.php b/web/yaamp/core/trading/poloniex_trading.php index e817bdf..1aef2b2 100644 --- a/web/yaamp/core/trading/poloniex_trading.php +++ b/web/yaamp/core/trading/poloniex_trading.php @@ -33,7 +33,8 @@ function doPoloniexTrading() { if ($symbol == 'BTC') { if (is_object($savebalance)) { - $savebalance->balance = $balance['available']; + $savebalance->balance = arraySafeVal($balance,'available'); + $savebalance->onsell = arraySafeVal($balance,'onOrders'); $savebalance->save(); } continue; diff --git a/web/yaamp/core/trading/trading.php b/web/yaamp/core/trading/trading.php index 525fa25..1dab4d7 100644 --- a/web/yaamp/core/trading/trading.php +++ b/web/yaamp/core/trading/trading.php @@ -1,15 +1,17 @@ uuid); break; + case 'binance': + doBinanceCancelOrder($order->uuid); + break; case 'c-cex': doCCexCancelOrder($order->uuid); break; @@ -31,12 +36,18 @@ function cancelExchangeOrder($order=false) case 'bleutrade': doBleutradeCancelOrder($order->uuid); break; + case 'crex24': + doCrex24CancelOrder($order->uuid); + break; case 'cryptopia': doCryptopiaCancelOrder($order->uuid); break; case 'hitbtc': doHitBTCCancelOrder($order->uuid); break; + case 'kucoin': + doKuCoinCancelOrder($order->uuid); + break; case 'livecoin': doLiveCoinCancelOrder($order->uuid); break; @@ -55,9 +66,14 @@ function runExchange($exchangeName=false) updateAlcurexMarkets(); break; - case 'bter': - doBterTrading(true); - updateBterMarkets(); + case 'binance': + doBinanceTrading(true); + updateBinanceMarkets(); + break; + + case 'crex24': + doCrex24Trading(true); + updateCrex24Markets(); break; case 'cryptopia': @@ -65,6 +81,10 @@ function runExchange($exchangeName=false) updateCryptopiaMarkets(); break; + case 'cryptobridge': + updateCryptoBridgeMarkets(); + break; + case 'bitstamp': getBitstampBalances(); break; @@ -73,6 +93,13 @@ function runExchange($exchangeName=false) doBittrexTrading(true); updateBittrexMarkets(); break; + case 'bitz': + updateBitzMarkets(); + break; + + case 'cexio': + getCexIoBalances(); + break; case 'c-cex': doCCexTrading(true); @@ -113,6 +140,11 @@ function runExchange($exchangeName=false) updateKrakenMarkets(); break; + case 'kucoin': + doKuCoinTrading(true); + updateKucoinMarkets(); + break; + case 'livecoin': doLiveCoinTrading(true); updateLiveCoinMarkets(); diff --git a/web/yaamp/core/trading/yobit_trading.php b/web/yaamp/core/trading/yobit_trading.php index ddc483a..f794a6f 100644 --- a/web/yaamp/core/trading/yobit_trading.php +++ b/web/yaamp/core/trading/yobit_trading.php @@ -37,6 +37,7 @@ function doYobitTrading($quick=false) if ($symbol == 'btc') { if (is_object($savebalance)) { $savebalance->balance = $amount; + $savebalance->onsell = arraySafeVal($balances['return']['funds_incl_orders'],$symbol,0.) - $amount; $savebalance->save(); } continue; @@ -51,6 +52,7 @@ function doYobitTrading($quick=false) $market = getdbosql('db_markets', "coinid=:coinid AND name='$exchange'", array(':coinid'=>$coin->id)); if (!$market) continue; $market->balance = $amount; + $market->ontrade = arraySafeVal($balances['return']['funds_incl_orders'],$symbol,0.) - $amount; $market->balancetime = time(); $market->save(); } diff --git a/web/yaamp/defaultconfig.php b/web/yaamp/defaultconfig.php index c260f44..5a41749 100644 --- a/web/yaamp/defaultconfig.php +++ b/web/yaamp/defaultconfig.php @@ -11,6 +11,8 @@ if (!defined('YAAMP_DBNAME')) define('YAAMP_DBNAME', 'yaamp'); if (!defined('YAAMP_DBUSER')) define('YAAMP_DBUSER', 'root'); if (!defined('YAAMP_DBPASSWORD')) define('YAAMP_DBPASSWORD', ''); +if (!defined('YIIMP_MYSQLDUMP_PATH')) define('YIIMP_MYSQLDUMP_PATH', '/root/backup'); + if (!defined('YIIMP_PUBLIC_EXPLORER')) define('YIIMP_PUBLIC_EXPLORER', true); if (!defined('YIIMP_PUBLIC_BENCHMARK')) define('YIIMP_PUBLIC_BENCHMARK', false); if (!defined('YIIMP_FIAT_ALTERNATIVE')) define('YIIMP_FIAT_ALTERNATIVE', 'EUR'); @@ -26,19 +28,22 @@ if (!defined('YAAMP_PAYMENTS_MINI')) define('YAAMP_PAYMENTS_MINI', 0.001); if (!defined('YAAMP_ALLOW_EXCHANGE')) define('YAAMP_ALLOW_EXCHANGE', false); if (!defined('EXCH_AUTO_WITHDRAW')) define('EXCH_AUTO_WITHDRAW', 9999.9999); +if (!defined('EXCH_BINANCE_KEY')) define('EXCH_BINANCE_KEY', ''); if (!defined('EXCH_BITTREX_KEY')) define('EXCH_BITTREX_KEY', ''); if (!defined('EXCH_BITSTAMP_ID')) define('EXCH_BITSTAMP_ID', ''); if (!defined('EXCH_BITSTAMP_KEY')) define('EXCH_BITSTAMP_KEY',''); if (!defined('EXCH_BLEUTRADE_KEY')) define('EXCH_BLEUTRADE_KEY', ''); -if (!defined('EXCH_BTER_KEY')) define('EXCH_BTER_KEY', ''); if (!defined('EXCH_CCEX_KEY')) define('EXCH_CCEX_KEY', ''); if (!defined('EXCH_CEXIO_ID')) define('EXCH_CEXIO_ID', ''); if (!defined('EXCH_CEXIO_KEY')) define('EXCH_CEXIO_KEY', ''); +if (!defined('EXCH_CREX24_KEY')) define('EXCH_CREX24_KEY', ''); if (!defined('EXCH_CRYPTOPIA_KEY')) define('EXCH_CRYPTOPIA_KEY', ''); if (!defined('EXCH_HITBTC_KEY')) define('EXCH_HITBTC_KEY', ''); if (!defined('EXCH_POLONIEX_KEY')) define('EXCH_POLONIEX_KEY', ''); if (!defined('EXCH_YOBIT_KEY')) define('EXCH_YOBIT_KEY', ''); if (!defined('EXCH_KRAKEN_KEY')) define('EXCH_KRAKEN_KEY', ''); +if (!defined('EXCH_KUCOIN_KEY')) define('EXCH_KUCOIN_KEY', ''); +if (!defined('EXCH_KUCOIN_PASSPHRASE')) define('EXCH_KUCOIN_PASSPHRASE', ''); if (!defined('EXCH_LIVECOIN_KEY')) define('EXCH_LIVECOIN_KEY', ''); if (!defined('EXCH_NOVA_KEY')) define('EXCH_NOVA_KEY', ''); if (!defined('EXCH_STOCKSEXCHANGE_KEY')) define('EXCH_STOCKSEXCHANGE_KEY', ''); @@ -46,6 +51,8 @@ if (!defined('EXCH_STOCKSEXCHANGE_KEY')) define('EXCH_STOCKSEXCHANGE_KEY', ''); if (!defined('YAAMP_BTCADDRESS')) define('YAAMP_BTCADDRESS', ''); if (!defined('YAAMP_SITE_URL')) define('YAAMP_SITE_URL', 'localhost'); if (!defined('YAAMP_API_URL')) define('YAAMP_API_URL', YAAMP_SITE_URL); +if (!defined('YAAMP_API_PAYOUTS')) define('YAAMP_API_PAYOUTS', false); +if (!defined('YAAMP_API_PAYOUTS_PERIOD')) define('YAAMP_API_PAYOUTS_PERIOD', 24 * 60 * 60); if (!defined('YAAMP_STRATUM_URL')) define('YAAMP_STRATUM_URL', YAAMP_SITE_URL); if (!defined('YAAMP_SITE_NAME')) define('YAAMP_SITE_NAME', 'YiiMP'); if (!defined('YAAMP_DEFAULT_ALGO')) define('YAAMP_DEFAULT_ALGO', 'x11'); @@ -53,7 +60,8 @@ if (!defined('YAAMP_ADMIN_EMAIL')) define('YAAMP_ADMIN_EMAIL', 'yiimp@spam.la'); if (!defined('YAAMP_ADMIN_IP')) define('YAAMP_ADMIN_IP', '127.0.0.1'); if (!defined('YAAMP_ADMIN_WEBCONSOLE')) define('YAAMP_ADMIN_WEBCONSOLE', true); -if (!defined('YAAMP_NOTIFY_NEW_COINS')) define('YAAMP_NOTIFY_NEW_COINS', true); +if (!defined('YAAMP_CREATE_NEW_COINS')) define('YAAMP_CREATE_NEW_COINS', true); +if (!defined('YAAMP_NOTIFY_NEW_COINS')) define('YAAMP_NOTIFY_NEW_COINS', false); if (!defined('YAAMP_LIMIT_ESTIMATE')) define('YAAMP_LIMIT_ESTIMATE', false); if (!defined('YAAMP_RENTAL')) define('YAAMP_RENTAL', false); diff --git a/web/yaamp/models/db_coinsModel.php b/web/yaamp/models/db_coinsModel.php index 3446eb1..5ce150d 100644 --- a/web/yaamp/models/db_coinsModel.php +++ b/web/yaamp/models/db_coinsModel.php @@ -47,6 +47,7 @@ class db_coins extends CActiveRecord 'rpcssl' => 'RPC SSL', 'rpccert' => 'RPC Certificate', 'serveruser' => 'Server user', + 'hasgetinfo' => 'Has getinfo', 'hassubmitblock'=> 'Has submitblock', 'hasmasternodes'=> 'Masternodes', 'usesegwit' => 'Use segwit', diff --git a/web/yaamp/modules/api/ApiController.php b/web/yaamp/modules/api/ApiController.php index 80074fc..7505700 100644 --- a/web/yaamp/modules/api/ApiController.php +++ b/web/yaamp/modules/api/ApiController.php @@ -6,8 +6,6 @@ class ApiController extends CommonController ///////////////////////////////////////////////// -// debuglog("saving renter {$_SERVER['REMOTE_ADDR']} $renter->address"); - public function actionStatus() { $client_ip = arraySafeVal($_SERVER,'REMOTE_ADDR'); @@ -20,8 +18,7 @@ class ApiController extends CommonController return; } - $memcache = controller()->memcache->memcache; - $json = memcache_get($memcache, "api_status"); + $json = controller()->memcache->get("api_status"); if (!empty($json)) { echo $json; @@ -83,6 +80,7 @@ class ApiController extends CommonController "estimate_current" => $price, "estimate_last24h" => $avgprice, "actual_last24h" => $btcmhday1, + "mbtc_mh_factor" => $algo_unit_factor, "hashrate_last24h" => (double) $hashrate1, ); if(YAAMP_RENTAL) { @@ -97,7 +95,7 @@ class ApiController extends CommonController $json = json_encode($stats); echo $json; - memcache_set($memcache, "api_status", $json, MEMCACHE_COMPRESSED, 30); + controller()->memcache->set("api_status", $json, 30, MEMCACHE_COMPRESSED); } public function actionCurrencies() @@ -112,9 +110,7 @@ class ApiController extends CommonController return; } - $memcache = controller()->memcache->memcache; - - $json = memcache_get($memcache, "api_currencies"); + $json = controller()->memcache->get("api_currencies"); if (empty($json)) { $data = array(); @@ -186,7 +182,7 @@ class ApiController extends CommonController $data[$symbol]['symbol'] = $coin->symbol2; } $json = json_encode($data); - memcache_set($memcache, "api_currencies", $json, MEMCACHE_COMPRESSED, 15); + controller()->memcache->set("api_currencies", $json, 15, MEMCACHE_COMPRESSED); } echo str_replace("},","},\n", $json); @@ -288,12 +284,38 @@ class ApiController extends CommonController } echo "]"; + + if(YAAMP_API_PAYOUTS) + { + $json_payouts = controller()->memcache->get("api_payouts-".$user->id); + if (empty($json_payouts)) { + $json_payouts = ",\"payouts\": "; + $json_payouts .= "["; + $list = getdbolist('db_payouts', "account_id={$user->id} AND completed>0 AND tx IS NOT NULL AND time >= ".(time() - YAAMP_API_PAYOUTS_PERIOD)." ORDER BY time DESC"); + foreach($list as $j => $payout) + { + if($j) $json_payouts .= ", "; + $json_payouts .= "{"; + $json_payouts .= "\"time\": ".(0 + $payout->time).","; + $json_payouts .= "\"amount\": \"{$payout->amount}\","; + $json_payouts .= "\"tx\": \"{$payout->tx}\""; + $json_payouts .= "}"; + } + $json_payouts .= "]"; + controller()->memcache->set("api_payouts-".$user->id, $json_payouts, 60, MEMCACHE_COMPRESSED); + } + echo str_replace("},","},\n", $json_payouts); + } + echo "}"; } + ///////////////////////////////////////////////// + public function actionRental() { if(!LimitRequest('api-rental', 10)) return; + if(!YAAMP_RENTAL) return; $key = getparam('key'); $renter = getdbosql('db_renters', "apikey=:apikey", array(':apikey'=>$key)); @@ -338,6 +360,8 @@ class ApiController extends CommonController public function actionRental_price() { + if(!YAAMP_RENTAL) return; + $key = getparam('key'); $renter = getdbosql('db_renters', "apikey=:apikey", array(':apikey'=>$key)); if(!$renter) return; @@ -355,6 +379,8 @@ class ApiController extends CommonController public function actionRental_hashrate() { + if(!YAAMP_RENTAL) return; + $key = getparam('key'); $renter = getdbosql('db_renters', "apikey=:apikey", array(':apikey'=>$key)); if(!$renter) return; @@ -372,6 +398,8 @@ class ApiController extends CommonController public function actionRental_start() { + if(!YAAMP_RENTAL) return; + $key = getparam('key'); $renter = getdbosql('db_renters', "apikey=:apikey", array(':apikey'=>$key)); if(!$renter || $renter->balance<=0) return; @@ -388,6 +416,8 @@ class ApiController extends CommonController public function actionRental_stop() { + if(!YAAMP_RENTAL) return; + $key = getparam('key'); $renter = getdbosql('db_renters', "apikey=:apikey", array(':apikey'=>$key)); if(!$renter) return; @@ -402,33 +432,5 @@ class ApiController extends CommonController $job->save(); } -// public function actionNodeReport() -// { -// $name = getparam('name'); -// $uptime = getparam('uptime'); - -// $server = getdbosql('db_servers', "name='$name'"); -// if(!$server) -// { -// $server = new db_servers; -// $server->name = $name; -// } - -// $server->uptime = $uptime; -// $server->save(); -// } - } -// function dummy() -// { -// $uptime = system('uptime'); -// $name = system('hostname'); - -// fetch_url("http://".YAAMP_SITE_URL."/api/nodereport?name=$name&uptime=$uptime"); -// } - - - - - diff --git a/web/yaamp/modules/bench/devices.php b/web/yaamp/modules/bench/devices.php index 5bc76d3..68174ee 100644 --- a/web/yaamp/modules/bench/devices.php +++ b/web/yaamp/modules/bench/devices.php @@ -105,11 +105,7 @@ foreach ($in_db as $row) { $chip = CHtml::link($chip, '/bench?chip='.$row['idchip'].'&algo=all'); } echo ''.$chip.''; - - if ($row['type'] == 'gpu') - echo ''.$row['device'].getProductIdSuffix($row).''; - else - echo ''.formatCPU($row).''; + echo ''.formatDevice($row).''; if (substr($vendorid,0,4) == '10de') echo ''.$vendorid.''; diff --git a/web/yaamp/modules/bench/functions.php b/web/yaamp/modules/bench/functions.php index 2681997..84b3e45 100644 --- a/web/yaamp/modules/bench/functions.php +++ b/web/yaamp/modules/bench/functions.php @@ -140,6 +140,20 @@ function formatCPU($row) return trim($device); } +function formatGPU($row) +{ + $label = $row['device'].getProductIdSuffix($row); + return strip_tags($label); +} + +function formatDevice($row) +{ + if ($row['type'] == 'gpu') + return formatGPU($row); + else + return formatCPU($row); +} + function getChipName($row) { if ($row['type'] == 'cpu') { @@ -163,8 +177,11 @@ function getChipName($row) } else { - // nNidia - $words = explode(' ', $row['device']); + // nVidia + $device = str_replace(' with Max-Q Design', '', $row['device']); + $device = str_replace(' COLLECTORS EDITION', '', $device); + + $words = explode(' ', $device); $chip = array_pop($words); $vendorid = $row['vendorid']; if (!is_numeric($chip)) { @@ -176,7 +193,10 @@ function getChipName($row) $chip = str_replace('650 Ti BOOST','650 Ti', $chip); $chip = str_replace('760 Ti OEM','760 Ti', $chip); $chip = str_replace(' (Pascal)',' Pascal', $chip); + $chip = str_replace('Quadro M6000 24GB','Quadro M6000', $chip); + $chip = str_replace('Tesla P100 (PCIe)','Tesla P100', $chip); $chip = str_replace('Tesla P100-SXM2-16GB','Tesla P100', $chip); + $chip = str_replace('Tesla P100-PCIE-16GB','Tesla P100', $chip); $chip = str_replace('Tesla V100-SXM2-16GB','Tesla V100', $chip); $chip = preg_replace('/ASUS ([6-9]\d\dM)/','\1', $chip); // ASUS 940M $chip = preg_replace('/MSI ([6-9]\d\dM)/','\1', $chip); // MSI 840M diff --git a/web/yaamp/modules/bench/index.php b/web/yaamp/modules/bench/index.php index f45cd6e..1546dfc 100644 --- a/web/yaamp/modules/bench/index.php +++ b/web/yaamp/modules/bench/index.php @@ -144,14 +144,12 @@ foreach ($db_rows as $row) { echo ''.CHtml::link($row['algo'],'/bench?algo='.$row['algo']).''; echo ''.$age.''; echo ''.($row['idchip'] ? CHtml::link($row['chip'],'/bench?chip='.$row['idchip']) : $row['chip']).''; - if ($row['type'] == 'cpu') { - echo ''.formatCPU($row).''; - echo ''.CHtml::link($row['vendorid'],'/bench?vid='.$row['vendorid']).''; - echo ''.$row['arch'].''; - } else { - echo ''.$row['device'].getProductIdSuffix($row).''; - echo ''.CHtml::link($row['vendorid'],'/bench?vid='.$row['vendorid']).''; + echo ''.formatDevice($row).''; + echo ''.CHtml::link($row['vendorid'],'/bench?vid='.$row['vendorid']).''; + if ($row['type'] == 'gpu') { echo ''.formatCudaArch($row['arch']).''; + } else { + echo ''.$row['arch'].''; } echo ''.$hashrate.''; diff --git a/web/yaamp/modules/explorer/ExplorerController.php b/web/yaamp/modules/explorer/ExplorerController.php index b122bf5..cfa1925 100644 --- a/web/yaamp/modules/explorer/ExplorerController.php +++ b/web/yaamp/modules/explorer/ExplorerController.php @@ -57,17 +57,25 @@ class ExplorerController extends CommonController $id = getiparam('id'); $coin = getdbo('db_coins', $id); + if($coin && $coin->no_explorer) { + $link = $coin->link_explorer; + //$txid = gethexparam('txid'); + //$hash = gethexparam('hash'); + //if (!empty($txid)) $link .= 'tx/'.$txid; + //elseif (!empty($hash)) $link .= 'block/'.$hash; + die("Block explorer disabled, please use $link"); + } $height = getiparam('height'); if($coin && intval($height)>0) { $remote = new WalletRPC($coin); $hash = $remote->getblockhash(intval($height)); } else { - $hash = getparam('hash'); + $hash = gethexparam('hash'); } - $txid = getparam('txid'); - $q = getparam('q'); + $txid = gethexparam('txid'); + $q = gethexparam('q'); if (strlen($q) >= 32 && ctype_xdigit($q)) { $remote = new WalletRPC($coin); $block = $remote->getblock($q); @@ -79,7 +87,7 @@ class ExplorerController extends CommonController } } - if($coin && !empty($txid) && ctype_xdigit($txid)) + if($coin && !empty($txid)) { $remote = new WalletRPC($coin); $tx = $remote->getrawtransaction($txid, 1); @@ -88,7 +96,7 @@ class ExplorerController extends CommonController $hash = arraySafeVal($tx,'blockhash'); } - if($coin && !empty($hash) && ctype_xdigit($hash)) + if($coin && !empty($hash)) $this->render('block', array('coin'=>$coin, 'hash'=>$hash)); else if($coin) @@ -108,9 +116,9 @@ class ExplorerController extends CommonController public function actionSearch() { $height = getiparam('height'); - $txid = arraySafeVal($_REQUEST,'txid'); - $hash = arraySafeVal($_REQUEST,'hash'); - $q = arraySafeVal($_REQUEST,'q'); + $txid = gethexparam('txid'); + $hash = gethexparam('hash'); + $q = gethexparam('q'); if (isset($_GET['SYM'])) { // only for visible coins $url = "/explorer/".$_GET['SYM']."?"; diff --git a/web/yaamp/modules/explorer/block.php b/web/yaamp/modules/explorer/block.php index 4738b4d..e1521b1 100644 --- a/web/yaamp/modules/explorer/block.php +++ b/web/yaamp/modules/explorer/block.php @@ -144,6 +144,12 @@ echo 'Size:'.$block['size'].' bytes'; if(isset($block['flags'])) echo 'Flags:'.$block['flags'].''; +if(isset($block['previousblockhash']) && $coin->algo == 'x16r') { + echo 'Hash order:'. + substr($block['previousblockhash'], -16). + ''; +} + if(isset($block['previousblockhash'])) echo 'Previous Hash:'. $coin->createExplorerLink($block['previousblockhash'], array('hash'=>$block['previousblockhash'])). @@ -219,6 +225,9 @@ foreach($block['tx'] as $txhash) echo ""; echo ""; + $nvout = count($tx['vout']);; + if ($nvout > 500) echo "Too much addresses to display ($nvout)"; + else foreach($tx['vout'] as $vout) { $value = $vout['value']; @@ -235,7 +244,7 @@ foreach($block['tx'] as $txhash) echo '
'; unset($tx['hex']); - echo colorizeJson(json_encode($tx, 128)); + echo ($nvout > 500) ? 'truncated' : colorizeJson(json_encode($tx, 128)); echo '
'; echo ""; diff --git a/web/yaamp/modules/explorer/coin.php b/web/yaamp/modules/explorer/coin.php index e4db45e..ce724c7 100644 --- a/web/yaamp/modules/explorer/coin.php +++ b/web/yaamp/modules/explorer/coin.php @@ -68,7 +68,7 @@ for($i = $start; $i > max(1, $start-21); $i--) $type = ''; if (arraySafeval($block,'nonce',0) > 0) $type = 'PoW'; else if (isset($block['auxpow'])) $type = 'Aux'; - else if (isset($block['mint']) || arraySafeVal($block,'flags') == 'proof-of-stake') $type = 'PoS'; + else if (isset($block['mint']) || strstr(arraySafeVal($block,'flags',''), 'proof-of-stake')) $type = 'PoS'; // nonce 256bits if ($type == '' && $coin->symbol=='ZEC') $type = 'PoW'; diff --git a/web/yaamp/modules/explorer/util.php b/web/yaamp/modules/explorer/util.php index fb66eaf..5d197cf 100644 --- a/web/yaamp/modules/explorer/util.php +++ b/web/yaamp/modules/explorer/util.php @@ -160,11 +160,24 @@ function versionToAlgo($coin, $version) $algos['DGC'] = array( 0=>'scrypt', 1=>'sha256', 2=>'x11' ); + $algos['DUO'] = array( + 0=>'sha256', 1=>'scrypt' + ); $algos['J'] = array( 2 =>'sha256', 3=>'x11', 4=>'x13', 5=>'x15', 6=>'scrypt', 7 =>'nist5', 8 =>'myr-gr', 9=>'penta', 10=>'whirlpool', 11=>'luffa', 12=>'keccak', 13=>'quark', 15=>'bastion' ); + $algos['GCH'] = array( + 0=>'x12', 1=>'x11', 2=>'x13', 3=>'sha256', 4=>'blake2s' + ); + $algos['GLT'] = array( + 0=>'sha256', 1=>'scrypt', 2=>'x11', 3=>'neoscrypt', 4=>'equihash', 5=>'yescrypt', 6=>'hmq1725', + 7=>'xevan', 8=>'nist5', 9=>'bitcore', 10=>'pawelhash', 11=>'x13', 12=>'x14', 13=>'x15', 14=>'x17', + 15=>'lyra2v2', 16=>'blake2s', 17=>'blake2b', 18=>'astralhash', 19=>'padihash', 20=>'jeonghash', + 21=>'keccak', 22=>'zhash', 23=>'globalhash', 24=>'skein', 25=>'myr-gr', 26=>'qubit', 27=>'skunk', + 28=>'quark', 29=>'x16r' + ); $algos['RICHX'] = array( 0=>'sha256', 1=>'scrypt', 2=>'myr-gr', 3=>'skein', 4=>'qubit' ); @@ -177,13 +190,23 @@ function versionToAlgo($coin, $version) $algos['XVG'] = array( 0=>'scrypt', 1=>'scrypt', 2=>'myr-gr', 3=>'x17', 4=>'blake2s', 10=>'lyra2v2', ); + $algos['XSH'] = array( + 0=>'scrypt', 1=>'scrypt', 2=>'myr-gr', 3=>'x17', 4=>'blake2s', 10=>'lyra2v2', 11=>'x16s', + ); + $algos['ARG'] = array( + 0=>'sha256', 1=>'scrypt', 2=>'lyra2v2', 3=>'myr-gr', 4=>'argon2d', 5=>'yescrypt', + ); $symbol = $coin->symbol; if (!empty($coin->symbol2)) $symbol = $coin->symbol2; if ($symbol == 'J') return arraySafeVal($algos[$symbol], $version, ''); + else if($symbol == 'GCH') + return arraySafeVal($algos[$symbol], ($version - 9), ''); else if($symbol == 'XVG') return arraySafeVal($algos[$symbol], ($version >> 11), 'scrypt'); + else if($symbol == 'XSH') + return arraySafeVal($algos[$symbol], (($version-536870000) >> 11), 'scrypt'); else if (isset($algos[$symbol])) return arraySafeVal($algos[$symbol], ($version >> 9) & 7, ''); return false; diff --git a/web/yaamp/modules/renting/all_orders_results.php b/web/yaamp/modules/renting/all_orders_results.php index b587dee..249be8f 100644 --- a/web/yaamp/modules/renting/all_orders_results.php +++ b/web/yaamp/modules/renting/all_orders_results.php @@ -80,7 +80,7 @@ echo ""; echo "

 * approximate from the last 5 minutes submitted shares
-  ** price in mBTC/Mh/day (mBTC/Gh/day for sha256 and blake algos)
+  ** price in mBTC/MH/day (GH/day for sha and blake algos)

"; echo "
"; diff --git a/web/yaamp/modules/renting/login.php b/web/yaamp/modules/renting/login.php index 5f4cc6d..e7ad453 100644 --- a/web/yaamp/modules/renting/login.php +++ b/web/yaamp/modules/renting/login.php @@ -13,6 +13,9 @@ $this->widget('UniForm'); $address = getparam('address'); if($address == 0) $address = ''; +if (!empty($address) && preg_match('/[^A-Za-z0-9]/', $address)) { + die; +} echo << echo "

 * approximate from the last 5 minutes submitted shares
-  ** price in mBTC/Mh/day (mBTC/Gh/day for sha256 and blake algos)
+  ** price in mBTC/MH/day (GH/day for sha and blake algos)

"; echo "
"; diff --git a/web/yaamp/modules/renting/status_results.php b/web/yaamp/modules/renting/status_results.php index 8e80e1a..d9fa8cc 100644 --- a/web/yaamp/modules/renting/status_results.php +++ b/web/yaamp/modules/renting/status_results.php @@ -90,7 +90,7 @@ foreach($algos as $item) echo ""; echo "

-  * values in mBTC/Mh/day (mBTC/Gh/day for sha256 and blake algos)
+  * values in mBTC/MH/day (GH/day for sha and blake algos)
 ** only hashpower with extranonce.subscribe or reconnect support can be rented

"; diff --git a/web/yaamp/modules/site/SiteController.php b/web/yaamp/modules/site/SiteController.php index df0a719..80cf6a5 100644 --- a/web/yaamp/modules/site/SiteController.php +++ b/web/yaamp/modules/site/SiteController.php @@ -415,7 +415,7 @@ class SiteController extends CommonController $algo = user()->getState('yaamp-algo'); $memcache = controller()->memcache->memcache; $memkey = $algo.'_'.str_replace('/','_',$partial); - $html = memcache_get($memcache, $memkey); + $html = controller()->memcache->get($memkey); if (!empty($html)) { echo $html; @@ -428,7 +428,7 @@ class SiteController extends CommonController $html = ob_get_clean(); echo $html; - memcache_set($memcache, $memkey, $html, MEMCACHE_COMPRESSED, $cachetime); + controller()->memcache->set($memkey, $html, $cachetime, MEMCACHE_COMPRESSED); } // Pool Status : public right panel with all algos and live stats @@ -1077,7 +1077,7 @@ class SiteController extends CommonController $this->goback(); } - public function actionCancelorder() + public function actionCancelorder() { if(!$this->admin) return; $order = getdbo('db_orders', getiparam('id')); @@ -1091,7 +1091,7 @@ class SiteController extends CommonController public function actionAlgo() { - $algo = substr(getparam('algo'), 0, 32); + $algo = getalgoparam(); $a = getdbosql('db_algos', "name=:name", array(':name'=>$algo)); if($a) @@ -1108,7 +1108,7 @@ class SiteController extends CommonController public function actionGomining() { - $algo = substr(getparam('algo'), 0, 32); + $algo = getalgoparam(); if ($algo == 'all') { return; } diff --git a/web/yaamp/modules/site/admin.php b/web/yaamp/modules/site/admin.php index e10542c..92620c6 100644 --- a/web/yaamp/modules/site/admin.php +++ b/web/yaamp/modules/site/admin.php @@ -12,14 +12,16 @@ $server = getparam('server'); echo << Select Server: - + +end; + +$serverlist = dbolist("SELECT DISTINCT rpchost FROM coins WHERE installed=1 ORDER BY rpchost"); +foreach ($serverlist as $srv) { + echo ''; +} + +echo <<  diff --git a/web/yaamp/modules/site/api.php b/web/yaamp/modules/site/api.php index daa525a..71ea821 100644 --- a/web/yaamp/modules/site/api.php +++ b/web/yaamp/modules/site/api.php @@ -45,9 +45,19 @@ result: "accepted": 82463372.083, "rejected": 0 }] + + ,"payouts":[{ + "time": 1529860641, + "amount": "0.001", + "tx": "transaction_id_of_the_payout" + }] + } - +

Pool Status

request: diff --git a/web/yaamp/modules/site/coin_form.php b/web/yaamp/modules/site/coin_form.php index af67481..3507ca4 100644 --- a/web/yaamp/modules/site/coin_form.php +++ b/web/yaamp/modules/site/coin_form.php @@ -147,6 +147,12 @@ echo CUFHtml::activeCheckBox($coin, 'installed'); echo '

Required to be visible in the Wallets board

'; echo CUFHtml::closeCtrlHolder(); +echo CUFHtml::openActiveCtrlHolder($coin, 'no_explorer'); +echo CUFHtml::activeLabelEx($coin, 'no_explorer'); +echo CUFHtml::activeCheckBox($coin, 'no_explorer'); +echo '

Disable block explorer for the public

'; +echo CUFHtml::closeCtrlHolder(); + echo CUFHtml::openActiveCtrlHolder($coin, 'watch'); echo CUFHtml::activeLabelEx($coin, 'watch'); echo CUFHtml::activeCheckBox($coin, 'watch'); @@ -201,6 +207,12 @@ echo CUFHtml::activeTextField($coin, 'charity_address', array('maxlength'=>200)) echo '

Foundation address if "dev fees" are required

'; echo CUFHtml::closeCtrlHolder(); +echo CUFHtml::openActiveCtrlHolder($coin, 'hasgetinfo'); +echo CUFHtml::activeLabelEx($coin, 'hasgetinfo'); +echo CUFHtml::activeCheckBox($coin, 'hasgetinfo'); +echo '

Enable if getinfo rpc method is present

'; +echo CUFHtml::closeCtrlHolder(); + echo CUFHtml::openActiveCtrlHolder($coin, 'hassubmitblock'); echo CUFHtml::activeLabelEx($coin, 'hassubmitblock'); echo CUFHtml::activeCheckBox($coin, 'hassubmitblock'); @@ -216,7 +228,7 @@ echo CUFHtml::closeCtrlHolder(); echo CUFHtml::openActiveCtrlHolder($coin, 'hasmasternodes'); echo CUFHtml::activeLabelEx($coin, 'hasmasternodes'); echo CUFHtml::activeCheckBox($coin, 'hasmasternodes'); -echo '

Require "payee" and "payee_amount" fields in getblocktemplate (DASH)

'; +echo '

Require "payee" and "payee_amount", or masternode object in getblocktemplate

'; echo CUFHtml::closeCtrlHolder(); echo CUFHtml::openActiveCtrlHolder($coin, 'usesegwit'); diff --git a/web/yaamp/modules/site/coin_results.php b/web/yaamp/modules/site/coin_results.php index eb01ea7..f25bb91 100644 --- a/web/yaamp/modules/site/coin_results.php +++ b/web/yaamp/modules/site/coin_results.php @@ -4,7 +4,8 @@ $coin = getdbo('db_coins', getiparam('id')); if (!$coin) $this->goback(); $PoS = ($coin->algo == 'PoS'); // or if 'stake' key is present in 'getinfo' method -$DCR = ($coin->rpcencoding == 'DCR'); +$DCR = ($coin->rpcencoding == 'DCR' || $coin->getOfficialSymbol() == 'DCR'); +$DGB = ($coin->rpcencoding == 'DGB' || $coin->getOfficialSymbol() == 'DGB'); $ETH = ($coin->rpcencoding == 'GETH'); $remote = new WalletRPC($coin); @@ -296,8 +297,8 @@ echo <<master_wallet; +if ($DCR || $DGB) $account = '*'; +else if ($ETH) $account = $coin->master_wallet; $txs = $remote->listtransactions($account, $maxrows); @@ -395,7 +396,8 @@ if ($DCR) { if ($lastday == '' && count($txs) == $maxrows) $lastday = strftime('%F', $tx['time']); } - ksort($txs_array); // reversed order + if ($info['version'] < 1010200) + ksort($txs_array); // was in reversed order } $rows = 0; diff --git a/web/yaamp/modules/site/coin_tickets.php b/web/yaamp/modules/site/coin_tickets.php index 3abed60..9b36934 100644 --- a/web/yaamp/modules/site/coin_tickets.php +++ b/web/yaamp/modules/site/coin_tickets.php @@ -179,7 +179,8 @@ if (!empty($txs_array)) { if ($lastday == '' && count($txs) == $maxrows) $lastday = strftime('%F', arraySafeVal($tx,'blocktime', $tx['time'])); } - ksort($txs_array); + if ($info['version'] < 1010200) + ksort($txs_array); } if (!empty($tickets)) foreach ($tickets['hashes'] as $n => $txid) { @@ -200,7 +201,8 @@ if (!empty($tickets)) foreach ($tickets['hashes'] as $n => $txid) { $stx['stx'] = $stx; $txs_array[$k] = $stx; } - ksort($txs_array); + if ($info['version'] < 1010200) + ksort($txs_array); } $rows = 0; diff --git a/web/yaamp/modules/site/common_results.php b/web/yaamp/modules/site/common_results.php index 3c25577..88abe8b 100644 --- a/web/yaamp/modules/site/common_results.php +++ b/web/yaamp/modules/site/common_results.php @@ -222,34 +222,6 @@ echo ''; // ---------------------------------------------------------------------------------------------------- -if (YAAMP_ALLOW_EXCHANGE) { -echo 'sell orders'; -foreach($markets as $market) -{ - $exchange = $market->name; - $onsell = bitcoinvaluetoa(dboscalar("select sum(amount*bid) from orders where market='$exchange'")); - $salebalances[$exchange] = $onsell; - - if($onsell > 0.2) - echo ''.$onsell.''; - else if($onsell > 0.1) - echo ''.$onsell.''; - else if($onsell == 0.0) - echo '-'; - else - echo ''.$onsell.''; - - $total_onsell += $onsell; -} - -$total_onsell = bitcoinvaluetoa($total_onsell); - -echo ''.$total_onsell.''; -echo ''; -} // YAAMP_ALLOW_EXCHANGE - -// ---------------------------------------------------------------------------------------------------- - echo 'BTC'; foreach($markets as $market) { @@ -274,6 +246,45 @@ echo ''; // ---------------------------------------------------------------------------------------------------- +echo 'orders'; +if (YAAMP_ALLOW_EXCHANGE) { + // yaamp mode + foreach($markets as $market) { + $exchange = $market->name; + $onsell = bitcoinvaluetoa(dboscalar("SELECT sum(amount*bid) FROM orders WHERE market='$exchange'")); + $salebalances[$exchange] = $onsell; + + if($onsell > 0.2) + echo ''.$onsell.''; + else if($onsell > 0.1) + echo ''.$onsell.''; + else if($onsell == 0.0) + echo '-'; + else + echo ''.$onsell.''; + + $total_onsell += $onsell; + } +} else { + // yiimp mode + $ontrade = dbolist("SELECT name, onsell FROM balances B ORDER by name"); + foreach($ontrade as $row) { + $exchange = $row['name']; + $onsell = bitcoinvaluetoa($row['onsell']); + $salebalances[$exchange] = $onsell; + + echo ''.($onsell == 0 ? '-' : $onsell).''; + + $total_onsell += (double) $onsell; + } + +} +$total_onsell = bitcoinvaluetoa($total_onsell); +echo ''.$total_onsell.''; +echo ''; + +// ---------------------------------------------------------------------------------------------------- + $t = time() - 48*60*60; $altmarkets = dbolist(" SELECT B.name, SUM((M.balance+M.ontrade)*M.price) AS balance @@ -496,34 +507,27 @@ function cronstate2text($state) } } -//$state_block = memcache_get($this->memcache->memcache, 'cronjob_block_state'); -$state_main = memcache_get($this->memcache->memcache, 'cronjob_main_state'); +$state_main = (int) $this->memcache->get('cronjob_main_state'); $btc = getdbosql('db_coins', "symbol='BTC'"); if (!$btc) $btc = json_decode('{"id": 6, "balance": 0}'); echo ''; for($i=0; $i<10; $i++) { -// if($i != $state_block-1 && $state_block>0) -// { -// $state = memcache_get($this->memcache->memcache, "cronjob_block_state_$i"); -// if($state) echo "block $i "; -// } - if($i != $state_main-1 && $state_main>0) { - $state = memcache_get($this->memcache->memcache, "cronjob_main_state_$i"); + $state = $this->memcache->get("cronjob_main_state_$i"); if($state) echo "main $i "; } } echo ''; -$block_time = sectoa(time()-memcache_get($this->memcache->memcache, "cronjob_block_time_start")); -$loop2_time = sectoa(time()-memcache_get($this->memcache->memcache, "cronjob_loop2_time_start")); -$main_time2 = sectoa(time()-memcache_get($this->memcache->memcache, "cronjob_main_time_start")); +$block_time = sectoa(time()-$this->memcache->get("cronjob_block_time_start")); +$loop2_time = sectoa(time()-$this->memcache->get("cronjob_loop2_time_start")); +$main_time2 = sectoa(time()-$this->memcache->get("cronjob_main_time_start")); -$main_time = sectoa(memcache_get($this->memcache->memcache, "cronjob_main_time")); +$main_time = sectoa($this->memcache->get("cronjob_main_time")); $main_text = cronstate2text($state_main); echo "*** main ($main_time) $state_main $main_text ($main_time2), loop2 ($loop2_time), block ($block_time)
"; diff --git a/web/yaamp/modules/site/index.php b/web/yaamp/modules/site/index.php index 38cb680..59318f1 100644 --- a/web/yaamp/modules/site/index.php +++ b/web/yaamp/modules/site/index.php @@ -29,10 +29,12 @@ $payout_freq = (YAAMP_PAYMENTS_FREQ / 3600)." hours";
LBRY COMMUNITY MINING POOL
+
    +
  • Welcome to the LBRY Community Mining Pool.
  • Please feel free to mine here as an alternative to the bigger pools.
  • No registration is required, we do payouts in the currency you mine. Use your wallet address as the username.
  • diff --git a/web/yaamp/modules/site/memcached.php b/web/yaamp/modules/site/memcached.php index bed417b..a1252a6 100644 --- a/web/yaamp/modules/site/memcached.php +++ b/web/yaamp/modules/site/memcached.php @@ -2,8 +2,7 @@ echo "refresh
    "; -$memcache = controller()->memcache->memcache; -$a = memcache_get($this->memcache->memcache, 'url-map'); +$a = controller()->memcache->memcache->get( 'url-map'); function printStats($stat) { @@ -51,7 +50,7 @@ function cmp($a, $b) if (!empty($a)) foreach($a as $url=>$n) { - $d = memcache_get($this->memcache->memcache, "$url-time"); + $d = $this->memcache->get("$url-time"); $avg = $d/$n; $res[] = array($url, $n, $d, $avg); diff --git a/web/yaamp/modules/site/results/current_results.php b/web/yaamp/modules/site/results/current_results.php index 5fc8e1c..c24a925 100644 --- a/web/yaamp/modules/site/results/current_results.php +++ b/web/yaamp/modules/site/results/current_results.php @@ -169,11 +169,7 @@ echo ""; echo ""; -echo "

    -  * best normalized multi algo
    -  ** fees are now fixed manually.
    -  *** values in mBTC/Mh/day (mBTC/Gh/day for sha256 and blake algos)
    -

    "; +echo '

     * values in mBTC/MH/day, per GH for sha & blake algos

    '; echo "

"; ?> diff --git a/web/yaamp/modules/site/results/found_results.php b/web/yaamp/modules/site/results/found_results.php index c181093..e37a636 100644 --- a/web/yaamp/modules/site/results/found_results.php +++ b/web/yaamp/modules/site/results/found_results.php @@ -90,7 +90,7 @@ foreach($db_blocks as $db_block) echo ''; echo ''; - echo ''.$link.' ('.$coin->algo.')'.$flags.''; + echo ''.$link.' ('.$db_block->algo.')'.$flags.''; echo ''.$reward.' '.$coin->symbol_show.''; echo ''.$difficulty.''; echo ''.$height.''; diff --git a/web/yaamp/modules/site/results/graph_hashrate_results.php b/web/yaamp/modules/site/results/graph_hashrate_results.php index 1741dd9..b585fb0 100644 --- a/web/yaamp/modules/site/results/graph_hashrate_results.php +++ b/web/yaamp/modules/site/results/graph_hashrate_results.php @@ -8,19 +8,16 @@ $factor = yaamp_algo_mBTC_factor($algo); // 1000 sha (GH/s), 1 for normal MH/s $step = 15*60; $t = time() - 24*60*60; - -$stats = getdbolist('db_hashrate', "time > $t AND algo=:algo ORDER BY time", array(':algo'=>$algo)); +$t = intval($t / $step) * $step; +$stats = getdbolist('db_hashrate', "time >= $t AND algo=:algo ORDER BY time", array(':algo'=>$algo)); +$tfirst = empty($stats) ? $t : $stats[0]->time; $averages = array(); -$json = ''; - -for($i = 0; $i < 95-count($stats); $i++) -{ +for($i = 0; $i < 95-count($stats); $i++) { $d = date('Y-m-d H:i:s', $t); - $json .= "[\"$d\",0],"; - $averages[] = array($d, 0); $t += $step; + if ($t >= $tfirst) break; } foreach($stats as $n) @@ -29,43 +26,18 @@ foreach($stats as $n) $m = round($r / $factor, 3); $d = date('Y-m-d H:i:s', $n->time); - $json .= "[\"$d\",$m],"; $averages[] = array($d, $m); } -echo '[['.rtrim($json,',').'],'; -echo '['; +if ($averages[0][1] == 0) $averages[0][1] = $averages[1][1]; -$json = ''; +$avg2 = array(); $average = $averages[0][1]; -foreach($averages as $n) -{ +foreach($averages as $n) { $average = ($average*(100-$percent) + $n[1]*$percent) / 100; $m = round($average, 3); - - $json .= "[\"{$n[0]}\",$m],"; + $avg2[] = array($n[0], $m); } -// $a = 10; -// foreach($averages as $i=>$n) -// { -// if($i < $a) continue; - -// $average = 0; -// for($j = $i-$a+1; $j<=$i; $j++) -// $average += $averages[$j][1]/$a; - -// $m = round($average, 3); - -// $json .= "[\"{$n[0]}\",$m]"; -// } - -echo rtrim($json,','); -echo ']]'; - - - - - - +echo '['.json_encode($averages).",\n".json_encode($avg2).']'; diff --git a/web/yaamp/modules/site/results/graph_price_results.php b/web/yaamp/modules/site/results/graph_price_results.php index 50536c5..77873cb 100644 --- a/web/yaamp/modules/site/results/graph_price_results.php +++ b/web/yaamp/modules/site/results/graph_price_results.php @@ -1,62 +1,38 @@ getState('yaamp-algo'); $step = 15*60; $t = time() - 24*60*60; - -$stats = getdbolist('db_hashrate', "time > $t AND algo=:algo ORDER BY time", array(':algo'=>$algo)); +$t = intval($t / $step) * $step; +$stats = getdbolist('db_hashrate', "time >= $t AND algo=:algo ORDER BY time", array(':algo'=>$algo)); +$tfirst = empty($stats) ? $t : $stats[0]->time; +$pfirst = empty($stats) ? 0.0 : (double) altcoinvaluetoa($stats[0]->price); $averages = array(); -$json = ''; -for($i = 0; $i < 95-count($stats); $i++) -{ +for($i = 0; $i < 95-count($stats); $i++) { $d = date('Y-m-d H:i:s', $t); - $json .= "[\"$d\",0],"; - + $averages[] = array($d, $pfirst); $t += $step; - $averages[] = array($d, 0); + if ($t >= $tfirst) break; } -foreach($stats as $n) -{ - $m = $n->price; - +foreach($stats as $n) { + $m = (double) altcoinvaluetoa($n->price); $d = date('Y-m-d H:i:s', $n->time); - $json .= "[\"$d\",$m],"; - $averages[] = array($d, $m); } -echo '[['; -echo rtrim($json, ','); -echo '],['; - -$json = ''; +$avg2 = array(); $average = $averages[0][1]; -foreach($averages as $n) -{ +foreach($averages as $n) { $average = ($average*(100-$percent) + $n[1]*$percent) / 100; $m = round($average, 5); - $json .= "[\"{$n[0]}\",$m],"; + $avg2[] = array($n[0], $m); } -// $a = 10; -// foreach($averages as $i=>$n) -// { -// if($i < $a) continue; - -// $average = 0; -// for($j = $i-$a+1; $j<=$i; $j++) -// $average += $averages[$j][1]/$a; - -// $m = round($average, 3); - -// echo "[\"{$n[0]}\",$m]"; -// } - -echo rtrim($json, ','); -echo ']]'; - +echo '['.json_encode($averages).",\n".json_encode($avg2).']'; diff --git a/web/yaamp/modules/site/results/mining_results.php b/web/yaamp/modules/site/results/mining_results.php index 9ea04e8..d6fb39c 100644 --- a/web/yaamp/modules/site/results/mining_results.php +++ b/web/yaamp/modules/site/results/mining_results.php @@ -222,11 +222,11 @@ if(isset($price_rent) && $showrental) echo ""; -echo "

-  *** estimated average time to find a block at full pool speed
-  ** approximate from the last 5 minutes submitted shares
-  * 24h estimation from network difficulty in mBTC/Mh/day (mBTC/Gh/day for sha256 and blake algos)
-

"; +echo '

+  *** estimated average time to find a block at full pool speed
+  ** approximate from the last 5 minutes submitted shares
+  * 24h estimation from net difficulty in mBTC/MH/day (GH/day for sha & blake algos)
+

'; echo "
"; diff --git a/web/yaamp/modules/site/results/wallet_miners_results.php b/web/yaamp/modules/site/results/wallet_miners_results.php index 0a876bd..51f5340 100644 --- a/web/yaamp/modules/site/results/wallet_miners_results.php +++ b/web/yaamp/modules/site/results/wallet_miners_results.php @@ -104,6 +104,8 @@ if(count($workers)) $version = substr($worker->version, 0, 20); $password = substr($worker->password, 0, 32); + if (empty($password) && !empty($worker->worker)) + $password = substr($worker->worker, 0, 32); $subscribe = Booltoa($worker->subscribe); diff --git a/web/yaamp/modules/site/results/wallet_results.php b/web/yaamp/modules/site/results/wallet_results.php index 99c4878..f7b34ec 100644 --- a/web/yaamp/modules/site/results/wallet_results.php +++ b/web/yaamp/modules/site/results/wallet_results.php @@ -215,7 +215,7 @@ echo '

'; echo '* approximate from current exchange rates
'; if ($refcoin->symbol == 'BTC') { $usd = number_format($mining->usdbtc, 2, '.', ' '); - echo '** bitstamp $usd USD/BTC'; + echo '** bitstamp '.$usd.' USD/BTC'; } echo '

'; diff --git a/web/yaamp/modules/site/tx.php b/web/yaamp/modules/site/tx.php index 2ed9cd9..7bc8deb 100644 --- a/web/yaamp/modules/site/tx.php +++ b/web/yaamp/modules/site/tx.php @@ -7,8 +7,6 @@ if(!$user) return; $this->pageTitle = $user->username.' | '.YAAMP_SITE_NAME; -$bitcoin = getdbosql('db_coins', "symbol='BTC'"); - echo "
"; echo "
Transactions to $user->username
"; echo "
"; @@ -26,7 +24,8 @@ echo "Tx"; echo ""; echo ""; -$coin = ($user->coinid == $bitcoin->id) ? $bitcoin : getdbo('db_coins', $user->coinid); +$bitcoin = getdbosql('db_coins', "symbol='BTC'"); +$coin = ($bitcoin && $user->coinid == $bitcoin->id) ? $bitcoin : getdbo('db_coins', $user->coinid); $total = 0; foreach($list as $payout) diff --git a/web/yaamp/modules/site/wallet.php b/web/yaamp/modules/site/wallet.php index abeaadd..dc9e28d 100644 --- a/web/yaamp/modules/site/wallet.php +++ b/web/yaamp/modules/site/wallet.php @@ -14,6 +14,10 @@ foreach($raw_recents as $addr) { } $address = getparam('address'); +if (!empty($address) && preg_match('/[^A-Za-z0-9]/', $address)) { + // Just to make happy XSS seekers who can hack their own browser html... + die; +} $drop_address = getparam('drop'); if (!empty($drop_address)) { @@ -137,9 +141,10 @@ foreach($recents as $addr) $balance = $balance>0? "$balance BTC": ''; echo ''.$balance.''; - echo ''. - ''. - ''; + + $delicon = $address == $addr ? '' : ''; + echo ''.$delicon.''; + echo ''; } diff --git a/web/yaamp/modules/thread/CronjobController.php b/web/yaamp/modules/thread/CronjobController.php index b6bd7db..74f46e1 100644 --- a/web/yaamp/modules/thread/CronjobController.php +++ b/web/yaamp/modules/thread/CronjobController.php @@ -3,12 +3,6 @@ require_once('serverconfig.php'); require_once('yaamp/defaultconfig.php'); -function ld($string) -{ - $d = date('h:i:s'); - echo("$d - $string\n"); -} - class CronjobController extends CommonController { private function monitorApache() @@ -47,7 +41,7 @@ class CronjobController extends CommonController public function actionRunBlocks() { -// debuglog(__METHOD__); +// screenlog(__FUNCTION__); set_time_limit(0); $this->monitorApache(); @@ -55,20 +49,21 @@ class CronjobController extends CommonController $last_complete = memcache_get($this->memcache->memcache, "cronjob_block_time_start"); if($last_complete+(5*60) < time()) dborun("update jobs set active=false"); - BackendBlockFind1(); - BackendClearEarnings(); + if(!memcache_get($this->memcache->memcache, 'balances_locked')) { + BackendClearEarnings(); + } BackendRentingUpdate(); BackendProcessList(); BackendBlocksUpdate(); memcache_set($this->memcache->memcache, "cronjob_block_time_start", time()); -// debuglog(__METHOD__); +// screenlog(__FUNCTION__.' done'); } public function actionRunLoop2() { -// debuglog(__METHOD__); +// screenlog(__FUNCTION__); set_time_limit(0); $this->monitorApache(); @@ -83,7 +78,7 @@ class CronjobController extends CommonController MonitorBTC(); $last = memcache_get($this->memcache->memcache, 'last_renting_payout2'); - if($last + 5*60 < time()) + if($last + 5*60 < time() && !memcache_get($this->memcache->memcache, 'balances_locked')) { memcache_set($this->memcache->memcache, 'last_renting_payout2', time()); BackendRentingPayout(); @@ -97,7 +92,7 @@ class CronjobController extends CommonController } memcache_set($this->memcache->memcache, "cronjob_loop2_time_start", time()); -// debuglog(__METHOD__); +// screenlog(__FUNCTION__.' done'); } public function actionRun() @@ -134,6 +129,7 @@ class CronjobController extends CommonController getBitstampBalances(); getCexIoBalances(); doBittrexTrading(); + doCrex24Trading(); doCryptopiaTrading(); doKrakenTrading(); doLiveCoinTrading(); @@ -143,11 +139,12 @@ class CronjobController extends CommonController case 2: if(!YAAMP_PRODUCTION) break; - doYobitTrading(); + doBinanceTrading(); doCCexTrading(); - doBterTrading(); doBleutradeTrading(); + doKuCoinTrading(); doNovaTrading(); + doYobitTrading(); doCoinsMarketsTrading(); break; @@ -207,10 +204,13 @@ class CronjobController extends CommonController sleep(10); BackendDoBackup(); - memcache_set($this->memcache->memcache, 'apache_locked', false); + // prevent user balances changes during payments (blocks thread) + memcache_set($this->memcache->memcache, 'balances_locked', true, 0, 300); BackendPayments(); + memcache_set($this->memcache->memcache, 'balances_locked', false); + BackendCleanDatabase(); // BackendOptimizeTables(); diff --git a/web/yaamp/modules/trading/index.php b/web/yaamp/modules/trading/index.php index db69d23..d510b07 100644 --- a/web/yaamp/modules/trading/index.php +++ b/web/yaamp/modules/trading/index.php @@ -10,6 +10,9 @@ JavascriptFile("/extensions/jqplot/plugins/jqplot.highlighter.js"); $height = '240px'; $wallet = user()->getState('yaamp-wallet'); +if (!empty($wallet) && preg_match('/[^A-Za-z0-9]/', $wallet)) { + die; +} $user = getuserparam($wallet); $algo_unit = 'Mh'; diff --git a/web/yaamp/ui/css/main.css b/web/yaamp/ui/css/main.css index b759a8e..747860e 100644 --- a/web/yaamp/ui/css/main.css +++ b/web/yaamp/ui/css/main.css @@ -149,7 +149,6 @@ hr font-weight: bold; text-align: center; padding: 10px; - width: 98%; background-color: #ccc; color: #333; } diff --git a/web/yaamp/ui/main.php b/web/yaamp/ui/main.php index 0d03948..693791d 100644 --- a/web/yaamp/ui/main.php +++ b/web/yaamp/ui/main.php @@ -126,8 +126,10 @@ function showPageHeader() $mining = getdbosql('db_mining'); $nextpayment = date('H:i T', $mining->last_payout+YAAMP_PAYMENTS_FREQ); + $eta = ($mining->last_payout+YAAMP_PAYMENTS_FREQ) - time(); + $eta_mn = 'in '.round($eta / 60).' minutes'; - echo 'Next Payout: '.$nextpayment.''; + echo 'Next Payout: '.$nextpayment.''; echo "
"; echo "
";