XMRig
7 years ago
commit
ed320731e9
93 changed files with 21078 additions and 0 deletions
@ -0,0 +1 @@ |
|||
/build |
@ -0,0 +1,127 @@ |
|||
cmake_minimum_required(VERSION 3.0) |
|||
project(xmrig C) |
|||
|
|||
set(HEADERS |
|||
compat.h |
|||
algo/cryptonight/cryptonight.h |
|||
elist.h |
|||
xmrig.h |
|||
version.h |
|||
options.h |
|||
cpu.h |
|||
persistent_memory.h |
|||
stratum.h |
|||
stats.h |
|||
util.h |
|||
donate.h |
|||
) |
|||
|
|||
set(HEADERS_CRYPTO |
|||
crypto/c_groestl.h |
|||
crypto/c_blake256.h |
|||
crypto/c_jh.h |
|||
crypto/c_skein.h |
|||
crypto/oaes_lib.h |
|||
crypto/oaes_config.h |
|||
crypto/aesb.h |
|||
) |
|||
|
|||
set(HEADERS_COMPAT |
|||
compat/winansi.h |
|||
) |
|||
|
|||
set(HEADERS_UTILS |
|||
utils/applog.h |
|||
utils/threads.h |
|||
utils/summary.h |
|||
) |
|||
|
|||
set(SOURCES |
|||
xmrig.c |
|||
algo/cryptonight/cryptonight_common.c |
|||
util.c |
|||
options.c |
|||
cpu.c |
|||
stratum.c |
|||
stats.c |
|||
memory.c |
|||
) |
|||
|
|||
set(SOURCES_CRYPTO |
|||
crypto/c_keccak.c |
|||
crypto/c_groestl.c |
|||
crypto/c_blake256.c |
|||
crypto/c_jh.c |
|||
crypto/c_skein.c |
|||
crypto/oaes_lib.c |
|||
crypto/aesb.c |
|||
) |
|||
|
|||
set(SOURCES_UTILS |
|||
utils/applog.c |
|||
utils/summary.c |
|||
) |
|||
|
|||
if (WIN32) |
|||
set(SOURCES_OS win/cpu_win.c win/memory_win.c win/xmrig_win.c compat/winansi.c) |
|||
set(EXTRA_LIBS ws2_32) |
|||
add_definitions(/D_WIN32_WINNT=0x600) |
|||
else() |
|||
set(SOURCES_OS unix/cpu_unix.c unix/memory_unix.c unix/xmrig_unix.c) |
|||
set(EXTRA_LIBS pthread) |
|||
endif() |
|||
|
|||
include_directories(.) |
|||
add_definitions(/DUSE_NATIVE_THREADS) |
|||
add_definitions(/D_GNU_SOURCE) |
|||
add_definitions(/DDEBUG_THREADS) |
|||
|
|||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "") |
|||
set(CMAKE_BUILD_TYPE Release) |
|||
endif() |
|||
|
|||
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -mbmi2") |
|||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wno-pointer-to-int-cast") |
|||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2") |
|||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2") |
|||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate") |
|||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-use -fprofile-correction") |
|||
|
|||
if (WIN32) |
|||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") |
|||
endif() |
|||
|
|||
include_directories(compat/jansson) |
|||
add_subdirectory(compat/jansson) |
|||
|
|||
find_package(CURL REQUIRED) |
|||
|
|||
if (CURL_FOUND) |
|||
include_directories(${CURL_INCLUDE_DIRS}) |
|||
add_definitions(/DCURL_STATICLIB) |
|||
link_directories(${CURL_LIBRARIES}) |
|||
endif() |
|||
|
|||
if (CMAKE_SIZEOF_VOID_P EQUAL 8) |
|||
add_subdirectory(algo/cryptonight/bmi2) |
|||
|
|||
set(CRYPTONIGHT64 |
|||
algo/cryptonight/cryptonight_av1_aesni.c |
|||
algo/cryptonight/cryptonight_av2_aesni_wolf.c |
|||
algo/cryptonight/cryptonight_av4_legacy.c |
|||
algo/cryptonight/cryptonight_av5_aesni_experimental.c |
|||
) |
|||
|
|||
add_executable(xmrig ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${CRYPTONIGHT64}) |
|||
target_link_libraries(xmrig jansson curl cryptonight_av3_aesni_bmi2 ${EXTRA_LIBS}) |
|||
else() |
|||
set(CRYPTONIGHT32 |
|||
algo/cryptonight/cryptonight_av1_aesni32.c |
|||
algo/cryptonight/cryptonight_av4_legacy.c |
|||
) |
|||
|
|||
add_executable(xmrig32 ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${CRYPTONIGHT32}) |
|||
target_link_libraries(xmrig32 jansson -L${CURL_LIBRARIES} ${EXTRA_LIBS}) |
|||
endif() |
|||
|
|||
source_group("HEADERS" FILES ${HEADERS}) |
@ -0,0 +1,674 @@ |
|||
GNU GENERAL PUBLIC LICENSE |
|||
Version 3, 29 June 2007 |
|||
|
|||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
|||
Everyone is permitted to copy and distribute verbatim copies |
|||
of this license document, but changing it is not allowed. |
|||
|
|||
Preamble |
|||
|
|||
The GNU General Public License is a free, copyleft license for |
|||
software and other kinds of works. |
|||
|
|||
The licenses for most software and other practical works are designed |
|||
to take away your freedom to share and change the works. By contrast, |
|||
the GNU General Public License is intended to guarantee your freedom to |
|||
share and change all versions of a program--to make sure it remains free |
|||
software for all its users. We, the Free Software Foundation, use the |
|||
GNU General Public License for most of our software; it applies also to |
|||
any other work released this way by its authors. You can apply it to |
|||
your programs, too. |
|||
|
|||
When we speak of free software, we are referring to freedom, not |
|||
price. Our General Public Licenses are designed to make sure that you |
|||
have the freedom to distribute copies of free software (and charge for |
|||
them if you wish), that you receive source code or can get it if you |
|||
want it, that you can change the software or use pieces of it in new |
|||
free programs, and that you know you can do these things. |
|||
|
|||
To protect your rights, we need to prevent others from denying you |
|||
these rights or asking you to surrender the rights. Therefore, you have |
|||
certain responsibilities if you distribute copies of the software, or if |
|||
you modify it: responsibilities to respect the freedom of others. |
|||
|
|||
For example, if you distribute copies of such a program, whether |
|||
gratis or for a fee, you must pass on to the recipients the same |
|||
freedoms that you received. You must make sure that they, too, receive |
|||
or can get the source code. And you must show them these terms so they |
|||
know their rights. |
|||
|
|||
Developers that use the GNU GPL protect your rights with two steps: |
|||
(1) assert copyright on the software, and (2) offer you this License |
|||
giving you legal permission to copy, distribute and/or modify it. |
|||
|
|||
For the developers' and authors' protection, the GPL clearly explains |
|||
that there is no warranty for this free software. For both users' and |
|||
authors' sake, the GPL requires that modified versions be marked as |
|||
changed, so that their problems will not be attributed erroneously to |
|||
authors of previous versions. |
|||
|
|||
Some devices are designed to deny users access to install or run |
|||
modified versions of the software inside them, although the manufacturer |
|||
can do so. This is fundamentally incompatible with the aim of |
|||
protecting users' freedom to change the software. The systematic |
|||
pattern of such abuse occurs in the area of products for individuals to |
|||
use, which is precisely where it is most unacceptable. Therefore, we |
|||
have designed this version of the GPL to prohibit the practice for those |
|||
products. If such problems arise substantially in other domains, we |
|||
stand ready to extend this provision to those domains in future versions |
|||
of the GPL, as needed to protect the freedom of users. |
|||
|
|||
Finally, every program is threatened constantly by software patents. |
|||
States should not allow patents to restrict development and use of |
|||
software on general-purpose computers, but in those that do, we wish to |
|||
avoid the special danger that patents applied to a free program could |
|||
make it effectively proprietary. To prevent this, the GPL assures that |
|||
patents cannot be used to render the program non-free. |
|||
|
|||
The precise terms and conditions for copying, distribution and |
|||
modification follow. |
|||
|
|||
TERMS AND CONDITIONS |
|||
|
|||
0. Definitions. |
|||
|
|||
"This License" refers to version 3 of the GNU General Public License. |
|||
|
|||
"Copyright" also means copyright-like laws that apply to other kinds of |
|||
works, such as semiconductor masks. |
|||
|
|||
"The Program" refers to any copyrightable work licensed under this |
|||
License. Each licensee is addressed as "you". "Licensees" and |
|||
"recipients" may be individuals or organizations. |
|||
|
|||
To "modify" a work means to copy from or adapt all or part of the work |
|||
in a fashion requiring copyright permission, other than the making of an |
|||
exact copy. The resulting work is called a "modified version" of the |
|||
earlier work or a work "based on" the earlier work. |
|||
|
|||
A "covered work" means either the unmodified Program or a work based |
|||
on the Program. |
|||
|
|||
To "propagate" a work means to do anything with it that, without |
|||
permission, would make you directly or secondarily liable for |
|||
infringement under applicable copyright law, except executing it on a |
|||
computer or modifying a private copy. Propagation includes copying, |
|||
distribution (with or without modification), making available to the |
|||
public, and in some countries other activities as well. |
|||
|
|||
To "convey" a work means any kind of propagation that enables other |
|||
parties to make or receive copies. Mere interaction with a user through |
|||
a computer network, with no transfer of a copy, is not conveying. |
|||
|
|||
An interactive user interface displays "Appropriate Legal Notices" |
|||
to the extent that it includes a convenient and prominently visible |
|||
feature that (1) displays an appropriate copyright notice, and (2) |
|||
tells the user that there is no warranty for the work (except to the |
|||
extent that warranties are provided), that licensees may convey the |
|||
work under this License, and how to view a copy of this License. If |
|||
the interface presents a list of user commands or options, such as a |
|||
menu, a prominent item in the list meets this criterion. |
|||
|
|||
1. Source Code. |
|||
|
|||
The "source code" for a work means the preferred form of the work |
|||
for making modifications to it. "Object code" means any non-source |
|||
form of a work. |
|||
|
|||
A "Standard Interface" means an interface that either is an official |
|||
standard defined by a recognized standards body, or, in the case of |
|||
interfaces specified for a particular programming language, one that |
|||
is widely used among developers working in that language. |
|||
|
|||
The "System Libraries" of an executable work include anything, other |
|||
than the work as a whole, that (a) is included in the normal form of |
|||
packaging a Major Component, but which is not part of that Major |
|||
Component, and (b) serves only to enable use of the work with that |
|||
Major Component, or to implement a Standard Interface for which an |
|||
implementation is available to the public in source code form. A |
|||
"Major Component", in this context, means a major essential component |
|||
(kernel, window system, and so on) of the specific operating system |
|||
(if any) on which the executable work runs, or a compiler used to |
|||
produce the work, or an object code interpreter used to run it. |
|||
|
|||
The "Corresponding Source" for a work in object code form means all |
|||
the source code needed to generate, install, and (for an executable |
|||
work) run the object code and to modify the work, including scripts to |
|||
control those activities. However, it does not include the work's |
|||
System Libraries, or general-purpose tools or generally available free |
|||
programs which are used unmodified in performing those activities but |
|||
which are not part of the work. For example, Corresponding Source |
|||
includes interface definition files associated with source files for |
|||
the work, and the source code for shared libraries and dynamically |
|||
linked subprograms that the work is specifically designed to require, |
|||
such as by intimate data communication or control flow between those |
|||
subprograms and other parts of the work. |
|||
|
|||
The Corresponding Source need not include anything that users |
|||
can regenerate automatically from other parts of the Corresponding |
|||
Source. |
|||
|
|||
The Corresponding Source for a work in source code form is that |
|||
same work. |
|||
|
|||
2. Basic Permissions. |
|||
|
|||
All rights granted under this License are granted for the term of |
|||
copyright on the Program, and are irrevocable provided the stated |
|||
conditions are met. This License explicitly affirms your unlimited |
|||
permission to run the unmodified Program. The output from running a |
|||
covered work is covered by this License only if the output, given its |
|||
content, constitutes a covered work. This License acknowledges your |
|||
rights of fair use or other equivalent, as provided by copyright law. |
|||
|
|||
You may make, run and propagate covered works that you do not |
|||
convey, without conditions so long as your license otherwise remains |
|||
in force. You may convey covered works to others for the sole purpose |
|||
of having them make modifications exclusively for you, or provide you |
|||
with facilities for running those works, provided that you comply with |
|||
the terms of this License in conveying all material for which you do |
|||
not control copyright. Those thus making or running the covered works |
|||
for you must do so exclusively on your behalf, under your direction |
|||
and control, on terms that prohibit them from making any copies of |
|||
your copyrighted material outside their relationship with you. |
|||
|
|||
Conveying under any other circumstances is permitted solely under |
|||
the conditions stated below. Sublicensing is not allowed; section 10 |
|||
makes it unnecessary. |
|||
|
|||
3. Protecting Users' Legal Rights From Anti-Circumvention Law. |
|||
|
|||
No covered work shall be deemed part of an effective technological |
|||
measure under any applicable law fulfilling obligations under article |
|||
11 of the WIPO copyright treaty adopted on 20 December 1996, or |
|||
similar laws prohibiting or restricting circumvention of such |
|||
measures. |
|||
|
|||
When you convey a covered work, you waive any legal power to forbid |
|||
circumvention of technological measures to the extent such circumvention |
|||
is effected by exercising rights under this License with respect to |
|||
the covered work, and you disclaim any intention to limit operation or |
|||
modification of the work as a means of enforcing, against the work's |
|||
users, your or third parties' legal rights to forbid circumvention of |
|||
technological measures. |
|||
|
|||
4. Conveying Verbatim Copies. |
|||
|
|||
You may convey verbatim copies of the Program's source code as you |
|||
receive it, in any medium, provided that you conspicuously and |
|||
appropriately publish on each copy an appropriate copyright notice; |
|||
keep intact all notices stating that this License and any |
|||
non-permissive terms added in accord with section 7 apply to the code; |
|||
keep intact all notices of the absence of any warranty; and give all |
|||
recipients a copy of this License along with the Program. |
|||
|
|||
You may charge any price or no price for each copy that you convey, |
|||
and you may offer support or warranty protection for a fee. |
|||
|
|||
5. Conveying Modified Source Versions. |
|||
|
|||
You may convey a work based on the Program, or the modifications to |
|||
produce it from the Program, in the form of source code under the |
|||
terms of section 4, provided that you also meet all of these conditions: |
|||
|
|||
a) The work must carry prominent notices stating that you modified |
|||
it, and giving a relevant date. |
|||
|
|||
b) The work must carry prominent notices stating that it is |
|||
released under this License and any conditions added under section |
|||
7. This requirement modifies the requirement in section 4 to |
|||
"keep intact all notices". |
|||
|
|||
c) You must license the entire work, as a whole, under this |
|||
License to anyone who comes into possession of a copy. This |
|||
License will therefore apply, along with any applicable section 7 |
|||
additional terms, to the whole of the work, and all its parts, |
|||
regardless of how they are packaged. This License gives no |
|||
permission to license the work in any other way, but it does not |
|||
invalidate such permission if you have separately received it. |
|||
|
|||
d) If the work has interactive user interfaces, each must display |
|||
Appropriate Legal Notices; however, if the Program has interactive |
|||
interfaces that do not display Appropriate Legal Notices, your |
|||
work need not make them do so. |
|||
|
|||
A compilation of a covered work with other separate and independent |
|||
works, which are not by their nature extensions of the covered work, |
|||
and which are not combined with it such as to form a larger program, |
|||
in or on a volume of a storage or distribution medium, is called an |
|||
"aggregate" if the compilation and its resulting copyright are not |
|||
used to limit the access or legal rights of the compilation's users |
|||
beyond what the individual works permit. Inclusion of a covered work |
|||
in an aggregate does not cause this License to apply to the other |
|||
parts of the aggregate. |
|||
|
|||
6. Conveying Non-Source Forms. |
|||
|
|||
You may convey a covered work in object code form under the terms |
|||
of sections 4 and 5, provided that you also convey the |
|||
machine-readable Corresponding Source under the terms of this License, |
|||
in one of these ways: |
|||
|
|||
a) Convey the object code in, or embodied in, a physical product |
|||
(including a physical distribution medium), accompanied by the |
|||
Corresponding Source fixed on a durable physical medium |
|||
customarily used for software interchange. |
|||
|
|||
b) Convey the object code in, or embodied in, a physical product |
|||
(including a physical distribution medium), accompanied by a |
|||
written offer, valid for at least three years and valid for as |
|||
long as you offer spare parts or customer support for that product |
|||
model, to give anyone who possesses the object code either (1) a |
|||
copy of the Corresponding Source for all the software in the |
|||
product that is covered by this License, on a durable physical |
|||
medium customarily used for software interchange, for a price no |
|||
more than your reasonable cost of physically performing this |
|||
conveying of source, or (2) access to copy the |
|||
Corresponding Source from a network server at no charge. |
|||
|
|||
c) Convey individual copies of the object code with a copy of the |
|||
written offer to provide the Corresponding Source. This |
|||
alternative is allowed only occasionally and noncommercially, and |
|||
only if you received the object code with such an offer, in accord |
|||
with subsection 6b. |
|||
|
|||
d) Convey the object code by offering access from a designated |
|||
place (gratis or for a charge), and offer equivalent access to the |
|||
Corresponding Source in the same way through the same place at no |
|||
further charge. You need not require recipients to copy the |
|||
Corresponding Source along with the object code. If the place to |
|||
copy the object code is a network server, the Corresponding Source |
|||
may be on a different server (operated by you or a third party) |
|||
that supports equivalent copying facilities, provided you maintain |
|||
clear directions next to the object code saying where to find the |
|||
Corresponding Source. Regardless of what server hosts the |
|||
Corresponding Source, you remain obligated to ensure that it is |
|||
available for as long as needed to satisfy these requirements. |
|||
|
|||
e) Convey the object code using peer-to-peer transmission, provided |
|||
you inform other peers where the object code and Corresponding |
|||
Source of the work are being offered to the general public at no |
|||
charge under subsection 6d. |
|||
|
|||
A separable portion of the object code, whose source code is excluded |
|||
from the Corresponding Source as a System Library, need not be |
|||
included in conveying the object code work. |
|||
|
|||
A "User Product" is either (1) a "consumer product", which means any |
|||
tangible personal property which is normally used for personal, family, |
|||
or household purposes, or (2) anything designed or sold for incorporation |
|||
into a dwelling. In determining whether a product is a consumer product, |
|||
doubtful cases shall be resolved in favor of coverage. For a particular |
|||
product received by a particular user, "normally used" refers to a |
|||
typical or common use of that class of product, regardless of the status |
|||
of the particular user or of the way in which the particular user |
|||
actually uses, or expects or is expected to use, the product. A product |
|||
is a consumer product regardless of whether the product has substantial |
|||
commercial, industrial or non-consumer uses, unless such uses represent |
|||
the only significant mode of use of the product. |
|||
|
|||
"Installation Information" for a User Product means any methods, |
|||
procedures, authorization keys, or other information required to install |
|||
and execute modified versions of a covered work in that User Product from |
|||
a modified version of its Corresponding Source. The information must |
|||
suffice to ensure that the continued functioning of the modified object |
|||
code is in no case prevented or interfered with solely because |
|||
modification has been made. |
|||
|
|||
If you convey an object code work under this section in, or with, or |
|||
specifically for use in, a User Product, and the conveying occurs as |
|||
part of a transaction in which the right of possession and use of the |
|||
User Product is transferred to the recipient in perpetuity or for a |
|||
fixed term (regardless of how the transaction is characterized), the |
|||
Corresponding Source conveyed under this section must be accompanied |
|||
by the Installation Information. But this requirement does not apply |
|||
if neither you nor any third party retains the ability to install |
|||
modified object code on the User Product (for example, the work has |
|||
been installed in ROM). |
|||
|
|||
The requirement to provide Installation Information does not include a |
|||
requirement to continue to provide support service, warranty, or updates |
|||
for a work that has been modified or installed by the recipient, or for |
|||
the User Product in which it has been modified or installed. Access to a |
|||
network may be denied when the modification itself materially and |
|||
adversely affects the operation of the network or violates the rules and |
|||
protocols for communication across the network. |
|||
|
|||
Corresponding Source conveyed, and Installation Information provided, |
|||
in accord with this section must be in a format that is publicly |
|||
documented (and with an implementation available to the public in |
|||
source code form), and must require no special password or key for |
|||
unpacking, reading or copying. |
|||
|
|||
7. Additional Terms. |
|||
|
|||
"Additional permissions" are terms that supplement the terms of this |
|||
License by making exceptions from one or more of its conditions. |
|||
Additional permissions that are applicable to the entire Program shall |
|||
be treated as though they were included in this License, to the extent |
|||
that they are valid under applicable law. If additional permissions |
|||
apply only to part of the Program, that part may be used separately |
|||
under those permissions, but the entire Program remains governed by |
|||
this License without regard to the additional permissions. |
|||
|
|||
When you convey a copy of a covered work, you may at your option |
|||
remove any additional permissions from that copy, or from any part of |
|||
it. (Additional permissions may be written to require their own |
|||
removal in certain cases when you modify the work.) You may place |
|||
additional permissions on material, added by you to a covered work, |
|||
for which you have or can give appropriate copyright permission. |
|||
|
|||
Notwithstanding any other provision of this License, for material you |
|||
add to a covered work, you may (if authorized by the copyright holders of |
|||
that material) supplement the terms of this License with terms: |
|||
|
|||
a) Disclaiming warranty or limiting liability differently from the |
|||
terms of sections 15 and 16 of this License; or |
|||
|
|||
b) Requiring preservation of specified reasonable legal notices or |
|||
author attributions in that material or in the Appropriate Legal |
|||
Notices displayed by works containing it; or |
|||
|
|||
c) Prohibiting misrepresentation of the origin of that material, or |
|||
requiring that modified versions of such material be marked in |
|||
reasonable ways as different from the original version; or |
|||
|
|||
d) Limiting the use for publicity purposes of names of licensors or |
|||
authors of the material; or |
|||
|
|||
e) Declining to grant rights under trademark law for use of some |
|||
trade names, trademarks, or service marks; or |
|||
|
|||
f) Requiring indemnification of licensors and authors of that |
|||
material by anyone who conveys the material (or modified versions of |
|||
it) with contractual assumptions of liability to the recipient, for |
|||
any liability that these contractual assumptions directly impose on |
|||
those licensors and authors. |
|||
|
|||
All other non-permissive additional terms are considered "further |
|||
restrictions" within the meaning of section 10. If the Program as you |
|||
received it, or any part of it, contains a notice stating that it is |
|||
governed by this License along with a term that is a further |
|||
restriction, you may remove that term. If a license document contains |
|||
a further restriction but permits relicensing or conveying under this |
|||
License, you may add to a covered work material governed by the terms |
|||
of that license document, provided that the further restriction does |
|||
not survive such relicensing or conveying. |
|||
|
|||
If you add terms to a covered work in accord with this section, you |
|||
must place, in the relevant source files, a statement of the |
|||
additional terms that apply to those files, or a notice indicating |
|||
where to find the applicable terms. |
|||
|
|||
Additional terms, permissive or non-permissive, may be stated in the |
|||
form of a separately written license, or stated as exceptions; |
|||
the above requirements apply either way. |
|||
|
|||
8. Termination. |
|||
|
|||
You may not propagate or modify a covered work except as expressly |
|||
provided under this License. Any attempt otherwise to propagate or |
|||
modify it is void, and will automatically terminate your rights under |
|||
this License (including any patent licenses granted under the third |
|||
paragraph of section 11). |
|||
|
|||
However, if you cease all violation of this License, then your |
|||
license from a particular copyright holder is reinstated (a) |
|||
provisionally, unless and until the copyright holder explicitly and |
|||
finally terminates your license, and (b) permanently, if the copyright |
|||
holder fails to notify you of the violation by some reasonable means |
|||
prior to 60 days after the cessation. |
|||
|
|||
Moreover, your license from a particular copyright holder is |
|||
reinstated permanently if the copyright holder notifies you of the |
|||
violation by some reasonable means, this is the first time you have |
|||
received notice of violation of this License (for any work) from that |
|||
copyright holder, and you cure the violation prior to 30 days after |
|||
your receipt of the notice. |
|||
|
|||
Termination of your rights under this section does not terminate the |
|||
licenses of parties who have received copies or rights from you under |
|||
this License. If your rights have been terminated and not permanently |
|||
reinstated, you do not qualify to receive new licenses for the same |
|||
material under section 10. |
|||
|
|||
9. Acceptance Not Required for Having Copies. |
|||
|
|||
You are not required to accept this License in order to receive or |
|||
run a copy of the Program. Ancillary propagation of a covered work |
|||
occurring solely as a consequence of using peer-to-peer transmission |
|||
to receive a copy likewise does not require acceptance. However, |
|||
nothing other than this License grants you permission to propagate or |
|||
modify any covered work. These actions infringe copyright if you do |
|||
not accept this License. Therefore, by modifying or propagating a |
|||
covered work, you indicate your acceptance of this License to do so. |
|||
|
|||
10. Automatic Licensing of Downstream Recipients. |
|||
|
|||
Each time you convey a covered work, the recipient automatically |
|||
receives a license from the original licensors, to run, modify and |
|||
propagate that work, subject to this License. You are not responsible |
|||
for enforcing compliance by third parties with this License. |
|||
|
|||
An "entity transaction" is a transaction transferring control of an |
|||
organization, or substantially all assets of one, or subdividing an |
|||
organization, or merging organizations. If propagation of a covered |
|||
work results from an entity transaction, each party to that |
|||
transaction who receives a copy of the work also receives whatever |
|||
licenses to the work the party's predecessor in interest had or could |
|||
give under the previous paragraph, plus a right to possession of the |
|||
Corresponding Source of the work from the predecessor in interest, if |
|||
the predecessor has it or can get it with reasonable efforts. |
|||
|
|||
You may not impose any further restrictions on the exercise of the |
|||
rights granted or affirmed under this License. For example, you may |
|||
not impose a license fee, royalty, or other charge for exercise of |
|||
rights granted under this License, and you may not initiate litigation |
|||
(including a cross-claim or counterclaim in a lawsuit) alleging that |
|||
any patent claim is infringed by making, using, selling, offering for |
|||
sale, or importing the Program or any portion of it. |
|||
|
|||
11. Patents. |
|||
|
|||
A "contributor" is a copyright holder who authorizes use under this |
|||
License of the Program or a work on which the Program is based. The |
|||
work thus licensed is called the contributor's "contributor version". |
|||
|
|||
A contributor's "essential patent claims" are all patent claims |
|||
owned or controlled by the contributor, whether already acquired or |
|||
hereafter acquired, that would be infringed by some manner, permitted |
|||
by this License, of making, using, or selling its contributor version, |
|||
but do not include claims that would be infringed only as a |
|||
consequence of further modification of the contributor version. For |
|||
purposes of this definition, "control" includes the right to grant |
|||
patent sublicenses in a manner consistent with the requirements of |
|||
this License. |
|||
|
|||
Each contributor grants you a non-exclusive, worldwide, royalty-free |
|||
patent license under the contributor's essential patent claims, to |
|||
make, use, sell, offer for sale, import and otherwise run, modify and |
|||
propagate the contents of its contributor version. |
|||
|
|||
In the following three paragraphs, a "patent license" is any express |
|||
agreement or commitment, however denominated, not to enforce a patent |
|||
(such as an express permission to practice a patent or covenant not to |
|||
sue for patent infringement). To "grant" such a patent license to a |
|||
party means to make such an agreement or commitment not to enforce a |
|||
patent against the party. |
|||
|
|||
If you convey a covered work, knowingly relying on a patent license, |
|||
and the Corresponding Source of the work is not available for anyone |
|||
to copy, free of charge and under the terms of this License, through a |
|||
publicly available network server or other readily accessible means, |
|||
then you must either (1) cause the Corresponding Source to be so |
|||
available, or (2) arrange to deprive yourself of the benefit of the |
|||
patent license for this particular work, or (3) arrange, in a manner |
|||
consistent with the requirements of this License, to extend the patent |
|||
license to downstream recipients. "Knowingly relying" means you have |
|||
actual knowledge that, but for the patent license, your conveying the |
|||
covered work in a country, or your recipient's use of the covered work |
|||
in a country, would infringe one or more identifiable patents in that |
|||
country that you have reason to believe are valid. |
|||
|
|||
If, pursuant to or in connection with a single transaction or |
|||
arrangement, you convey, or propagate by procuring conveyance of, a |
|||
covered work, and grant a patent license to some of the parties |
|||
receiving the covered work authorizing them to use, propagate, modify |
|||
or convey a specific copy of the covered work, then the patent license |
|||
you grant is automatically extended to all recipients of the covered |
|||
work and works based on it. |
|||
|
|||
A patent license is "discriminatory" if it does not include within |
|||
the scope of its coverage, prohibits the exercise of, or is |
|||
conditioned on the non-exercise of one or more of the rights that are |
|||
specifically granted under this License. You may not convey a covered |
|||
work if you are a party to an arrangement with a third party that is |
|||
in the business of distributing software, under which you make payment |
|||
to the third party based on the extent of your activity of conveying |
|||
the work, and under which the third party grants, to any of the |
|||
parties who would receive the covered work from you, a discriminatory |
|||
patent license (a) in connection with copies of the covered work |
|||
conveyed by you (or copies made from those copies), or (b) primarily |
|||
for and in connection with specific products or compilations that |
|||
contain the covered work, unless you entered into that arrangement, |
|||
or that patent license was granted, prior to 28 March 2007. |
|||
|
|||
Nothing in this License shall be construed as excluding or limiting |
|||
any implied license or other defenses to infringement that may |
|||
otherwise be available to you under applicable patent law. |
|||
|
|||
12. No Surrender of Others' Freedom. |
|||
|
|||
If conditions are imposed on you (whether by court order, agreement or |
|||
otherwise) that contradict the conditions of this License, they do not |
|||
excuse you from the conditions of this License. If you cannot convey a |
|||
covered work so as to satisfy simultaneously your obligations under this |
|||
License and any other pertinent obligations, then as a consequence you may |
|||
not convey it at all. For example, if you agree to terms that obligate you |
|||
to collect a royalty for further conveying from those to whom you convey |
|||
the Program, the only way you could satisfy both those terms and this |
|||
License would be to refrain entirely from conveying the Program. |
|||
|
|||
13. Use with the GNU Affero General Public License. |
|||
|
|||
Notwithstanding any other provision of this License, you have |
|||
permission to link or combine any covered work with a work licensed |
|||
under version 3 of the GNU Affero General Public License into a single |
|||
combined work, and to convey the resulting work. The terms of this |
|||
License will continue to apply to the part which is the covered work, |
|||
but the special requirements of the GNU Affero General Public License, |
|||
section 13, concerning interaction through a network will apply to the |
|||
combination as such. |
|||
|
|||
14. Revised Versions of this License. |
|||
|
|||
The Free Software Foundation may publish revised and/or new versions of |
|||
the GNU General Public License from time to time. Such new versions will |
|||
be similar in spirit to the present version, but may differ in detail to |
|||
address new problems or concerns. |
|||
|
|||
Each version is given a distinguishing version number. If the |
|||
Program specifies that a certain numbered version of the GNU General |
|||
Public License "or any later version" applies to it, you have the |
|||
option of following the terms and conditions either of that numbered |
|||
version or of any later version published by the Free Software |
|||
Foundation. If the Program does not specify a version number of the |
|||
GNU General Public License, you may choose any version ever published |
|||
by the Free Software Foundation. |
|||
|
|||
If the Program specifies that a proxy can decide which future |
|||
versions of the GNU General Public License can be used, that proxy's |
|||
public statement of acceptance of a version permanently authorizes you |
|||
to choose that version for the Program. |
|||
|
|||
Later license versions may give you additional or different |
|||
permissions. However, no additional obligations are imposed on any |
|||
author or copyright holder as a result of your choosing to follow a |
|||
later version. |
|||
|
|||
15. Disclaimer of Warranty. |
|||
|
|||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY |
|||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT |
|||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY |
|||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, |
|||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM |
|||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF |
|||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
|||
|
|||
16. Limitation of Liability. |
|||
|
|||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
|||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS |
|||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY |
|||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE |
|||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF |
|||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD |
|||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), |
|||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF |
|||
SUCH DAMAGES. |
|||
|
|||
17. Interpretation of Sections 15 and 16. |
|||
|
|||
If the disclaimer of warranty and limitation of liability provided |
|||
above cannot be given local legal effect according to their terms, |
|||
reviewing courts shall apply local law that most closely approximates |
|||
an absolute waiver of all civil liability in connection with the |
|||
Program, unless a warranty or assumption of liability accompanies a |
|||
copy of the Program in return for a fee. |
|||
|
|||
END OF TERMS AND CONDITIONS |
|||
|
|||
How to Apply These Terms to Your New Programs |
|||
|
|||
If you develop a new program, and you want it to be of the greatest |
|||
possible use to the public, the best way to achieve this is to make it |
|||
free software which everyone can redistribute and change under these terms. |
|||
|
|||
To do so, attach the following notices to the program. It is safest |
|||
to attach them to the start of each source file to most effectively |
|||
state the exclusion of warranty; and each file should have at least |
|||
the "copyright" line and a pointer to where the full notice is found. |
|||
|
|||
{one line to give the program's name and a brief idea of what it does.} |
|||
Copyright (C) {year} {name of author} |
|||
|
|||
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/>. |
|||
|
|||
Also add information on how to contact you by electronic and paper mail. |
|||
|
|||
If the program does terminal interaction, make it output a short |
|||
notice like this when it starts in an interactive mode: |
|||
|
|||
{project} Copyright (C) {year} {fullname} |
|||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
|||
This is free software, and you are welcome to redistribute it |
|||
under certain conditions; type `show c' for details. |
|||
|
|||
The hypothetical commands `show w' and `show c' should show the appropriate |
|||
parts of the General Public License. Of course, your program's commands |
|||
might be different; for a GUI interface, you would use an "about box". |
|||
|
|||
You should also get your employer (if you work as a programmer) or school, |
|||
if any, to sign a "copyright disclaimer" for the program, if necessary. |
|||
For more information on this, and how to apply and follow the GNU GPL, see |
|||
<http://www.gnu.org/licenses/>. |
|||
|
|||
The GNU General Public License does not permit incorporating your program |
|||
into proprietary programs. If your program is a subroutine library, you |
|||
may consider it more useful to permit linking proprietary applications with |
|||
the library. If this is what you want to do, use the GNU Lesser General |
|||
Public License instead of this License. But first, please read |
|||
<http://www.gnu.org/philosophy/why-not-lgpl.html>. |
@ -0,0 +1,94 @@ |
|||
# XMRig |
|||
XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support. |
|||
Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code. |
|||
|
|||
#### Table of contents |
|||
* [Features](#features) |
|||
* [Download](#download) |
|||
* [Usage](#usage) |
|||
* [Build](#build) |
|||
* [Other information](#other-information) |
|||
|
|||
## Features |
|||
* High performance, faster than others (290+ H/s on i7 6700). |
|||
* Official Windows support. |
|||
* Small Windows executable, only 350 KB without dependencies. |
|||
* Support for backup (failover) mining server. |
|||
* keepalived support. |
|||
* Command line options compatible with cpuminer. |
|||
* It's open source software. |
|||
|
|||
## Download |
|||
* Binary releases: https://github.com/xmrig/xmrig/releases |
|||
* Git tree: https://github.com/xmrig/xmrig.git |
|||
* Clone with `git clone https://github.com/xmrig/xmrig.git` |
|||
|
|||
## Usage |
|||
### Basic example |
|||
``` |
|||
xmrig.exe -o xmr-eu.dwarfpool.com:8005 -b xmr-usa.dwarfpool.com:8005 -u YOUR_WALLET -p x -k |
|||
``` |
|||
|
|||
### Options |
|||
``` |
|||
-o, --url=URL URL of mining server |
|||
-b, --backup-url=URL URL of backup mining server |
|||
-O, --userpass=U:P username:password pair for mining server |
|||
-u, --user=USERNAME username for mining server |
|||
-p, --pass=PASSWORD password for mining server |
|||
-t, --threads=N number of miner threads |
|||
-v, --av=N algorithm variation, 0 auto select |
|||
-k, --keepalive send keepalived for prevent timeout (need pool support) |
|||
-r, --retries=N number of times to retry before switch to backup server (default: 5) |
|||
-R, --retry-pause=N time to pause between retries (default: 5) |
|||
--cpu-affinity set process affinity to cpu core(s), mask 0x3 for cores 0 and 1 |
|||
--no-color disable colored output |
|||
--donate-level=N donate level, default 5% (5 minutes in 100 minutes) |
|||
-B, --background run the miner in the background |
|||
-c, --config=FILE load a JSON-format configuration file |
|||
-h, --help display this help and exit |
|||
-V, --version output version information and exit |
|||
``` |
|||
|
|||
## Build |
|||
### Ubuntu (Debian-based distros) |
|||
``` |
|||
sudo apt-get install git build-essential cmake libcurl4-openssl-dev |
|||
git clone https://github.com/xmrig/xmrig.git |
|||
cd xmrig |
|||
mkdir build |
|||
cd build |
|||
cmake .. |
|||
make |
|||
``` |
|||
|
|||
### Windows |
|||
It's complicated, you need [MSYS2](http://www.msys2.org/), custom libcurl build, and of course CMake too. |
|||
Configure options for libcurl: |
|||
``` |
|||
./configure --disable-shared --enable-optimize --enable-threaded-resolver --disable-libcurl-option --disable-ares --disable-rt --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-manual --disable-ipv6 --disable-sspi --disable-crypto-auth --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --without-zlib --without-winssl --without-ssl --without-libssh2 --without-nghttp2 --disable-cookies --without-ca-bundle |
|||
``` |
|||
CMake options: |
|||
``` |
|||
cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCURL_INCLUDE_DIR="c:\<path>\curl-7.53.1\include" -DCURL_LIBRARY="c:\<path>\curl-7.53.1\lib\.libs" |
|||
``` |
|||
|
|||
## Other information |
|||
* Now only support 64 bit operating systems (Windows/Linux). |
|||
* No HTTP support, only stratum protocol support. |
|||
* No TLS support. |
|||
* Default donation 5% (5 minutes in 100 minutes) can be reduced to 1% via command line option `--donate-level`. |
|||
|
|||
|
|||
### CPU mining performance |
|||
* **i7-6700** - 290+ H/s (4 threads, cpu affinity 0xAA) |
|||
* **Dual E5620** - 377 H/s (12 threads, cpu affinity 0xEEEE) |
|||
|
|||
Please note performance is highly dependent on system load. The numbers above are obtained on an idle system. Tasks heavily using a processor cache, such as video playback, can greatly degrade hashrate. Optimal number of threads depends on the size of the L3 cache of a processor, 1 thread requires 2 MB of cache. |
|||
|
|||
### Maximum performance checklist |
|||
* Idle operating system. |
|||
* Do not exceed optimal thread count. |
|||
* Use modern CPUs with AES-NI instructuon set. |
|||
* Try setup optimal cpu affinity. |
|||
* Enable fast memory (Large/Huge pages). |
@ -0,0 +1,2 @@ |
|||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbmi2") |
|||
add_library(cryptonight_av3_aesni_bmi2 STATIC ../cryptonight_av3_aesni_bmi2.c) |
@ -0,0 +1,72 @@ |
|||
/* 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__ |
|||
#define __CRYPTONIGHT_H__ |
|||
|
|||
#include <stddef.h> |
|||
#include <stdint.h> |
|||
|
|||
#define MEMORY (1 << 21) /* 2 MiB */ |
|||
#define MEMORY_M128I (MEMORY >> 4) // 2 MiB / 16 = 128 ki * __m128i
|
|||
#define ITER (1 << 20) |
|||
#define AES_BLOCK_SIZE 16 |
|||
#define AES_KEY_SIZE 32 /*16*/ |
|||
#define INIT_SIZE_BLK 8 |
|||
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE) // 128
|
|||
#define INIT_SIZE_M128I (INIT_SIZE_BYTE >> 4) // 8
|
|||
|
|||
#pragma pack(push, 1) |
|||
union hash_state { |
|||
uint8_t b[200]; |
|||
uint64_t w[25]; |
|||
}; |
|||
#pragma pack(pop) |
|||
|
|||
#pragma pack(push, 1) |
|||
union cn_slow_hash_state { |
|||
union hash_state hs; |
|||
struct { |
|||
uint8_t k[64]; |
|||
uint8_t init[INIT_SIZE_BYTE]; |
|||
}; |
|||
}; |
|||
#pragma pack(pop) |
|||
|
|||
|
|||
struct cryptonight_ctx { |
|||
union cn_slow_hash_state state; |
|||
uint8_t text[INIT_SIZE_BYTE] __attribute((aligned(16))); |
|||
uint64_t a[2] __attribute__((aligned(16))); |
|||
uint64_t b[2] __attribute__((aligned(16))); |
|||
uint64_t c[2] __attribute__((aligned(16))); |
|||
}; |
|||
|
|||
|
|||
extern void (* const extra_hashes[4])(const void *, size_t, char *); |
|||
|
|||
void cryptonight_init(int variant); |
|||
void cryptonight_hash(void* output, const void* input, size_t input_len); |
|||
int scanhash_cryptonight(int thr_id, uint32_t *hash, uint32_t *restrict pdata, const uint32_t *restrict ptarget, uint32_t max_nonce, unsigned long *restrict hashes_done, const char *memory, struct cryptonight_ctx *persistentctx); |
|||
|
|||
#endif /* __CRYPTONIGHT_H__ */ |
@ -0,0 +1,216 @@ |
|||
/* 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 <x86intrin.h> |
|||
#include <string.h> |
|||
|
|||
#include "cryptonight.h" |
|||
#include "crypto/c_keccak.h" |
|||
|
|||
|
|||
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2) |
|||
{ |
|||
__m128i tmp4; |
|||
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF); |
|||
tmp4 = _mm_slli_si128(*tmp1, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
*tmp1 = _mm_xor_si128(*tmp1, *tmp2); |
|||
} |
|||
|
|||
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3) |
|||
{ |
|||
__m128i tmp2, tmp4; |
|||
|
|||
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00); |
|||
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA); |
|||
tmp4 = _mm_slli_si128(*tmp3, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp2); |
|||
} |
|||
|
|||
// Special thanks to Intel for helping me
|
|||
// with ExpandAESKey256() and its subroutines
|
|||
static inline void ExpandAESKey256(char *keybuf) |
|||
{ |
|||
__m128i tmp1, tmp2, tmp3, *keys; |
|||
|
|||
keys = (__m128i *)keybuf; |
|||
|
|||
tmp1 = _mm_load_si128((__m128i *)keybuf); |
|||
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10)); |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[2] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[3] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[4] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[5] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[6] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[7] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[8] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[9] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[10] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[11] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[12] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[13] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[14] = tmp1; |
|||
} |
|||
|
|||
void cryptonight_av1_aesni(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) |
|||
{ |
|||
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200); |
|||
uint8_t ExpandedKey[256]; |
|||
size_t i, j; |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE); |
|||
ExpandAESKey256(ExpandedKey); |
|||
|
|||
__m128i *longoutput, *expkey, *xmminput; |
|||
longoutput = (__m128i *) memory; |
|||
expkey = (__m128i *)ExpandedKey; |
|||
xmminput = (__m128i *)ctx->text; |
|||
|
|||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) |
|||
{ |
|||
for(j = 0; j < 10; j++) |
|||
{ |
|||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]); |
|||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]); |
|||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]); |
|||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]); |
|||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]); |
|||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]); |
|||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]); |
|||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]); |
|||
} |
|||
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]); |
|||
} |
|||
|
|||
for (i = 0; i < 2; i++) |
|||
{ |
|||
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4]; |
|||
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6]; |
|||
} |
|||
|
|||
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]); |
|||
__m128i b_x = _mm_load_si128((__m128i *) ctx->b); |
|||
|
|||
uint64_t c[2] __attribute((aligned(16))); |
|||
uint64_t d[2] __attribute((aligned(16))); |
|||
|
|||
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) { |
|||
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a)); |
|||
_mm_store_si128((__m128i *) c, c_x); |
|||
|
|||
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0]; |
|||
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x)); |
|||
b_x = c_x; |
|||
|
|||
d[0] = d_ptr[0]; |
|||
d[1] = d_ptr[1]; |
|||
|
|||
{ |
|||
unsigned __int128 res = (unsigned __int128) c[0] * d[0]; |
|||
|
|||
d_ptr[0] = ctx->a[0] += res >> 64; |
|||
d_ptr[1] = ctx->a[1] += (uint64_t) res; |
|||
} |
|||
|
|||
ctx->a[0] ^= d[0]; |
|||
ctx->a[1] ^= d[1]; |
|||
|
|||
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]); |
|||
} |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE); |
|||
ExpandAESKey256(ExpandedKey); |
|||
|
|||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) { |
|||
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]); |
|||
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]); |
|||
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]); |
|||
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]); |
|||
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]); |
|||
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]); |
|||
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]); |
|||
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]); |
|||
|
|||
for(j = 0; j < 10; j++) |
|||
{ |
|||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]); |
|||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]); |
|||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]); |
|||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]); |
|||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]); |
|||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]); |
|||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]); |
|||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]); |
|||
} |
|||
|
|||
} |
|||
|
|||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE); |
|||
keccakf((uint64_t *) &ctx->state.hs, 24); |
|||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output); |
|||
} |
@ -0,0 +1,239 @@ |
|||
/* 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 <x86intrin.h> |
|||
#include <string.h> |
|||
|
|||
#include "cryptonight.h" |
|||
#include "crypto/c_keccak.h" |
|||
|
|||
|
|||
static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) { |
|||
// multiplier = ab = a * 2^32 + b
|
|||
// multiplicand = cd = c * 2^32 + d
|
|||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
|||
uint64_t a = multiplier >> 32; |
|||
uint64_t b = multiplier & 0xFFFFFFFF; |
|||
uint64_t c = multiplicand >> 32; |
|||
uint64_t d = multiplicand & 0xFFFFFFFF; |
|||
|
|||
//uint64_t ac = a * c;
|
|||
uint64_t ad = a * d; |
|||
//uint64_t bc = b * c;
|
|||
uint64_t bd = b * d; |
|||
|
|||
uint64_t adbc = ad + (b * c); |
|||
uint64_t adbc_carry = adbc < ad ? 1 : 0; |
|||
|
|||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
|||
uint64_t product_lo = bd + (adbc << 32); |
|||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0; |
|||
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry; |
|||
|
|||
return product_lo; |
|||
} |
|||
|
|||
|
|||
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2) |
|||
{ |
|||
__m128i tmp4; |
|||
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF); |
|||
tmp4 = _mm_slli_si128(*tmp1, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
*tmp1 = _mm_xor_si128(*tmp1, *tmp2); |
|||
} |
|||
|
|||
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3) |
|||
{ |
|||
__m128i tmp2, tmp4; |
|||
|
|||
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00); |
|||
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA); |
|||
tmp4 = _mm_slli_si128(*tmp3, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp2); |
|||
} |
|||
|
|||
// Special thanks to Intel for helping me
|
|||
// with ExpandAESKey256() and its subroutines
|
|||
static inline void ExpandAESKey256(char *keybuf) |
|||
{ |
|||
__m128i tmp1, tmp2, tmp3, *keys; |
|||
|
|||
keys = (__m128i *)keybuf; |
|||
|
|||
tmp1 = _mm_load_si128((__m128i *)keybuf); |
|||
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10)); |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[2] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[3] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[4] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[5] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[6] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[7] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[8] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[9] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[10] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[11] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[12] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[13] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[14] = tmp1; |
|||
} |
|||
|
|||
void cryptonight_av1_aesni32(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) |
|||
{ |
|||
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200); |
|||
uint8_t ExpandedKey[256]; |
|||
size_t i, j; |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE); |
|||
ExpandAESKey256(ExpandedKey); |
|||
|
|||
__m128i *longoutput, *expkey, *xmminput; |
|||
longoutput = (__m128i *) memory; |
|||
expkey = (__m128i *)ExpandedKey; |
|||
xmminput = (__m128i *)ctx->text; |
|||
|
|||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) |
|||
{ |
|||
for(j = 0; j < 10; j++) |
|||
{ |
|||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]); |
|||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]); |
|||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]); |
|||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]); |
|||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]); |
|||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]); |
|||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]); |
|||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]); |
|||
} |
|||
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]); |
|||
} |
|||
|
|||
for (i = 0; i < 2; i++) |
|||
{ |
|||
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4]; |
|||
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6]; |
|||
} |
|||
|
|||
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]); |
|||
__m128i b_x = _mm_load_si128((__m128i *) ctx->b); |
|||
|
|||
uint64_t c[2] __attribute((aligned(16))); |
|||
uint64_t d[2] __attribute((aligned(16))); |
|||
uint64_t hi; |
|||
|
|||
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) { |
|||
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a)); |
|||
_mm_store_si128((__m128i *) c, c_x); |
|||
|
|||
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0]; |
|||
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x)); |
|||
b_x = c_x; |
|||
|
|||
d[0] = d_ptr[0]; |
|||
d[1] = d_ptr[1]; |
|||
|
|||
d_ptr[1] = ctx->a[1] += mul128(c[0], d[0], &hi); |
|||
d_ptr[0] = ctx->a[0] += hi; |
|||
|
|||
ctx->a[0] ^= d[0]; |
|||
ctx->a[1] ^= d[1]; |
|||
|
|||
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]); |
|||
} |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE); |
|||
ExpandAESKey256(ExpandedKey); |
|||
|
|||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) { |
|||
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]); |
|||
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]); |
|||
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]); |
|||
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]); |
|||
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]); |
|||
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]); |
|||
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]); |
|||
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]); |
|||
|
|||
for(j = 0; j < 10; j++) |
|||
{ |
|||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]); |
|||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]); |
|||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]); |
|||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]); |
|||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]); |
|||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]); |
|||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]); |
|||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]); |
|||
} |
|||
|
|||
} |
|||
|
|||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE); |
|||
keccakf((uint64_t *) &ctx->state.hs, 24); |
|||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output); |
|||
} |
@ -0,0 +1,237 @@ |
|||
/* 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 <x86intrin.h> |
|||
|
|||
#include "cryptonight.h" |
|||
#include "crypto/c_keccak.h" |
|||
|
|||
|
|||
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2) |
|||
{ |
|||
__m128i tmp4; |
|||
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF); |
|||
tmp4 = _mm_slli_si128(*tmp1, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
*tmp1 = _mm_xor_si128(*tmp1, *tmp2); |
|||
} |
|||
|
|||
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3) |
|||
{ |
|||
__m128i tmp2, tmp4; |
|||
|
|||
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00); |
|||
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA); |
|||
tmp4 = _mm_slli_si128(*tmp3, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp2); |
|||
} |
|||
|
|||
// Special thanks to Intel for helping me
|
|||
// with ExpandAESKey256() and its subroutines
|
|||
static inline void ExpandAESKey256(char *keybuf) |
|||
{ |
|||
__m128i tmp1, tmp2, tmp3, *keys; |
|||
|
|||
keys = (__m128i *)keybuf; |
|||
|
|||
tmp1 = _mm_load_si128((__m128i *)keybuf); |
|||
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10)); |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[2] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[3] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[4] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[5] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[6] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[7] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[8] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[9] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[10] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[11] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[12] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[13] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[14] = tmp1; |
|||
} |
|||
|
|||
void cryptonight_av2_aesni_wolf(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) |
|||
{ |
|||
keccak((const uint8_t *) input, 76, (uint8_t *) &ctx->state.hs, 200); |
|||
uint8_t ExpandedKey[256]; |
|||
size_t i, j; |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE); |
|||
ExpandAESKey256(ExpandedKey); |
|||
|
|||
__m128i *longoutput, *expkey, *xmminput; |
|||
longoutput = (__m128i *)memory; |
|||
expkey = (__m128i *)ExpandedKey; |
|||
xmminput = (__m128i *)ctx->text; |
|||
|
|||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) |
|||
{ |
|||
for(j = 0; j < 10; j++) |
|||
{ |
|||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]); |
|||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]); |
|||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]); |
|||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]); |
|||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]); |
|||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]); |
|||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]); |
|||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]); |
|||
} |
|||
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]); |
|||
} |
|||
|
|||
for (i = 0; i < 2; i++) |
|||
{ |
|||
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4]; |
|||
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6]; |
|||
} |
|||
|
|||
__m128i b_x = _mm_load_si128((__m128i *)ctx->b); |
|||
uint64_t a[2] __attribute((aligned(16))), b[2] __attribute((aligned(16))); |
|||
a[0] = ctx->a[0]; |
|||
a[1] = ctx->a[1]; |
|||
|
|||
for(i = 0; __builtin_expect(i < 0x80000, 1); i++) |
|||
{ |
|||
__m128i c_x = _mm_load_si128((__m128i *)&memory[a[0] & 0x1FFFF0]); |
|||
__m128i a_x = _mm_load_si128((__m128i *)a); |
|||
uint64_t c[2]; |
|||
c_x = _mm_aesenc_si128(c_x, a_x); |
|||
|
|||
_mm_store_si128((__m128i *)c, c_x); |
|||
__builtin_prefetch(&memory[c[0] & 0x1FFFF0], 0, 1); |
|||
|
|||
b_x = _mm_xor_si128(b_x, c_x); |
|||
_mm_store_si128((__m128i *)&memory[a[0] & 0x1FFFF0], b_x); |
|||
|
|||
uint64_t *nextblock = (uint64_t *)&memory[c[0] & 0x1FFFF0]; |
|||
uint64_t b[2]; |
|||
b[0] = nextblock[0]; |
|||
b[1] = nextblock[1]; |
|||
|
|||
{ |
|||
uint64_t hi, lo; |
|||
// hi,lo = 64bit x 64bit multiply of c[0] and b[0]
|
|||
|
|||
__asm__("mulq %3\n\t" |
|||
: "=d" (hi), |
|||
"=a" (lo) |
|||
: "%a" (c[0]), |
|||
"rm" (b[0]) |
|||
: "cc" ); |
|||
|
|||
a[0] += hi; |
|||
a[1] += lo; |
|||
} |
|||
|
|||
uint64_t *dst = (uint64_t *) &memory[c[0] & 0x1FFFF0]; |
|||
dst[0] = a[0]; |
|||
dst[1] = a[1]; |
|||
|
|||
a[0] ^= b[0]; |
|||
a[1] ^= b[1]; |
|||
b_x = c_x; |
|||
__builtin_prefetch(&memory[a[0] & 0x1FFFF0], 0, 3); |
|||
} |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE); |
|||
ExpandAESKey256(ExpandedKey); |
|||
|
|||
//for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE)
|
|||
// aesni_parallel_xor(&ctx->text, ExpandedKey, &ctx->long_state[i]);
|
|||
|
|||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) |
|||
{ |
|||
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]); |
|||
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]); |
|||
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]); |
|||
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]); |
|||
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]); |
|||
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]); |
|||
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]); |
|||
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]); |
|||
|
|||
for(j = 0; j < 10; j++) |
|||
{ |
|||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]); |
|||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]); |
|||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]); |
|||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]); |
|||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]); |
|||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]); |
|||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]); |
|||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]); |
|||
} |
|||
|
|||
} |
|||
|
|||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE); |
|||
keccakf((uint64_t *) &ctx->state.hs, 24); |
|||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output); |
|||
} |
@ -0,0 +1,214 @@ |
|||
/* 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 <x86intrin.h> |
|||
#include <string.h> |
|||
|
|||
#include "cryptonight.h" |
|||
#include "crypto/c_keccak.h" |
|||
|
|||
|
|||
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2) |
|||
{ |
|||
__m128i tmp4; |
|||
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF); |
|||
tmp4 = _mm_slli_si128(*tmp1, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
*tmp1 = _mm_xor_si128(*tmp1, *tmp2); |
|||
} |
|||
|
|||
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3) |
|||
{ |
|||
__m128i tmp2, tmp4; |
|||
|
|||
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00); |
|||
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA); |
|||
tmp4 = _mm_slli_si128(*tmp3, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp2); |
|||
} |
|||
|
|||
// Special thanks to Intel for helping me
|
|||
// with ExpandAESKey256() and its subroutines
|
|||
static inline void ExpandAESKey256(char *keybuf) |
|||
{ |
|||
__m128i tmp1, tmp2, tmp3, *keys; |
|||
|
|||
keys = (__m128i *)keybuf; |
|||
|
|||
tmp1 = _mm_load_si128((__m128i *)keybuf); |
|||
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10)); |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[2] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[3] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[4] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[5] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[6] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[7] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[8] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[9] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[10] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[11] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[12] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[13] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[14] = tmp1; |
|||
} |
|||
|
|||
void cryptonight_av3_aesni_bmi2(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) |
|||
{ |
|||
keccak((const uint8_t *) input, 76, (uint8_t *) &ctx->state.hs, 200); |
|||
uint8_t ExpandedKey[256]; |
|||
size_t i, j; |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE); |
|||
ExpandAESKey256(ExpandedKey); |
|||
|
|||
__m128i *longoutput, *expkey, *xmminput; |
|||
longoutput = (__m128i *) memory; |
|||
expkey = (__m128i *)ExpandedKey; |
|||
xmminput = (__m128i *)ctx->text; |
|||
|
|||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) |
|||
{ |
|||
for(j = 0; j < 10; j++) |
|||
{ |
|||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]); |
|||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]); |
|||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]); |
|||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]); |
|||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]); |
|||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]); |
|||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]); |
|||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]); |
|||
} |
|||
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]); |
|||
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]); |
|||
} |
|||
|
|||
for (i = 0; i < 2; i++) |
|||
{ |
|||
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4]; |
|||
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6]; |
|||
} |
|||
|
|||
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]); |
|||
__m128i b_x = _mm_load_si128((__m128i *) ctx->b); |
|||
|
|||
uint64_t c[2] __attribute((aligned(16))); |
|||
uint64_t d[2] __attribute((aligned(16))); |
|||
uint64_t hi; |
|||
|
|||
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) { |
|||
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a)); |
|||
_mm_store_si128((__m128i *) c, c_x); |
|||
|
|||
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0]; |
|||
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x)); |
|||
b_x = c_x; |
|||
|
|||
d[0] = d_ptr[0]; |
|||
d[1] = d_ptr[1]; |
|||
|
|||
d_ptr[1] = ctx->a[1] += _mulx_u64(c[0], d[0], &hi); |
|||
d_ptr[0] = ctx->a[0] += hi; |
|||
|
|||
ctx->a[0] ^= d[0]; |
|||
ctx->a[1] ^= d[1]; |
|||
|
|||
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]); |
|||
|
|||
} |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE); |
|||
ExpandAESKey256(ExpandedKey); |
|||
|
|||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) { |
|||
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]); |
|||
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]); |
|||
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]); |
|||
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]); |
|||
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]); |
|||
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]); |
|||
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]); |
|||
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]); |
|||
|
|||
for(j = 0; j < 10; j++) |
|||
{ |
|||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]); |
|||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]); |
|||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]); |
|||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]); |
|||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]); |
|||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]); |
|||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]); |
|||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]); |
|||
} |
|||
|
|||
} |
|||
|
|||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE); |
|||
keccakf((uint64_t *) &ctx->state.hs, 24); |
|||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output); |
|||
} |
@ -0,0 +1,151 @@ |
|||
/* 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 <x86intrin.h> |
|||
#include <string.h> |
|||
|
|||
#include "cryptonight.h" |
|||
#include "compat.h" |
|||
#include "crypto/c_keccak.h" |
|||
#include "crypto/aesb.h" |
|||
#include "crypto/oaes_lib.h" |
|||
|
|||
|
|||
static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) { |
|||
// multiplier = ab = a * 2^32 + b
|
|||
// multiplicand = cd = c * 2^32 + d
|
|||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
|||
uint64_t a = multiplier >> 32; |
|||
uint64_t b = multiplier & 0xFFFFFFFF; |
|||
uint64_t c = multiplicand >> 32; |
|||
uint64_t d = multiplicand & 0xFFFFFFFF; |
|||
|
|||
//uint64_t ac = a * c;
|
|||
uint64_t ad = a * d; |
|||
//uint64_t bc = b * c;
|
|||
uint64_t bd = b * d; |
|||
|
|||
uint64_t adbc = ad + (b * c); |
|||
uint64_t adbc_carry = adbc < ad ? 1 : 0; |
|||
|
|||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
|||
uint64_t product_lo = bd + (adbc << 32); |
|||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0; |
|||
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry; |
|||
|
|||
return product_lo; |
|||
} |
|||
|
|||
|
|||
static inline void mul_sum_xor_dst(const uint8_t* a, uint8_t* c, uint8_t* dst) { |
|||
uint64_t hi, lo = mul128(((uint64_t*) a)[0], ((uint64_t*) dst)[0], &hi) + ((uint64_t*) c)[1]; |
|||
hi += ((uint64_t*) c)[0]; |
|||
|
|||
((uint64_t*) c)[0] = ((uint64_t*) dst)[0] ^ hi; |
|||
((uint64_t*) c)[1] = ((uint64_t*) dst)[1] ^ lo; |
|||
((uint64_t*) dst)[0] = hi; |
|||
((uint64_t*) dst)[1] = lo; |
|||
} |
|||
|
|||
|
|||
static inline void xor_blocks(uint8_t* a, const uint8_t* b) { |
|||
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0]; |
|||
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1]; |
|||
} |
|||
|
|||
|
|||
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) { |
|||
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0]; |
|||
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1]; |
|||
} |
|||
|
|||
|
|||
void cryptonight_av4_legacy(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) { |
|||
oaes_ctx *aes_ctx = (oaes_ctx*) oaes_alloc(); |
|||
size_t i, j; |
|||
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200); |
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
|
|||
oaes_key_import_data(aes_ctx, ctx->state.hs.b, AES_KEY_SIZE); |
|||
|
|||
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) { |
|||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 0], aes_ctx->key->exp_data); |
|||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 1], aes_ctx->key->exp_data); |
|||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 2], aes_ctx->key->exp_data); |
|||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 3], aes_ctx->key->exp_data); |
|||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 4], aes_ctx->key->exp_data); |
|||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 5], aes_ctx->key->exp_data); |
|||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 6], aes_ctx->key->exp_data); |
|||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 7], aes_ctx->key->exp_data); |
|||
memcpy((void *) &memory[i], ctx->text, INIT_SIZE_BYTE); |
|||
} |
|||
|
|||
xor_blocks_dst(&ctx->state.k[0], &ctx->state.k[32], (uint8_t*) ctx->a); |
|||
xor_blocks_dst(&ctx->state.k[16], &ctx->state.k[48], (uint8_t*) ctx->b); |
|||
|
|||
for (i = 0; likely(i < ITER / 4); ++i) { |
|||
/* Dependency chain: address -> read value ------+
|
|||
* written value <-+ hard function (AES or MUL) <+ |
|||
* next address <-+ |
|||
*/ |
|||
/* Iteration 1 */ |
|||
j = ctx->a[0] & 0x1FFFF0; |
|||
aesb_single_round((const uint8_t*) &memory[j], (uint8_t *) ctx->c, (const uint8_t *) ctx->a); |
|||
xor_blocks_dst((const uint8_t*) ctx->c, (const uint8_t*) ctx->b, (uint8_t*) &memory[j]); |
|||
/* Iteration 2 */ |
|||
mul_sum_xor_dst((const uint8_t*) ctx->c, (uint8_t*) ctx->a, (uint8_t*) &memory[ctx->c[0] & 0x1FFFF0]); |
|||
/* Iteration 3 */ |
|||
j = ctx->a[0] & 0x1FFFF0; |
|||
aesb_single_round(&memory[j], (uint8_t *) ctx->b, (uint8_t *) ctx->a); |
|||
xor_blocks_dst((const uint8_t*) ctx->b, (const uint8_t*) ctx->c, (uint8_t*) &memory[j]); |
|||
/* Iteration 4 */ |
|||
mul_sum_xor_dst((const uint8_t*) ctx->b, (uint8_t*) ctx->a, (uint8_t*) &memory[ctx->b[0] & 0x1FFFF0]); |
|||
} |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
oaes_key_import_data(aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE); |
|||
|
|||
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) { |
|||
xor_blocks(&ctx->text[0 * AES_BLOCK_SIZE], &memory[i + 0 * AES_BLOCK_SIZE]); |
|||
aesb_pseudo_round_mut(&ctx->text[0 * AES_BLOCK_SIZE], aes_ctx->key->exp_data); |
|||
xor_blocks(&ctx->text[1 * AES_BLOCK_SIZE], &memory[i + 1 * AES_BLOCK_SIZE]); |
|||
aesb_pseudo_round_mut(&ctx->text[1 * AES_BLOCK_SIZE], aes_ctx->key->exp_data); |
|||
xor_blocks(&ctx->text[2 * AES_BLOCK_SIZE], &memory[i + 2 * AES_BLOCK_SIZE]); |
|||
aesb_pseudo_round_mut(&ctx->text[2 * AES_BLOCK_SIZE], aes_ctx->key->exp_data); |
|||
xor_blocks(&ctx->text[3 * AES_BLOCK_SIZE], &memory[i + 3 * AES_BLOCK_SIZE]); |
|||
aesb_pseudo_round_mut(&ctx->text[3 * AES_BLOCK_SIZE], aes_ctx->key->exp_data); |
|||
xor_blocks(&ctx->text[4 * AES_BLOCK_SIZE], &memory[i + 4 * AES_BLOCK_SIZE]); |
|||
aesb_pseudo_round_mut(&ctx->text[4 * AES_BLOCK_SIZE], aes_ctx->key->exp_data); |
|||
xor_blocks(&ctx->text[5 * AES_BLOCK_SIZE], &memory[i + 5 * AES_BLOCK_SIZE]); |
|||
aesb_pseudo_round_mut(&ctx->text[5 * AES_BLOCK_SIZE], aes_ctx->key->exp_data); |
|||
xor_blocks(&ctx->text[6 * AES_BLOCK_SIZE], &memory[i + 6 * AES_BLOCK_SIZE]); |
|||
aesb_pseudo_round_mut(&ctx->text[6 * AES_BLOCK_SIZE], aes_ctx->key->exp_data); |
|||
xor_blocks(&ctx->text[7 * AES_BLOCK_SIZE], &memory[i + 7 * AES_BLOCK_SIZE]); |
|||
aesb_pseudo_round_mut(&ctx->text[7 * AES_BLOCK_SIZE], aes_ctx->key->exp_data); |
|||
} |
|||
|
|||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE); |
|||
keccakf((uint64_t *) &ctx->state.hs, 24); |
|||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output); |
|||
oaes_free((OAES_CTX **) &aes_ctx); |
|||
} |
@ -0,0 +1,248 @@ |
|||
/* 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 <x86intrin.h> |
|||
#include <string.h> |
|||
|
|||
#include "cryptonight.h" |
|||
#include "crypto/c_keccak.h" |
|||
|
|||
|
|||
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2) |
|||
{ |
|||
__m128i tmp4; |
|||
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF); |
|||
tmp4 = _mm_slli_si128(*tmp1, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp1 = _mm_xor_si128(*tmp1, tmp4); |
|||
*tmp1 = _mm_xor_si128(*tmp1, *tmp2); |
|||
} |
|||
|
|||
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3) |
|||
{ |
|||
__m128i tmp2, tmp4; |
|||
|
|||
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00); |
|||
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA); |
|||
tmp4 = _mm_slli_si128(*tmp3, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
tmp4 = _mm_slli_si128(tmp4, 0x04); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp4); |
|||
*tmp3 = _mm_xor_si128(*tmp3, tmp2); |
|||
} |
|||
|
|||
// Special thanks to Intel for helping me
|
|||
// with ExpandAESKey256() and its subroutines
|
|||
static inline void ExpandAESKey256(char *keybuf) |
|||
{ |
|||
__m128i tmp1, tmp2, tmp3, *keys; |
|||
|
|||
keys = (__m128i *)keybuf; |
|||
|
|||
tmp1 = _mm_load_si128((__m128i *)keybuf); |
|||
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10)); |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[2] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[3] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[4] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[5] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[6] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[7] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[8] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[9] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[10] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[11] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[12] = tmp1; |
|||
ExpandAESKey256_sub2(&tmp1, &tmp3); |
|||
keys[13] = tmp3; |
|||
|
|||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40); |
|||
ExpandAESKey256_sub1(&tmp1, &tmp2); |
|||
keys[14] = tmp1; |
|||
} |
|||
|
|||
void cryptonight_av5_aesni_experimental(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) |
|||
{ |
|||
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200); |
|||
uint8_t ExpandedKey[256]; |
|||
size_t i, j; |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE); |
|||
ExpandAESKey256(ExpandedKey); |
|||
|
|||
__m128i *longoutput, *expkey, *xmminput; |
|||
longoutput = (__m128i *) memory; |
|||
expkey = (__m128i *) ExpandedKey; |
|||
xmminput = (__m128i *)ctx->text; |
|||
|
|||
// prefetch expkey, all of xmminput and enough longoutput for 4 loops
|
|||
_mm_prefetch(xmminput, _MM_HINT_T0 ); |
|||
_mm_prefetch(xmminput + 4, _MM_HINT_T0 ); |
|||
|
|||
for (i = 0; i < 64; i += 16) { |
|||
_mm_prefetch(longoutput + i, _MM_HINT_T0); |
|||
_mm_prefetch(longoutput + i + 4, _MM_HINT_T0); |
|||
_mm_prefetch(longoutput + i + 8, _MM_HINT_T0); |
|||
_mm_prefetch(longoutput + i + 12, _MM_HINT_T0); |
|||
} |
|||
|
|||
_mm_prefetch(expkey, _MM_HINT_T0); |
|||
_mm_prefetch(expkey + 4, _MM_HINT_T0); |
|||
_mm_prefetch(expkey + 8, _MM_HINT_T0); |
|||
|
|||
for (i = 0; __builtin_expect(i < MEMORY_M128I, 1); i += INIT_SIZE_M128I) { |
|||
__builtin_prefetch(longoutput + i + 64, 1, 0); |
|||
__builtin_prefetch(longoutput + i + 68, 1, 0); |
|||
|
|||
for(j = 0; j < 10; j++) { |
|||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]); |
|||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]); |
|||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]); |
|||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]); |
|||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]); |
|||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]); |
|||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]); |
|||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]); |
|||
} |
|||
|
|||
_mm_store_si128(&(longoutput[i ]), xmminput[0]); |
|||
_mm_store_si128(&(longoutput[i + 1 ]), xmminput[1]); |
|||
_mm_store_si128(&(longoutput[i + 2 ]), xmminput[2]); |
|||
_mm_store_si128(&(longoutput[i + 3 ]), xmminput[3]); |
|||
_mm_store_si128(&(longoutput[i + 4 ]), xmminput[4]); |
|||
_mm_store_si128(&(longoutput[i + 5 ]), xmminput[5]); |
|||
_mm_store_si128(&(longoutput[i + 6 ]), xmminput[6]); |
|||
_mm_store_si128(&(longoutput[i + 7 ]), xmminput[7]); |
|||
} |
|||
|
|||
ctx->a[0] = ((uint64_t *) ctx->state.k)[0] ^ ((uint64_t *) ctx->state.k)[4]; |
|||
ctx->b[0] = ((uint64_t *) ctx->state.k)[2] ^ ((uint64_t *) ctx->state.k)[6]; |
|||
ctx->a[1] = ((uint64_t *) ctx->state.k)[1] ^ ((uint64_t *) ctx->state.k)[5]; |
|||
ctx->b[1] = ((uint64_t *) ctx->state.k)[3] ^ ((uint64_t *) ctx->state.k)[7]; |
|||
|
|||
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]); |
|||
__m128i b_x = _mm_load_si128((__m128i *) ctx->b); |
|||
|
|||
uint64_t c[2] __attribute((aligned(16))); |
|||
uint64_t d[2] __attribute((aligned(16))); |
|||
|
|||
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) { |
|||
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a)); |
|||
_mm_store_si128((__m128i *) c, c_x); |
|||
|
|||
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0]; |
|||
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x)); |
|||
b_x = c_x; |
|||
|
|||
d[0] = d_ptr[0]; |
|||
d[1] = d_ptr[1]; |
|||
|
|||
{ |
|||
unsigned __int128 res = (unsigned __int128) c[0] * d[0]; |
|||
|
|||
d_ptr[0] = ctx->a[0] += res >> 64; |
|||
d_ptr[1] = ctx->a[1] += (uint64_t) res; |
|||
} |
|||
|
|||
ctx->a[0] ^= d[0]; |
|||
ctx->a[1] ^= d[1]; |
|||
|
|||
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]); |
|||
} |
|||
|
|||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); |
|||
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE); |
|||
ExpandAESKey256(ExpandedKey); |
|||
|
|||
_mm_prefetch(xmminput, _MM_HINT_T0 ); |
|||
_mm_prefetch(xmminput + 4, _MM_HINT_T0 ); |
|||
|
|||
for (i = 0; i < 64; i += 16) { |
|||
_mm_prefetch(longoutput + i, _MM_HINT_T0); |
|||
_mm_prefetch(longoutput + i + 4, _MM_HINT_T0); |
|||
_mm_prefetch(longoutput + i + 8, _MM_HINT_T0); |
|||
_mm_prefetch(longoutput + i + 12, _MM_HINT_T0); |
|||
} |
|||
|
|||
_mm_prefetch(expkey, _MM_HINT_T0); |
|||
_mm_prefetch(expkey + 4, _MM_HINT_T0); |
|||
_mm_prefetch(expkey + 8, _MM_HINT_T0); |
|||
|
|||
for (i = 0; __builtin_expect(i < MEMORY_M128I, 1); i += INIT_SIZE_M128I) { |
|||
_mm_prefetch(longoutput + i + 64, _MM_HINT_T0); |
|||
_mm_prefetch(longoutput + i + 68, _MM_HINT_T0); |
|||
|
|||
xmminput[0] = _mm_xor_si128(longoutput[i ], xmminput[0]); |
|||
xmminput[1] = _mm_xor_si128(longoutput[i + 1], xmminput[1]); |
|||
xmminput[2] = _mm_xor_si128(longoutput[i + 2], xmminput[2]); |
|||
xmminput[3] = _mm_xor_si128(longoutput[i + 3], xmminput[3]); |
|||
xmminput[4] = _mm_xor_si128(longoutput[i + 4], xmminput[4]); |
|||
xmminput[5] = _mm_xor_si128(longoutput[i + 5], xmminput[5]); |
|||
xmminput[6] = _mm_xor_si128(longoutput[i + 6], xmminput[6]); |
|||
xmminput[7] = _mm_xor_si128(longoutput[i + 7], xmminput[7]); |
|||
|
|||
for(j = 0; j < 10; j++) { |
|||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]); |
|||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]); |
|||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]); |
|||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]); |
|||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]); |
|||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]); |
|||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]); |
|||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]); |
|||
} |
|||
|
|||
} |
|||
|
|||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE); |
|||
keccakf((uint64_t *) &ctx->state.hs, 24); |
|||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output); |
|||
} |
@ -0,0 +1,142 @@ |
|||
/* 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> |
|||
|
|||
#ifndef BUILD_TEST |
|||
# include "xmrig.h" |
|||
#endif |
|||
|
|||
#include "crypto/c_groestl.h" |
|||
#include "crypto/c_blake256.h" |
|||
#include "crypto/c_jh.h" |
|||
#include "crypto/c_skein.h" |
|||
#include "cryptonight.h" |
|||
#include "options.h" |
|||
|
|||
|
|||
#if defined(__x86_64__) |
|||
void cryptonight_av1_aesni(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
void cryptonight_av2_aesni_wolf(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
void cryptonight_av3_aesni_bmi2(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
void cryptonight_av5_aesni_experimental(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
#elif defined(__i386__) |
|||
void cryptonight_av1_aesni32(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
#endif |
|||
|
|||
void cryptonight_av4_legacy(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
|
|||
void (*cryptonight_hash_ctx)(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx) = NULL; |
|||
|
|||
|
|||
void cryptonight_init(int variant) |
|||
{ |
|||
switch (variant) { |
|||
#if defined(__x86_64__) |
|||
case XMR_VARIANT_AESNI: |
|||
cryptonight_hash_ctx = cryptonight_av1_aesni; |
|||
break; |
|||
|
|||
case XMR_VARIANT_AESNI_WOLF: |
|||
cryptonight_hash_ctx = cryptonight_av2_aesni_wolf; |
|||
break; |
|||
|
|||
case XMR_VARIANT_AESNI_BMI2: |
|||
cryptonight_hash_ctx = cryptonight_av3_aesni_bmi2; |
|||
break; |
|||
|
|||
case XMR_VARIANT_EXPERIMENTAL: |
|||
cryptonight_hash_ctx = cryptonight_av5_aesni_experimental; |
|||
break; |
|||
#elif defined(__i386__) |
|||
case XMR_VARIANT_AESNI: |
|||
cryptonight_hash_ctx = cryptonight_av1_aesni32; |
|||
break; |
|||
#endif |
|||
|
|||
case XMR_VARIANT_LEGACY: |
|||
cryptonight_hash_ctx = cryptonight_av4_legacy; |
|||
break; |
|||
|
|||
default: |
|||
break; |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
static inline void do_blake_hash(const void* input, size_t len, char* output) { |
|||
blake256_hash((uint8_t*)output, input, len); |
|||
} |
|||
|
|||
|
|||
static inline void do_groestl_hash(const void* input, size_t len, char* output) { |
|||
groestl(input, len * 8, (uint8_t*)output); |
|||
} |
|||
|
|||
|
|||
static inline void do_jh_hash(const void* input, size_t len, char* output) { |
|||
jh_hash(32 * 8, input, 8 * len, (uint8_t*)output); |
|||
} |
|||
|
|||
|
|||
static inline void do_skein_hash(const void* input, size_t len, char* output) { |
|||
skein_hash(8 * 32, input, 8 * len, (uint8_t*)output); |
|||
} |
|||
|
|||
|
|||
void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash}; |
|||
|
|||
|
|||
void cryptonight_hash(void* output, const void* input, size_t len) { |
|||
uint8_t *memory __attribute((aligned(16))) = (uint8_t *) malloc(MEMORY); |
|||
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); |
|||
|
|||
cryptonight_hash_ctx(output, input, memory, ctx); |
|||
|
|||
free(memory); |
|||
free(ctx); |
|||
} |
|||
|
|||
|
|||
#ifndef BUILD_TEST |
|||
int scanhash_cryptonight(int thr_id, uint32_t *hash, uint32_t *restrict pdata, const uint32_t *restrict ptarget, uint32_t max_nonce, unsigned long *restrict hashes_done, const char *restrict memory, struct cryptonight_ctx *persistentctx) { |
|||
uint32_t *nonceptr = (uint32_t*) (((char*)pdata) + 39); |
|||
uint32_t n = *nonceptr - 1; |
|||
const uint32_t first_nonce = n + 1; |
|||
|
|||
do { |
|||
*nonceptr = ++n; |
|||
cryptonight_hash_ctx(hash, pdata, memory, persistentctx); |
|||
|
|||
if (unlikely(hash[7] < ptarget[7])) { |
|||
*hashes_done = n - first_nonce + 1; |
|||
return true; |
|||
} |
|||
} while (likely((n <= max_nonce && !work_restart[thr_id].restart))); |
|||
|
|||
*hashes_done = n - first_nonce + 1; |
|||
return 0; |
|||
} |
|||
#endif |
@ -0,0 +1,47 @@ |
|||
/* 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 __COMPAT_H__ |
|||
#define __COMPAT_H__ |
|||
|
|||
#define unlikely(expr) (__builtin_expect(!!(expr), 0)) |
|||
#define likely(expr) (__builtin_expect(!!(expr), 1)) |
|||
|
|||
#ifdef WIN32 |
|||
|
|||
#include <windows.h> |
|||
|
|||
#define sleep(secs) Sleep((secs) * 1000) |
|||
|
|||
enum { |
|||
PRIO_PROCESS = 0, |
|||
}; |
|||
|
|||
static inline int setpriority(int which, int who, int prio) |
|||
{ |
|||
return -!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE); |
|||
} |
|||
|
|||
#endif /* WIN32 */ |
|||
|
|||
#endif /* __COMPAT_H__ */ |
@ -0,0 +1,23 @@ |
|||
cmake_minimum_required (VERSION 2.8) |
|||
project (jansson C) |
|||
|
|||
add_definitions(-DHAVE_CONFIG_H) |
|||
|
|||
# Add the lib sources. |
|||
file(GLOB JANSSON_SRC *.c) |
|||
|
|||
set(JANSSON_HDR_PRIVATE |
|||
${CMAKE_CURRENT_SOURCE_DIR}/hashtable.h |
|||
${CMAKE_CURRENT_SOURCE_DIR}/jansson_private.h |
|||
${CMAKE_CURRENT_SOURCE_DIR}/strbuffer.h |
|||
${CMAKE_CURRENT_SOURCE_DIR}/utf.h |
|||
${CMAKE_CURRENT_SOURCE_DIR}/jansson_private_config.h) |
|||
|
|||
set(JANSSON_HDR_PUBLIC |
|||
${CMAKE_CURRENT_SOURCE_DIR}/jansson_config.h |
|||
${CMAKE_CURRENT_SOURCE_DIR}/jansson.h) |
|||
|
|||
add_library(jansson STATIC |
|||
${JANSSON_SRC} |
|||
${JANSSON_HDR_PRIVATE} |
|||
${JANSSON_HDR_PUBLIC}) |
@ -0,0 +1,19 @@ |
|||
Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org> |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in |
|||
all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
THE SOFTWARE. |
@ -0,0 +1,446 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* |
|||
* Jansson is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#ifndef _GNU_SOURCE |
|||
#define _GNU_SOURCE |
|||
#endif |
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <assert.h> |
|||
|
|||
#include "jansson.h" |
|||
#include "jansson_private.h" |
|||
#include "strbuffer.h" |
|||
#include "utf.h" |
|||
|
|||
#define MAX_INTEGER_STR_LENGTH 100 |
|||
#define MAX_REAL_STR_LENGTH 100 |
|||
|
|||
#define FLAGS_TO_INDENT(f) ((f) & 0x1F) |
|||
#define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F) |
|||
|
|||
static int dump_to_strbuffer(const char *buffer, size_t size, void *data) |
|||
{ |
|||
return strbuffer_append_bytes((strbuffer_t *)data, buffer, size); |
|||
} |
|||
|
|||
static int dump_to_file(const char *buffer, size_t size, void *data) |
|||
{ |
|||
FILE *dest = (FILE *)data; |
|||
if(fwrite(buffer, size, 1, dest) != 1) |
|||
return -1; |
|||
return 0; |
|||
} |
|||
|
|||
/* 32 spaces (the maximum indentation size) */ |
|||
static const char whitespace[] = " "; |
|||
|
|||
static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t dump, void *data) |
|||
{ |
|||
if(FLAGS_TO_INDENT(flags) > 0) |
|||
{ |
|||
unsigned int ws_count = FLAGS_TO_INDENT(flags), n_spaces = depth * ws_count; |
|||
|
|||
if(dump("\n", 1, data)) |
|||
return -1; |
|||
|
|||
while(n_spaces > 0) |
|||
{ |
|||
int cur_n = n_spaces < sizeof whitespace - 1 ? n_spaces : sizeof whitespace - 1; |
|||
|
|||
if(dump(whitespace, cur_n, data)) |
|||
return -1; |
|||
|
|||
n_spaces -= cur_n; |
|||
} |
|||
} |
|||
else if(space && !(flags & JSON_COMPACT)) |
|||
{ |
|||
return dump(" ", 1, data); |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
static int dump_string(const char *str, size_t len, json_dump_callback_t dump, void *data, size_t flags) |
|||
{ |
|||
const char *pos, *end, *lim; |
|||
int32_t codepoint; |
|||
|
|||
if(dump("\"", 1, data)) |
|||
return -1; |
|||
|
|||
end = pos = str; |
|||
lim = str + len; |
|||
while(1) |
|||
{ |
|||
const char *text; |
|||
char seq[13]; |
|||
int length; |
|||
|
|||
while(end < lim) |
|||
{ |
|||
end = utf8_iterate(pos, lim - pos, &codepoint); |
|||
if(!end) |
|||
return -1; |
|||
|
|||
/* mandatory escape or control char */ |
|||
if(codepoint == '\\' || codepoint == '"' || codepoint < 0x20) |
|||
break; |
|||
|
|||
/* slash */ |
|||
if((flags & JSON_ESCAPE_SLASH) && codepoint == '/') |
|||
break; |
|||
|
|||
/* non-ASCII */ |
|||
if((flags & JSON_ENSURE_ASCII) && codepoint > 0x7F) |
|||
break; |
|||
|
|||
pos = end; |
|||
} |
|||
|
|||
if(pos != str) { |
|||
if(dump(str, pos - str, data)) |
|||
return -1; |
|||
} |
|||
|
|||
if(end == pos) |
|||
break; |
|||
|
|||
/* handle \, /, ", and control codes */ |
|||
length = 2; |
|||
switch(codepoint) |
|||
{ |
|||
case '\\': text = "\\\\"; break; |
|||
case '\"': text = "\\\""; break; |
|||
case '\b': text = "\\b"; break; |
|||
case '\f': text = "\\f"; break; |
|||
case '\n': text = "\\n"; break; |
|||
case '\r': text = "\\r"; break; |
|||
case '\t': text = "\\t"; break; |
|||
case '/': text = "\\/"; break; |
|||
default: |
|||
{ |
|||
/* codepoint is in BMP */ |
|||
if(codepoint < 0x10000) |
|||
{ |
|||
snprintf(seq, sizeof(seq), "\\u%04X", (unsigned int)codepoint); |
|||
length = 6; |
|||
} |
|||
|
|||
/* not in BMP -> construct a UTF-16 surrogate pair */ |
|||
else |
|||
{ |
|||
int32_t first, last; |
|||
|
|||
codepoint -= 0x10000; |
|||
first = 0xD800 | ((codepoint & 0xffc00) >> 10); |
|||
last = 0xDC00 | (codepoint & 0x003ff); |
|||
|
|||
snprintf(seq, sizeof(seq), "\\u%04X\\u%04X", (unsigned int)first, (unsigned int)last); |
|||
length = 12; |
|||
} |
|||
|
|||
text = seq; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if(dump(text, length, data)) |
|||
return -1; |
|||
|
|||
str = pos = end; |
|||
} |
|||
|
|||
return dump("\"", 1, data); |
|||
} |
|||
|
|||
static int compare_keys(const void *key1, const void *key2) |
|||
{ |
|||
return strcmp(*(const char **)key1, *(const char **)key2); |
|||
} |
|||
|
|||
static int do_dump(const json_t *json, size_t flags, int depth, |
|||
json_dump_callback_t dump, void *data) |
|||
{ |
|||
if(!json) |
|||
return -1; |
|||
|
|||
switch(json_typeof(json)) { |
|||
case JSON_NULL: |
|||
return dump("null", 4, data); |
|||
|
|||
case JSON_TRUE: |
|||
return dump("true", 4, data); |
|||
|
|||
case JSON_FALSE: |
|||
return dump("false", 5, data); |
|||
|
|||
case JSON_INTEGER: |
|||
{ |
|||
char buffer[MAX_INTEGER_STR_LENGTH]; |
|||
int size; |
|||
|
|||
size = snprintf(buffer, MAX_INTEGER_STR_LENGTH, |
|||
"%" JSON_INTEGER_FORMAT, |
|||
json_integer_value(json)); |
|||
if(size < 0 || size >= MAX_INTEGER_STR_LENGTH) |
|||
return -1; |
|||
|
|||
return dump(buffer, size, data); |
|||
} |
|||
|
|||
case JSON_REAL: |
|||
{ |
|||
char buffer[MAX_REAL_STR_LENGTH]; |
|||
int size; |
|||
double value = json_real_value(json); |
|||
|
|||
size = jsonp_dtostr(buffer, MAX_REAL_STR_LENGTH, value, |
|||
FLAGS_TO_PRECISION(flags)); |
|||
if(size < 0) |
|||
return -1; |
|||
|
|||
return dump(buffer, size, data); |
|||
} |
|||
|
|||
case JSON_STRING: |
|||
return dump_string(json_string_value(json), json_string_length(json), dump, data, flags); |
|||
|
|||
case JSON_ARRAY: |
|||
{ |
|||
size_t n; |
|||
size_t i; |
|||
|
|||
json_array_t *array; |
|||
|
|||
/* detect circular references */ |
|||
array = json_to_array(json); |
|||
if(array->visited) |
|||
goto array_error; |
|||
array->visited = 1; |
|||
|
|||
n = json_array_size(json); |
|||
|
|||
if(dump("[", 1, data)) |
|||
goto array_error; |
|||
if(n == 0) { |
|||
array->visited = 0; |
|||
return dump("]", 1, data); |
|||
} |
|||
if(dump_indent(flags, depth + 1, 0, dump, data)) |
|||
goto array_error; |
|||
|
|||
for(i = 0; i < n; ++i) { |
|||
if(do_dump(json_array_get(json, i), flags, depth + 1, |
|||
dump, data)) |
|||
goto array_error; |
|||
|
|||
if(i < n - 1) |
|||
{ |
|||
if(dump(",", 1, data) || |
|||
dump_indent(flags, depth + 1, 1, dump, data)) |
|||
goto array_error; |
|||
} |
|||
else |
|||
{ |
|||
if(dump_indent(flags, depth, 0, dump, data)) |
|||
goto array_error; |
|||
} |
|||
} |
|||
|
|||
array->visited = 0; |
|||
return dump("]", 1, data); |
|||
|
|||
array_error: |
|||
array->visited = 0; |
|||
return -1; |
|||
} |
|||
|
|||
case JSON_OBJECT: |
|||
{ |
|||
json_object_t *object; |
|||
void *iter; |
|||
const char *separator; |
|||
int separator_length; |
|||
|
|||
if(flags & JSON_COMPACT) { |
|||
separator = ":"; |
|||
separator_length = 1; |
|||
} |
|||
else { |
|||
separator = ": "; |
|||
separator_length = 2; |
|||
} |
|||
|
|||
/* detect circular references */ |
|||
object = json_to_object(json); |
|||
if(object->visited) |
|||
goto object_error; |
|||
object->visited = 1; |
|||
|
|||
iter = json_object_iter((json_t *)json); |
|||
|
|||
if(dump("{", 1, data)) |
|||
goto object_error; |
|||
if(!iter) { |
|||
object->visited = 0; |
|||
return dump("}", 1, data); |
|||
} |
|||
if(dump_indent(flags, depth + 1, 0, dump, data)) |
|||
goto object_error; |
|||
|
|||
if(flags & JSON_SORT_KEYS) |
|||
{ |
|||
const char **keys; |
|||
size_t size, i; |
|||
|
|||
size = json_object_size(json); |
|||
keys = jsonp_malloc(size * sizeof(const char *)); |
|||
if(!keys) |
|||
goto object_error; |
|||
|
|||
i = 0; |
|||
while(iter) |
|||
{ |
|||
keys[i] = json_object_iter_key(iter); |
|||
iter = json_object_iter_next((json_t *)json, iter); |
|||
i++; |
|||
} |
|||
assert(i == size); |
|||
|
|||
qsort(keys, size, sizeof(const char *), compare_keys); |
|||
|
|||
for(i = 0; i < size; i++) |
|||
{ |
|||
const char *key; |
|||
json_t *value; |
|||
|
|||
key = keys[i]; |
|||
value = json_object_get(json, key); |
|||
assert(value); |
|||
|
|||
dump_string(key, strlen(key), dump, data, flags); |
|||
if(dump(separator, separator_length, data) || |
|||
do_dump(value, flags, depth + 1, dump, data)) |
|||
{ |
|||
jsonp_free(keys); |
|||
goto object_error; |
|||
} |
|||
|
|||
if(i < size - 1) |
|||
{ |
|||
if(dump(",", 1, data) || |
|||
dump_indent(flags, depth + 1, 1, dump, data)) |
|||
{ |
|||
jsonp_free(keys); |
|||
goto object_error; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if(dump_indent(flags, depth, 0, dump, data)) |
|||
{ |
|||
jsonp_free(keys); |
|||
goto object_error; |
|||
} |
|||
} |
|||
} |
|||
|
|||
jsonp_free(keys); |
|||
} |
|||
else |
|||
{ |
|||
/* Don't sort keys */ |
|||
|
|||
while(iter) |
|||
{ |
|||
void *next = json_object_iter_next((json_t *)json, iter); |
|||
const char *key = json_object_iter_key(iter); |
|||
|
|||
dump_string(key, strlen(key), dump, data, flags); |
|||
if(dump(separator, separator_length, data) || |
|||
do_dump(json_object_iter_value(iter), flags, depth + 1, |
|||
dump, data)) |
|||
goto object_error; |
|||
|
|||
if(next) |
|||
{ |
|||
if(dump(",", 1, data) || |
|||
dump_indent(flags, depth + 1, 1, dump, data)) |
|||
goto object_error; |
|||
} |
|||
else |
|||
{ |
|||
if(dump_indent(flags, depth, 0, dump, data)) |
|||
goto object_error; |
|||
} |
|||
|
|||
iter = next; |
|||
} |
|||
} |
|||
|
|||
object->visited = 0; |
|||
return dump("}", 1, data); |
|||
|
|||
object_error: |
|||
object->visited = 0; |
|||
return -1; |
|||
} |
|||
|
|||
default: |
|||
/* not reached */ |
|||
return -1; |
|||
} |
|||
} |
|||
|
|||
char *json_dumps(const json_t *json, size_t flags) |
|||
{ |
|||
strbuffer_t strbuff; |
|||
char *result; |
|||
|
|||
if(strbuffer_init(&strbuff)) |
|||
return NULL; |
|||
|
|||
if(json_dump_callback(json, dump_to_strbuffer, (void *)&strbuff, flags)) |
|||
result = NULL; |
|||
else |
|||
result = jsonp_strdup(strbuffer_value(&strbuff)); |
|||
|
|||
strbuffer_close(&strbuff); |
|||
return result; |
|||
} |
|||
|
|||
int json_dumpf(const json_t *json, FILE *output, size_t flags) |
|||
{ |
|||
return json_dump_callback(json, dump_to_file, (void *)output, flags); |
|||
} |
|||
|
|||
int json_dump_file(const json_t *json, const char *path, size_t flags) |
|||
{ |
|||
int result; |
|||
|
|||
FILE *output = fopen(path, "w"); |
|||
if(!output) |
|||
return -1; |
|||
|
|||
result = json_dumpf(json, output, flags); |
|||
|
|||
fclose(output); |
|||
return result; |
|||
} |
|||
|
|||
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags) |
|||
{ |
|||
if(!(flags & JSON_ENCODE_ANY)) { |
|||
if(!json_is_array(json) && !json_is_object(json)) |
|||
return -1; |
|||
} |
|||
|
|||
return do_dump(json, flags, 0, callback, data); |
|||
} |
@ -0,0 +1,63 @@ |
|||
#include <string.h> |
|||
#include "jansson_private.h" |
|||
|
|||
void jsonp_error_init(json_error_t *error, const char *source) |
|||
{ |
|||
if(error) |
|||
{ |
|||
error->text[0] = '\0'; |
|||
error->line = -1; |
|||
error->column = -1; |
|||
error->position = 0; |
|||
if(source) |
|||
jsonp_error_set_source(error, source); |
|||
else |
|||
error->source[0] = '\0'; |
|||
} |
|||
} |
|||
|
|||
void jsonp_error_set_source(json_error_t *error, const char *source) |
|||
{ |
|||
size_t length; |
|||
|
|||
if(!error || !source) |
|||
return; |
|||
|
|||
length = strlen(source); |
|||
if(length < JSON_ERROR_SOURCE_LENGTH) |
|||
strncpy(error->source, source, length + 1); |
|||
else { |
|||
size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4; |
|||
strncpy(error->source, "...", 3); |
|||
strncpy(error->source + 3, source + extra, length - extra + 1); |
|||
} |
|||
} |
|||
|
|||
void jsonp_error_set(json_error_t *error, int line, int column, |
|||
size_t position, const char *msg, ...) |
|||
{ |
|||
va_list ap; |
|||
|
|||
va_start(ap, msg); |
|||
jsonp_error_vset(error, line, column, position, msg, ap); |
|||
va_end(ap); |
|||
} |
|||
|
|||
void jsonp_error_vset(json_error_t *error, int line, int column, |
|||
size_t position, const char *msg, va_list ap) |
|||
{ |
|||
if(!error) |
|||
return; |
|||
|
|||
if(error->text[0] != '\0') { |
|||
/* error already set */ |
|||
return; |
|||
} |
|||
|
|||
error->line = line; |
|||
error->column = column; |
|||
error->position = (int)position; |
|||
|
|||
vsnprintf(error->text, JSON_ERROR_TEXT_LENGTH, msg, ap); |
|||
error->text[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; |
|||
} |
@ -0,0 +1,356 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* |
|||
* This library is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#if HAVE_CONFIG_H |
|||
#include <jansson_private_config.h> |
|||
#endif |
|||
|
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
#if HAVE_STDINT_H |
|||
#include <stdint.h> |
|||
#endif |
|||
|
|||
#include <jansson_config.h> /* for JSON_INLINE */ |
|||
#include "jansson_private.h" /* for container_of() */ |
|||
#include "hashtable.h" |
|||
|
|||
#ifndef INITIAL_HASHTABLE_ORDER |
|||
#define INITIAL_HASHTABLE_ORDER 3 |
|||
#endif |
|||
|
|||
typedef struct hashtable_list list_t; |
|||
typedef struct hashtable_pair pair_t; |
|||
typedef struct hashtable_bucket bucket_t; |
|||
|
|||
extern volatile uint32_t hashtable_seed; |
|||
|
|||
/* Implementation of the hash function */ |
|||
#include "lookup3.h" |
|||
|
|||
#define list_to_pair(list_) container_of(list_, pair_t, list) |
|||
#define ordered_list_to_pair(list_) container_of(list_, pair_t, ordered_list) |
|||
#define hash_str(key) ((size_t)hashlittle((key), strlen(key), hashtable_seed)) |
|||
|
|||
static JSON_INLINE void list_init(list_t *list) |
|||
{ |
|||
list->next = list; |
|||
list->prev = list; |
|||
} |
|||
|
|||
static JSON_INLINE void list_insert(list_t *list, list_t *node) |
|||
{ |
|||
node->next = list; |
|||
node->prev = list->prev; |
|||
list->prev->next = node; |
|||
list->prev = node; |
|||
} |
|||
|
|||
static JSON_INLINE void list_remove(list_t *list) |
|||
{ |
|||
list->prev->next = list->next; |
|||
list->next->prev = list->prev; |
|||
} |
|||
|
|||
static JSON_INLINE int bucket_is_empty(hashtable_t *hashtable, bucket_t *bucket) |
|||
{ |
|||
return bucket->first == &hashtable->list && bucket->first == bucket->last; |
|||
} |
|||
|
|||
static void insert_to_bucket(hashtable_t *hashtable, bucket_t *bucket, |
|||
list_t *list) |
|||
{ |
|||
if(bucket_is_empty(hashtable, bucket)) |
|||
{ |
|||
list_insert(&hashtable->list, list); |
|||
bucket->first = bucket->last = list; |
|||
} |
|||
else |
|||
{ |
|||
list_insert(bucket->first, list); |
|||
bucket->first = list; |
|||
} |
|||
} |
|||
|
|||
static pair_t *hashtable_find_pair(hashtable_t *hashtable, bucket_t *bucket, |
|||
const char *key, size_t hash) |
|||
{ |
|||
list_t *list; |
|||
pair_t *pair; |
|||
|
|||
if(bucket_is_empty(hashtable, bucket)) |
|||
return NULL; |
|||
|
|||
list = bucket->first; |
|||
while(1) |
|||
{ |
|||
pair = list_to_pair(list); |
|||
if(pair->hash == hash && strcmp(pair->key, key) == 0) |
|||
return pair; |
|||
|
|||
if(list == bucket->last) |
|||
break; |
|||
|
|||
list = list->next; |
|||
} |
|||
|
|||
return NULL; |
|||
} |
|||
|
|||
/* returns 0 on success, -1 if key was not found */ |
|||
static int hashtable_do_del(hashtable_t *hashtable, |
|||
const char *key, size_t hash) |
|||
{ |
|||
pair_t *pair; |
|||
bucket_t *bucket; |
|||
size_t index; |
|||
|
|||
index = hash & hashmask(hashtable->order); |
|||
bucket = &hashtable->buckets[index]; |
|||
|
|||
pair = hashtable_find_pair(hashtable, bucket, key, hash); |
|||
if(!pair) |
|||
return -1; |
|||
|
|||
if(&pair->list == bucket->first && &pair->list == bucket->last) |
|||
bucket->first = bucket->last = &hashtable->list; |
|||
|
|||
else if(&pair->list == bucket->first) |
|||
bucket->first = pair->list.next; |
|||
|
|||
else if(&pair->list == bucket->last) |
|||
bucket->last = pair->list.prev; |
|||
|
|||
list_remove(&pair->list); |
|||
list_remove(&pair->ordered_list); |
|||
json_decref(pair->value); |
|||
|
|||
jsonp_free(pair); |
|||
hashtable->size--; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
static void hashtable_do_clear(hashtable_t *hashtable) |
|||
{ |
|||
list_t *list, *next; |
|||
pair_t *pair; |
|||
|
|||
for(list = hashtable->list.next; list != &hashtable->list; list = next) |
|||
{ |
|||
next = list->next; |
|||
pair = list_to_pair(list); |
|||
json_decref(pair->value); |
|||
jsonp_free(pair); |
|||
} |
|||
} |
|||
|
|||
static int hashtable_do_rehash(hashtable_t *hashtable) |
|||
{ |
|||
list_t *list, *next; |
|||
pair_t *pair; |
|||
size_t i, index, new_size, new_order; |
|||
struct hashtable_bucket *new_buckets; |
|||
|
|||
new_order = hashtable->order + 1; |
|||
new_size = hashsize(new_order); |
|||
|
|||
new_buckets = jsonp_malloc(new_size * sizeof(bucket_t)); |
|||
if(!new_buckets) |
|||
return -1; |
|||
|
|||
jsonp_free(hashtable->buckets); |
|||
hashtable->buckets = new_buckets; |
|||
hashtable->order = new_order; |
|||
|
|||
for(i = 0; i < hashsize(hashtable->order); i++) |
|||
{ |
|||
hashtable->buckets[i].first = hashtable->buckets[i].last = |
|||
&hashtable->list; |
|||
} |
|||
|
|||
list = hashtable->list.next; |
|||
list_init(&hashtable->list); |
|||
|
|||
for(; list != &hashtable->list; list = next) { |
|||
next = list->next; |
|||
pair = list_to_pair(list); |
|||
index = pair->hash % new_size; |
|||
insert_to_bucket(hashtable, &hashtable->buckets[index], &pair->list); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int hashtable_init(hashtable_t *hashtable) |
|||
{ |
|||
size_t i; |
|||
|
|||
hashtable->size = 0; |
|||
hashtable->order = INITIAL_HASHTABLE_ORDER; |
|||
hashtable->buckets = jsonp_malloc(hashsize(hashtable->order) * sizeof(bucket_t)); |
|||
if(!hashtable->buckets) |
|||
return -1; |
|||
|
|||
list_init(&hashtable->list); |
|||
list_init(&hashtable->ordered_list); |
|||
|
|||
for(i = 0; i < hashsize(hashtable->order); i++) |
|||
{ |
|||
hashtable->buckets[i].first = hashtable->buckets[i].last = |
|||
&hashtable->list; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void hashtable_close(hashtable_t *hashtable) |
|||
{ |
|||
hashtable_do_clear(hashtable); |
|||
jsonp_free(hashtable->buckets); |
|||
} |
|||
|
|||
int hashtable_set(hashtable_t *hashtable, const char *key, json_t *value) |
|||
{ |
|||
pair_t *pair; |
|||
bucket_t *bucket; |
|||
size_t hash, index; |
|||
|
|||
/* rehash if the load ratio exceeds 1 */ |
|||
if(hashtable->size >= hashsize(hashtable->order)) |
|||
if(hashtable_do_rehash(hashtable)) |
|||
return -1; |
|||
|
|||
hash = hash_str(key); |
|||
index = hash & hashmask(hashtable->order); |
|||
bucket = &hashtable->buckets[index]; |
|||
pair = hashtable_find_pair(hashtable, bucket, key, hash); |
|||
|
|||
if(pair) |
|||
{ |
|||
json_decref(pair->value); |
|||
pair->value = value; |
|||
} |
|||
else |
|||
{ |
|||
/* offsetof(...) returns the size of pair_t without the last,
|
|||
flexible member. This way, the correct amount is |
|||
allocated. */ |
|||
|
|||
size_t len = strlen(key); |
|||
if(len >= (size_t)-1 - offsetof(pair_t, key)) { |
|||
/* Avoid an overflow if the key is very long */ |
|||
return -1; |
|||
} |
|||
|
|||
pair = jsonp_malloc(offsetof(pair_t, key) + len + 1); |
|||
if(!pair) |
|||
return -1; |
|||
|
|||
pair->hash = hash; |
|||
strncpy(pair->key, key, len + 1); |
|||
pair->value = value; |
|||
list_init(&pair->list); |
|||
list_init(&pair->ordered_list); |
|||
|
|||
insert_to_bucket(hashtable, bucket, &pair->list); |
|||
list_insert(&hashtable->ordered_list, &pair->ordered_list); |
|||
|
|||
hashtable->size++; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
void *hashtable_get(hashtable_t *hashtable, const char *key) |
|||
{ |
|||
pair_t *pair; |
|||
size_t hash; |
|||
bucket_t *bucket; |
|||
|
|||
hash = hash_str(key); |
|||
bucket = &hashtable->buckets[hash & hashmask(hashtable->order)]; |
|||
|
|||
pair = hashtable_find_pair(hashtable, bucket, key, hash); |
|||
if(!pair) |
|||
return NULL; |
|||
|
|||
return pair->value; |
|||
} |
|||
|
|||
int hashtable_del(hashtable_t *hashtable, const char *key) |
|||
{ |
|||
size_t hash = hash_str(key); |
|||
return hashtable_do_del(hashtable, key, hash); |
|||
} |
|||
|
|||
void hashtable_clear(hashtable_t *hashtable) |
|||
{ |
|||
size_t i; |
|||
|
|||
hashtable_do_clear(hashtable); |
|||
|
|||
for(i = 0; i < hashsize(hashtable->order); i++) |
|||
{ |
|||
hashtable->buckets[i].first = hashtable->buckets[i].last = |
|||
&hashtable->list; |
|||
} |
|||
|
|||
list_init(&hashtable->list); |
|||
list_init(&hashtable->ordered_list); |
|||
hashtable->size = 0; |
|||
} |
|||
|
|||
void *hashtable_iter(hashtable_t *hashtable) |
|||
{ |
|||
return hashtable_iter_next(hashtable, &hashtable->ordered_list); |
|||
} |
|||
|
|||
void *hashtable_iter_at(hashtable_t *hashtable, const char *key) |
|||
{ |
|||
pair_t *pair; |
|||
size_t hash; |
|||
bucket_t *bucket; |
|||
|
|||
hash = hash_str(key); |
|||
bucket = &hashtable->buckets[hash & hashmask(hashtable->order)]; |
|||
|
|||
pair = hashtable_find_pair(hashtable, bucket, key, hash); |
|||
if(!pair) |
|||
return NULL; |
|||
|
|||
return &pair->ordered_list; |
|||
} |
|||
|
|||
void *hashtable_iter_next(hashtable_t *hashtable, void *iter) |
|||
{ |
|||
list_t *list = (list_t *)iter; |
|||
if(list->next == &hashtable->ordered_list) |
|||
return NULL; |
|||
return list->next; |
|||
} |
|||
|
|||
void *hashtable_iter_key(void *iter) |
|||
{ |
|||
pair_t *pair = ordered_list_to_pair((list_t *)iter); |
|||
return pair->key; |
|||
} |
|||
|
|||
void *hashtable_iter_value(void *iter) |
|||
{ |
|||
pair_t *pair = ordered_list_to_pair((list_t *)iter); |
|||
return pair->value; |
|||
} |
|||
|
|||
void hashtable_iter_set(void *iter, json_t *value) |
|||
{ |
|||
pair_t *pair = ordered_list_to_pair((list_t *)iter); |
|||
|
|||
json_decref(pair->value); |
|||
pair->value = value; |
|||
} |
@ -0,0 +1,176 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* |
|||
* This library is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#ifndef HASHTABLE_H |
|||
#define HASHTABLE_H |
|||
|
|||
#include <stdlib.h> |
|||
#include "jansson.h" |
|||
|
|||
struct hashtable_list { |
|||
struct hashtable_list *prev; |
|||
struct hashtable_list *next; |
|||
}; |
|||
|
|||
/* "pair" may be a bit confusing a name, but think of it as a
|
|||
key-value pair. In this case, it just encodes some extra data, |
|||
too */ |
|||
struct hashtable_pair { |
|||
struct hashtable_list list; |
|||
struct hashtable_list ordered_list; |
|||
size_t hash; |
|||
json_t *value; |
|||
char key[1]; |
|||
}; |
|||
|
|||
struct hashtable_bucket { |
|||
struct hashtable_list *first; |
|||
struct hashtable_list *last; |
|||
}; |
|||
|
|||
typedef struct hashtable { |
|||
size_t size; |
|||
struct hashtable_bucket *buckets; |
|||
size_t order; /* hashtable has pow(2, order) buckets */ |
|||
struct hashtable_list list; |
|||
struct hashtable_list ordered_list; |
|||
} hashtable_t; |
|||
|
|||
|
|||
#define hashtable_key_to_iter(key_) \ |
|||
(&(container_of(key_, struct hashtable_pair, key)->ordered_list)) |
|||
|
|||
|
|||
/**
|
|||
* hashtable_init - Initialize a hashtable object |
|||
* |
|||
* @hashtable: The (statically allocated) hashtable object |
|||
* |
|||
* Initializes a statically allocated hashtable object. The object |
|||
* should be cleared with hashtable_close when it's no longer used. |
|||
* |
|||
* Returns 0 on success, -1 on error (out of memory). |
|||
*/ |
|||
int hashtable_init(hashtable_t *hashtable); |
|||
|
|||
/**
|
|||
* hashtable_close - Release all resources used by a hashtable object |
|||
* |
|||
* @hashtable: The hashtable |
|||
* |
|||
* Destroys a statically allocated hashtable object. |
|||
*/ |
|||
void hashtable_close(hashtable_t *hashtable); |
|||
|
|||
/**
|
|||
* hashtable_set - Add/modify value in hashtable |
|||
* |
|||
* @hashtable: The hashtable object |
|||
* @key: The key |
|||
* @serial: For addition order of keys |
|||
* @value: The value |
|||
* |
|||
* If a value with the given key already exists, its value is replaced |
|||
* with the new value. Value is "stealed" in the sense that hashtable |
|||
* doesn't increment its refcount but decreases the refcount when the |
|||
* value is no longer needed. |
|||
* |
|||
* Returns 0 on success, -1 on failure (out of memory). |
|||
*/ |
|||
int hashtable_set(hashtable_t *hashtable, const char *key, json_t *value); |
|||
|
|||
/**
|
|||
* hashtable_get - Get a value associated with a key |
|||
* |
|||
* @hashtable: The hashtable object |
|||
* @key: The key |
|||
* |
|||
* Returns value if it is found, or NULL otherwise. |
|||
*/ |
|||
void *hashtable_get(hashtable_t *hashtable, const char *key); |
|||
|
|||
/**
|
|||
* hashtable_del - Remove a value from the hashtable |
|||
* |
|||
* @hashtable: The hashtable object |
|||
* @key: The key |
|||
* |
|||
* Returns 0 on success, or -1 if the key was not found. |
|||
*/ |
|||
int hashtable_del(hashtable_t *hashtable, const char *key); |
|||
|
|||
/**
|
|||
* hashtable_clear - Clear hashtable |
|||
* |
|||
* @hashtable: The hashtable object |
|||
* |
|||
* Removes all items from the hashtable. |
|||
*/ |
|||
void hashtable_clear(hashtable_t *hashtable); |
|||
|
|||
/**
|
|||
* hashtable_iter - Iterate over hashtable |
|||
* |
|||
* @hashtable: The hashtable object |
|||
* |
|||
* Returns an opaque iterator to the first element in the hashtable. |
|||
* The iterator should be passed to hashtable_iter_* functions. |
|||
* The hashtable items are not iterated over in any particular order. |
|||
* |
|||
* There's no need to free the iterator in any way. The iterator is |
|||
* valid as long as the item that is referenced by the iterator is not |
|||
* deleted. Other values may be added or deleted. In particular, |
|||
* hashtable_iter_next() may be called on an iterator, and after that |
|||
* the key/value pair pointed by the old iterator may be deleted. |
|||
*/ |
|||
void *hashtable_iter(hashtable_t *hashtable); |
|||
|
|||
/**
|
|||
* hashtable_iter_at - Return an iterator at a specific key |
|||
* |
|||
* @hashtable: The hashtable object |
|||
* @key: The key that the iterator should point to |
|||
* |
|||
* Like hashtable_iter() but returns an iterator pointing to a |
|||
* specific key. |
|||
*/ |
|||
void *hashtable_iter_at(hashtable_t *hashtable, const char *key); |
|||
|
|||
/**
|
|||
* hashtable_iter_next - Advance an iterator |
|||
* |
|||
* @hashtable: The hashtable object |
|||
* @iter: The iterator |
|||
* |
|||
* Returns a new iterator pointing to the next element in the |
|||
* hashtable or NULL if the whole hastable has been iterated over. |
|||
*/ |
|||
void *hashtable_iter_next(hashtable_t *hashtable, void *iter); |
|||
|
|||
/**
|
|||
* hashtable_iter_key - Retrieve the key pointed by an iterator |
|||
* |
|||
* @iter: The iterator |
|||
*/ |
|||
void *hashtable_iter_key(void *iter); |
|||
|
|||
/**
|
|||
* hashtable_iter_value - Retrieve the value pointed by an iterator |
|||
* |
|||
* @iter: The iterator |
|||
*/ |
|||
void *hashtable_iter_value(void *iter); |
|||
|
|||
/**
|
|||
* hashtable_iter_set - Set the value pointed by an iterator |
|||
* |
|||
* @iter: The iterator |
|||
* @value: The value to set |
|||
*/ |
|||
void hashtable_iter_set(void *iter, json_t *value); |
|||
|
|||
#endif |
@ -0,0 +1,277 @@ |
|||
/* Generate sizeof(uint32_t) bytes of as random data as possible to seed
|
|||
the hash function. |
|||
*/ |
|||
|
|||
#ifdef HAVE_CONFIG_H |
|||
#include <jansson_private_config.h> |
|||
#endif |
|||
|
|||
#include <stdio.h> |
|||
#include <time.h> |
|||
|
|||
#ifdef HAVE_STDINT_H |
|||
#include <stdint.h> |
|||
#endif |
|||
|
|||
#ifdef HAVE_FCNTL_H |
|||
#include <fcntl.h> |
|||
#endif |
|||
|
|||
#ifdef HAVE_SCHED_H |
|||
#include <sched.h> |
|||
#endif |
|||
|
|||
#ifdef HAVE_UNISTD_H |
|||
#include <unistd.h> |
|||
#endif |
|||
|
|||
#ifdef HAVE_SYS_STAT_H |
|||
#include <sys/stat.h> |
|||
#endif |
|||
|
|||
#ifdef HAVE_SYS_TIME_H |
|||
#include <sys/time.h> |
|||
#endif |
|||
|
|||
#ifdef HAVE_SYS_TYPES_H |
|||
#include <sys/types.h> |
|||
#endif |
|||
|
|||
#if defined(_WIN32) |
|||
/* For GetModuleHandle(), GetProcAddress() and GetCurrentProcessId() */ |
|||
#include <windows.h> |
|||
#endif |
|||
|
|||
#include "jansson.h" |
|||
|
|||
|
|||
static uint32_t buf_to_uint32(char *data) { |
|||
size_t i; |
|||
uint32_t result = 0; |
|||
|
|||
for (i = 0; i < sizeof(uint32_t); i++) |
|||
result = (result << 8) | (unsigned char)data[i]; |
|||
|
|||
return result; |
|||
} |
|||
|
|||
|
|||
|
|||
/* /dev/urandom */ |
|||
#if !defined(_WIN32) && defined(USE_URANDOM) |
|||
static int seed_from_urandom(uint32_t *seed) { |
|||
/* Use unbuffered I/O if we have open(), close() and read(). Otherwise
|
|||
fall back to fopen() */ |
|||
|
|||
char data[sizeof(uint32_t)]; |
|||
int ok; |
|||
|
|||
#if defined(HAVE_OPEN) && defined(HAVE_CLOSE) && defined(HAVE_READ) |
|||
int urandom; |
|||
urandom = open("/dev/urandom", O_RDONLY); |
|||
if (urandom == -1) |
|||
return 1; |
|||
|
|||
ok = read(urandom, data, sizeof(uint32_t)) == sizeof(uint32_t); |
|||
close(urandom); |
|||
#else |
|||
FILE *urandom; |
|||
|
|||
urandom = fopen("/dev/urandom", "rb"); |
|||
if (!urandom) |
|||
return 1; |
|||
|
|||
ok = fread(data, 1, sizeof(uint32_t), urandom) == sizeof(uint32_t); |
|||
fclose(urandom); |
|||
#endif |
|||
|
|||
if (!ok) |
|||
return 1; |
|||
|
|||
*seed = buf_to_uint32(data); |
|||
return 0; |
|||
} |
|||
#endif |
|||
|
|||
/* Windows Crypto API */ |
|||
#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI) |
|||
#include <wincrypt.h> |
|||
|
|||
typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv, LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags); |
|||
typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer); |
|||
typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags); |
|||
|
|||
static int seed_from_windows_cryptoapi(uint32_t *seed) |
|||
{ |
|||
HINSTANCE hAdvAPI32 = NULL; |
|||
CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL; |
|||
CRYPTGENRANDOM pCryptGenRandom = NULL; |
|||
CRYPTRELEASECONTEXT pCryptReleaseContext = NULL; |
|||
HCRYPTPROV hCryptProv = 0; |
|||
BYTE data[sizeof(uint32_t)]; |
|||
int ok; |
|||
|
|||
hAdvAPI32 = GetModuleHandle(TEXT("advapi32.dll")); |
|||
if(hAdvAPI32 == NULL) |
|||
return 1; |
|||
|
|||
pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(hAdvAPI32, "CryptAcquireContextA"); |
|||
if (!pCryptAcquireContext) |
|||
return 1; |
|||
|
|||
pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(hAdvAPI32, "CryptGenRandom"); |
|||
if (!pCryptGenRandom) |
|||
return 1; |
|||
|
|||
pCryptReleaseContext = (CRYPTRELEASECONTEXT)GetProcAddress(hAdvAPI32, "CryptReleaseContext"); |
|||
if (!pCryptReleaseContext) |
|||
return 1; |
|||
|
|||
if (!pCryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) |
|||
return 1; |
|||
|
|||
ok = pCryptGenRandom(hCryptProv, sizeof(uint32_t), data); |
|||
pCryptReleaseContext(hCryptProv, 0); |
|||
|
|||
if (!ok) |
|||
return 1; |
|||
|
|||
*seed = buf_to_uint32((char *)data); |
|||
return 0; |
|||
} |
|||
#endif |
|||
|
|||
/* gettimeofday() and getpid() */ |
|||
static int seed_from_timestamp_and_pid(uint32_t *seed) { |
|||
#ifdef HAVE_GETTIMEOFDAY |
|||
/* XOR of seconds and microseconds */ |
|||
struct timeval tv; |
|||
gettimeofday(&tv, NULL); |
|||
*seed = (uint32_t)tv.tv_sec ^ (uint32_t)tv.tv_usec; |
|||
#else |
|||
/* Seconds only */ |
|||
*seed = (uint32_t)time(NULL); |
|||
#endif |
|||
|
|||
/* XOR with PID for more randomness */ |
|||
#if defined(_WIN32) |
|||
*seed ^= (uint32_t)GetCurrentProcessId(); |
|||
#elif defined(HAVE_GETPID) |
|||
*seed ^= (uint32_t)getpid(); |
|||
#endif |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
static uint32_t generate_seed() { |
|||
uint32_t seed; |
|||
int done = 0; |
|||
|
|||
#if !defined(_WIN32) && defined(USE_URANDOM) |
|||
if (!done && seed_from_urandom(&seed) == 0) |
|||
done = 1; |
|||
#endif |
|||
|
|||
#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI) |
|||
if (!done && seed_from_windows_cryptoapi(&seed) == 0) |
|||
done = 1; |
|||
#endif |
|||
|
|||
if (!done) { |
|||
/* Fall back to timestamp and PID if no better randomness is
|
|||
available */ |
|||
seed_from_timestamp_and_pid(&seed); |
|||
} |
|||
|
|||
/* Make sure the seed is never zero */ |
|||
if (seed == 0) |
|||
seed = 1; |
|||
|
|||
return seed; |
|||
} |
|||
|
|||
|
|||
volatile uint32_t hashtable_seed = 0; |
|||
|
|||
#if defined(HAVE_ATOMIC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32)) |
|||
static volatile char seed_initialized = 0; |
|||
|
|||
void json_object_seed(size_t seed) { |
|||
uint32_t new_seed = (uint32_t)seed; |
|||
|
|||
if (hashtable_seed == 0) { |
|||
if (__atomic_test_and_set(&seed_initialized, __ATOMIC_RELAXED) == 0) { |
|||
/* Do the seeding ourselves */ |
|||
if (new_seed == 0) |
|||
new_seed = generate_seed(); |
|||
|
|||
__atomic_store_n(&hashtable_seed, new_seed, __ATOMIC_RELEASE); |
|||
} else { |
|||
/* Wait for another thread to do the seeding */ |
|||
do { |
|||
#ifdef HAVE_SCHED_YIELD |
|||
sched_yield(); |
|||
#endif |
|||
} while(__atomic_load_n(&hashtable_seed, __ATOMIC_ACQUIRE) == 0); |
|||
} |
|||
} |
|||
} |
|||
#elif defined(HAVE_SYNC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32)) |
|||
void json_object_seed(size_t seed) { |
|||
uint32_t new_seed = (uint32_t)seed; |
|||
|
|||
if (hashtable_seed == 0) { |
|||
if (new_seed == 0) { |
|||
/* Explicit synchronization fences are not supported by the
|
|||
__sync builtins, so every thread getting here has to |
|||
generate the seed value. |
|||
*/ |
|||
new_seed = generate_seed(); |
|||
} |
|||
|
|||
do { |
|||
if (__sync_bool_compare_and_swap(&hashtable_seed, 0, new_seed)) { |
|||
/* We were the first to seed */ |
|||
break; |
|||
} else { |
|||
/* Wait for another thread to do the seeding */ |
|||
#ifdef HAVE_SCHED_YIELD |
|||
sched_yield(); |
|||
#endif |
|||
} |
|||
} while(hashtable_seed == 0); |
|||
} |
|||
} |
|||
#elif defined(_WIN32) |
|||
static long seed_initialized = 0; |
|||
void json_object_seed(size_t seed) { |
|||
uint32_t new_seed = (uint32_t)seed; |
|||
|
|||
if (hashtable_seed == 0) { |
|||
if (InterlockedIncrement(&seed_initialized) == 1) { |
|||
/* Do the seeding ourselves */ |
|||
if (new_seed == 0) |
|||
new_seed = generate_seed(); |
|||
|
|||
hashtable_seed = new_seed; |
|||
} else { |
|||
/* Wait for another thread to do the seeding */ |
|||
do { |
|||
SwitchToThread(); |
|||
} while (hashtable_seed == 0); |
|||
} |
|||
} |
|||
} |
|||
#else |
|||
/* Fall back to a thread-unsafe version */ |
|||
void json_object_seed(size_t seed) { |
|||
uint32_t new_seed = (uint32_t)seed; |
|||
|
|||
if (hashtable_seed == 0) { |
|||
if (new_seed == 0) |
|||
new_seed = generate_seed(); |
|||
|
|||
hashtable_seed = new_seed; |
|||
} |
|||
} |
|||
#endif |
@ -0,0 +1,311 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* |
|||
* Jansson is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#ifndef JANSSON_H |
|||
#define JANSSON_H |
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> /* for size_t */ |
|||
#include <stdarg.h> |
|||
|
|||
#include "jansson_config.h" |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
/* version */ |
|||
|
|||
#define JANSSON_MAJOR_VERSION 2 |
|||
#define JANSSON_MINOR_VERSION 9 |
|||
#define JANSSON_MICRO_VERSION 0 |
|||
|
|||
/* Micro version is omitted if it's 0 */ |
|||
#define JANSSON_VERSION "2.9" |
|||
|
|||
/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
|
|||
for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */ |
|||
#define JANSSON_VERSION_HEX ((JANSSON_MAJOR_VERSION << 16) | \ |
|||
(JANSSON_MINOR_VERSION << 8) | \ |
|||
(JANSSON_MICRO_VERSION << 0)) |
|||
|
|||
|
|||
/* types */ |
|||
|
|||
typedef enum { |
|||
JSON_OBJECT, |
|||
JSON_ARRAY, |
|||
JSON_STRING, |
|||
JSON_INTEGER, |
|||
JSON_REAL, |
|||
JSON_TRUE, |
|||
JSON_FALSE, |
|||
JSON_NULL |
|||
} json_type; |
|||
|
|||
typedef struct json_t { |
|||
json_type type; |
|||
size_t refcount; |
|||
} json_t; |
|||
|
|||
#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */ |
|||
#if JSON_INTEGER_IS_LONG_LONG |
|||
#ifdef _WIN32 |
|||
#define JSON_INTEGER_FORMAT "I64d" |
|||
#else |
|||
#define JSON_INTEGER_FORMAT "lld" |
|||
#endif |
|||
typedef long long json_int_t; |
|||
#else |
|||
#define JSON_INTEGER_FORMAT "ld" |
|||
typedef long json_int_t; |
|||
#endif /* JSON_INTEGER_IS_LONG_LONG */ |
|||
#endif |
|||
|
|||
#define json_typeof(json) ((json)->type) |
|||
#define json_is_object(json) ((json) && json_typeof(json) == JSON_OBJECT) |
|||
#define json_is_array(json) ((json) && json_typeof(json) == JSON_ARRAY) |
|||
#define json_is_string(json) ((json) && json_typeof(json) == JSON_STRING) |
|||
#define json_is_integer(json) ((json) && json_typeof(json) == JSON_INTEGER) |
|||
#define json_is_real(json) ((json) && json_typeof(json) == JSON_REAL) |
|||
#define json_is_number(json) (json_is_integer(json) || json_is_real(json)) |
|||
#define json_is_true(json) ((json) && json_typeof(json) == JSON_TRUE) |
|||
#define json_is_false(json) ((json) && json_typeof(json) == JSON_FALSE) |
|||
#define json_boolean_value json_is_true |
|||
#define json_is_boolean(json) (json_is_true(json) || json_is_false(json)) |
|||
#define json_is_null(json) ((json) && json_typeof(json) == JSON_NULL) |
|||
|
|||
/* construction, destruction, reference counting */ |
|||
|
|||
json_t *json_object(void); |
|||
json_t *json_array(void); |
|||
json_t *json_string(const char *value); |
|||
json_t *json_stringn(const char *value, size_t len); |
|||
json_t *json_string_nocheck(const char *value); |
|||
json_t *json_stringn_nocheck(const char *value, size_t len); |
|||
json_t *json_integer(json_int_t value); |
|||
json_t *json_real(double value); |
|||
json_t *json_true(void); |
|||
json_t *json_false(void); |
|||
#define json_boolean(val) ((val) ? json_true() : json_false()) |
|||
json_t *json_null(void); |
|||
|
|||
static JSON_INLINE |
|||
json_t *json_incref(json_t *json) |
|||
{ |
|||
if(json && json->refcount != (size_t)-1) |
|||
++json->refcount; |
|||
return json; |
|||
} |
|||
|
|||
/* do not call json_delete directly */ |
|||
void json_delete(json_t *json); |
|||
|
|||
static JSON_INLINE |
|||
void json_decref(json_t *json) |
|||
{ |
|||
if(json && json->refcount != (size_t)-1 && --json->refcount == 0) |
|||
json_delete(json); |
|||
} |
|||
|
|||
#if defined(__GNUC__) || defined(__clang__) |
|||
static JSON_INLINE |
|||
void json_decrefp(json_t **json) |
|||
{ |
|||
if(json) { |
|||
json_decref(*json); |
|||
*json = NULL; |
|||
} |
|||
} |
|||
|
|||
#define json_auto_t json_t __attribute__((cleanup(json_decrefp))) |
|||
#endif |
|||
|
|||
|
|||
/* error reporting */ |
|||
|
|||
#define JSON_ERROR_TEXT_LENGTH 160 |
|||
#define JSON_ERROR_SOURCE_LENGTH 80 |
|||
|
|||
typedef struct { |
|||
int line; |
|||
int column; |
|||
int position; |
|||
char source[JSON_ERROR_SOURCE_LENGTH]; |
|||
char text[JSON_ERROR_TEXT_LENGTH]; |
|||
} json_error_t; |
|||
|
|||
|
|||
/* getters, setters, manipulation */ |
|||
|
|||
void json_object_seed(size_t seed); |
|||
size_t json_object_size(const json_t *object); |
|||
json_t *json_object_get(const json_t *object, const char *key); |
|||
int json_object_set_new(json_t *object, const char *key, json_t *value); |
|||
int json_object_set_new_nocheck(json_t *object, const char *key, json_t *value); |
|||
int json_object_del(json_t *object, const char *key); |
|||
int json_object_clear(json_t *object); |
|||
int json_object_update(json_t *object, json_t *other); |
|||
int json_object_update_existing(json_t *object, json_t *other); |
|||
int json_object_update_missing(json_t *object, json_t *other); |
|||
void *json_object_iter(json_t *object); |
|||
void *json_object_iter_at(json_t *object, const char *key); |
|||
void *json_object_key_to_iter(const char *key); |
|||
void *json_object_iter_next(json_t *object, void *iter); |
|||
const char *json_object_iter_key(void *iter); |
|||
json_t *json_object_iter_value(void *iter); |
|||
int json_object_iter_set_new(json_t *object, void *iter, json_t *value); |
|||
|
|||
#define json_object_foreach(object, key, value) \ |
|||
for(key = json_object_iter_key(json_object_iter(object)); \ |
|||
key && (value = json_object_iter_value(json_object_key_to_iter(key))); \ |
|||
key = json_object_iter_key(json_object_iter_next(object, json_object_key_to_iter(key)))) |
|||
|
|||
#define json_object_foreach_safe(object, n, key, value) \ |
|||
for(key = json_object_iter_key(json_object_iter(object)), \ |
|||
n = json_object_iter_next(object, json_object_key_to_iter(key)); \ |
|||
key && (value = json_object_iter_value(json_object_key_to_iter(key))); \ |
|||
key = json_object_iter_key(n), \ |
|||
n = json_object_iter_next(object, json_object_key_to_iter(key))) |
|||
|
|||
#define json_array_foreach(array, index, value) \ |
|||
for(index = 0; \ |
|||
index < json_array_size(array) && (value = json_array_get(array, index)); \ |
|||
index++) |
|||
|
|||
static JSON_INLINE |
|||
int json_object_set(json_t *object, const char *key, json_t *value) |
|||
{ |
|||
return json_object_set_new(object, key, json_incref(value)); |
|||
} |
|||
|
|||
static JSON_INLINE |
|||
int json_object_set_nocheck(json_t *object, const char *key, json_t *value) |
|||
{ |
|||
return json_object_set_new_nocheck(object, key, json_incref(value)); |
|||
} |
|||
|
|||
static JSON_INLINE |
|||
int json_object_iter_set(json_t *object, void *iter, json_t *value) |
|||
{ |
|||
return json_object_iter_set_new(object, iter, json_incref(value)); |
|||
} |
|||
|
|||
size_t json_array_size(const json_t *array); |
|||
json_t *json_array_get(const json_t *array, size_t index); |
|||
int json_array_set_new(json_t *array, size_t index, json_t *value); |
|||
int json_array_append_new(json_t *array, json_t *value); |
|||
int json_array_insert_new(json_t *array, size_t index, json_t *value); |
|||
int json_array_remove(json_t *array, size_t index); |
|||
int json_array_clear(json_t *array); |
|||
int json_array_extend(json_t *array, json_t *other); |
|||
|
|||
static JSON_INLINE |
|||
int json_array_set(json_t *array, size_t ind, json_t *value) |
|||
{ |
|||
return json_array_set_new(array, ind, json_incref(value)); |
|||
} |
|||
|
|||
static JSON_INLINE |
|||
int json_array_append(json_t *array, json_t *value) |
|||
{ |
|||
return json_array_append_new(array, json_incref(value)); |
|||
} |
|||
|
|||
static JSON_INLINE |
|||
int json_array_insert(json_t *array, size_t ind, json_t *value) |
|||
{ |
|||
return json_array_insert_new(array, ind, json_incref(value)); |
|||
} |
|||
|
|||
const char *json_string_value(const json_t *string); |
|||
size_t json_string_length(const json_t *string); |
|||
json_int_t json_integer_value(const json_t *integer); |
|||
double json_real_value(const json_t *real); |
|||
double json_number_value(const json_t *json); |
|||
|
|||
int json_string_set(json_t *string, const char *value); |
|||
int json_string_setn(json_t *string, const char *value, size_t len); |
|||
int json_string_set_nocheck(json_t *string, const char *value); |
|||
int json_string_setn_nocheck(json_t *string, const char *value, size_t len); |
|||
int json_integer_set(json_t *integer, json_int_t value); |
|||
int json_real_set(json_t *real, double value); |
|||
|
|||
/* pack, unpack */ |
|||
|
|||
json_t *json_pack(const char *fmt, ...); |
|||
json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...); |
|||
json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap); |
|||
|
|||
#define JSON_VALIDATE_ONLY 0x1 |
|||
#define JSON_STRICT 0x2 |
|||
|
|||
int json_unpack(json_t *root, const char *fmt, ...); |
|||
int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...); |
|||
int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, va_list ap); |
|||
|
|||
|
|||
/* equality */ |
|||
|
|||
int json_equal(json_t *value1, json_t *value2); |
|||
|
|||
|
|||
/* copying */ |
|||
|
|||
json_t *json_copy(json_t *value); |
|||
json_t *json_deep_copy(const json_t *value); |
|||
|
|||
|
|||
/* decoding */ |
|||
|
|||
#define JSON_REJECT_DUPLICATES 0x1 |
|||
#define JSON_DISABLE_EOF_CHECK 0x2 |
|||
#define JSON_DECODE_ANY 0x4 |
|||
#define JSON_DECODE_INT_AS_REAL 0x8 |
|||
#define JSON_ALLOW_NUL 0x10 |
|||
|
|||
typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data); |
|||
|
|||
json_t *json_loads(const char *input, size_t flags, json_error_t *error); |
|||
json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error); |
|||
json_t *json_loadf(FILE *input, size_t flags, json_error_t *error); |
|||
json_t *json_load_file(const char *path, size_t flags, json_error_t *error); |
|||
json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error); |
|||
|
|||
|
|||
/* encoding */ |
|||
|
|||
#define JSON_MAX_INDENT 0x1F |
|||
#define JSON_INDENT(n) ((n) & JSON_MAX_INDENT) |
|||
#define JSON_COMPACT 0x20 |
|||
#define JSON_ENSURE_ASCII 0x40 |
|||
#define JSON_SORT_KEYS 0x80 |
|||
#define JSON_PRESERVE_ORDER 0x100 |
|||
#define JSON_ENCODE_ANY 0x200 |
|||
#define JSON_ESCAPE_SLASH 0x400 |
|||
#define JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11) |
|||
|
|||
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data); |
|||
|
|||
char *json_dumps(const json_t *json, size_t flags); |
|||
int json_dumpf(const json_t *json, FILE *output, size_t flags); |
|||
int json_dump_file(const json_t *json, const char *path, size_t flags); |
|||
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags); |
|||
|
|||
/* custom memory allocation */ |
|||
|
|||
typedef void *(*json_malloc_t)(size_t); |
|||
typedef void (*json_free_t)(void *); |
|||
|
|||
void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn); |
|||
void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn); |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif |
@ -0,0 +1,43 @@ |
|||
/*
|
|||
* Copyright (c) 2010-2016 Petri Lehtinen <petri@digip.org> |
|||
* |
|||
* Jansson is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
* |
|||
* |
|||
* This file specifies a part of the site-specific configuration for |
|||
* Jansson, namely those things that affect the public API in |
|||
* jansson.h. |
|||
* |
|||
* The configure script copies this file to jansson_config.h and |
|||
* replaces @var@ substitutions by values that fit your system. If you |
|||
* cannot run the configure script, you can do the value substitution |
|||
* by hand. |
|||
*/ |
|||
|
|||
#ifndef JANSSON_CONFIG_H |
|||
#define JANSSON_CONFIG_H |
|||
|
|||
/* If your compiler supports the inline keyword in C, JSON_INLINE is
|
|||
defined to `inline', otherwise empty. In C++, the inline is always |
|||
supported. */ |
|||
#ifdef __cplusplus |
|||
#define JSON_INLINE inline |
|||
#else |
|||
#define JSON_INLINE inline |
|||
#endif |
|||
|
|||
/* If your compiler supports the `long long` type and the strtoll()
|
|||
library function, JSON_INTEGER_IS_LONG_LONG is defined to 1, |
|||
otherwise to 0. */ |
|||
#define JSON_INTEGER_IS_LONG_LONG 1 |
|||
|
|||
/* If locale.h and localeconv() are available, define to 1,
|
|||
otherwise to 0. */ |
|||
#define JSON_HAVE_LOCALECONV 1 |
|||
|
|||
/* Maximum recursion depth for parsing JSON input.
|
|||
This limits the depth of e.g. array-within-array constructions. */ |
|||
#define JSON_PARSER_MAX_DEPTH 2048 |
|||
|
|||
#endif |
@ -0,0 +1,108 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* |
|||
* Jansson is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#ifndef JANSSON_PRIVATE_H |
|||
#define JANSSON_PRIVATE_H |
|||
|
|||
#include <stddef.h> |
|||
#include "jansson.h" |
|||
#include "hashtable.h" |
|||
#include "strbuffer.h" |
|||
|
|||
#define container_of(ptr_, type_, member_) \ |
|||
((type_ *)((char *)ptr_ - offsetof(type_, member_))) |
|||
|
|||
/* On some platforms, max() may already be defined */ |
|||
#ifndef max |
|||
#define max(a, b) ((a) > (b) ? (a) : (b)) |
|||
#endif |
|||
|
|||
/* va_copy is a C99 feature. In C89 implementations, it's sometimes
|
|||
available as __va_copy. If not, memcpy() should do the trick. */ |
|||
#ifndef va_copy |
|||
#ifdef __va_copy |
|||
#define va_copy __va_copy |
|||
#else |
|||
#define va_copy(a, b) memcpy(&(a), &(b), sizeof(va_list)) |
|||
#endif |
|||
#endif |
|||
|
|||
typedef struct { |
|||
json_t json; |
|||
hashtable_t hashtable; |
|||
int visited; |
|||
} json_object_t; |
|||
|
|||
typedef struct { |
|||
json_t json; |
|||
size_t size; |
|||
size_t entries; |
|||
json_t **table; |
|||
int visited; |
|||
} json_array_t; |
|||
|
|||
typedef struct { |
|||
json_t json; |
|||
char *value; |
|||
size_t length; |
|||
} json_string_t; |
|||
|
|||
typedef struct { |
|||
json_t json; |
|||
double value; |
|||
} json_real_t; |
|||
|
|||
typedef struct { |
|||
json_t json; |
|||
json_int_t value; |
|||
} json_integer_t; |
|||
|
|||
#define json_to_object(json_) container_of(json_, json_object_t, json) |
|||
#define json_to_array(json_) container_of(json_, json_array_t, json) |
|||
#define json_to_string(json_) container_of(json_, json_string_t, json) |
|||
#define json_to_real(json_) container_of(json_, json_real_t, json) |
|||
#define json_to_integer(json_) container_of(json_, json_integer_t, json) |
|||
|
|||
/* Create a string by taking ownership of an existing buffer */ |
|||
json_t *jsonp_stringn_nocheck_own(const char *value, size_t len); |
|||
|
|||
/* Error message formatting */ |
|||
void jsonp_error_init(json_error_t *error, const char *source); |
|||
void jsonp_error_set_source(json_error_t *error, const char *source); |
|||
void jsonp_error_set(json_error_t *error, int line, int column, |
|||
size_t position, const char *msg, ...); |
|||
void jsonp_error_vset(json_error_t *error, int line, int column, |
|||
size_t position, const char *msg, va_list ap); |
|||
|
|||
/* Locale independent string<->double conversions */ |
|||
int jsonp_strtod(strbuffer_t *strbuffer, double *out); |
|||
int jsonp_dtostr(char *buffer, size_t size, double value, int prec); |
|||
|
|||
/* Wrappers for custom memory functions */ |
|||
void* jsonp_malloc(size_t size); |
|||
void jsonp_free(void *ptr); |
|||
char *jsonp_strndup(const char *str, size_t length); |
|||
char *jsonp_strdup(const char *str); |
|||
char *jsonp_strndup(const char *str, size_t len); |
|||
|
|||
|
|||
/* Windows compatibility */ |
|||
#if defined(_WIN32) || defined(WIN32) |
|||
# if defined(_MSC_VER) /* MS compiller */ |
|||
# if (_MSC_VER < 1900) && !defined(snprintf) /* snprintf not defined yet & not introduced */ |
|||
# define snprintf _snprintf |
|||
# endif |
|||
# if (_MSC_VER < 1500) && !defined(vsnprintf) /* vsnprintf not defined yet & not introduced */ |
|||
# define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a) |
|||
# endif |
|||
# else /* Other Windows compiller, old definition */ |
|||
# define snprintf _snprintf |
|||
# define vsnprintf _vsnprintf |
|||
# endif |
|||
#endif |
|||
|
|||
#endif |
@ -0,0 +1,159 @@ |
|||
/* jansson_private_config.h. Generated from jansson_private_config.h.in by configure. */ |
|||
/* jansson_private_config.h.in. Generated from configure.ac by autoheader. */ |
|||
|
|||
/* Define to 1 if gcc's __atomic builtins are available */ |
|||
#define HAVE_ATOMIC_BUILTINS 1 |
|||
|
|||
/* Define to 1 if you have the `close' function. */ |
|||
#define HAVE_CLOSE 1 |
|||
|
|||
/* Define to 1 if you have the <dlfcn.h> header file. */ |
|||
/* #undef HAVE_DLFCN_H */ |
|||
|
|||
/* Define to 1 if you have the <endian.h> header file. */ |
|||
/* #undef HAVE_ENDIAN_H */ |
|||
|
|||
/* Define to 1 if you have the <fcntl.h> header file. */ |
|||
#define HAVE_FCNTL_H 1 |
|||
|
|||
/* Define to 1 if you have the `getpid' function. */ |
|||
#define HAVE_GETPID 1 |
|||
|
|||
/* Define to 1 if you have the `gettimeofday' function. */ |
|||
#define HAVE_GETTIMEOFDAY 1 |
|||
|
|||
/* Define to 1 if you have the <inttypes.h> header file. */ |
|||
#define HAVE_INTTYPES_H 1 |
|||
|
|||
/* Define to 1 if you have the `localeconv' function. */ |
|||
#define HAVE_LOCALECONV 1 |
|||
|
|||
/* Define to 1 if you have the <locale.h> header file. */ |
|||
#define HAVE_LOCALE_H 1 |
|||
|
|||
/* Define to 1 if the system has the type 'long long int'. */ |
|||
#define HAVE_LONG_LONG_INT 1 |
|||
|
|||
/* Define to 1 if you have the <memory.h> header file. */ |
|||
#define HAVE_MEMORY_H 1 |
|||
|
|||
/* Define to 1 if you have the `open' function. */ |
|||
#define HAVE_OPEN 1 |
|||
|
|||
/* Define to 1 if you have the `read' function. */ |
|||
#define HAVE_READ 1 |
|||
|
|||
/* Define to 1 if you have the <sched.h> header file. */ |
|||
#define HAVE_SCHED_H 1 |
|||
|
|||
/* Define to 1 if you have the `sched_yield' function. */ |
|||
#define HAVE_SCHED_YIELD 1 |
|||
|
|||
/* Define to 1 if you have the <stdint.h> header file. */ |
|||
#define HAVE_STDINT_H 1 |
|||
|
|||
/* Define to 1 if you have the <stdlib.h> header file. */ |
|||
#define HAVE_STDLIB_H 1 |
|||
|
|||
/* Define to 1 if you have the <strings.h> header file. */ |
|||
#define HAVE_STRINGS_H 1 |
|||
|
|||
/* Define to 1 if you have the <string.h> header file. */ |
|||
#define HAVE_STRING_H 1 |
|||
|
|||
/* Define to 1 if you have the `strtoll' function. */ |
|||
#define HAVE_STRTOLL 1 |
|||
|
|||
/* Define to 1 if gcc's __sync builtins are available */ |
|||
#define HAVE_SYNC_BUILTINS 1 |
|||
|
|||
/* Define to 1 if you have the <sys/param.h> header file. */ |
|||
#define HAVE_SYS_PARAM_H 1 |
|||
|
|||
/* Define to 1 if you have the <sys/stat.h> header file. */ |
|||
#define HAVE_SYS_STAT_H 1 |
|||
|
|||
/* Define to 1 if you have the <sys/time.h> header file. */ |
|||
#define HAVE_SYS_TIME_H 1 |
|||
|
|||
/* Define to 1 if you have the <sys/types.h> header file. */ |
|||
#define HAVE_SYS_TYPES_H 1 |
|||
|
|||
/* Define to 1 if you have the <unistd.h> header file. */ |
|||
#define HAVE_UNISTD_H 1 |
|||
|
|||
/* Define to 1 if the system has the type 'unsigned long long int'. */ |
|||
#define HAVE_UNSIGNED_LONG_LONG_INT 1 |
|||
|
|||
/* Number of buckets new object hashtables contain is 2 raised to this power.
|
|||
E.g. 3 -> 2^3 = 8. */ |
|||
#define INITIAL_HASHTABLE_ORDER 3 |
|||
|
|||
/* Define to the sub-directory where libtool stores uninstalled libraries. */ |
|||
#define LT_OBJDIR ".libs/" |
|||
|
|||
/* Name of package */ |
|||
#define PACKAGE "jansson" |
|||
|
|||
/* Define to the address where bug reports for this package should be sent. */ |
|||
#define PACKAGE_BUGREPORT "petri@digip.org" |
|||
|
|||
/* Define to the full name of this package. */ |
|||
#define PACKAGE_NAME "jansson" |
|||
|
|||
/* Define to the full name and version of this package. */ |
|||
#define PACKAGE_STRING "jansson 2.9" |
|||
|
|||
/* Define to the one symbol short name of this package. */ |
|||
#define PACKAGE_TARNAME "jansson" |
|||
|
|||
/* Define to the home page for this package. */ |
|||
#define PACKAGE_URL "" |
|||
|
|||
/* Define to the version of this package. */ |
|||
#define PACKAGE_VERSION "2.9" |
|||
|
|||
/* Define to 1 if you have the ANSI C header files. */ |
|||
#define STDC_HEADERS 1 |
|||
|
|||
/* Define to 1 if /dev/urandom should be used for seeding the hash function */ |
|||
#define USE_URANDOM 1 |
|||
|
|||
/* Define to 1 if CryptGenRandom should be used for seeding the hash function
|
|||
*/ |
|||
#define USE_WINDOWS_CRYPTOAPI 1 |
|||
|
|||
/* Version number of package */ |
|||
#define VERSION "2.9" |
|||
|
|||
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
|||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the |
|||
#define below would cause a syntax error. */ |
|||
/* #undef _UINT32_T */ |
|||
|
|||
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
|
|||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the |
|||
#define below would cause a syntax error. */ |
|||
/* #undef _UINT8_T */ |
|||
|
|||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
|||
calls it, or to nothing if 'inline' is not supported under any name. */ |
|||
#ifndef __cplusplus |
|||
/* #undef inline */ |
|||
#endif |
|||
|
|||
/* Define to the type of a signed integer type of width exactly 32 bits if
|
|||
such a type exists and the standard includes do not define it. */ |
|||
/* #undef int32_t */ |
|||
|
|||
/* Define to the type of an unsigned integer type of width exactly 16 bits if
|
|||
such a type exists and the standard includes do not define it. */ |
|||
/* #undef uint16_t */ |
|||
|
|||
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
|||
such a type exists and the standard includes do not define it. */ |
|||
/* #undef uint32_t */ |
|||
|
|||
/* Define to the type of an unsigned integer type of width exactly 8 bits if
|
|||
such a type exists and the standard includes do not define it. */ |
|||
/* #undef uint8_t */ |
File diff suppressed because it is too large
@ -0,0 +1,381 @@ |
|||
/*
|
|||
------------------------------------------------------------------------------- |
|||
lookup3.c, by Bob Jenkins, May 2006, Public Domain. |
|||
|
|||
These are functions for producing 32-bit hashes for hash table lookup. |
|||
hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() |
|||
are externally useful functions. Routines to test the hash are included |
|||
if SELF_TEST is defined. You can use this free for any purpose. It's in |
|||
the public domain. It has no warranty. |
|||
|
|||
You probably want to use hashlittle(). hashlittle() and hashbig() |
|||
hash byte arrays. hashlittle() is is faster than hashbig() on |
|||
little-endian machines. Intel and AMD are little-endian machines. |
|||
On second thought, you probably want hashlittle2(), which is identical to |
|||
hashlittle() except it returns two 32-bit hashes for the price of one. |
|||
You could implement hashbig2() if you wanted but I haven't bothered here. |
|||
|
|||
If you want to find a hash of, say, exactly 7 integers, do |
|||
a = i1; b = i2; c = i3; |
|||
mix(a,b,c); |
|||
a += i4; b += i5; c += i6; |
|||
mix(a,b,c); |
|||
a += i7; |
|||
final(a,b,c); |
|||
then use c as the hash value. If you have a variable length array of |
|||
4-byte integers to hash, use hashword(). If you have a byte array (like |
|||
a character string), use hashlittle(). If you have several byte arrays, or |
|||
a mix of things, see the comments above hashlittle(). |
|||
|
|||
Why is this so big? I read 12 bytes at a time into 3 4-byte integers, |
|||
then mix those integers. This is fast (you can do a lot more thorough |
|||
mixing with 12*3 instructions on 3 integers than you can with 3 instructions |
|||
on 1 byte), but shoehorning those bytes into integers efficiently is messy. |
|||
------------------------------------------------------------------------------- |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
|
|||
#ifdef HAVE_CONFIG_H |
|||
#include <jansson_private_config.h> |
|||
#endif |
|||
|
|||
#ifdef HAVE_STDINT_H |
|||
#include <stdint.h> /* defines uint32_t etc */ |
|||
#endif |
|||
|
|||
#ifdef HAVE_SYS_PARAM_H |
|||
#include <sys/param.h> /* attempt to define endianness */ |
|||
#endif |
|||
|
|||
#ifdef HAVE_ENDIAN_H |
|||
# include <endian.h> /* attempt to define endianness */ |
|||
#endif |
|||
|
|||
/*
|
|||
* My best guess at if you are big-endian or little-endian. This may |
|||
* need adjustment. |
|||
*/ |
|||
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ |
|||
__BYTE_ORDER == __LITTLE_ENDIAN) || \ |
|||
(defined(i386) || defined(__i386__) || defined(__i486__) || \ |
|||
defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) |
|||
# define HASH_LITTLE_ENDIAN 1 |
|||
# define HASH_BIG_ENDIAN 0 |
|||
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ |
|||
__BYTE_ORDER == __BIG_ENDIAN) || \ |
|||
(defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) |
|||
# define HASH_LITTLE_ENDIAN 0 |
|||
# define HASH_BIG_ENDIAN 1 |
|||
#else |
|||
# define HASH_LITTLE_ENDIAN 0 |
|||
# define HASH_BIG_ENDIAN 0 |
|||
#endif |
|||
|
|||
#define hashsize(n) ((uint32_t)1<<(n)) |
|||
#define hashmask(n) (hashsize(n)-1) |
|||
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) |
|||
|
|||
/*
|
|||
------------------------------------------------------------------------------- |
|||
mix -- mix 3 32-bit values reversibly. |
|||
|
|||
This is reversible, so any information in (a,b,c) before mix() is |
|||
still in (a,b,c) after mix(). |
|||
|
|||
If four pairs of (a,b,c) inputs are run through mix(), or through |
|||
mix() in reverse, there are at least 32 bits of the output that |
|||
are sometimes the same for one pair and different for another pair. |
|||
This was tested for: |
|||
* pairs that differed by one bit, by two bits, in any combination |
|||
of top bits of (a,b,c), or in any combination of bottom bits of |
|||
(a,b,c). |
|||
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed |
|||
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as |
|||
is commonly produced by subtraction) look like a single 1-bit |
|||
difference. |
|||
* the base values were pseudorandom, all zero but one bit set, or |
|||
all zero plus a counter that starts at zero. |
|||
|
|||
Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that |
|||
satisfy this are |
|||
4 6 8 16 19 4 |
|||
9 15 3 18 27 15 |
|||
14 9 3 7 17 3 |
|||
Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing |
|||
for "differ" defined as + with a one-bit base and a two-bit delta. I |
|||
used http://burtleburtle.net/bob/hash/avalanche.html to choose
|
|||
the operations, constants, and arrangements of the variables. |
|||
|
|||
This does not achieve avalanche. There are input bits of (a,b,c) |
|||
that fail to affect some output bits of (a,b,c), especially of a. The |
|||
most thoroughly mixed value is c, but it doesn't really even achieve |
|||
avalanche in c. |
|||
|
|||
This allows some parallelism. Read-after-writes are good at doubling |
|||
the number of bits affected, so the goal of mixing pulls in the opposite |
|||
direction as the goal of parallelism. I did what I could. Rotates |
|||
seem to cost as much as shifts on every machine I could lay my hands |
|||
on, and rotates are much kinder to the top and bottom bits, so I used |
|||
rotates. |
|||
------------------------------------------------------------------------------- |
|||
*/ |
|||
#define mix(a,b,c) \ |
|||
{ \ |
|||
a -= c; a ^= rot(c, 4); c += b; \ |
|||
b -= a; b ^= rot(a, 6); a += c; \ |
|||
c -= b; c ^= rot(b, 8); b += a; \ |
|||
a -= c; a ^= rot(c,16); c += b; \ |
|||
b -= a; b ^= rot(a,19); a += c; \ |
|||
c -= b; c ^= rot(b, 4); b += a; \ |
|||
} |
|||
|
|||
/*
|
|||
------------------------------------------------------------------------------- |
|||
final -- final mixing of 3 32-bit values (a,b,c) into c |
|||
|
|||
Pairs of (a,b,c) values differing in only a few bits will usually |
|||
produce values of c that look totally different. This was tested for |
|||
* pairs that differed by one bit, by two bits, in any combination |
|||
of top bits of (a,b,c), or in any combination of bottom bits of |
|||
(a,b,c). |
|||
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed |
|||
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as |
|||
is commonly produced by subtraction) look like a single 1-bit |
|||
difference. |
|||
* the base values were pseudorandom, all zero but one bit set, or |
|||
all zero plus a counter that starts at zero. |
|||
|
|||
These constants passed: |
|||
14 11 25 16 4 14 24 |
|||
12 14 25 16 4 14 24 |
|||
and these came close: |
|||
4 8 15 26 3 22 24 |
|||
10 8 15 26 3 22 24 |
|||
11 8 15 26 3 22 24 |
|||
------------------------------------------------------------------------------- |
|||
*/ |
|||
#define final(a,b,c) \ |
|||
{ \ |
|||
c ^= b; c -= rot(b,14); \ |
|||
a ^= c; a -= rot(c,11); \ |
|||
b ^= a; b -= rot(a,25); \ |
|||
c ^= b; c -= rot(b,16); \ |
|||
a ^= c; a -= rot(c,4); \ |
|||
b ^= a; b -= rot(a,14); \ |
|||
c ^= b; c -= rot(b,24); \ |
|||
} |
|||
|
|||
/*
|
|||
------------------------------------------------------------------------------- |
|||
hashlittle() -- hash a variable-length key into a 32-bit value |
|||
k : the key (the unaligned variable-length array of bytes) |
|||
length : the length of the key, counting by bytes |
|||
initval : can be any 4-byte value |
|||
Returns a 32-bit value. Every bit of the key affects every bit of |
|||
the return value. Two keys differing by one or two bits will have |
|||
totally different hash values. |
|||
|
|||
The best hash table sizes are powers of 2. There is no need to do |
|||
mod a prime (mod is sooo slow!). If you need less than 32 bits, |
|||
use a bitmask. For example, if you need only 10 bits, do |
|||
h = (h & hashmask(10)); |
|||
In which case, the hash table should have hashsize(10) elements. |
|||
|
|||
If you are hashing n strings (uint8_t **)k, do it like this: |
|||
for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h); |
|||
|
|||
By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this |
|||
code any way you wish, private, educational, or commercial. It's free. |
|||
|
|||
Use for hash table lookup, or anything where one collision in 2^^32 is |
|||
acceptable. Do NOT use for cryptographic purposes. |
|||
------------------------------------------------------------------------------- |
|||
*/ |
|||
|
|||
static uint32_t hashlittle(const void *key, size_t length, uint32_t initval) |
|||
{ |
|||
uint32_t a,b,c; /* internal state */ |
|||
union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ |
|||
|
|||
/* Set up the internal state */ |
|||
a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; |
|||
|
|||
u.ptr = key; |
|||
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { |
|||
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ |
|||
|
|||
/* Detect Valgrind or AddressSanitizer */ |
|||
#ifdef VALGRIND |
|||
# define NO_MASKING_TRICK 1 |
|||
#else |
|||
# if defined(__has_feature) /* Clang */ |
|||
# if __has_feature(address_sanitizer) /* is ASAN enabled? */ |
|||
# define NO_MASKING_TRICK 1 |
|||
# endif |
|||
# else |
|||
# if defined(__SANITIZE_ADDRESS__) /* GCC 4.8.x, is ASAN enabled? */ |
|||
# define NO_MASKING_TRICK 1 |
|||
# endif |
|||
# endif |
|||
#endif |
|||
|
|||
#ifdef NO_MASKING_TRICK |
|||
const uint8_t *k8; |
|||
#endif |
|||
|
|||
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ |
|||
while (length > 12) |
|||
{ |
|||
a += k[0]; |
|||
b += k[1]; |
|||
c += k[2]; |
|||
mix(a,b,c); |
|||
length -= 12; |
|||
k += 3; |
|||
} |
|||
|
|||
/*----------------------------- handle the last (probably partial) block */ |
|||
/*
|
|||
* "k[2]&0xffffff" actually reads beyond the end of the string, but |
|||
* then masks off the part it's not allowed to read. Because the |
|||
* string is aligned, the masked-off tail is in the same word as the |
|||
* rest of the string. Every machine with memory protection I've seen |
|||
* does it on word boundaries, so is OK with this. But VALGRIND will |
|||
* still catch it and complain. The masking trick does make the hash |
|||
* noticably faster for short strings (like English words). |
|||
*/ |
|||
#ifndef NO_MASKING_TRICK |
|||
|
|||
switch(length) |
|||
{ |
|||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; |
|||
case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; |
|||
case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; |
|||
case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; |
|||
case 8 : b+=k[1]; a+=k[0]; break; |
|||
case 7 : b+=k[1]&0xffffff; a+=k[0]; break; |
|||
case 6 : b+=k[1]&0xffff; a+=k[0]; break; |
|||
case 5 : b+=k[1]&0xff; a+=k[0]; break; |
|||
case 4 : a+=k[0]; break; |
|||
case 3 : a+=k[0]&0xffffff; break; |
|||
case 2 : a+=k[0]&0xffff; break; |
|||
case 1 : a+=k[0]&0xff; break; |
|||
case 0 : return c; /* zero length strings require no mixing */ |
|||
} |
|||
|
|||
#else /* make valgrind happy */ |
|||
|
|||
k8 = (const uint8_t *)k; |
|||
switch(length) |
|||
{ |
|||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; |
|||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ |
|||
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ |
|||
case 9 : c+=k8[8]; /* fall through */ |
|||
case 8 : b+=k[1]; a+=k[0]; break; |
|||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ |
|||
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ |
|||
case 5 : b+=k8[4]; /* fall through */ |
|||
case 4 : a+=k[0]; break; |
|||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ |
|||
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ |
|||
case 1 : a+=k8[0]; break; |
|||
case 0 : return c; |
|||
} |
|||
|
|||
#endif /* !valgrind */ |
|||
|
|||
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { |
|||
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ |
|||
const uint8_t *k8; |
|||
|
|||
/*--------------- all but last block: aligned reads and different mixing */ |
|||
while (length > 12) |
|||
{ |
|||
a += k[0] + (((uint32_t)k[1])<<16); |
|||
b += k[2] + (((uint32_t)k[3])<<16); |
|||
c += k[4] + (((uint32_t)k[5])<<16); |
|||
mix(a,b,c); |
|||
length -= 12; |
|||
k += 6; |
|||
} |
|||
|
|||
/*----------------------------- handle the last (probably partial) block */ |
|||
k8 = (const uint8_t *)k; |
|||
switch(length) |
|||
{ |
|||
case 12: c+=k[4]+(((uint32_t)k[5])<<16); |
|||
b+=k[2]+(((uint32_t)k[3])<<16); |
|||
a+=k[0]+(((uint32_t)k[1])<<16); |
|||
break; |
|||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ |
|||
case 10: c+=k[4]; |
|||
b+=k[2]+(((uint32_t)k[3])<<16); |
|||
a+=k[0]+(((uint32_t)k[1])<<16); |
|||
break; |
|||
case 9 : c+=k8[8]; /* fall through */ |
|||
case 8 : b+=k[2]+(((uint32_t)k[3])<<16); |
|||
a+=k[0]+(((uint32_t)k[1])<<16); |
|||
break; |
|||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ |
|||
case 6 : b+=k[2]; |
|||
a+=k[0]+(((uint32_t)k[1])<<16); |
|||
break; |
|||
case 5 : b+=k8[4]; /* fall through */ |
|||
case 4 : a+=k[0]+(((uint32_t)k[1])<<16); |
|||
break; |
|||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ |
|||
case 2 : a+=k[0]; |
|||
break; |
|||
case 1 : a+=k8[0]; |
|||
break; |
|||
case 0 : return c; /* zero length requires no mixing */ |
|||
} |
|||
|
|||
} else { /* need to read the key one byte at a time */ |
|||
const uint8_t *k = (const uint8_t *)key; |
|||
|
|||
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */ |
|||
while (length > 12) |
|||
{ |
|||
a += k[0]; |
|||
a += ((uint32_t)k[1])<<8; |
|||
a += ((uint32_t)k[2])<<16; |
|||
a += ((uint32_t)k[3])<<24; |
|||
b += k[4]; |
|||
b += ((uint32_t)k[5])<<8; |
|||
b += ((uint32_t)k[6])<<16; |
|||
b += ((uint32_t)k[7])<<24; |
|||
c += k[8]; |
|||
c += ((uint32_t)k[9])<<8; |
|||
c += ((uint32_t)k[10])<<16; |
|||
c += ((uint32_t)k[11])<<24; |
|||
mix(a,b,c); |
|||
length -= 12; |
|||
k += 12; |
|||
} |
|||
|
|||
/*-------------------------------- last block: affect all 32 bits of (c) */ |
|||
switch(length) /* all the case statements fall through */ |
|||
{ |
|||
case 12: c+=((uint32_t)k[11])<<24; |
|||
case 11: c+=((uint32_t)k[10])<<16; |
|||
case 10: c+=((uint32_t)k[9])<<8; |
|||
case 9 : c+=k[8]; |
|||
case 8 : b+=((uint32_t)k[7])<<24; |
|||
case 7 : b+=((uint32_t)k[6])<<16; |
|||
case 6 : b+=((uint32_t)k[5])<<8; |
|||
case 5 : b+=k[4]; |
|||
case 4 : a+=((uint32_t)k[3])<<24; |
|||
case 3 : a+=((uint32_t)k[2])<<16; |
|||
case 2 : a+=((uint32_t)k[1])<<8; |
|||
case 1 : a+=k[0]; |
|||
break; |
|||
case 0 : return c; |
|||
} |
|||
} |
|||
|
|||
final(a,b,c); |
|||
return c; |
|||
} |
@ -0,0 +1,69 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* Copyright (c) 2011-2012 Basile Starynkevitch <basile@starynkevitch.net> |
|||
* |
|||
* Jansson is free software; you can redistribute it and/or modify it |
|||
* under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
#include "jansson.h" |
|||
#include "jansson_private.h" |
|||
|
|||
/* C89 allows these to be macros */ |
|||
#undef malloc |
|||
#undef free |
|||
|
|||
/* memory function pointers */ |
|||
static json_malloc_t do_malloc = malloc; |
|||
static json_free_t do_free = free; |
|||
|
|||
void *jsonp_malloc(size_t size) |
|||
{ |
|||
if(!size) |
|||
return NULL; |
|||
|
|||
return (*do_malloc)(size); |
|||
} |
|||
|
|||
void jsonp_free(void *ptr) |
|||
{ |
|||
if(!ptr) |
|||
return; |
|||
|
|||
(*do_free)(ptr); |
|||
} |
|||
|
|||
char *jsonp_strdup(const char *str) |
|||
{ |
|||
return jsonp_strndup(str, strlen(str)); |
|||
} |
|||
|
|||
char *jsonp_strndup(const char *str, size_t len) |
|||
{ |
|||
char *new_str; |
|||
|
|||
new_str = jsonp_malloc(len + 1); |
|||
if(!new_str) |
|||
return NULL; |
|||
|
|||
memcpy(new_str, str, len); |
|||
new_str[len] = '\0'; |
|||
return new_str; |
|||
} |
|||
|
|||
void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn) |
|||
{ |
|||
do_malloc = malloc_fn; |
|||
do_free = free_fn; |
|||
} |
|||
|
|||
void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn) |
|||
{ |
|||
if (malloc_fn) |
|||
*malloc_fn = do_malloc; |
|||
if (free_fn) |
|||
*free_fn = do_free; |
|||
} |
@ -0,0 +1,871 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* Copyright (c) 2011-2012 Graeme Smecher <graeme.smecher@mail.mcgill.ca> |
|||
* |
|||
* Jansson is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#include <string.h> |
|||
#include "jansson.h" |
|||
#include "jansson_private.h" |
|||
#include "utf.h" |
|||
|
|||
typedef struct { |
|||
int line; |
|||
int column; |
|||
size_t pos; |
|||
char token; |
|||
} token_t; |
|||
|
|||
typedef struct { |
|||
const char *start; |
|||
const char *fmt; |
|||
token_t prev_token; |
|||
token_t token; |
|||
token_t next_token; |
|||
json_error_t *error; |
|||
size_t flags; |
|||
int line; |
|||
int column; |
|||
size_t pos; |
|||
} scanner_t; |
|||
|
|||
#define token(scanner) ((scanner)->token.token) |
|||
|
|||
static const char * const type_names[] = { |
|||
"object", |
|||
"array", |
|||
"string", |
|||
"integer", |
|||
"real", |
|||
"true", |
|||
"false", |
|||
"null" |
|||
}; |
|||
|
|||
#define type_name(x) type_names[json_typeof(x)] |
|||
|
|||
static const char unpack_value_starters[] = "{[siIbfFOon"; |
|||
|
|||
static void scanner_init(scanner_t *s, json_error_t *error, |
|||
size_t flags, const char *fmt) |
|||
{ |
|||
s->error = error; |
|||
s->flags = flags; |
|||
s->fmt = s->start = fmt; |
|||
memset(&s->prev_token, 0, sizeof(token_t)); |
|||
memset(&s->token, 0, sizeof(token_t)); |
|||
memset(&s->next_token, 0, sizeof(token_t)); |
|||
s->line = 1; |
|||
s->column = 0; |
|||
s->pos = 0; |
|||
} |
|||
|
|||
static void next_token(scanner_t *s) |
|||
{ |
|||
const char *t; |
|||
s->prev_token = s->token; |
|||
|
|||
if(s->next_token.line) { |
|||
s->token = s->next_token; |
|||
s->next_token.line = 0; |
|||
return; |
|||
} |
|||
|
|||
t = s->fmt; |
|||
s->column++; |
|||
s->pos++; |
|||
|
|||
/* skip space and ignored chars */ |
|||
while(*t == ' ' || *t == '\t' || *t == '\n' || *t == ',' || *t == ':') { |
|||
if(*t == '\n') { |
|||
s->line++; |
|||
s->column = 1; |
|||
} |
|||
else |
|||
s->column++; |
|||
|
|||
s->pos++; |
|||
t++; |
|||
} |
|||
|
|||
s->token.token = *t; |
|||
s->token.line = s->line; |
|||
s->token.column = s->column; |
|||
s->token.pos = s->pos; |
|||
|
|||
t++; |
|||
s->fmt = t; |
|||
} |
|||
|
|||
static void prev_token(scanner_t *s) |
|||
{ |
|||
s->next_token = s->token; |
|||
s->token = s->prev_token; |
|||
} |
|||
|
|||
static void set_error(scanner_t *s, const char *source, const char *fmt, ...) |
|||
{ |
|||
va_list ap; |
|||
va_start(ap, fmt); |
|||
|
|||
jsonp_error_vset(s->error, s->token.line, s->token.column, s->token.pos, |
|||
fmt, ap); |
|||
|
|||
jsonp_error_set_source(s->error, source); |
|||
|
|||
va_end(ap); |
|||
} |
|||
|
|||
static json_t *pack(scanner_t *s, va_list *ap); |
|||
|
|||
|
|||
/* ours will be set to 1 if jsonp_free() must be called for the result
|
|||
afterwards */ |
|||
static char *read_string(scanner_t *s, va_list *ap, |
|||
const char *purpose, size_t *out_len, int *ours) |
|||
{ |
|||
char t; |
|||
strbuffer_t strbuff; |
|||
const char *str; |
|||
size_t length; |
|||
|
|||
next_token(s); |
|||
t = token(s); |
|||
prev_token(s); |
|||
|
|||
if(t != '#' && t != '%' && t != '+') { |
|||
/* Optimize the simple case */ |
|||
str = va_arg(*ap, const char *); |
|||
|
|||
if(!str) { |
|||
set_error(s, "<args>", "NULL string argument"); |
|||
return NULL; |
|||
} |
|||
|
|||
length = strlen(str); |
|||
|
|||
if(!utf8_check_string(str, length)) { |
|||
set_error(s, "<args>", "Invalid UTF-8 %s", purpose); |
|||
return NULL; |
|||
} |
|||
|
|||
*out_len = length; |
|||
*ours = 0; |
|||
return (char *)str; |
|||
} |
|||
|
|||
strbuffer_init(&strbuff); |
|||
|
|||
while(1) { |
|||
str = va_arg(*ap, const char *); |
|||
if(!str) { |
|||
set_error(s, "<args>", "NULL string argument"); |
|||
strbuffer_close(&strbuff); |
|||
return NULL; |
|||
} |
|||
|
|||
next_token(s); |
|||
|
|||
if(token(s) == '#') { |
|||
length = va_arg(*ap, int); |
|||
} |
|||
else if(token(s) == '%') { |
|||
length = va_arg(*ap, size_t); |
|||
} |
|||
else { |
|||
prev_token(s); |
|||
length = strlen(str); |
|||
} |
|||
|
|||
if(strbuffer_append_bytes(&strbuff, str, length) == -1) { |
|||
set_error(s, "<internal>", "Out of memory"); |
|||
strbuffer_close(&strbuff); |
|||
return NULL; |
|||
} |
|||
|
|||
next_token(s); |
|||
if(token(s) != '+') { |
|||
prev_token(s); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if(!utf8_check_string(strbuff.value, strbuff.length)) { |
|||
set_error(s, "<args>", "Invalid UTF-8 %s", purpose); |
|||
strbuffer_close(&strbuff); |
|||
return NULL; |
|||
} |
|||
|
|||
*out_len = strbuff.length; |
|||
*ours = 1; |
|||
return strbuffer_steal_value(&strbuff); |
|||
} |
|||
|
|||
static json_t *pack_object(scanner_t *s, va_list *ap) |
|||
{ |
|||
json_t *object = json_object(); |
|||
next_token(s); |
|||
|
|||
while(token(s) != '}') { |
|||
char *key; |
|||
size_t len; |
|||
int ours; |
|||
json_t *value; |
|||
|
|||
if(!token(s)) { |
|||
set_error(s, "<format>", "Unexpected end of format string"); |
|||
goto error; |
|||
} |
|||
|
|||
if(token(s) != 's') { |
|||
set_error(s, "<format>", "Expected format 's', got '%c'", token(s)); |
|||
goto error; |
|||
} |
|||
|
|||
key = read_string(s, ap, "object key", &len, &ours); |
|||
if(!key) |
|||
goto error; |
|||
|
|||
next_token(s); |
|||
|
|||
value = pack(s, ap); |
|||
if(!value) { |
|||
if(ours) |
|||
jsonp_free(key); |
|||
|
|||
goto error; |
|||
} |
|||
|
|||
if(json_object_set_new_nocheck(object, key, value)) { |
|||
set_error(s, "<internal>", "Unable to add key \"%s\"", key); |
|||
if(ours) |
|||
jsonp_free(key); |
|||
|
|||
goto error; |
|||
} |
|||
|
|||
if(ours) |
|||
jsonp_free(key); |
|||
|
|||
next_token(s); |
|||
} |
|||
|
|||
return object; |
|||
|
|||
error: |
|||
json_decref(object); |
|||
return NULL; |
|||
} |
|||
|
|||
static json_t *pack_array(scanner_t *s, va_list *ap) |
|||
{ |
|||
json_t *array = json_array(); |
|||
next_token(s); |
|||
|
|||
while(token(s) != ']') { |
|||
json_t *value; |
|||
|
|||
if(!token(s)) { |
|||
set_error(s, "<format>", "Unexpected end of format string"); |
|||
goto error; |
|||
} |
|||
|
|||
value = pack(s, ap); |
|||
if(!value) |
|||
goto error; |
|||
|
|||
if(json_array_append_new(array, value)) { |
|||
set_error(s, "<internal>", "Unable to append to array"); |
|||
goto error; |
|||
} |
|||
|
|||
next_token(s); |
|||
} |
|||
return array; |
|||
|
|||
error: |
|||
json_decref(array); |
|||
return NULL; |
|||
} |
|||
|
|||
static json_t *pack_string(scanner_t *s, va_list *ap) |
|||
{ |
|||
char *str; |
|||
size_t len; |
|||
int ours; |
|||
int nullable; |
|||
|
|||
next_token(s); |
|||
nullable = token(s) == '?'; |
|||
if (!nullable) |
|||
prev_token(s); |
|||
|
|||
str = read_string(s, ap, "string", &len, &ours); |
|||
if (!str) { |
|||
return nullable ? json_null() : NULL; |
|||
} else if (ours) { |
|||
return jsonp_stringn_nocheck_own(str, len); |
|||
} else { |
|||
return json_stringn_nocheck(str, len); |
|||
} |
|||
} |
|||
|
|||
static json_t *pack(scanner_t *s, va_list *ap) |
|||
{ |
|||
switch(token(s)) { |
|||
case '{': |
|||
return pack_object(s, ap); |
|||
|
|||
case '[': |
|||
return pack_array(s, ap); |
|||
|
|||
case 's': /* string */ |
|||
return pack_string(s, ap); |
|||
|
|||
case 'n': /* null */ |
|||
return json_null(); |
|||
|
|||
case 'b': /* boolean */ |
|||
return va_arg(*ap, int) ? json_true() : json_false(); |
|||
|
|||
case 'i': /* integer from int */ |
|||
return json_integer(va_arg(*ap, int)); |
|||
|
|||
case 'I': /* integer from json_int_t */ |
|||
return json_integer(va_arg(*ap, json_int_t)); |
|||
|
|||
case 'f': /* real */ |
|||
return json_real(va_arg(*ap, double)); |
|||
|
|||
case 'O': /* a json_t object; increments refcount */ |
|||
{ |
|||
int nullable; |
|||
json_t *json; |
|||
|
|||
next_token(s); |
|||
nullable = token(s) == '?'; |
|||
if (!nullable) |
|||
prev_token(s); |
|||
|
|||
json = va_arg(*ap, json_t *); |
|||
if (!json && nullable) { |
|||
return json_null(); |
|||
} else { |
|||
return json_incref(json); |
|||
} |
|||
} |
|||
|
|||
case 'o': /* a json_t object; doesn't increment refcount */ |
|||
{ |
|||
int nullable; |
|||
json_t *json; |
|||
|
|||
next_token(s); |
|||
nullable = token(s) == '?'; |
|||
if (!nullable) |
|||
prev_token(s); |
|||
|
|||
json = va_arg(*ap, json_t *); |
|||
if (!json && nullable) { |
|||
return json_null(); |
|||
} else { |
|||
return json; |
|||
} |
|||
} |
|||
|
|||
default: |
|||
set_error(s, "<format>", "Unexpected format character '%c'", |
|||
token(s)); |
|||
return NULL; |
|||
} |
|||
} |
|||
|
|||
static int unpack(scanner_t *s, json_t *root, va_list *ap); |
|||
|
|||
static int unpack_object(scanner_t *s, json_t *root, va_list *ap) |
|||
{ |
|||
int ret = -1; |
|||
int strict = 0; |
|||
int gotopt = 0; |
|||
|
|||
/* Use a set (emulated by a hashtable) to check that all object
|
|||
keys are accessed. Checking that the correct number of keys |
|||
were accessed is not enough, as the same key can be unpacked |
|||
multiple times. |
|||
*/ |
|||
hashtable_t key_set; |
|||
|
|||
if(hashtable_init(&key_set)) { |
|||
set_error(s, "<internal>", "Out of memory"); |
|||
return -1; |
|||
} |
|||
|
|||
if(root && !json_is_object(root)) { |
|||
set_error(s, "<validation>", "Expected object, got %s", |
|||
type_name(root)); |
|||
goto out; |
|||
} |
|||
next_token(s); |
|||
|
|||
while(token(s) != '}') { |
|||
const char *key; |
|||
json_t *value; |
|||
int opt = 0; |
|||
|
|||
if(strict != 0) { |
|||
set_error(s, "<format>", "Expected '}' after '%c', got '%c'", |
|||
(strict == 1 ? '!' : '*'), token(s)); |
|||
goto out; |
|||
} |
|||
|
|||
if(!token(s)) { |
|||
set_error(s, "<format>", "Unexpected end of format string"); |
|||
goto out; |
|||
} |
|||
|
|||
if(token(s) == '!' || token(s) == '*') { |
|||
strict = (token(s) == '!' ? 1 : -1); |
|||
next_token(s); |
|||
continue; |
|||
} |
|||
|
|||
if(token(s) != 's') { |
|||
set_error(s, "<format>", "Expected format 's', got '%c'", token(s)); |
|||
goto out; |
|||
} |
|||
|
|||
key = va_arg(*ap, const char *); |
|||
if(!key) { |
|||
set_error(s, "<args>", "NULL object key"); |
|||
goto out; |
|||
} |
|||
|
|||
next_token(s); |
|||
|
|||
if(token(s) == '?') { |
|||
opt = gotopt = 1; |
|||
next_token(s); |
|||
} |
|||
|
|||
if(!root) { |
|||
/* skipping */ |
|||
value = NULL; |
|||
} |
|||
else { |
|||
value = json_object_get(root, key); |
|||
if(!value && !opt) { |
|||
set_error(s, "<validation>", "Object item not found: %s", key); |
|||
goto out; |
|||
} |
|||
} |
|||
|
|||
if(unpack(s, value, ap)) |
|||
goto out; |
|||
|
|||
hashtable_set(&key_set, key, json_null()); |
|||
next_token(s); |
|||
} |
|||
|
|||
if(strict == 0 && (s->flags & JSON_STRICT)) |
|||
strict = 1; |
|||
|
|||
if(root && strict == 1) { |
|||
/* We need to check that all non optional items have been parsed */ |
|||
const char *key; |
|||
int have_unrecognized_keys = 0; |
|||
strbuffer_t unrecognized_keys; |
|||
json_t *value; |
|||
long unpacked = 0; |
|||
if (gotopt) { |
|||
/* We have optional keys, we need to iter on each key */ |
|||
json_object_foreach(root, key, value) { |
|||
if(!hashtable_get(&key_set, key)) { |
|||
unpacked++; |
|||
|
|||
/* Save unrecognized keys for the error message */ |
|||
if (!have_unrecognized_keys) { |
|||
strbuffer_init(&unrecognized_keys); |
|||
have_unrecognized_keys = 1; |
|||
} else { |
|||
strbuffer_append_bytes(&unrecognized_keys, ", ", 2); |
|||
} |
|||
strbuffer_append_bytes(&unrecognized_keys, key, strlen(key)); |
|||
} |
|||
} |
|||
} else { |
|||
/* No optional keys, we can just compare the number of items */ |
|||
unpacked = (long)json_object_size(root) - (long)key_set.size; |
|||
} |
|||
if (unpacked) { |
|||
if (!gotopt) { |
|||
/* Save unrecognized keys for the error message */ |
|||
json_object_foreach(root, key, value) { |
|||
if(!hashtable_get(&key_set, key)) { |
|||
if (!have_unrecognized_keys) { |
|||
strbuffer_init(&unrecognized_keys); |
|||
have_unrecognized_keys = 1; |
|||
} else { |
|||
strbuffer_append_bytes(&unrecognized_keys, ", ", 2); |
|||
} |
|||
strbuffer_append_bytes(&unrecognized_keys, key, strlen(key)); |
|||
} |
|||
} |
|||
} |
|||
set_error(s, "<validation>", |
|||
"%li object item(s) left unpacked: %s", |
|||
unpacked, strbuffer_value(&unrecognized_keys)); |
|||
strbuffer_close(&unrecognized_keys); |
|||
goto out; |
|||
} |
|||
} |
|||
|
|||
ret = 0; |
|||
|
|||
out: |
|||
hashtable_close(&key_set); |
|||
return ret; |
|||
} |
|||
|
|||
static int unpack_array(scanner_t *s, json_t *root, va_list *ap) |
|||
{ |
|||
size_t i = 0; |
|||
int strict = 0; |
|||
|
|||
if(root && !json_is_array(root)) { |
|||
set_error(s, "<validation>", "Expected array, got %s", type_name(root)); |
|||
return -1; |
|||
} |
|||
next_token(s); |
|||
|
|||
while(token(s) != ']') { |
|||
json_t *value; |
|||
|
|||
if(strict != 0) { |
|||
set_error(s, "<format>", "Expected ']' after '%c', got '%c'", |
|||
(strict == 1 ? '!' : '*'), |
|||
token(s)); |
|||
return -1; |
|||
} |
|||
|
|||
if(!token(s)) { |
|||
set_error(s, "<format>", "Unexpected end of format string"); |
|||
return -1; |
|||
} |
|||
|
|||
if(token(s) == '!' || token(s) == '*') { |
|||
strict = (token(s) == '!' ? 1 : -1); |
|||
next_token(s); |
|||
continue; |
|||
} |
|||
|
|||
if(!strchr(unpack_value_starters, token(s))) { |
|||
set_error(s, "<format>", "Unexpected format character '%c'", |
|||
token(s)); |
|||
return -1; |
|||
} |
|||
|
|||
if(!root) { |
|||
/* skipping */ |
|||
value = NULL; |
|||
} |
|||
else { |
|||
value = json_array_get(root, i); |
|||
if(!value) { |
|||
set_error(s, "<validation>", "Array index %lu out of range", |
|||
(unsigned long)i); |
|||
return -1; |
|||
} |
|||
} |
|||
|
|||
if(unpack(s, value, ap)) |
|||
return -1; |
|||
|
|||
next_token(s); |
|||
i++; |
|||
} |
|||
|
|||
if(strict == 0 && (s->flags & JSON_STRICT)) |
|||
strict = 1; |
|||
|
|||
if(root && strict == 1 && i != json_array_size(root)) { |
|||
long diff = (long)json_array_size(root) - (long)i; |
|||
set_error(s, "<validation>", "%li array item(s) left unpacked", diff); |
|||
return -1; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
static int unpack(scanner_t *s, json_t *root, va_list *ap) |
|||
{ |
|||
switch(token(s)) |
|||
{ |
|||
case '{': |
|||
return unpack_object(s, root, ap); |
|||
|
|||
case '[': |
|||
return unpack_array(s, root, ap); |
|||
|
|||
case 's': |
|||
if(root && !json_is_string(root)) { |
|||
set_error(s, "<validation>", "Expected string, got %s", |
|||
type_name(root)); |
|||
return -1; |
|||
} |
|||
|
|||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
|||
const char **str_target; |
|||
size_t *len_target = NULL; |
|||
|
|||
str_target = va_arg(*ap, const char **); |
|||
if(!str_target) { |
|||
set_error(s, "<args>", "NULL string argument"); |
|||
return -1; |
|||
} |
|||
|
|||
next_token(s); |
|||
|
|||
if(token(s) == '%') { |
|||
len_target = va_arg(*ap, size_t *); |
|||
if(!len_target) { |
|||
set_error(s, "<args>", "NULL string length argument"); |
|||
return -1; |
|||
} |
|||
} |
|||
else |
|||
prev_token(s); |
|||
|
|||
if(root) { |
|||
*str_target = json_string_value(root); |
|||
if(len_target) |
|||
*len_target = json_string_length(root); |
|||
} |
|||
} |
|||
return 0; |
|||
|
|||
case 'i': |
|||
if(root && !json_is_integer(root)) { |
|||
set_error(s, "<validation>", "Expected integer, got %s", |
|||
type_name(root)); |
|||
return -1; |
|||
} |
|||
|
|||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
|||
int *target = va_arg(*ap, int*); |
|||
if(root) |
|||
*target = (int)json_integer_value(root); |
|||
} |
|||
|
|||
return 0; |
|||
|
|||
case 'I': |
|||
if(root && !json_is_integer(root)) { |
|||
set_error(s, "<validation>", "Expected integer, got %s", |
|||
type_name(root)); |
|||
return -1; |
|||
} |
|||
|
|||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
|||
json_int_t *target = va_arg(*ap, json_int_t*); |
|||
if(root) |
|||
*target = json_integer_value(root); |
|||
} |
|||
|
|||
return 0; |
|||
|
|||
case 'b': |
|||
if(root && !json_is_boolean(root)) { |
|||
set_error(s, "<validation>", "Expected true or false, got %s", |
|||
type_name(root)); |
|||
return -1; |
|||
} |
|||
|
|||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
|||
int *target = va_arg(*ap, int*); |
|||
if(root) |
|||
*target = json_is_true(root); |
|||
} |
|||
|
|||
return 0; |
|||
|
|||
case 'f': |
|||
if(root && !json_is_real(root)) { |
|||
set_error(s, "<validation>", "Expected real, got %s", |
|||
type_name(root)); |
|||
return -1; |
|||
} |
|||
|
|||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
|||
double *target = va_arg(*ap, double*); |
|||
if(root) |
|||
*target = json_real_value(root); |
|||
} |
|||
|
|||
return 0; |
|||
|
|||
case 'F': |
|||
if(root && !json_is_number(root)) { |
|||
set_error(s, "<validation>", "Expected real or integer, got %s", |
|||
type_name(root)); |
|||
return -1; |
|||
} |
|||
|
|||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
|||
double *target = va_arg(*ap, double*); |
|||
if(root) |
|||
*target = json_number_value(root); |
|||
} |
|||
|
|||
return 0; |
|||
|
|||
case 'O': |
|||
if(root && !(s->flags & JSON_VALIDATE_ONLY)) |
|||
json_incref(root); |
|||
/* Fall through */ |
|||
|
|||
case 'o': |
|||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
|||
json_t **target = va_arg(*ap, json_t**); |
|||
if(root) |
|||
*target = root; |
|||
} |
|||
|
|||
return 0; |
|||
|
|||
case 'n': |
|||
/* Never assign, just validate */ |
|||
if(root && !json_is_null(root)) { |
|||
set_error(s, "<validation>", "Expected null, got %s", |
|||
type_name(root)); |
|||
return -1; |
|||
} |
|||
return 0; |
|||
|
|||
default: |
|||
set_error(s, "<format>", "Unexpected format character '%c'", |
|||
token(s)); |
|||
return -1; |
|||
} |
|||
} |
|||
|
|||
json_t *json_vpack_ex(json_error_t *error, size_t flags, |
|||
const char *fmt, va_list ap) |
|||
{ |
|||
scanner_t s; |
|||
va_list ap_copy; |
|||
json_t *value; |
|||
|
|||
if(!fmt || !*fmt) { |
|||
jsonp_error_init(error, "<format>"); |
|||
jsonp_error_set(error, -1, -1, 0, "NULL or empty format string"); |
|||
return NULL; |
|||
} |
|||
jsonp_error_init(error, NULL); |
|||
|
|||
scanner_init(&s, error, flags, fmt); |
|||
next_token(&s); |
|||
|
|||
va_copy(ap_copy, ap); |
|||
value = pack(&s, &ap_copy); |
|||
va_end(ap_copy); |
|||
|
|||
if(!value) |
|||
return NULL; |
|||
|
|||
next_token(&s); |
|||
if(token(&s)) { |
|||
json_decref(value); |
|||
set_error(&s, "<format>", "Garbage after format string"); |
|||
return NULL; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...) |
|||
{ |
|||
json_t *value; |
|||
va_list ap; |
|||
|
|||
va_start(ap, fmt); |
|||
value = json_vpack_ex(error, flags, fmt, ap); |
|||
va_end(ap); |
|||
|
|||
return value; |
|||
} |
|||
|
|||
json_t *json_pack(const char *fmt, ...) |
|||
{ |
|||
json_t *value; |
|||
va_list ap; |
|||
|
|||
va_start(ap, fmt); |
|||
value = json_vpack_ex(NULL, 0, fmt, ap); |
|||
va_end(ap); |
|||
|
|||
return value; |
|||
} |
|||
|
|||
int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, |
|||
const char *fmt, va_list ap) |
|||
{ |
|||
scanner_t s; |
|||
va_list ap_copy; |
|||
|
|||
if(!root) { |
|||
jsonp_error_init(error, "<root>"); |
|||
jsonp_error_set(error, -1, -1, 0, "NULL root value"); |
|||
return -1; |
|||
} |
|||
|
|||
if(!fmt || !*fmt) { |
|||
jsonp_error_init(error, "<format>"); |
|||
jsonp_error_set(error, -1, -1, 0, "NULL or empty format string"); |
|||
return -1; |
|||
} |
|||
jsonp_error_init(error, NULL); |
|||
|
|||
scanner_init(&s, error, flags, fmt); |
|||
next_token(&s); |
|||
|
|||
va_copy(ap_copy, ap); |
|||
if(unpack(&s, root, &ap_copy)) { |
|||
va_end(ap_copy); |
|||
return -1; |
|||
} |
|||
va_end(ap_copy); |
|||
|
|||
next_token(&s); |
|||
if(token(&s)) { |
|||
set_error(&s, "<format>", "Garbage after format string"); |
|||
return -1; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...) |
|||
{ |
|||
int ret; |
|||
va_list ap; |
|||
|
|||
va_start(ap, fmt); |
|||
ret = json_vunpack_ex(root, error, flags, fmt, ap); |
|||
va_end(ap); |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
int json_unpack(json_t *root, const char *fmt, ...) |
|||
{ |
|||
int ret; |
|||
va_list ap; |
|||
|
|||
va_start(ap, fmt); |
|||
ret = json_vunpack_ex(root, NULL, 0, fmt, ap); |
|||
va_end(ap); |
|||
|
|||
return ret; |
|||
} |
@ -0,0 +1,111 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* |
|||
* Jansson is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#ifndef _GNU_SOURCE |
|||
#define _GNU_SOURCE |
|||
#endif |
|||
|
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include "jansson_private.h" |
|||
#include "strbuffer.h" |
|||
|
|||
#define STRBUFFER_MIN_SIZE 16 |
|||
#define STRBUFFER_FACTOR 2 |
|||
#define STRBUFFER_SIZE_MAX ((size_t)-1) |
|||
|
|||
int strbuffer_init(strbuffer_t *strbuff) |
|||
{ |
|||
strbuff->size = STRBUFFER_MIN_SIZE; |
|||
strbuff->length = 0; |
|||
|
|||
strbuff->value = jsonp_malloc(strbuff->size); |
|||
if(!strbuff->value) |
|||
return -1; |
|||
|
|||
/* initialize to empty */ |
|||
strbuff->value[0] = '\0'; |
|||
return 0; |
|||
} |
|||
|
|||
void strbuffer_close(strbuffer_t *strbuff) |
|||
{ |
|||
if(strbuff->value) |
|||
jsonp_free(strbuff->value); |
|||
|
|||
strbuff->size = 0; |
|||
strbuff->length = 0; |
|||
strbuff->value = NULL; |
|||
} |
|||
|
|||
void strbuffer_clear(strbuffer_t *strbuff) |
|||
{ |
|||
strbuff->length = 0; |
|||
strbuff->value[0] = '\0'; |
|||
} |
|||
|
|||
const char *strbuffer_value(const strbuffer_t *strbuff) |
|||
{ |
|||
return strbuff->value; |
|||
} |
|||
|
|||
char *strbuffer_steal_value(strbuffer_t *strbuff) |
|||
{ |
|||
char *result = strbuff->value; |
|||
strbuff->value = NULL; |
|||
return result; |
|||
} |
|||
|
|||
int strbuffer_append_byte(strbuffer_t *strbuff, char byte) |
|||
{ |
|||
return strbuffer_append_bytes(strbuff, &byte, 1); |
|||
} |
|||
|
|||
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size) |
|||
{ |
|||
if(size >= strbuff->size - strbuff->length) |
|||
{ |
|||
size_t new_size; |
|||
char *new_value; |
|||
|
|||
/* avoid integer overflow */ |
|||
if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR |
|||
|| size > STRBUFFER_SIZE_MAX - 1 |
|||
|| strbuff->length > STRBUFFER_SIZE_MAX - 1 - size) |
|||
return -1; |
|||
|
|||
new_size = max(strbuff->size * STRBUFFER_FACTOR, |
|||
strbuff->length + size + 1); |
|||
|
|||
new_value = jsonp_malloc(new_size); |
|||
if(!new_value) |
|||
return -1; |
|||
|
|||
memcpy(new_value, strbuff->value, strbuff->length); |
|||
|
|||
jsonp_free(strbuff->value); |
|||
strbuff->value = new_value; |
|||
strbuff->size = new_size; |
|||
} |
|||
|
|||
memcpy(strbuff->value + strbuff->length, data, size); |
|||
strbuff->length += size; |
|||
strbuff->value[strbuff->length] = '\0'; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
char strbuffer_pop(strbuffer_t *strbuff) |
|||
{ |
|||
if(strbuff->length > 0) { |
|||
char c = strbuff->value[--strbuff->length]; |
|||
strbuff->value[strbuff->length] = '\0'; |
|||
return c; |
|||
} |
|||
else |
|||
return '\0'; |
|||
} |
@ -0,0 +1,34 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* |
|||
* Jansson is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#ifndef STRBUFFER_H |
|||
#define STRBUFFER_H |
|||
|
|||
#include <stdlib.h> |
|||
|
|||
typedef struct { |
|||
char *value; |
|||
size_t length; /* bytes used */ |
|||
size_t size; /* bytes allocated */ |
|||
} strbuffer_t; |
|||
|
|||
int strbuffer_init(strbuffer_t *strbuff); |
|||
void strbuffer_close(strbuffer_t *strbuff); |
|||
|
|||
void strbuffer_clear(strbuffer_t *strbuff); |
|||
|
|||
const char *strbuffer_value(const strbuffer_t *strbuff); |
|||
|
|||
/* Steal the value and close the strbuffer */ |
|||
char *strbuffer_steal_value(strbuffer_t *strbuff); |
|||
|
|||
int strbuffer_append_byte(strbuffer_t *strbuff, char byte); |
|||
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size); |
|||
|
|||
char strbuffer_pop(strbuffer_t *strbuff); |
|||
|
|||
#endif |
@ -0,0 +1,145 @@ |
|||
#include <assert.h> |
|||
#include <errno.h> |
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
#include <math.h> |
|||
#ifdef __MINGW32__ |
|||
#undef __NO_ISOCEXT /* ensure stdlib.h will declare prototypes for mingw own 'strtod' replacement, called '__strtod' */ |
|||
#endif |
|||
#include "jansson_private.h" |
|||
#include "strbuffer.h" |
|||
|
|||
/* need jansson_private_config.h to get the correct snprintf */ |
|||
#ifdef HAVE_CONFIG_H |
|||
#include <jansson_private_config.h> |
|||
#endif |
|||
|
|||
#ifdef __MINGW32__ |
|||
#define strtod __strtod |
|||
#endif |
|||
|
|||
#if JSON_HAVE_LOCALECONV |
|||
#include <locale.h> |
|||
|
|||
/*
|
|||
- This code assumes that the decimal separator is exactly one |
|||
character. |
|||
|
|||
- If setlocale() is called by another thread between the call to |
|||
localeconv() and the call to sprintf() or strtod(), the result may |
|||
be wrong. setlocale() is not thread-safe and should not be used |
|||
this way. Multi-threaded programs should use uselocale() instead. |
|||
*/ |
|||
|
|||
static void to_locale(strbuffer_t *strbuffer) |
|||
{ |
|||
const char *point; |
|||
char *pos; |
|||
|
|||
point = localeconv()->decimal_point; |
|||
if(*point == '.') { |
|||
/* No conversion needed */ |
|||
return; |
|||
} |
|||
|
|||
pos = strchr(strbuffer->value, '.'); |
|||
if(pos) |
|||
*pos = *point; |
|||
} |
|||
|
|||
static void from_locale(char *buffer) |
|||
{ |
|||
const char *point; |
|||
char *pos; |
|||
|
|||
point = localeconv()->decimal_point; |
|||
if(*point == '.') { |
|||
/* No conversion needed */ |
|||
return; |
|||
} |
|||
|
|||
pos = strchr(buffer, *point); |
|||
if(pos) |
|||
*pos = '.'; |
|||
} |
|||
#endif |
|||
|
|||
int jsonp_strtod(strbuffer_t *strbuffer, double *out) |
|||
{ |
|||
double value; |
|||
char *end; |
|||
|
|||
#if JSON_HAVE_LOCALECONV |
|||
to_locale(strbuffer); |
|||
#endif |
|||
|
|||
errno = 0; |
|||
value = strtod(strbuffer->value, &end); |
|||
assert(end == strbuffer->value + strbuffer->length); |
|||
|
|||
if((value == HUGE_VAL || value == -HUGE_VAL) && errno == ERANGE) { |
|||
/* Overflow */ |
|||
return -1; |
|||
} |
|||
|
|||
*out = value; |
|||
return 0; |
|||
} |
|||
|
|||
int jsonp_dtostr(char *buffer, size_t size, double value, int precision) |
|||
{ |
|||
int ret; |
|||
char *start, *end; |
|||
size_t length; |
|||
|
|||
if (precision == 0) |
|||
precision = 17; |
|||
|
|||
ret = snprintf(buffer, size, "%.*g", precision, value); |
|||
if(ret < 0) |
|||
return -1; |
|||
|
|||
length = (size_t)ret; |
|||
if(length >= size) |
|||
return -1; |
|||
|
|||
#if JSON_HAVE_LOCALECONV |
|||
from_locale(buffer); |
|||
#endif |
|||
|
|||
/* Make sure there's a dot or 'e' in the output. Otherwise
|
|||
a real is converted to an integer when decoding */ |
|||
if(strchr(buffer, '.') == NULL && |
|||
strchr(buffer, 'e') == NULL) |
|||
{ |
|||
if(length + 3 >= size) { |
|||
/* No space to append ".0" */ |
|||
return -1; |
|||
} |
|||
buffer[length] = '.'; |
|||
buffer[length + 1] = '0'; |
|||
buffer[length + 2] = '\0'; |
|||
length += 2; |
|||
} |
|||
|
|||
/* Remove leading '+' from positive exponent. Also remove leading
|
|||
zeros from exponents (added by some printf() implementations) */ |
|||
start = strchr(buffer, 'e'); |
|||
if(start) { |
|||
start++; |
|||
end = start + 1; |
|||
|
|||
if(*start == '-') |
|||
start++; |
|||
|
|||
while(*end == '0') |
|||
end++; |
|||
|
|||
if(end != start) { |
|||
memmove(start, end, length - (size_t)(end - buffer)); |
|||
length -= (size_t)(end - start); |
|||
} |
|||
} |
|||
|
|||
return (int)length; |
|||
} |
@ -0,0 +1,187 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* |
|||
* Jansson is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#include <string.h> |
|||
#include "utf.h" |
|||
|
|||
int utf8_encode(int32_t codepoint, char *buffer, size_t *size) |
|||
{ |
|||
if(codepoint < 0) |
|||
return -1; |
|||
else if(codepoint < 0x80) |
|||
{ |
|||
buffer[0] = (char)codepoint; |
|||
*size = 1; |
|||
} |
|||
else if(codepoint < 0x800) |
|||
{ |
|||
buffer[0] = 0xC0 + ((codepoint & 0x7C0) >> 6); |
|||
buffer[1] = 0x80 + ((codepoint & 0x03F)); |
|||
*size = 2; |
|||
} |
|||
else if(codepoint < 0x10000) |
|||
{ |
|||
buffer[0] = 0xE0 + ((codepoint & 0xF000) >> 12); |
|||
buffer[1] = 0x80 + ((codepoint & 0x0FC0) >> 6); |
|||
buffer[2] = 0x80 + ((codepoint & 0x003F)); |
|||
*size = 3; |
|||
} |
|||
else if(codepoint <= 0x10FFFF) |
|||
{ |
|||
buffer[0] = 0xF0 + ((codepoint & 0x1C0000) >> 18); |
|||
buffer[1] = 0x80 + ((codepoint & 0x03F000) >> 12); |
|||
buffer[2] = 0x80 + ((codepoint & 0x000FC0) >> 6); |
|||
buffer[3] = 0x80 + ((codepoint & 0x00003F)); |
|||
*size = 4; |
|||
} |
|||
else |
|||
return -1; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
size_t utf8_check_first(char byte) |
|||
{ |
|||
unsigned char u = (unsigned char)byte; |
|||
|
|||
if(u < 0x80) |
|||
return 1; |
|||
|
|||
if(0x80 <= u && u <= 0xBF) { |
|||
/* second, third or fourth byte of a multi-byte
|
|||
sequence, i.e. a "continuation byte" */ |
|||
return 0; |
|||
} |
|||
else if(u == 0xC0 || u == 0xC1) { |
|||
/* overlong encoding of an ASCII byte */ |
|||
return 0; |
|||
} |
|||
else if(0xC2 <= u && u <= 0xDF) { |
|||
/* 2-byte sequence */ |
|||
return 2; |
|||
} |
|||
|
|||
else if(0xE0 <= u && u <= 0xEF) { |
|||
/* 3-byte sequence */ |
|||
return 3; |
|||
} |
|||
else if(0xF0 <= u && u <= 0xF4) { |
|||
/* 4-byte sequence */ |
|||
return 4; |
|||
} |
|||
else { /* u >= 0xF5 */ |
|||
/* Restricted (start of 4-, 5- or 6-byte sequence) or invalid
|
|||
UTF-8 */ |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint) |
|||
{ |
|||
size_t i; |
|||
int32_t value = 0; |
|||
unsigned char u = (unsigned char)buffer[0]; |
|||
|
|||
if(size == 2) |
|||
{ |
|||
value = u & 0x1F; |
|||
} |
|||
else if(size == 3) |
|||
{ |
|||
value = u & 0xF; |
|||
} |
|||
else if(size == 4) |
|||
{ |
|||
value = u & 0x7; |
|||
} |
|||
else |
|||
return 0; |
|||
|
|||
for(i = 1; i < size; i++) |
|||
{ |
|||
u = (unsigned char)buffer[i]; |
|||
|
|||
if(u < 0x80 || u > 0xBF) { |
|||
/* not a continuation byte */ |
|||
return 0; |
|||
} |
|||
|
|||
value = (value << 6) + (u & 0x3F); |
|||
} |
|||
|
|||
if(value > 0x10FFFF) { |
|||
/* not in Unicode range */ |
|||
return 0; |
|||
} |
|||
|
|||
else if(0xD800 <= value && value <= 0xDFFF) { |
|||
/* invalid code point (UTF-16 surrogate halves) */ |
|||
return 0; |
|||
} |
|||
|
|||
else if((size == 2 && value < 0x80) || |
|||
(size == 3 && value < 0x800) || |
|||
(size == 4 && value < 0x10000)) { |
|||
/* overlong encoding */ |
|||
return 0; |
|||
} |
|||
|
|||
if(codepoint) |
|||
*codepoint = value; |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
const char *utf8_iterate(const char *buffer, size_t bufsize, int32_t *codepoint) |
|||
{ |
|||
size_t count; |
|||
int32_t value; |
|||
|
|||
if(!bufsize) |
|||
return buffer; |
|||
|
|||
count = utf8_check_first(buffer[0]); |
|||
if(count <= 0) |
|||
return NULL; |
|||
|
|||
if(count == 1) |
|||
value = (unsigned char)buffer[0]; |
|||
else |
|||
{ |
|||
if(count > bufsize || !utf8_check_full(buffer, count, &value)) |
|||
return NULL; |
|||
} |
|||
|
|||
if(codepoint) |
|||
*codepoint = value; |
|||
|
|||
return buffer + count; |
|||
} |
|||
|
|||
int utf8_check_string(const char *string, size_t length) |
|||
{ |
|||
size_t i; |
|||
|
|||
for(i = 0; i < length; i++) |
|||
{ |
|||
size_t count = utf8_check_first(string[i]); |
|||
if(count == 0) |
|||
return 0; |
|||
else if(count > 1) |
|||
{ |
|||
if(count > length - i) |
|||
return 0; |
|||
|
|||
if(!utf8_check_full(&string[i], count, NULL)) |
|||
return 0; |
|||
|
|||
i += count - 1; |
|||
} |
|||
} |
|||
|
|||
return 1; |
|||
} |
@ -0,0 +1,27 @@ |
|||
/*
|
|||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> |
|||
* |
|||
* Jansson is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. See LICENSE for details. |
|||
*/ |
|||
|
|||
#ifndef UTF_H |
|||
#define UTF_H |
|||
|
|||
#ifdef HAVE_CONFIG_H |
|||
#include <jansson_private_config.h> |
|||
#endif |
|||
|
|||
#ifdef HAVE_STDINT_H |
|||
#include <stdint.h> |
|||
#endif |
|||
|
|||
int utf8_encode(int32_t codepoint, char *buffer, size_t *size); |
|||
|
|||
size_t utf8_check_first(char byte); |
|||
size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint); |
|||
const char *utf8_iterate(const char *buffer, size_t size, int32_t *codepoint); |
|||
|
|||
int utf8_check_string(const char *string, size_t length); |
|||
|
|||
#endif |
File diff suppressed because it is too large
@ -0,0 +1,392 @@ |
|||
/**
|
|||
* Old Git implementation of windows terminal colors (2009) |
|||
* before use of a threaded wrapper. |
|||
*/ |
|||
|
|||
#undef NOGDI |
|||
#include <windows.h> |
|||
#include <wingdi.h> |
|||
#include <winreg.h> |
|||
#include <malloc.h> |
|||
#include <stdio.h> |
|||
#include <io.h> |
|||
|
|||
#include "compat/winansi.h" |
|||
/*
|
|||
* Copyright 2008 Peter Harris <git@peter.is-a-geek.org> |
|||
*/ |
|||
|
|||
/*
|
|||
Functions to be wrapped: |
|||
*/ |
|||
#undef printf |
|||
#undef fprintf |
|||
#undef fputs |
|||
#undef vfprintf |
|||
/* TODO: write */ |
|||
|
|||
/*
|
|||
ANSI codes used by git: m, K |
|||
|
|||
This file is git-specific. Therefore, this file does not attempt |
|||
to implement any codes that are not used by git. |
|||
*/ |
|||
|
|||
static HANDLE console; |
|||
static WORD plain_attr; |
|||
static WORD attr; |
|||
static int negative; |
|||
|
|||
static void init(void) |
|||
{ |
|||
CONSOLE_SCREEN_BUFFER_INFO sbi; |
|||
|
|||
static int initialized = 0; |
|||
if (initialized) |
|||
return; |
|||
|
|||
console = GetStdHandle(STD_OUTPUT_HANDLE); |
|||
if (console == INVALID_HANDLE_VALUE) |
|||
console = NULL; |
|||
|
|||
if (!console) |
|||
return; |
|||
|
|||
GetConsoleScreenBufferInfo(console, &sbi); |
|||
attr = plain_attr = sbi.wAttributes; |
|||
negative = 0; |
|||
|
|||
initialized = 1; |
|||
} |
|||
|
|||
static int write_console(const char *str, int len) |
|||
{ |
|||
/* convert utf-8 to utf-16, write directly to console */ |
|||
int wlen = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0); |
|||
wchar_t *wbuf = (wchar_t *)alloca(wlen * sizeof(wchar_t)); |
|||
MultiByteToWideChar(CP_UTF8, 0, str, len, wbuf, wlen); |
|||
|
|||
WriteConsoleW(console, wbuf, wlen, NULL, NULL); |
|||
|
|||
/* return original (utf-8 encoded) length */ |
|||
return len; |
|||
} |
|||
|
|||
#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) |
|||
#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) |
|||
|
|||
static void set_console_attr(void) |
|||
{ |
|||
WORD attributes = attr; |
|||
if (negative) { |
|||
attributes &= ~FOREGROUND_ALL; |
|||
attributes &= ~BACKGROUND_ALL; |
|||
|
|||
/* This could probably use a bitmask
|
|||
instead of a series of ifs */ |
|||
if (attr & FOREGROUND_RED) |
|||
attributes |= BACKGROUND_RED; |
|||
if (attr & FOREGROUND_GREEN) |
|||
attributes |= BACKGROUND_GREEN; |
|||
if (attr & FOREGROUND_BLUE) |
|||
attributes |= BACKGROUND_BLUE; |
|||
|
|||
if (attr & BACKGROUND_RED) |
|||
attributes |= FOREGROUND_RED; |
|||
if (attr & BACKGROUND_GREEN) |
|||
attributes |= FOREGROUND_GREEN; |
|||
if (attr & BACKGROUND_BLUE) |
|||
attributes |= FOREGROUND_BLUE; |
|||
} |
|||
SetConsoleTextAttribute(console, attributes); |
|||
} |
|||
|
|||
static void erase_in_line(void) |
|||
{ |
|||
CONSOLE_SCREEN_BUFFER_INFO sbi; |
|||
DWORD dummy; /* Needed for Windows 7 (or Vista) regression */ |
|||
|
|||
if (!console) |
|||
return; |
|||
|
|||
GetConsoleScreenBufferInfo(console, &sbi); |
|||
FillConsoleOutputCharacterA(console, ' ', |
|||
sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition, |
|||
&dummy); |
|||
} |
|||
|
|||
|
|||
static const char *set_attr(const char *str) |
|||
{ |
|||
const char *func; |
|||
size_t len = strspn(str, "0123456789;"); |
|||
func = str + len; |
|||
|
|||
switch (*func) { |
|||
case 'm': |
|||
do { |
|||
long val = strtol(str, (char **)&str, 10); |
|||
switch (val) { |
|||
case 0: /* reset */ |
|||
attr = plain_attr; |
|||
negative = 0; |
|||
break; |
|||
case 1: /* bold */ |
|||
attr |= FOREGROUND_INTENSITY; |
|||
break; |
|||
case 2: /* faint */ |
|||
case 22: /* normal */ |
|||
attr &= ~FOREGROUND_INTENSITY; |
|||
break; |
|||
case 3: /* italic */ |
|||
/* Unsupported */ |
|||
break; |
|||
case 4: /* underline */ |
|||
case 21: /* double underline */ |
|||
/* Wikipedia says this flag does nothing */ |
|||
/* Furthermore, mingw doesn't define this flag
|
|||
attr |= COMMON_LVB_UNDERSCORE; */ |
|||
break; |
|||
case 24: /* no underline */ |
|||
/* attr &= ~COMMON_LVB_UNDERSCORE; */ |
|||
break; |
|||
case 5: /* slow blink */ |
|||
case 6: /* fast blink */ |
|||
/* We don't have blink, but we do have
|
|||
background intensity */ |
|||
attr |= BACKGROUND_INTENSITY; |
|||
break; |
|||
case 25: /* no blink */ |
|||
attr &= ~BACKGROUND_INTENSITY; |
|||
break; |
|||
case 7: /* negative */ |
|||
negative = 1; |
|||
break; |
|||
case 27: /* positive */ |
|||
negative = 0; |
|||
break; |
|||
case 8: /* conceal */ |
|||
case 28: /* reveal */ |
|||
/* Unsupported */ |
|||
break; |
|||
case 30: /* Black */ |
|||
attr &= ~FOREGROUND_ALL; |
|||
break; |
|||
case 31: /* Red */ |
|||
attr &= ~FOREGROUND_ALL; |
|||
attr |= FOREGROUND_RED; |
|||
break; |
|||
case 32: /* Green */ |
|||
attr &= ~FOREGROUND_ALL; |
|||
attr |= FOREGROUND_GREEN; |
|||
break; |
|||
case 33: /* Yellow */ |
|||
attr &= ~FOREGROUND_ALL; |
|||
attr |= FOREGROUND_RED | FOREGROUND_GREEN; |
|||
break; |
|||
case 34: /* Blue */ |
|||
attr &= ~FOREGROUND_ALL; |
|||
attr |= FOREGROUND_BLUE; |
|||
break; |
|||
case 35: /* Magenta */ |
|||
attr &= ~FOREGROUND_ALL; |
|||
attr |= FOREGROUND_RED | FOREGROUND_BLUE; |
|||
break; |
|||
case 36: /* Cyan */ |
|||
attr &= ~FOREGROUND_ALL; |
|||
attr |= FOREGROUND_GREEN | FOREGROUND_BLUE; |
|||
break; |
|||
case 37: /* White */ |
|||
attr |= FOREGROUND_RED | |
|||
FOREGROUND_GREEN | |
|||
FOREGROUND_BLUE; |
|||
break; |
|||
case 38: /* Unknown */ |
|||
break; |
|||
case 39: /* reset */ |
|||
attr &= ~FOREGROUND_ALL; |
|||
attr |= (plain_attr & FOREGROUND_ALL); |
|||
break; |
|||
case 40: /* Black */ |
|||
attr &= ~BACKGROUND_ALL; |
|||
break; |
|||
case 41: /* Red */ |
|||
attr &= ~BACKGROUND_ALL; |
|||
attr |= BACKGROUND_RED; |
|||
break; |
|||
case 42: /* Green */ |
|||
attr &= ~BACKGROUND_ALL; |
|||
attr |= BACKGROUND_GREEN; |
|||
break; |
|||
case 43: /* Yellow */ |
|||
attr &= ~BACKGROUND_ALL; |
|||
attr |= BACKGROUND_RED | BACKGROUND_GREEN; |
|||
break; |
|||
case 44: /* Blue */ |
|||
attr &= ~BACKGROUND_ALL; |
|||
attr |= BACKGROUND_BLUE; |
|||
break; |
|||
case 45: /* Magenta */ |
|||
attr &= ~BACKGROUND_ALL; |
|||
attr |= BACKGROUND_RED | BACKGROUND_BLUE; |
|||
break; |
|||
case 46: /* Cyan */ |
|||
attr &= ~BACKGROUND_ALL; |
|||
attr |= BACKGROUND_GREEN | BACKGROUND_BLUE; |
|||
break; |
|||
case 47: /* White */ |
|||
attr |= BACKGROUND_RED | |
|||
BACKGROUND_GREEN | |
|||
BACKGROUND_BLUE; |
|||
break; |
|||
case 48: /* Unknown */ |
|||
break; |
|||
case 49: /* reset */ |
|||
attr &= ~BACKGROUND_ALL; |
|||
attr |= (plain_attr & BACKGROUND_ALL); |
|||
break; |
|||
default: |
|||
/* Unsupported code */ |
|||
break; |
|||
} |
|||
str++; |
|||
} while (*(str - 1) == ';'); |
|||
|
|||
set_console_attr(); |
|||
break; |
|||
case 'K': |
|||
erase_in_line(); |
|||
break; |
|||
default: |
|||
/* Unsupported code */ |
|||
break; |
|||
} |
|||
|
|||
return func + 1; |
|||
} |
|||
|
|||
static int ansi_emulate(const char *str, FILE *stream) |
|||
{ |
|||
int rv = 0; |
|||
const char *pos = str; |
|||
|
|||
fflush(stream); |
|||
|
|||
while (*pos) { |
|||
pos = strstr(str, "\033["); |
|||
if (pos) { |
|||
int len = (int) (pos - str); |
|||
|
|||
if (len) { |
|||
int out_len = write_console(str, len); |
|||
rv += out_len; |
|||
if (out_len < len) |
|||
return rv; |
|||
} |
|||
|
|||
str = pos + 2; |
|||
rv += 2; |
|||
|
|||
pos = set_attr(str); |
|||
rv += (int) (pos - str); |
|||
str = pos; |
|||
} |
|||
else { |
|||
int len = (int) strlen(str); |
|||
rv += write_console(str, len); |
|||
return rv; |
|||
} |
|||
} |
|||
return rv; |
|||
} |
|||
|
|||
int winansi_fputs(const char *str, FILE *stream) |
|||
{ |
|||
int rv; |
|||
|
|||
if (!isatty(fileno(stream))) |
|||
return fputs(str, stream); |
|||
|
|||
init(); |
|||
|
|||
if (!console) |
|||
return fputs(str, stream); |
|||
|
|||
rv = ansi_emulate(str, stream); |
|||
|
|||
if (rv >= 0) |
|||
return 0; |
|||
else |
|||
return EOF; |
|||
} |
|||
|
|||
int winansi_vfprintf(FILE *stream, const char *format, va_list list) |
|||
{ |
|||
int len, rv; |
|||
char small_buf[256] = { 0 }; |
|||
char *buf = small_buf; |
|||
va_list cp; |
|||
|
|||
if (!isatty(fileno(stream))) |
|||
goto abort; |
|||
|
|||
init(); |
|||
|
|||
if (!console) |
|||
goto abort; |
|||
|
|||
va_copy(cp, list); |
|||
len = vsnprintf(small_buf, sizeof(small_buf), format, cp); |
|||
#ifdef WIN32 |
|||
/* bug on long strings without that */ |
|||
if (len == -1) |
|||
len = _vscprintf(format, cp); |
|||
#endif |
|||
va_end(cp); |
|||
|
|||
if (len > sizeof(small_buf) - 1) { |
|||
buf = malloc(len + 1); |
|||
if (!buf) |
|||
goto abort; |
|||
|
|||
len = vsnprintf(buf, len + 1, format, list); |
|||
#ifdef WIN32 |
|||
if (len == -1) |
|||
len = _vscprintf(format, list); |
|||
#endif |
|||
} |
|||
|
|||
rv = ansi_emulate(buf, stream); |
|||
|
|||
if (buf != small_buf) |
|||
free(buf); |
|||
return rv; |
|||
|
|||
abort: |
|||
rv = vfprintf(stream, format, list); |
|||
return rv; |
|||
} |
|||
|
|||
int winansi_fprintf(FILE *stream, const char *format, ...) |
|||
{ |
|||
va_list list; |
|||
int rv; |
|||
|
|||
va_start(list, format); |
|||
rv = winansi_vfprintf(stream, format, list); |
|||
va_end(list); |
|||
|
|||
return rv; |
|||
} |
|||
|
|||
int winansi_printf(const char *format, ...) |
|||
{ |
|||
va_list list; |
|||
int rv; |
|||
|
|||
va_start(list, format); |
|||
rv = winansi_vfprintf(stdout, format, list); |
|||
va_end(list); |
|||
|
|||
return rv; |
|||
} |
@ -0,0 +1,32 @@ |
|||
/*
|
|||
* ANSI emulation wrappers |
|||
*/ |
|||
#ifdef WIN32 |
|||
#include <windows.h> |
|||
#include <stddef.h> |
|||
#include <stdio.h> |
|||
|
|||
#define isatty(fd) _isatty(fd) |
|||
#define fileno(fd) _fileno(fd) |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
int winansi_fputs(const char *str, FILE *stream); |
|||
int winansi_printf(const char *format, ...); |
|||
int winansi_fprintf(FILE *stream, const char *format, ...); |
|||
int winansi_vfprintf(FILE *stream, const char *format, va_list list); |
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#undef fputs |
|||
#undef fprintf |
|||
#undef vfprintf |
|||
|
|||
#define fputs winansi_fputs |
|||
#define printf winansi_printf |
|||
#define fprintf winansi_fprintf |
|||
#define vfprintf winansi_vfprintf |
|||
|
|||
#endif |
@ -0,0 +1,100 @@ |
|||
/* 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 <cpuid.h> |
|||
#include <string.h> |
|||
#include <stdbool.h> |
|||
#include "cpu.h" |
|||
|
|||
|
|||
#define VENDOR_ID (0) |
|||
#define PROCESSOR_INFO (1) |
|||
#define CACHE_TLB_DESCRIPTOR (2) |
|||
#define EXTENDED_FEATURES (7) |
|||
#define PROCESSOR_BRAND_STRING_1 (0x80000002) |
|||
#define PROCESSOR_BRAND_STRING_2 (0x80000003) |
|||
#define PROCESSOR_BRAND_STRING_3 (0x80000004) |
|||
|
|||
#define EAX_Reg (0) |
|||
#define EBX_Reg (1) |
|||
#define ECX_Reg (2) |
|||
#define EDX_Reg (3) |
|||
|
|||
|
|||
static inline void cpuid(int level, int output[4]) { |
|||
int a, b, c, d; |
|||
__cpuid_count(level, 0, a, b, c, d); |
|||
|
|||
output[0] = a; |
|||
output[1] = b; |
|||
output[2] = c; |
|||
output[3] = d; |
|||
} |
|||
|
|||
|
|||
static void cpu_brand_string(char* s) { |
|||
int cpu_info[4] = { 0 }; |
|||
cpuid(VENDOR_ID, cpu_info); |
|||
|
|||
if (cpu_info[EAX_Reg] >= 4) { |
|||
for (int i = 0; i < 4; i++) { |
|||
cpuid(0x80000002 + i, cpu_info); |
|||
memcpy(s, cpu_info, sizeof(cpu_info)); |
|||
s += 16; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
static bool has_aes_ni() |
|||
{ |
|||
int cpu_info[4] = { 0 }; |
|||
cpuid(PROCESSOR_INFO, cpu_info); |
|||
|
|||
return cpu_info[ECX_Reg] & bit_AES; |
|||
} |
|||
|
|||
|
|||
static bool has_bmi2() { |
|||
int cpu_info[4] = { 0 }; |
|||
cpuid(EXTENDED_FEATURES, cpu_info); |
|||
|
|||
return cpu_info[EBX_Reg] & bit_BMI2; |
|||
} |
|||
|
|||
|
|||
void cpu_init_common() { |
|||
cpu_brand_string(cpu_info.brand); |
|||
|
|||
# ifdef __x86_64__ |
|||
cpu_info.flags |= CPU_FLAG_X86_64; |
|||
# endif |
|||
|
|||
if (has_aes_ni()) { |
|||
cpu_info.flags |= CPU_FLAG_AES; |
|||
} |
|||
|
|||
if (has_bmi2()) { |
|||
cpu_info.flags |= CPU_FLAG_BMI2; |
|||
} |
|||
} |
@ -0,0 +1,48 @@ |
|||
/* 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__ |
|||
#define __CPU_H__ |
|||
|
|||
struct cpu_info { |
|||
int count; |
|||
int flags; |
|||
char brand[48]; |
|||
}; |
|||
|
|||
extern struct cpu_info cpu_info; |
|||
|
|||
|
|||
enum cpu_flags { |
|||
CPU_FLAG_X86_64 = 1, |
|||
CPU_FLAG_AES = 2, |
|||
CPU_FLAG_BMI2 = 4 |
|||
}; |
|||
|
|||
|
|||
|
|||
void cpu_init(); |
|||
int get_optimal_threads_count(); |
|||
int affine_to_cpu_mask(int id, unsigned long mask); |
|||
|
|||
#endif /* __CPU_H__ */ |
@ -0,0 +1,170 @@ |
|||
/*
|
|||
--------------------------------------------------------------------------- |
|||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. |
|||
|
|||
The redistribution and use of this software (with or without changes) |
|||
is allowed without the payment of fees or royalties provided that: |
|||
|
|||
source code distributions include the above copyright notice, this |
|||
list of conditions and the following disclaimer; |
|||
|
|||
binary distributions include the above copyright notice, this list |
|||
of conditions and the following disclaimer in their documentation. |
|||
|
|||
This software is provided 'as is' with no explicit or implied warranties |
|||
in respect of its operation, including, but not limited to, correctness |
|||
and fitness for purpose. |
|||
--------------------------------------------------------------------------- |
|||
Issue Date: 20/12/2007 |
|||
*/ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
#include "aesb.h" |
|||
|
|||
#if defined(__cplusplus) |
|||
extern "C" |
|||
{ |
|||
#endif |
|||
|
|||
#define TABLE_ALIGN 32 |
|||
#define WPOLY 0x011b |
|||
#define N_COLS 4 |
|||
#define AES_BLOCK_SIZE 16 |
|||
#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2)) |
|||
|
|||
#if defined(_MSC_VER) |
|||
#define ALIGN __declspec(align(TABLE_ALIGN)) |
|||
#elif defined(__GNUC__) |
|||
#define ALIGN __attribute__ ((aligned(16))) |
|||
#else |
|||
#define ALIGN |
|||
#endif |
|||
|
|||
#define rf1(r,c) (r) |
|||
#define word_in(x,c) (*((uint32_t*)(x)+(c))) |
|||
#define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = (v)) |
|||
|
|||
#define s(x,c) x[c] |
|||
#define si(y,x,c) (s(y,c) = word_in(x, c)) |
|||
#define so(y,x,c) word_out(y, c, s(x,c)) |
|||
#define state_in(y,x) si(y,x,0); si(y,x,1); si(y,x,2); si(y,x,3) |
|||
#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) |
|||
#define round(y,x,k) \ |
|||
y[0] = (k)[0] ^ (t_fn[0][x[0] & 0xff] ^ t_fn[1][(x[1] >> 8) & 0xff] ^ t_fn[2][(x[2] >> 16) & 0xff] ^ t_fn[3][x[3] >> 24]); \ |
|||
y[1] = (k)[1] ^ (t_fn[0][x[1] & 0xff] ^ t_fn[1][(x[2] >> 8) & 0xff] ^ t_fn[2][(x[3] >> 16) & 0xff] ^ t_fn[3][x[0] >> 24]); \ |
|||
y[2] = (k)[2] ^ (t_fn[0][x[2] & 0xff] ^ t_fn[1][(x[3] >> 8) & 0xff] ^ t_fn[2][(x[0] >> 16) & 0xff] ^ t_fn[3][x[1] >> 24]); \ |
|||
y[3] = (k)[3] ^ (t_fn[0][x[3] & 0xff] ^ t_fn[1][(x[0] >> 8) & 0xff] ^ t_fn[2][(x[1] >> 16) & 0xff] ^ t_fn[3][x[2] >> 24]); |
|||
#define to_byte(x) ((x) & 0xff) |
|||
#define bval(x,n) to_byte((x) >> (8 * (n))) |
|||
|
|||
#define fwd_var(x,r,c)\ |
|||
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ |
|||
: r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ |
|||
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ |
|||
: ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) |
|||
|
|||
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) |
|||
|
|||
#define sb_data(w) {\ |
|||
w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ |
|||
w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ |
|||
w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ |
|||
w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ |
|||
w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ |
|||
w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ |
|||
w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ |
|||
w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ |
|||
w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ |
|||
w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ |
|||
w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ |
|||
w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ |
|||
w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ |
|||
w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ |
|||
w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ |
|||
w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ |
|||
w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ |
|||
w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ |
|||
w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ |
|||
w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ |
|||
w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ |
|||
w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ |
|||
w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ |
|||
w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ |
|||
w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ |
|||
w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ |
|||
w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ |
|||
w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ |
|||
w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ |
|||
w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ |
|||
w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ |
|||
w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } |
|||
|
|||
#define rc_data(w) {\ |
|||
w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\ |
|||
w(0x1b), w(0x36) } |
|||
|
|||
#define bytes2word(b0, b1, b2, b3) (((uint32_t)(b3) << 24) | \ |
|||
((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0)) |
|||
|
|||
#define h0(x) (x) |
|||
#define w0(p) bytes2word(p, 0, 0, 0) |
|||
#define w1(p) bytes2word(0, p, 0, 0) |
|||
#define w2(p) bytes2word(0, 0, p, 0) |
|||
#define w3(p) bytes2word(0, 0, 0, p) |
|||
|
|||
#define u0(p) bytes2word(f2(p), p, p, f3(p)) |
|||
#define u1(p) bytes2word(f3(p), f2(p), p, p) |
|||
#define u2(p) bytes2word(p, f3(p), f2(p), p) |
|||
#define u3(p) bytes2word(p, p, f3(p), f2(p)) |
|||
|
|||
#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) |
|||
#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) |
|||
#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) |
|||
#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) |
|||
|
|||
#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) |
|||
#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) |
|||
#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) ^ (((x>>5) & 4) * WPOLY)) |
|||
#define f3(x) (f2(x) ^ x) |
|||
#define f9(x) (f8(x) ^ x) |
|||
#define fb(x) (f8(x) ^ f2(x) ^ x) |
|||
#define fd(x) (f8(x) ^ f4(x) ^ x) |
|||
#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) |
|||
|
|||
#define t_dec(m,n) t_##m##n |
|||
#define t_set(m,n) t_##m##n |
|||
#define t_use(m,n) t_##m##n |
|||
|
|||
#define d_4(t,n,b,e,f,g,h) ALIGN const t n[4][256] = { b(e), b(f), b(g), b(h) } |
|||
|
|||
#define four_tables(x,tab,vf,rf,c) \ |
|||
(tab[0][bval(vf(x,0,c),rf(0,c))] \ |
|||
^ tab[1][bval(vf(x,1,c),rf(1,c))] \ |
|||
^ tab[2][bval(vf(x,2,c),rf(2,c))] \ |
|||
^ tab[3][bval(vf(x,3,c),rf(3,c))]) |
|||
|
|||
d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3); |
|||
|
|||
inline void aesb_single_round(const uint8_t *restrict in, uint8_t *out, const uint8_t *restrict expandedKey) { |
|||
round(((uint32_t*) out), ((uint32_t*) in), ((uint32_t*) expandedKey)); |
|||
} |
|||
|
|||
inline void aesb_pseudo_round_mut(uint8_t *restrict val, const uint8_t *restrict expandedKey) { |
|||
uint32_t b1[4]; |
|||
round(b1, ((uint32_t*) val), ((const uint32_t *) expandedKey)); |
|||
round(((uint32_t*) val), b1, ((const uint32_t *) expandedKey) + 1 * N_COLS); |
|||
round(b1, ((uint32_t*) val), ((const uint32_t *) expandedKey) + 2 * N_COLS); |
|||
round(((uint32_t*) val), b1, ((const uint32_t *) expandedKey) + 3 * N_COLS); |
|||
round(b1, ((uint32_t*) val), ((const uint32_t *) expandedKey) + 4 * N_COLS); |
|||
round(((uint32_t*) val), b1, ((const uint32_t *) expandedKey) + 5 * N_COLS); |
|||
round(b1, ((uint32_t*) val), ((const uint32_t *) expandedKey) + 6 * N_COLS); |
|||
round(((uint32_t*) val), b1, ((const uint32_t *) expandedKey) + 7 * N_COLS); |
|||
round(b1, ((uint32_t*) val), ((const uint32_t *) expandedKey) + 8 * N_COLS); |
|||
round(((uint32_t*) val), b1, ((const uint32_t *) expandedKey) + 9 * N_COLS); |
|||
} |
|||
|
|||
|
|||
#if defined(__cplusplus) |
|||
} |
|||
#endif |
@ -0,0 +1,10 @@ |
|||
#ifndef __AESB_H__ |
|||
#define __AESB_H__ |
|||
|
|||
void aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey); |
|||
void aesb_pseudo_round_mut(uint8_t *val, const uint8_t *expandedKey); |
|||
|
|||
#define fast_aesb_single_round aesb_single_round |
|||
#define fast_aesb_pseudo_round_mut aesb_pseudo_round_mut |
|||
|
|||
#endif /* __AESB_H__ */ |
@ -0,0 +1,326 @@ |
|||
/*
|
|||
* 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 <stdio.h> |
|||
#include <stdint.h> |
|||
#include "c_blake256.h" |
|||
|
|||
#define U8TO32(p) \ |
|||
(((uint32_t)((p)[0]) << 24) | ((uint32_t)((p)[1]) << 16) | \ |
|||
((uint32_t)((p)[2]) << 8) | ((uint32_t)((p)[3]) )) |
|||
#define U32TO8(p, v) \ |
|||
(p)[0] = (uint8_t)((v) >> 24); (p)[1] = (uint8_t)((v) >> 16); \ |
|||
(p)[2] = (uint8_t)((v) >> 8); (p)[3] = (uint8_t)((v) ); |
|||
|
|||
const uint8_t sigma[][16] = { |
|||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}, |
|||
{14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3}, |
|||
{11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4}, |
|||
{ 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8}, |
|||
{ 9, 0, 5, 7, 2, 4,10,15,14, 1,11,12, 6, 8, 3,13}, |
|||
{ 2,12, 6,10, 0,11, 8, 3, 4,13, 7, 5,15,14, 1, 9}, |
|||
{12, 5, 1,15,14,13, 4,10, 0, 7, 6, 3, 9, 2, 8,11}, |
|||
{13,11, 7,14,12, 1, 3, 9, 5, 0,15, 4, 8, 6, 2,10}, |
|||
{ 6,15,14, 9,11, 3, 0, 8,12, 2,13, 7, 1, 4,10, 5}, |
|||
{10, 2, 8, 4, 7, 6, 1, 5,15,11, 9,14, 3,12,13, 0}, |
|||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}, |
|||
{14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3}, |
|||
{11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4}, |
|||
{ 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8} |
|||
}; |
|||
|
|||
const uint32_t cst[16] = { |
|||
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, |
|||
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, |
|||
0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, |
|||
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917 |
|||
}; |
|||
|
|||
static const uint8_t padding[] = { |
|||
0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
|||
}; |
|||
|
|||
|
|||
void blake256_compress(state *S, const uint8_t *block) { |
|||
uint32_t v[16], m[16], i; |
|||
|
|||
#define ROT(x,n) (((x)<<(32-n))|((x)>>(n))) |
|||
#define G(a,b,c,d,e) \ |
|||
v[a] += (m[sigma[i][e]] ^ cst[sigma[i][e+1]]) + v[b]; \ |
|||
v[d] = ROT(v[d] ^ v[a],16); \ |
|||
v[c] += v[d]; \ |
|||
v[b] = ROT(v[b] ^ v[c],12); \ |
|||
v[a] += (m[sigma[i][e+1]] ^ cst[sigma[i][e]])+v[b]; \ |
|||
v[d] = ROT(v[d] ^ v[a], 8); \ |
|||
v[c] += v[d]; \ |
|||
v[b] = ROT(v[b] ^ v[c], 7); |
|||
|
|||
for (i = 0; i < 16; ++i) m[i] = U8TO32(block + i * 4); |
|||
for (i = 0; i < 8; ++i) v[i] = S->h[i]; |
|||
v[ 8] = S->s[0] ^ 0x243F6A88; |
|||
v[ 9] = S->s[1] ^ 0x85A308D3; |
|||
v[10] = S->s[2] ^ 0x13198A2E; |
|||
v[11] = S->s[3] ^ 0x03707344; |
|||
v[12] = 0xA4093822; |
|||
v[13] = 0x299F31D0; |
|||
v[14] = 0x082EFA98; |
|||
v[15] = 0xEC4E6C89; |
|||
|
|||
if (S->nullt == 0) { |
|||
v[12] ^= S->t[0]; |
|||
v[13] ^= S->t[0]; |
|||
v[14] ^= S->t[1]; |
|||
v[15] ^= S->t[1]; |
|||
} |
|||
|
|||
for (i = 0; i < 14; ++i) { |
|||
G(0, 4, 8, 12, 0); |
|||
G(1, 5, 9, 13, 2); |
|||
G(2, 6, 10, 14, 4); |
|||
G(3, 7, 11, 15, 6); |
|||
G(3, 4, 9, 14, 14); |
|||
G(2, 7, 8, 13, 12); |
|||
G(0, 5, 10, 15, 8); |
|||
G(1, 6, 11, 12, 10); |
|||
} |
|||
|
|||
for (i = 0; i < 16; ++i) S->h[i % 8] ^= v[i]; |
|||
for (i = 0; i < 8; ++i) S->h[i] ^= S->s[i % 4]; |
|||
} |
|||
|
|||
void blake256_init(state *S) { |
|||
S->h[0] = 0x6A09E667; |
|||
S->h[1] = 0xBB67AE85; |
|||
S->h[2] = 0x3C6EF372; |
|||
S->h[3] = 0xA54FF53A; |
|||
S->h[4] = 0x510E527F; |
|||
S->h[5] = 0x9B05688C; |
|||
S->h[6] = 0x1F83D9AB; |
|||
S->h[7] = 0x5BE0CD19; |
|||
S->t[0] = S->t[1] = S->buflen = S->nullt = 0; |
|||
S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0; |
|||
} |
|||
|
|||
void blake224_init(state *S) { |
|||
S->h[0] = 0xC1059ED8; |
|||
S->h[1] = 0x367CD507; |
|||
S->h[2] = 0x3070DD17; |
|||
S->h[3] = 0xF70E5939; |
|||
S->h[4] = 0xFFC00B31; |
|||
S->h[5] = 0x68581511; |
|||
S->h[6] = 0x64F98FA7; |
|||
S->h[7] = 0xBEFA4FA4; |
|||
S->t[0] = S->t[1] = S->buflen = S->nullt = 0; |
|||
S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0; |
|||
} |
|||
|
|||
// datalen = number of bits
|
|||
void blake256_update(state *S, const uint8_t *data, uint64_t datalen) { |
|||
int left = S->buflen >> 3; |
|||
int fill = 64 - left; |
|||
|
|||
if (left && (((datalen >> 3) & 0x3F) >= (unsigned) fill)) { |
|||
memcpy((void *) (S->buf + left), (void *) data, fill); |
|||
S->t[0] += 512; |
|||
if (S->t[0] == 0) S->t[1]++; |
|||
blake256_compress(S, S->buf); |
|||
data += fill; |
|||
datalen -= (fill << 3); |
|||
left = 0; |
|||
} |
|||
|
|||
while (datalen >= 512) { |
|||
S->t[0] += 512; |
|||
if (S->t[0] == 0) S->t[1]++; |
|||
blake256_compress(S, data); |
|||
data += 64; |
|||
datalen -= 512; |
|||
} |
|||
|
|||
if (datalen > 0) { |
|||
memcpy((void *) (S->buf + left), (void *) data, datalen >> 3); |
|||
S->buflen = (left << 3) + datalen; |
|||
} else { |
|||
S->buflen = 0; |
|||
} |
|||
} |
|||
|
|||
// datalen = number of bits
|
|||
void blake224_update(state *S, const uint8_t *data, uint64_t datalen) { |
|||
blake256_update(S, data, datalen); |
|||
} |
|||
|
|||
void blake256_final_h(state *S, uint8_t *digest, uint8_t pa, uint8_t pb) { |
|||
uint8_t msglen[8]; |
|||
uint32_t lo = S->t[0] + S->buflen, hi = S->t[1]; |
|||
if (lo < (unsigned) S->buflen) hi++; |
|||
U32TO8(msglen + 0, hi); |
|||
U32TO8(msglen + 4, lo); |
|||
|
|||
if (S->buflen == 440) { /* one padding byte */ |
|||
S->t[0] -= 8; |
|||
blake256_update(S, &pa, 8); |
|||
} else { |
|||
if (S->buflen < 440) { /* enough space to fill the block */ |
|||
if (S->buflen == 0) S->nullt = 1; |
|||
S->t[0] -= 440 - S->buflen; |
|||
blake256_update(S, padding, 440 - S->buflen); |
|||
} else { /* need 2 compressions */ |
|||
S->t[0] -= 512 - S->buflen; |
|||
blake256_update(S, padding, 512 - S->buflen); |
|||
S->t[0] -= 440; |
|||
blake256_update(S, padding + 1, 440); |
|||
S->nullt = 1; |
|||
} |
|||
blake256_update(S, &pb, 8); |
|||
S->t[0] -= 8; |
|||
} |
|||
S->t[0] -= 64; |
|||
blake256_update(S, msglen, 64); |
|||
|
|||
U32TO8(digest + 0, S->h[0]); |
|||
U32TO8(digest + 4, S->h[1]); |
|||
U32TO8(digest + 8, S->h[2]); |
|||
U32TO8(digest + 12, S->h[3]); |
|||
U32TO8(digest + 16, S->h[4]); |
|||
U32TO8(digest + 20, S->h[5]); |
|||
U32TO8(digest + 24, S->h[6]); |
|||
U32TO8(digest + 28, S->h[7]); |
|||
} |
|||
|
|||
void blake256_final(state *S, uint8_t *digest) { |
|||
blake256_final_h(S, digest, 0x81, 0x01); |
|||
} |
|||
|
|||
void blake224_final(state *S, uint8_t *digest) { |
|||
blake256_final_h(S, digest, 0x80, 0x00); |
|||
} |
|||
|
|||
// inlen = number of bytes
|
|||
void blake256_hash(uint8_t *out, const uint8_t *in, uint64_t inlen) { |
|||
state S; |
|||
blake256_init(&S); |
|||
blake256_update(&S, in, inlen * 8); |
|||
blake256_final(&S, out); |
|||
} |
|||
|
|||
// inlen = number of bytes
|
|||
void blake224_hash(uint8_t *out, const uint8_t *in, uint64_t inlen) { |
|||
state S; |
|||
blake224_init(&S); |
|||
blake224_update(&S, in, inlen * 8); |
|||
blake224_final(&S, out); |
|||
} |
|||
|
|||
// keylen = number of bytes
|
|||
void hmac_blake256_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) { |
|||
const uint8_t *key = _key; |
|||
uint8_t keyhash[32]; |
|||
uint8_t pad[64]; |
|||
uint64_t i; |
|||
|
|||
if (keylen > 64) { |
|||
blake256_hash(keyhash, key, keylen); |
|||
key = keyhash; |
|||
keylen = 32; |
|||
} |
|||
|
|||
blake256_init(&S->inner); |
|||
memset(pad, 0x36, 64); |
|||
for (i = 0; i < keylen; ++i) { |
|||
pad[i] ^= key[i]; |
|||
} |
|||
blake256_update(&S->inner, pad, 512); |
|||
|
|||
blake256_init(&S->outer); |
|||
memset(pad, 0x5c, 64); |
|||
for (i = 0; i < keylen; ++i) { |
|||
pad[i] ^= key[i]; |
|||
} |
|||
blake256_update(&S->outer, pad, 512); |
|||
|
|||
memset(keyhash, 0, 32); |
|||
} |
|||
|
|||
// keylen = number of bytes
|
|||
void hmac_blake224_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) { |
|||
const uint8_t *key = _key; |
|||
uint8_t keyhash[32]; |
|||
uint8_t pad[64]; |
|||
uint64_t i; |
|||
|
|||
if (keylen > 64) { |
|||
blake256_hash(keyhash, key, keylen); |
|||
key = keyhash; |
|||
keylen = 28; |
|||
} |
|||
|
|||
blake224_init(&S->inner); |
|||
memset(pad, 0x36, 64); |
|||
for (i = 0; i < keylen; ++i) { |
|||
pad[i] ^= key[i]; |
|||
} |
|||
blake224_update(&S->inner, pad, 512); |
|||
|
|||
blake224_init(&S->outer); |
|||
memset(pad, 0x5c, 64); |
|||
for (i = 0; i < keylen; ++i) { |
|||
pad[i] ^= key[i]; |
|||
} |
|||
blake224_update(&S->outer, pad, 512); |
|||
|
|||
memset(keyhash, 0, 32); |
|||
} |
|||
|
|||
// datalen = number of bits
|
|||
void hmac_blake256_update(hmac_state *S, const uint8_t *data, uint64_t datalen) { |
|||
// update the inner state
|
|||
blake256_update(&S->inner, data, datalen); |
|||
} |
|||
|
|||
// datalen = number of bits
|
|||
void hmac_blake224_update(hmac_state *S, const uint8_t *data, uint64_t datalen) { |
|||
// update the inner state
|
|||
blake224_update(&S->inner, data, datalen); |
|||
} |
|||
|
|||
void hmac_blake256_final(hmac_state *S, uint8_t *digest) { |
|||
uint8_t ihash[32]; |
|||
blake256_final(&S->inner, ihash); |
|||
blake256_update(&S->outer, ihash, 256); |
|||
blake256_final(&S->outer, digest); |
|||
memset(ihash, 0, 32); |
|||
} |
|||
|
|||
void hmac_blake224_final(hmac_state *S, uint8_t *digest) { |
|||
uint8_t ihash[32]; |
|||
blake224_final(&S->inner, ihash); |
|||
blake224_update(&S->outer, ihash, 224); |
|||
blake224_final(&S->outer, digest); |
|||
memset(ihash, 0, 32); |
|||
} |
|||
|
|||
// keylen = number of bytes; inlen = number of bytes
|
|||
void hmac_blake256_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const uint8_t *in, uint64_t inlen) { |
|||
hmac_state S; |
|||
hmac_blake256_init(&S, key, keylen); |
|||
hmac_blake256_update(&S, in, inlen * 8); |
|||
hmac_blake256_final(&S, out); |
|||
} |
|||
|
|||
// keylen = number of bytes; inlen = number of bytes
|
|||
void hmac_blake224_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const uint8_t *in, uint64_t inlen) { |
|||
hmac_state S; |
|||
hmac_blake224_init(&S, key, keylen); |
|||
hmac_blake224_update(&S, in, inlen * 8); |
|||
hmac_blake224_final(&S, out); |
|||
} |
@ -0,0 +1,43 @@ |
|||
#ifndef _BLAKE256_H_ |
|||
#define _BLAKE256_H_ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
typedef struct { |
|||
uint32_t h[8], s[4], t[2]; |
|||
int buflen, nullt; |
|||
uint8_t buf[64]; |
|||
} state; |
|||
|
|||
typedef struct { |
|||
state inner; |
|||
state outer; |
|||
} hmac_state; |
|||
|
|||
void blake256_init(state *); |
|||
void blake224_init(state *); |
|||
|
|||
void blake256_update(state *, const uint8_t *, uint64_t); |
|||
void blake224_update(state *, const uint8_t *, uint64_t); |
|||
|
|||
void blake256_final(state *, uint8_t *); |
|||
void blake224_final(state *, uint8_t *); |
|||
|
|||
void blake256_hash(uint8_t *, const uint8_t *, uint64_t); |
|||
void blake224_hash(uint8_t *, const uint8_t *, uint64_t); |
|||
|
|||
/* HMAC functions: */ |
|||
|
|||
void hmac_blake256_init(hmac_state *, const uint8_t *, uint64_t); |
|||
void hmac_blake224_init(hmac_state *, const uint8_t *, uint64_t); |
|||
|
|||
void hmac_blake256_update(hmac_state *, const uint8_t *, uint64_t); |
|||
void hmac_blake224_update(hmac_state *, const uint8_t *, uint64_t); |
|||
|
|||
void hmac_blake256_final(hmac_state *, uint8_t *); |
|||
void hmac_blake224_final(hmac_state *, uint8_t *); |
|||
|
|||
void hmac_blake256_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint64_t); |
|||
void hmac_blake224_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint64_t); |
|||
|
|||
#endif /* _BLAKE256_H_ */ |
@ -0,0 +1,360 @@ |
|||
/* 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 "groestl_tables.h" |
|||
|
|||
#define P_TYPE 0 |
|||
#define Q_TYPE 1 |
|||
|
|||
const uint8_t shift_Values[2][8] = {{0,1,2,3,4,5,6,7},{1,3,5,7,0,2,4,6}}; |
|||
|
|||
const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6}; |
|||
|
|||
|
|||
#define ROTATE_COLUMN_DOWN(v1, v2, amount_bytes, temp_var) {temp_var = (v1<<(8*amount_bytes))|(v2>>(8*(4-amount_bytes))); \ |
|||
v2 = (v2<<(8*amount_bytes))|(v1>>(8*(4-amount_bytes))); \ |
|||
v1 = temp_var;} |
|||
|
|||
|
|||
#define COLUMN(x,y,i,c0,c1,c2,c3,c4,c5,c6,c7,tv1,tv2,tu,tl,t) \ |
|||
tu = T[2*(uint32_t)x[4*c0+0]]; \ |
|||
tl = T[2*(uint32_t)x[4*c0+0]+1]; \ |
|||
tv1 = T[2*(uint32_t)x[4*c1+1]]; \ |
|||
tv2 = T[2*(uint32_t)x[4*c1+1]+1]; \ |
|||
ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \ |
|||
tu ^= tv1; \ |
|||
tl ^= tv2; \ |
|||
tv1 = T[2*(uint32_t)x[4*c2+2]]; \ |
|||
tv2 = T[2*(uint32_t)x[4*c2+2]+1]; \ |
|||
ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \ |
|||
tu ^= tv1; \ |
|||
tl ^= tv2; \ |
|||
tv1 = T[2*(uint32_t)x[4*c3+3]]; \ |
|||
tv2 = T[2*(uint32_t)x[4*c3+3]+1]; \ |
|||
ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \ |
|||
tu ^= tv1; \ |
|||
tl ^= tv2; \ |
|||
tl ^= T[2*(uint32_t)x[4*c4+0]]; \ |
|||
tu ^= T[2*(uint32_t)x[4*c4+0]+1]; \ |
|||
tv1 = T[2*(uint32_t)x[4*c5+1]]; \ |
|||
tv2 = T[2*(uint32_t)x[4*c5+1]+1]; \ |
|||
ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \ |
|||
tl ^= tv1; \ |
|||
tu ^= tv2; \ |
|||
tv1 = T[2*(uint32_t)x[4*c6+2]]; \ |
|||
tv2 = T[2*(uint32_t)x[4*c6+2]+1]; \ |
|||
ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \ |
|||
tl ^= tv1; \ |
|||
tu ^= tv2; \ |
|||
tv1 = T[2*(uint32_t)x[4*c7+3]]; \ |
|||
tv2 = T[2*(uint32_t)x[4*c7+3]+1]; \ |
|||
ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \ |
|||
tl ^= tv1; \ |
|||
tu ^= tv2; \ |
|||
y[i] = tu; \ |
|||
y[i+1] = tl; |
|||
|
|||
|
|||
/* compute one round of P (short variants) */ |
|||
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* x32 = (uint32_t*)x; |
|||
x32[ 0] ^= 0x00000000^r; |
|||
x32[ 2] ^= 0x00000010^r; |
|||
x32[ 4] ^= 0x00000020^r; |
|||
x32[ 6] ^= 0x00000030^r; |
|||
x32[ 8] ^= 0x00000040^r; |
|||
x32[10] ^= 0x00000050^r; |
|||
x32[12] ^= 0x00000060^r; |
|||
x32[14] ^= 0x00000070^r; |
|||
COLUMN(x,y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y, 6, 6, 8, 10, 12, 15, 1, 3, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y, 8, 8, 10, 12, 14, 1, 3, 5, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y,10, 10, 12, 14, 0, 3, 5, 7, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y,12, 12, 14, 0, 2, 5, 7, 9, 11, 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) { |
|||
uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; |
|||
uint32_t* x32 = (uint32_t*)x; |
|||
x32[ 0] = ~x32[ 0]; |
|||
x32[ 1] ^= 0xffffffff^r; |
|||
x32[ 2] = ~x32[ 2]; |
|||
x32[ 3] ^= 0xefffffff^r; |
|||
x32[ 4] = ~x32[ 4]; |
|||
x32[ 5] ^= 0xdfffffff^r; |
|||
x32[ 6] = ~x32[ 6]; |
|||
x32[ 7] ^= 0xcfffffff^r; |
|||
x32[ 8] = ~x32[ 8]; |
|||
x32[ 9] ^= 0xbfffffff^r; |
|||
x32[10] = ~x32[10]; |
|||
x32[11] ^= 0xafffffff^r; |
|||
x32[12] = ~x32[12]; |
|||
x32[13] ^= 0x9fffffff^r; |
|||
x32[14] = ~x32[14]; |
|||
x32[15] ^= 0x8fffffff^r; |
|||
COLUMN(x,y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y, 6, 8, 12, 0, 4, 7, 11, 15, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y, 8, 10, 14, 2, 6, 9, 13, 1, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y,10, 12, 0, 4, 8, 11, 15, 3, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); |
|||
COLUMN(x,y,12, 14, 2, 6, 10, 13, 1, 5, 9, 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) { |
|||
int i; |
|||
uint32_t Ptmp[2*COLS512]; |
|||
uint32_t Qtmp[2*COLS512]; |
|||
uint32_t y[2*COLS512]; |
|||
uint32_t z[2*COLS512]; |
|||
|
|||
for (i = 0; i < 2*COLS512; i++) { |
|||
z[i] = m[i]; |
|||
Ptmp[i] = h[i]^m[i]; |
|||
} |
|||
|
|||
/* compute Q(m) */ |
|||
RND512Q((uint8_t*)z, y, 0x00000000); |
|||
RND512Q((uint8_t*)y, z, 0x01000000); |
|||
RND512Q((uint8_t*)z, y, 0x02000000); |
|||
RND512Q((uint8_t*)y, z, 0x03000000); |
|||
RND512Q((uint8_t*)z, y, 0x04000000); |
|||
RND512Q((uint8_t*)y, z, 0x05000000); |
|||
RND512Q((uint8_t*)z, y, 0x06000000); |
|||
RND512Q((uint8_t*)y, z, 0x07000000); |
|||
RND512Q((uint8_t*)z, y, 0x08000000); |
|||
RND512Q((uint8_t*)y, Qtmp, 0x09000000); |
|||
|
|||
/* compute P(h+m) */ |
|||
RND512P((uint8_t*)Ptmp, y, 0x00000000); |
|||
RND512P((uint8_t*)y, z, 0x00000001); |
|||
RND512P((uint8_t*)z, y, 0x00000002); |
|||
RND512P((uint8_t*)y, z, 0x00000003); |
|||
RND512P((uint8_t*)z, y, 0x00000004); |
|||
RND512P((uint8_t*)y, z, 0x00000005); |
|||
RND512P((uint8_t*)z, y, 0x00000006); |
|||
RND512P((uint8_t*)y, z, 0x00000007); |
|||
RND512P((uint8_t*)z, y, 0x00000008); |
|||
RND512P((uint8_t*)y, Ptmp, 0x00000009); |
|||
|
|||
/* compute P(h+m) + Q(m) + h */ |
|||
for (i = 0; i < 2*COLS512; i++) { |
|||
h[i] ^= Ptmp[i]^Qtmp[i]; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* digest up to msglen bytes of input (full blocks only) */ |
|||
static void Transform(groestlHashState *ctx, |
|||
const uint8_t *input, |
|||
int msglen) { |
|||
|
|||
/* digest message, one block at a time */ |
|||
for (; msglen >= SIZE512; |
|||
msglen -= SIZE512, input += SIZE512) { |
|||
F512(ctx->chaining,(uint32_t*)input); |
|||
|
|||
/* increment block counter */ |
|||
ctx->block_counter1++; |
|||
if (ctx->block_counter1 == 0) ctx->block_counter2++; |
|||
} |
|||
} |
|||
|
|||
/* given state h, do h <- P(h)+h */ |
|||
static void OutputTransformation(groestlHashState *ctx) { |
|||
int j; |
|||
uint32_t temp[2*COLS512]; |
|||
uint32_t y[2*COLS512]; |
|||
uint32_t z[2*COLS512]; |
|||
|
|||
|
|||
|
|||
for (j = 0; j < 2*COLS512; j++) { |
|||
temp[j] = ctx->chaining[j]; |
|||
} |
|||
RND512P((uint8_t*)temp, y, 0x00000000); |
|||
RND512P((uint8_t*)y, z, 0x00000001); |
|||
RND512P((uint8_t*)z, y, 0x00000002); |
|||
RND512P((uint8_t*)y, z, 0x00000003); |
|||
RND512P((uint8_t*)z, y, 0x00000004); |
|||
RND512P((uint8_t*)y, z, 0x00000005); |
|||
RND512P((uint8_t*)z, y, 0x00000006); |
|||
RND512P((uint8_t*)y, z, 0x00000007); |
|||
RND512P((uint8_t*)z, y, 0x00000008); |
|||
RND512P((uint8_t*)y, temp, 0x00000009); |
|||
for (j = 0; j < 2*COLS512; j++) { |
|||
ctx->chaining[j] ^= temp[j]; |
|||
} |
|||
} |
|||
|
|||
/* initialise context */ |
|||
static void Init(groestlHashState* ctx) { |
|||
int i = 0; |
|||
/* allocate memory for state and data buffer */ |
|||
|
|||
for(;i<(SIZE512/sizeof(uint32_t));i++) |
|||
{ |
|||
ctx->chaining[i] = 0; |
|||
} |
|||
|
|||
/* set initial value */ |
|||
ctx->chaining[2*COLS512-1] = u32BIG((uint32_t)HASH_BIT_LEN); |
|||
|
|||
/* set other variables */ |
|||
ctx->buf_ptr = 0; |
|||
ctx->block_counter1 = 0; |
|||
ctx->block_counter2 = 0; |
|||
ctx->bits_in_last_byte = 0; |
|||
} |
|||
|
|||
/* update state with databitlen bits of input */ |
|||
static void Update(groestlHashState* ctx, |
|||
const BitSequence* input, |
|||
DataLength databitlen) { |
|||
int index = 0; |
|||
int msglen = (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) { |
|||
while (ctx->buf_ptr < SIZE512 && index < msglen) { |
|||
ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; |
|||
} |
|||
if (ctx->buf_ptr < SIZE512) { |
|||
/* buffer still not full, return */ |
|||
if (rem) { |
|||
ctx->bits_in_last_byte = rem; |
|||
ctx->buffer[(int)ctx->buf_ptr++] = input[index]; |
|||
} |
|||
return; |
|||
} |
|||
|
|||
/* digest buffer */ |
|||
ctx->buf_ptr = 0; |
|||
Transform(ctx, ctx->buffer, SIZE512); |
|||
} |
|||
|
|||
/* digest bulk of message */ |
|||
Transform(ctx, input+index, msglen-index); |
|||
index += ((msglen-index)/SIZE512)*SIZE512; |
|||
|
|||
/* store remaining data in buffer */ |
|||
while (index < msglen) { |
|||
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) { |
|||
ctx->bits_in_last_byte = rem; |
|||
ctx->buffer[(int)ctx->buf_ptr++] = input[index]; |
|||
} |
|||
} |
|||
|
|||
#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, |
|||
BitSequence* output) { |
|||
int i, j = 0, hashbytelen = HASH_BIT_LEN/8; |
|||
uint8_t *s = (BitSequence*)ctx->chaining; |
|||
|
|||
/* pad with '1'-bit and first few '0'-bits */ |
|||
if (BILB) { |
|||
ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<<BILB)-1)<<(8-BILB); |
|||
ctx->buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-BILB); |
|||
BILB = 0; |
|||
} |
|||
else ctx->buffer[(int)ctx->buf_ptr++] = 0x80; |
|||
|
|||
/* pad with '0'-bits */ |
|||
if (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) { |
|||
/* padding requires two blocks */ |
|||
while (ctx->buf_ptr < SIZE512) { |
|||
ctx->buffer[(int)ctx->buf_ptr++] = 0; |
|||
} |
|||
/* digest first padding block */ |
|||
Transform(ctx, ctx->buffer, SIZE512); |
|||
ctx->buf_ptr = 0; |
|||
} |
|||
while (ctx->buf_ptr < SIZE512-LENGTHFIELDLEN) { |
|||
ctx->buffer[(int)ctx->buf_ptr++] = 0; |
|||
} |
|||
|
|||
/* length padding */ |
|||
ctx->block_counter1++; |
|||
if (ctx->block_counter1 == 0) ctx->block_counter2++; |
|||
ctx->buf_ptr = SIZE512; |
|||
|
|||
while (ctx->buf_ptr > SIZE512-(int)sizeof(uint32_t)) { |
|||
ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter1; |
|||
ctx->block_counter1 >>= 8; |
|||
} |
|||
while (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) { |
|||
ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2; |
|||
ctx->block_counter2 >>= 8; |
|||
} |
|||
/* digest final padding block */ |
|||
Transform(ctx, ctx->buffer, SIZE512); |
|||
/* perform output transformation */ |
|||
OutputTransformation(ctx); |
|||
|
|||
/* store hash result in output */ |
|||
for (i = SIZE512-hashbytelen; i < SIZE512; i++,j++) { |
|||
output[j] = s[i]; |
|||
} |
|||
|
|||
/* zeroise relevant variables and deallocate memory */ |
|||
for (i = 0; i < COLS512; i++) { |
|||
ctx->chaining[i] = 0; |
|||
} |
|||
for (i = 0; i < SIZE512; i++) { |
|||
ctx->buffer[i] = 0; |
|||
} |
|||
} |
|||
|
|||
/* hash bit sequence */ |
|||
void groestl(const BitSequence* data, |
|||
DataLength databitlen, |
|||
BitSequence* hashval) { |
|||
|
|||
groestlHashState context; |
|||
|
|||
/* initialise */ |
|||
Init(&context); |
|||
|
|||
|
|||
/* process message */ |
|||
Update(&context, data, databitlen); |
|||
|
|||
/* finalise */ |
|||
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; |
|||
} |
|||
|
|||
*/ |
@ -0,0 +1,60 @@ |
|||
#ifndef __hash_h |
|||
#define __hash_h |
|||
/*
|
|||
#include "crypto_uint8.h" |
|||
#include "crypto_uint32.h" |
|||
#include "crypto_uint64.h" |
|||
#include "crypto_hash.h" |
|||
|
|||
typedef crypto_uint8 uint8_t; |
|||
typedef crypto_uint32 uint32_t; |
|||
typedef crypto_uint64 uint64_t; |
|||
*/ |
|||
#include <stdint.h> |
|||
|
|||
#include "hash.h" |
|||
|
|||
/* some sizes (number of bytes) */ |
|||
#define ROWS 8 |
|||
#define LENGTHFIELDLEN ROWS |
|||
#define COLS512 8 |
|||
|
|||
#define SIZE512 (ROWS*COLS512) |
|||
|
|||
#define ROUNDS512 10 |
|||
#define HASH_BIT_LEN 256 |
|||
|
|||
#define ROTL32(v, n) ((((v)<<(n))|((v)>>(32-(n))))&li_32(ffffffff)) |
|||
|
|||
|
|||
#define li_32(h) 0x##h##u |
|||
#define EXT_BYTE(var,n) ((uint8_t)((uint32_t)(var) >> (8*n))) |
|||
#define u32BIG(a) \ |
|||
((ROTL32(a,8) & li_32(00FF00FF)) | \ |
|||
(ROTL32(a,24) & li_32(FF00FF00))) |
|||
|
|||
|
|||
/* NIST API begin */ |
|||
typedef struct { |
|||
uint32_t chaining[SIZE512/sizeof(uint32_t)]; /* actual state */ |
|||
uint32_t block_counter1, |
|||
block_counter2; /* message block counter(s) */ |
|||
BitSequence buffer[SIZE512]; /* data buffer */ |
|||
int buf_ptr; /* data buffer pointer */ |
|||
int bits_in_last_byte; /* no. of message bits in last byte of
|
|||
data buffer */ |
|||
} groestlHashState; |
|||
|
|||
/*void Init(hashState*);
|
|||
void Update(hashState*, const BitSequence*, DataLength); |
|||
void Final(hashState*, BitSequence*); */ |
|||
void groestl(const BitSequence*, DataLength, BitSequence*); |
|||
/* NIST API end */ |
|||
|
|||
/*
|
|||
int crypto_hash(unsigned char *out, |
|||
const unsigned char *in, |
|||
unsigned long long len); |
|||
*/ |
|||
|
|||
#endif /* __hash_h */ |
@ -0,0 +1,367 @@ |
|||
/*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 <stdint.h> |
|||
#include <string.h> |
|||
|
|||
/*typedef unsigned long long uint64;*/ |
|||
typedef uint64_t uint64; |
|||
|
|||
/*define data alignment for different C compilers*/ |
|||
#if defined(__GNUC__) |
|||
#define DATA_ALIGN16(x) x __attribute__ ((aligned(16))) |
|||
#else |
|||
#define DATA_ALIGN16(x) __declspec(align(16)) x |
|||
#endif |
|||
|
|||
|
|||
typedef struct { |
|||
int hashbitlen; /*the message digest size*/ |
|||
unsigned long long databitlen; /*the message size in bits*/ |
|||
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*/ |
|||
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*/ |
|||
unsigned char buffer[64]; /*the 512-bit message block to be hashed;*/ |
|||
} 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 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 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]={ |
|||
{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}, |
|||
{0x3,0xa3,0x5a,0x5c,0x9a,0x19,0xe,0xdb,0x40,0x3f,0xb2,0xa,0x87,0xc1,0x44,0x10,0x1c,0x5,0x19,0x80,0x84,0x9e,0x95,0x1d,0x6f,0x33,0xeb,0xad,0x5e,0xe7,0xcd,0xdc}, |
|||
{0x10,0xba,0x13,0x92,0x2,0xbf,0x6b,0x41,0xdc,0x78,0x65,0x15,0xf7,0xbb,0x27,0xd0,0xa,0x2c,0x81,0x39,0x37,0xaa,0x78,0x50,0x3f,0x1a,0xbf,0xd2,0x41,0x0,0x91,0xd3}, |
|||
{0x42,0x2d,0x5a,0xd,0xf6,0xcc,0x7e,0x90,0xdd,0x62,0x9f,0x9c,0x92,0xc0,0x97,0xce,0x18,0x5c,0xa7,0xb,0xc7,0x2b,0x44,0xac,0xd1,0xdf,0x65,0xd6,0x63,0xc6,0xfc,0x23}, |
|||
{0x97,0x6e,0x6c,0x3,0x9e,0xe0,0xb8,0x1a,0x21,0x5,0x45,0x7e,0x44,0x6c,0xec,0xa8,0xee,0xf1,0x3,0xbb,0x5d,0x8e,0x61,0xfa,0xfd,0x96,0x97,0xb2,0x94,0x83,0x81,0x97}, |
|||
{0x4a,0x8e,0x85,0x37,0xdb,0x3,0x30,0x2f,0x2a,0x67,0x8d,0x2d,0xfb,0x9f,0x6a,0x95,0x8a,0xfe,0x73,0x81,0xf8,0xb8,0x69,0x6c,0x8a,0xc7,0x72,0x46,0xc0,0x7f,0x42,0x14}, |
|||
{0xc5,0xf4,0x15,0x8f,0xbd,0xc7,0x5e,0xc4,0x75,0x44,0x6f,0xa7,0x8f,0x11,0xbb,0x80,0x52,0xde,0x75,0xb7,0xae,0xe4,0x88,0xbc,0x82,0xb8,0x0,0x1e,0x98,0xa6,0xa3,0xf4}, |
|||
{0x8e,0xf4,0x8f,0x33,0xa9,0xa3,0x63,0x15,0xaa,0x5f,0x56,0x24,0xd5,0xb7,0xf9,0x89,0xb6,0xf1,0xed,0x20,0x7c,0x5a,0xe0,0xfd,0x36,0xca,0xe9,0x5a,0x6,0x42,0x2c,0x36}, |
|||
{0xce,0x29,0x35,0x43,0x4e,0xfe,0x98,0x3d,0x53,0x3a,0xf9,0x74,0x73,0x9a,0x4b,0xa7,0xd0,0xf5,0x1f,0x59,0x6f,0x4e,0x81,0x86,0xe,0x9d,0xad,0x81,0xaf,0xd8,0x5a,0x9f}, |
|||
{0xa7,0x5,0x6,0x67,0xee,0x34,0x62,0x6a,0x8b,0xb,0x28,0xbe,0x6e,0xb9,0x17,0x27,0x47,0x74,0x7,0x26,0xc6,0x80,0x10,0x3f,0xe0,0xa0,0x7e,0x6f,0xc6,0x7e,0x48,0x7b}, |
|||
{0xd,0x55,0xa,0xa5,0x4a,0xf8,0xa4,0xc0,0x91,0xe3,0xe7,0x9f,0x97,0x8e,0xf1,0x9e,0x86,0x76,0x72,0x81,0x50,0x60,0x8d,0xd4,0x7e,0x9e,0x5a,0x41,0xf3,0xe5,0xb0,0x62}, |
|||
{0xfc,0x9f,0x1f,0xec,0x40,0x54,0x20,0x7a,0xe3,0xe4,0x1a,0x0,0xce,0xf4,0xc9,0x84,0x4f,0xd7,0x94,0xf5,0x9d,0xfa,0x95,0xd8,0x55,0x2e,0x7e,0x11,0x24,0xc3,0x54,0xa5}, |
|||
{0x5b,0xdf,0x72,0x28,0xbd,0xfe,0x6e,0x28,0x78,0xf5,0x7f,0xe2,0xf,0xa5,0xc4,0xb2,0x5,0x89,0x7c,0xef,0xee,0x49,0xd3,0x2e,0x44,0x7e,0x93,0x85,0xeb,0x28,0x59,0x7f}, |
|||
{0x70,0x5f,0x69,0x37,0xb3,0x24,0x31,0x4a,0x5e,0x86,0x28,0xf1,0x1d,0xd6,0xe4,0x65,0xc7,0x1b,0x77,0x4,0x51,0xb9,0x20,0xe7,0x74,0xfe,0x43,0xe8,0x23,0xd4,0x87,0x8a}, |
|||
{0x7d,0x29,0xe8,0xa3,0x92,0x76,0x94,0xf2,0xdd,0xcb,0x7a,0x9,0x9b,0x30,0xd9,0xc1,0x1d,0x1b,0x30,0xfb,0x5b,0xdc,0x1b,0xe0,0xda,0x24,0x49,0x4f,0xf2,0x9c,0x82,0xbf}, |
|||
{0xa4,0xe7,0xba,0x31,0xb4,0x70,0xbf,0xff,0xd,0x32,0x44,0x5,0xde,0xf8,0xbc,0x48,0x3b,0xae,0xfc,0x32,0x53,0xbb,0xd3,0x39,0x45,0x9f,0xc3,0xc1,0xe0,0x29,0x8b,0xa0}, |
|||
{0xe5,0xc9,0x5,0xfd,0xf7,0xae,0x9,0xf,0x94,0x70,0x34,0x12,0x42,0x90,0xf1,0x34,0xa2,0x71,0xb7,0x1,0xe3,0x44,0xed,0x95,0xe9,0x3b,0x8e,0x36,0x4f,0x2f,0x98,0x4a}, |
|||
{0x88,0x40,0x1d,0x63,0xa0,0x6c,0xf6,0x15,0x47,0xc1,0x44,0x4b,0x87,0x52,0xaf,0xff,0x7e,0xbb,0x4a,0xf1,0xe2,0xa,0xc6,0x30,0x46,0x70,0xb6,0xc5,0xcc,0x6e,0x8c,0xe6}, |
|||
{0xa4,0xd5,0xa4,0x56,0xbd,0x4f,0xca,0x0,0xda,0x9d,0x84,0x4b,0xc8,0x3e,0x18,0xae,0x73,0x57,0xce,0x45,0x30,0x64,0xd1,0xad,0xe8,0xa6,0xce,0x68,0x14,0x5c,0x25,0x67}, |
|||
{0xa3,0xda,0x8c,0xf2,0xcb,0xe,0xe1,0x16,0x33,0xe9,0x6,0x58,0x9a,0x94,0x99,0x9a,0x1f,0x60,0xb2,0x20,0xc2,0x6f,0x84,0x7b,0xd1,0xce,0xac,0x7f,0xa0,0xd1,0x85,0x18}, |
|||
{0x32,0x59,0x5b,0xa1,0x8d,0xdd,0x19,0xd3,0x50,0x9a,0x1c,0xc0,0xaa,0xa5,0xb4,0x46,0x9f,0x3d,0x63,0x67,0xe4,0x4,0x6b,0xba,0xf6,0xca,0x19,0xab,0xb,0x56,0xee,0x7e}, |
|||
{0x1f,0xb1,0x79,0xea,0xa9,0x28,0x21,0x74,0xe9,0xbd,0xf7,0x35,0x3b,0x36,0x51,0xee,0x1d,0x57,0xac,0x5a,0x75,0x50,0xd3,0x76,0x3a,0x46,0xc2,0xfe,0xa3,0x7d,0x70,0x1}, |
|||
{0xf7,0x35,0xc1,0xaf,0x98,0xa4,0xd8,0x42,0x78,0xed,0xec,0x20,0x9e,0x6b,0x67,0x79,0x41,0x83,0x63,0x15,0xea,0x3a,0xdb,0xa8,0xfa,0xc3,0x3b,0x4d,0x32,0x83,0x2c,0x83}, |
|||
{0xa7,0x40,0x3b,0x1f,0x1c,0x27,0x47,0xf3,0x59,0x40,0xf0,0x34,0xb7,0x2d,0x76,0x9a,0xe7,0x3e,0x4e,0x6c,0xd2,0x21,0x4f,0xfd,0xb8,0xfd,0x8d,0x39,0xdc,0x57,0x59,0xef}, |
|||
{0x8d,0x9b,0xc,0x49,0x2b,0x49,0xeb,0xda,0x5b,0xa2,0xd7,0x49,0x68,0xf3,0x70,0xd,0x7d,0x3b,0xae,0xd0,0x7a,0x8d,0x55,0x84,0xf5,0xa5,0xe9,0xf0,0xe4,0xf8,0x8e,0x65}, |
|||
{0xa0,0xb8,0xa2,0xf4,0x36,0x10,0x3b,0x53,0xc,0xa8,0x7,0x9e,0x75,0x3e,0xec,0x5a,0x91,0x68,0x94,0x92,0x56,0xe8,0x88,0x4f,0x5b,0xb0,0x5c,0x55,0xf8,0xba,0xbc,0x4c}, |
|||
{0xe3,0xbb,0x3b,0x99,0xf3,0x87,0x94,0x7b,0x75,0xda,0xf4,0xd6,0x72,0x6b,0x1c,0x5d,0x64,0xae,0xac,0x28,0xdc,0x34,0xb3,0x6d,0x6c,0x34,0xa5,0x50,0xb8,0x28,0xdb,0x71}, |
|||
{0xf8,0x61,0xe2,0xf2,0x10,0x8d,0x51,0x2a,0xe3,0xdb,0x64,0x33,0x59,0xdd,0x75,0xfc,0x1c,0xac,0xbc,0xf1,0x43,0xce,0x3f,0xa2,0x67,0xbb,0xd1,0x3c,0x2,0xe8,0x43,0xb0}, |
|||
{0x33,0xa,0x5b,0xca,0x88,0x29,0xa1,0x75,0x7f,0x34,0x19,0x4d,0xb4,0x16,0x53,0x5c,0x92,0x3b,0x94,0xc3,0xe,0x79,0x4d,0x1e,0x79,0x74,0x75,0xd7,0xb6,0xee,0xaf,0x3f}, |
|||
{0xea,0xa8,0xd4,0xf7,0xbe,0x1a,0x39,0x21,0x5c,0xf4,0x7e,0x9,0x4c,0x23,0x27,0x51,0x26,0xa3,0x24,0x53,0xba,0x32,0x3c,0xd2,0x44,0xa3,0x17,0x4a,0x6d,0xa6,0xd5,0xad}, |
|||
{0xb5,0x1d,0x3e,0xa6,0xaf,0xf2,0xc9,0x8,0x83,0x59,0x3d,0x98,0x91,0x6b,0x3c,0x56,0x4c,0xf8,0x7c,0xa1,0x72,0x86,0x60,0x4d,0x46,0xe2,0x3e,0xcc,0x8,0x6e,0xc7,0xf6}, |
|||
{0x2f,0x98,0x33,0xb3,0xb1,0xbc,0x76,0x5e,0x2b,0xd6,0x66,0xa5,0xef,0xc4,0xe6,0x2a,0x6,0xf4,0xb6,0xe8,0xbe,0xc1,0xd4,0x36,0x74,0xee,0x82,0x15,0xbc,0xef,0x21,0x63}, |
|||
{0xfd,0xc1,0x4e,0xd,0xf4,0x53,0xc9,0x69,0xa7,0x7d,0x5a,0xc4,0x6,0x58,0x58,0x26,0x7e,0xc1,0x14,0x16,0x6,0xe0,0xfa,0x16,0x7e,0x90,0xaf,0x3d,0x28,0x63,0x9d,0x3f}, |
|||
{0xd2,0xc9,0xf2,0xe3,0x0,0x9b,0xd2,0xc,0x5f,0xaa,0xce,0x30,0xb7,0xd4,0xc,0x30,0x74,0x2a,0x51,0x16,0xf2,0xe0,0x32,0x98,0xd,0xeb,0x30,0xd8,0xe3,0xce,0xf8,0x9a}, |
|||
{0x4b,0xc5,0x9e,0x7b,0xb5,0xf1,0x79,0x92,0xff,0x51,0xe6,0x6e,0x4,0x86,0x68,0xd3,0x9b,0x23,0x4d,0x57,0xe6,0x96,0x67,0x31,0xcc,0xe6,0xa6,0xf3,0x17,0xa,0x75,0x5}, |
|||
{0xb1,0x76,0x81,0xd9,0x13,0x32,0x6c,0xce,0x3c,0x17,0x52,0x84,0xf8,0x5,0xa2,0x62,0xf4,0x2b,0xcb,0xb3,0x78,0x47,0x15,0x47,0xff,0x46,0x54,0x82,0x23,0x93,0x6a,0x48}, |
|||
{0x38,0xdf,0x58,0x7,0x4e,0x5e,0x65,0x65,0xf2,0xfc,0x7c,0x89,0xfc,0x86,0x50,0x8e,0x31,0x70,0x2e,0x44,0xd0,0xb,0xca,0x86,0xf0,0x40,0x9,0xa2,0x30,0x78,0x47,0x4e}, |
|||
{0x65,0xa0,0xee,0x39,0xd1,0xf7,0x38,0x83,0xf7,0x5e,0xe9,0x37,0xe4,0x2c,0x3a,0xbd,0x21,0x97,0xb2,0x26,0x1,0x13,0xf8,0x6f,0xa3,0x44,0xed,0xd1,0xef,0x9f,0xde,0xe7}, |
|||
{0x8b,0xa0,0xdf,0x15,0x76,0x25,0x92,0xd9,0x3c,0x85,0xf7,0xf6,0x12,0xdc,0x42,0xbe,0xd8,0xa7,0xec,0x7c,0xab,0x27,0xb0,0x7e,0x53,0x8d,0x7d,0xda,0xaa,0x3e,0xa8,0xde}, |
|||
{0xaa,0x25,0xce,0x93,0xbd,0x2,0x69,0xd8,0x5a,0xf6,0x43,0xfd,0x1a,0x73,0x8,0xf9,0xc0,0x5f,0xef,0xda,0x17,0x4a,0x19,0xa5,0x97,0x4d,0x66,0x33,0x4c,0xfd,0x21,0x6a}, |
|||
{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 F8(hashState *state); /*The compression function F8 */ |
|||
|
|||
/*The API functions*/ |
|||
static HashReturn Init(hashState *state, int hashbitlen); |
|||
static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen); |
|||
static HashReturn Final(hashState *state, 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)); |
|||
/*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)); |
|||
/*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)); |
|||
/*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)); |
|||
/*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)); |
|||
/*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)); |
|||
|
|||
/*The MDS transform*/ |
|||
#define L(m0,m1,m2,m3,m4,m5,m6,m7) \ |
|||
(m4) ^= (m1); \ |
|||
(m5) ^= (m2); \ |
|||
(m6) ^= (m0) ^ (m3); \ |
|||
(m7) ^= (m0); \ |
|||
(m0) ^= (m5); \ |
|||
(m1) ^= (m6); \ |
|||
(m2) ^= (m4) ^ (m7); \ |
|||
(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) \ |
|||
m3 = ~(m3); \ |
|||
m7 = ~(m7); \ |
|||
m0 ^= ((~(m2)) & (cc0)); \ |
|||
m4 ^= ((~(m6)) & (cc1)); \ |
|||
temp0 = (cc0) ^ ((m0) & (m1));\ |
|||
temp1 = (cc1) ^ ((m4) & (m5));\ |
|||
m0 ^= ((m2) & (m3)); \ |
|||
m4 ^= ((m6) & (m7)); \ |
|||
m3 ^= ((~(m1)) & (m2)); \ |
|||
m7 ^= ((~(m5)) & (m6)); \ |
|||
m1 ^= ((m0) & (m2)); \ |
|||
m5 ^= ((m4) & (m6)); \ |
|||
m2 ^= ((m0) & (~(m3))); \ |
|||
m6 ^= ((m4) & (~(m7))); \ |
|||
m0 ^= ((m1) | (m3)); \ |
|||
m4 ^= ((m5) | (m7)); \ |
|||
m3 ^= ((m1) & (m2)); \ |
|||
m7 ^= ((m5) & (m6)); \ |
|||
m1 ^= (temp0 & (m0)); \ |
|||
m5 ^= (temp1 & (m4)); \ |
|||
m2 ^= temp0; \ |
|||
m6 ^= temp1; |
|||
|
|||
/*The bijective function E8, in bitslice form*/ |
|||
static void E8(hashState *state) |
|||
{ |
|||
uint64 i,roundnumber,temp0,temp1; |
|||
|
|||
for (roundnumber = 0; roundnumber < 42; roundnumber = roundnumber+7) { |
|||
/*round 7*roundnumber+0: Sbox, MDS and Swapping layers*/ |
|||
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] ); |
|||
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]); |
|||
} |
|||
|
|||
/*round 7*roundnumber+1: Sbox, MDS and Swapping layers*/ |
|||
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] ); |
|||
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]); |
|||
} |
|||
|
|||
/*round 7*roundnumber+2: Sbox, MDS and Swapping layers*/ |
|||
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] ); |
|||
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]); |
|||
} |
|||
|
|||
/*round 7*roundnumber+3: Sbox, MDS and Swapping layers*/ |
|||
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] ); |
|||
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]); |
|||
} |
|||
|
|||
/*round 7*roundnumber+4: Sbox, MDS and Swapping layers*/ |
|||
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] ); |
|||
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]); |
|||
} |
|||
|
|||
/*round 7*roundnumber+5: Sbox, MDS and Swapping layers*/ |
|||
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] ); |
|||
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]); |
|||
} |
|||
|
|||
/*round 7*roundnumber+6: Sbox and MDS layers*/ |
|||
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] ); |
|||
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) { |
|||
temp0 = state->x[i][0]; state->x[i][0] = state->x[i][1]; state->x[i][1] = temp0; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
/*The compression function F8 */ |
|||
static void F8(hashState *state) |
|||
{ |
|||
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]; |
|||
|
|||
/*the bijective function E8 */ |
|||
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]; |
|||
} |
|||
|
|||
/*before hashing a message, initialize the hash state as H0 */ |
|||
static HashReturn Init(hashState *state, int hashbitlen) |
|||
{ |
|||
state->databitlen = 0; |
|||
state->datasize_in_buffer = 0; |
|||
|
|||
/*initialize the initial hash value of JH*/ |
|||
state->hashbitlen = hashbitlen; |
|||
|
|||
/*load the intital hash value into state*/ |
|||
switch (hashbitlen) |
|||
{ |
|||
case 224: memcpy(state->x,JH224_H0,128); break; |
|||
case 256: memcpy(state->x,JH256_H0,128); break; |
|||
case 384: memcpy(state->x,JH384_H0,128); break; |
|||
case 512: memcpy(state->x,JH512_H0,128); break; |
|||
} |
|||
|
|||
return(SUCCESS); |
|||
} |
|||
|
|||
|
|||
/*hash each 512-bit message block, except the last partial block*/ |
|||
static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) |
|||
{ |
|||
DataLength index; /*the starting address of the data to be compressed*/ |
|||
|
|||
state->databitlen += databitlen; |
|||
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 ( (databitlen & 7) == 0 ) { |
|||
memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)) ; |
|||
} |
|||
else memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)+1) ; |
|||
state->datasize_in_buffer += databitlen; |
|||
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) ) { |
|||
memcpy( state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3) ) ; |
|||
index = 64-(state->datasize_in_buffer >> 3); |
|||
databitlen = databitlen - (512 - state->datasize_in_buffer); |
|||
F8(state); |
|||
state->datasize_in_buffer = 0; |
|||
} |
|||
|
|||
/*hash the remaining full message blocks*/ |
|||
for ( ; databitlen >= 512; index = index+64, databitlen = databitlen - 512) { |
|||
memcpy(state->buffer, data+index, 64); |
|||
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 & 7) == 0) |
|||
memcpy(state->buffer, data+index, (databitlen & 0x1ff) >> 3); |
|||
else |
|||
memcpy(state->buffer, data+index, ((databitlen & 0x1ff) >> 3)+1); |
|||
state->datasize_in_buffer = databitlen; |
|||
} |
|||
|
|||
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) |
|||
{ |
|||
unsigned int i; |
|||
|
|||
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); |
|||
state->buffer[0] = 0x80; |
|||
state->buffer[63] = state->databitlen & 0xff; |
|||
state->buffer[62] = (state->databitlen >> 8) & 0xff; |
|||
state->buffer[61] = (state->databitlen >> 16) & 0xff; |
|||
state->buffer[60] = (state->databitlen >> 24) & 0xff; |
|||
state->buffer[59] = (state->databitlen >> 32) & 0xff; |
|||
state->buffer[58] = (state->databitlen >> 40) & 0xff; |
|||
state->buffer[57] = (state->databitlen >> 48) & 0xff; |
|||
state->buffer[56] = (state->databitlen >> 56) & 0xff; |
|||
F8(state); |
|||
} |
|||
else { |
|||
/*set the rest of the bytes in the buffer to 0*/ |
|||
if ( (state->datasize_in_buffer & 7) == 0) |
|||
for (i = (state->databitlen & 0x1ff) >> 3; i < 64; i++) state->buffer[i] = 0; |
|||
else |
|||
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)); |
|||
|
|||
F8(state); |
|||
memset(state->buffer, 0, 64); |
|||
state->buffer[63] = state->databitlen & 0xff; |
|||
state->buffer[62] = (state->databitlen >> 8) & 0xff; |
|||
state->buffer[61] = (state->databitlen >> 16) & 0xff; |
|||
state->buffer[60] = (state->databitlen >> 24) & 0xff; |
|||
state->buffer[59] = (state->databitlen >> 32) & 0xff; |
|||
state->buffer[58] = (state->databitlen >> 40) & 0xff; |
|||
state->buffer[57] = (state->databitlen >> 48) & 0xff; |
|||
state->buffer[56] = (state->databitlen >> 56) & 0xff; |
|||
F8(state); |
|||
} |
|||
|
|||
/*truncating the final hash value to generate the message digest*/ |
|||
switch(state->hashbitlen) { |
|||
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 384: memcpy(hashval,(unsigned char*)state->x+64+16,48); break; |
|||
case 512: memcpy(hashval,(unsigned char*)state->x+64,64); break; |
|||
} |
|||
|
|||
return(SUCCESS); |
|||
} |
|||
|
|||
/* hash a message,
|
|||
three inputs: message digest size in bits (hashbitlen); message (data); message length in bits (databitlen) |
|||
one output: message digest (hashval) |
|||
*/ |
|||
HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval) |
|||
{ |
|||
hashState state; |
|||
|
|||
if ( hashbitlen == 224 || hashbitlen == 256 || hashbitlen == 384 || hashbitlen == 512 ) { |
|||
Init(&state, hashbitlen); |
|||
Update(&state, data, databitlen); |
|||
Final(&state, hashval); |
|||
return SUCCESS; |
|||
} |
|||
else |
|||
return(BAD_HASHLEN); |
|||
} |
@ -0,0 +1,19 @@ |
|||
/*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 |
|||
|
|||
#include "hash.h" |
|||
|
|||
HashReturn jh_hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval); |
@ -0,0 +1,123 @@ |
|||
// keccak.c
|
|||
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
|
|||
// A baseline Keccak (3rd round) implementation.
|
|||
|
|||
#include <stdint.h> |
|||
#include <string.h> |
|||
|
|||
#define HASH_DATA_AREA 136 |
|||
#define KECCAK_ROUNDS 24 |
|||
|
|||
#ifndef ROTL64 |
|||
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) |
|||
#endif |
|||
|
|||
const uint64_t keccakf_rndc[24] = |
|||
{ |
|||
0x0000000000000001, 0x0000000000008082, 0x800000000000808a, |
|||
0x8000000080008000, 0x000000000000808b, 0x0000000080000001, |
|||
0x8000000080008081, 0x8000000000008009, 0x000000000000008a, |
|||
0x0000000000000088, 0x0000000080008009, 0x000000008000000a, |
|||
0x000000008000808b, 0x800000000000008b, 0x8000000000008089, |
|||
0x8000000000008003, 0x8000000000008002, 0x8000000000000080, |
|||
0x000000000000800a, 0x800000008000000a, 0x8000000080008081, |
|||
0x8000000000008080, 0x0000000080000001, 0x8000000080008008 |
|||
}; |
|||
|
|||
const int keccakf_rotc[24] = |
|||
{ |
|||
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, |
|||
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 |
|||
}; |
|||
|
|||
const int keccakf_piln[24] = |
|||
{ |
|||
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, |
|||
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 |
|||
}; |
|||
|
|||
// update the state with given number of rounds
|
|||
|
|||
void keccakf(uint64_t st[25], int rounds) |
|||
{ |
|||
int i, j, round; |
|||
uint64_t t, bc[5]; |
|||
|
|||
for (round = 0; round < rounds; ++round) { |
|||
|
|||
// Theta
|
|||
bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20]; |
|||
bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21]; |
|||
bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22]; |
|||
bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23]; |
|||
bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24]; |
|||
|
|||
for (i = 0; i < 5; ++i) { |
|||
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); |
|||
st[i ] ^= t; |
|||
st[i + 5] ^= t; |
|||
st[i + 10] ^= t; |
|||
st[i + 15] ^= t; |
|||
st[i + 20] ^= t; |
|||
} |
|||
|
|||
// Rho Pi
|
|||
t = st[1]; |
|||
for (i = 0; i < 24; ++i) { |
|||
bc[0] = st[keccakf_piln[i]]; |
|||
st[keccakf_piln[i]] = ROTL64(t, keccakf_rotc[i]); |
|||
t = bc[0]; |
|||
} |
|||
|
|||
// Chi
|
|||
for (j = 0; j < 25; j += 5) { |
|||
bc[0] = st[j ]; |
|||
bc[1] = st[j + 1]; |
|||
bc[2] = st[j + 2]; |
|||
bc[3] = st[j + 3]; |
|||
bc[4] = st[j + 4]; |
|||
st[j ] ^= (~bc[1]) & bc[2]; |
|||
st[j + 1] ^= (~bc[2]) & bc[3]; |
|||
st[j + 2] ^= (~bc[3]) & bc[4]; |
|||
st[j + 3] ^= (~bc[4]) & bc[0]; |
|||
st[j + 4] ^= (~bc[0]) & bc[1]; |
|||
} |
|||
|
|||
// Iota
|
|||
st[0] ^= keccakf_rndc[round]; |
|||
} |
|||
} |
|||
|
|||
// compute a keccak hash (md) of given byte length from "in"
|
|||
typedef uint64_t state_t[25]; |
|||
|
|||
void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen) |
|||
{ |
|||
state_t st; |
|||
uint8_t temp[144]; |
|||
int i, rsiz, rsizw; |
|||
|
|||
rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen; |
|||
rsizw = rsiz / 8; |
|||
|
|||
memset(st, 0, sizeof(st)); |
|||
|
|||
for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) { |
|||
for (i = 0; i < rsizw; i++) |
|||
st[i] ^= ((uint64_t *) in)[i]; |
|||
keccakf(st, KECCAK_ROUNDS); |
|||
} |
|||
|
|||
// last block and padding
|
|||
memcpy(temp, in, inlen); |
|||
temp[inlen++] = 1; |
|||
memset(temp + inlen, 0, rsiz - inlen); |
|||
temp[rsiz - 1] |= 0x80; |
|||
|
|||
for (i = 0; i < rsizw; i++) |
|||
st[i] ^= ((uint64_t *) temp)[i]; |
|||
|
|||
keccakf(st, KECCAK_ROUNDS); |
|||
|
|||
memcpy(md, st, mdlen); |
|||
} |
@ -0,0 +1,26 @@ |
|||
// keccak.h
|
|||
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
|
|||
|
|||
#ifndef KECCAK_H |
|||
#define KECCAK_H |
|||
|
|||
#include <stdint.h> |
|||
#include <string.h> |
|||
|
|||
#ifndef KECCAK_ROUNDS |
|||
#define KECCAK_ROUNDS 24 |
|||
#endif |
|||
|
|||
#ifndef ROTL64 |
|||
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) |
|||
#endif |
|||
|
|||
// compute a keccak hash (md) of given byte length from "in"
|
|||
int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen); |
|||
|
|||
// update the state
|
|||
void keccakf(uint64_t st[25], int norounds); |
|||
|
|||
void keccak1600(const uint8_t *in, int inlen, uint8_t *md); |
|||
|
|||
#endif |
File diff suppressed because it is too large
@ -0,0 +1,47 @@ |
|||
#ifndef _SKEIN_H_ |
|||
#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 */ |
|||
|
|||
typedef enum |
|||
{ |
|||
SKEIN_SUCCESS = 0, /* return codes from Skein calls */ |
|||
SKEIN_FAIL = 1, |
|||
SKEIN_BAD_HASHLEN = 2 |
|||
} |
|||
SkeinHashReturn; |
|||
|
|||
typedef size_t SkeinDataLength; /* bit count type */ |
|||
typedef u08b_t SkeinBitSequence; /* bit stream type */ |
|||
|
|||
/* "all-in-one" call */ |
|||
SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data, |
|||
SkeinDataLength databitlen, SkeinBitSequence *hashval); |
|||
|
|||
#endif /* ifndef _SKEIN_H_ */ |
@ -0,0 +1,38 @@ |
|||
#ifndef __tables_h |
|||
#define __tables_h |
|||
|
|||
|
|||
const uint32_t T[512] = {0xa5f432c6, 0xc6a597f4, 0x84976ff8, 0xf884eb97, 0x99b05eee, 0xee99c7b0, 0x8d8c7af6, 0xf68df78c, 0xd17e8ff, 0xff0de517, 0xbddc0ad6, 0xd6bdb7dc, 0xb1c816de, 0xdeb1a7c8, 0x54fc6d91, 0x915439fc |
|||
, 0x50f09060, 0x6050c0f0, 0x3050702, 0x2030405, 0xa9e02ece, 0xcea987e0, 0x7d87d156, 0x567dac87, 0x192bcce7, 0xe719d52b, 0x62a613b5, 0xb56271a6, 0xe6317c4d, 0x4de69a31, 0x9ab559ec, 0xec9ac3b5 |
|||
, 0x45cf408f, 0x8f4505cf, 0x9dbca31f, 0x1f9d3ebc, 0x40c04989, 0x894009c0, 0x879268fa, 0xfa87ef92, 0x153fd0ef, 0xef15c53f, 0xeb2694b2, 0xb2eb7f26, 0xc940ce8e, 0x8ec90740, 0xb1de6fb, 0xfb0bed1d |
|||
, 0xec2f6e41, 0x41ec822f, 0x67a91ab3, 0xb3677da9, 0xfd1c435f, 0x5ffdbe1c, 0xea256045, 0x45ea8a25, 0xbfdaf923, 0x23bf46da, 0xf7025153, 0x53f7a602, 0x96a145e4, 0xe496d3a1, 0x5bed769b, 0x9b5b2ded |
|||
, 0xc25d2875, 0x75c2ea5d, 0x1c24c5e1, 0xe11cd924, 0xaee9d43d, 0x3dae7ae9, 0x6abef24c, 0x4c6a98be, 0x5aee826c, 0x6c5ad8ee, 0x41c3bd7e, 0x7e41fcc3, 0x206f3f5, 0xf502f106, 0x4fd15283, 0x834f1dd1 |
|||
, 0x5ce48c68, 0x685cd0e4, 0xf4075651, 0x51f4a207, 0x345c8dd1, 0xd134b95c, 0x818e1f9, 0xf908e918, 0x93ae4ce2, 0xe293dfae, 0x73953eab, 0xab734d95, 0x53f59762, 0x6253c4f5, 0x3f416b2a, 0x2a3f5441 |
|||
, 0xc141c08, 0x80c1014, 0x52f66395, 0x955231f6, 0x65afe946, 0x46658caf, 0x5ee27f9d, 0x9d5e21e2, 0x28784830, 0x30286078, 0xa1f8cf37, 0x37a16ef8, 0xf111b0a, 0xa0f1411, 0xb5c4eb2f, 0x2fb55ec4 |
|||
, 0x91b150e, 0xe091c1b, 0x365a7e24, 0x2436485a, 0x9bb6ad1b, 0x1b9b36b6, 0x3d4798df, 0xdf3da547, 0x266aa7cd, 0xcd26816a, 0x69bbf54e, 0x4e699cbb, 0xcd4c337f, 0x7fcdfe4c, 0x9fba50ea, 0xea9fcfba |
|||
, 0x1b2d3f12, 0x121b242d, 0x9eb9a41d, 0x1d9e3ab9, 0x749cc458, 0x5874b09c, 0x2e724634, 0x342e6872, 0x2d774136, 0x362d6c77, 0xb2cd11dc, 0xdcb2a3cd, 0xee299db4, 0xb4ee7329, 0xfb164d5b, 0x5bfbb616 |
|||
, 0xf601a5a4, 0xa4f65301, 0x4dd7a176, 0x764decd7, 0x61a314b7, 0xb76175a3, 0xce49347d, 0x7dcefa49, 0x7b8ddf52, 0x527ba48d, 0x3e429fdd, 0xdd3ea142, 0x7193cd5e, 0x5e71bc93, 0x97a2b113, 0x139726a2 |
|||
, 0xf504a2a6, 0xa6f55704, 0x68b801b9, 0xb96869b8, 0x0, 0x0, 0x2c74b5c1, 0xc12c9974, 0x60a0e040, 0x406080a0, 0x1f21c2e3, 0xe31fdd21, 0xc8433a79, 0x79c8f243, 0xed2c9ab6, 0xb6ed772c |
|||
, 0xbed90dd4, 0xd4beb3d9, 0x46ca478d, 0x8d4601ca, 0xd9701767, 0x67d9ce70, 0x4bddaf72, 0x724be4dd, 0xde79ed94, 0x94de3379, 0xd467ff98, 0x98d42b67, 0xe82393b0, 0xb0e87b23, 0x4ade5b85, 0x854a11de |
|||
, 0x6bbd06bb, 0xbb6b6dbd, 0x2a7ebbc5, 0xc52a917e, 0xe5347b4f, 0x4fe59e34, 0x163ad7ed, 0xed16c13a, 0xc554d286, 0x86c51754, 0xd762f89a, 0x9ad72f62, 0x55ff9966, 0x6655ccff, 0x94a7b611, 0x119422a7 |
|||
, 0xcf4ac08a, 0x8acf0f4a, 0x1030d9e9, 0xe910c930, 0x60a0e04, 0x406080a, 0x819866fe, 0xfe81e798, 0xf00baba0, 0xa0f05b0b, 0x44ccb478, 0x7844f0cc, 0xbad5f025, 0x25ba4ad5, 0xe33e754b, 0x4be3963e |
|||
, 0xf30eaca2, 0xa2f35f0e, 0xfe19445d, 0x5dfeba19, 0xc05bdb80, 0x80c01b5b, 0x8a858005, 0x58a0a85, 0xadecd33f, 0x3fad7eec, 0xbcdffe21, 0x21bc42df, 0x48d8a870, 0x7048e0d8, 0x40cfdf1, 0xf104f90c |
|||
, 0xdf7a1963, 0x63dfc67a, 0xc1582f77, 0x77c1ee58, 0x759f30af, 0xaf75459f, 0x63a5e742, 0x426384a5, 0x30507020, 0x20304050, 0x1a2ecbe5, 0xe51ad12e, 0xe12effd, 0xfd0ee112, 0x6db708bf, 0xbf6d65b7 |
|||
, 0x4cd45581, 0x814c19d4, 0x143c2418, 0x1814303c, 0x355f7926, 0x26354c5f, 0x2f71b2c3, 0xc32f9d71, 0xe13886be, 0xbee16738, 0xa2fdc835, 0x35a26afd, 0xcc4fc788, 0x88cc0b4f, 0x394b652e, 0x2e395c4b |
|||
, 0x57f96a93, 0x93573df9, 0xf20d5855, 0x55f2aa0d, 0x829d61fc, 0xfc82e39d, 0x47c9b37a, 0x7a47f4c9, 0xacef27c8, 0xc8ac8bef, 0xe73288ba, 0xbae76f32, 0x2b7d4f32, 0x322b647d, 0x95a442e6, 0xe695d7a4 |
|||
, 0xa0fb3bc0, 0xc0a09bfb, 0x98b3aa19, 0x199832b3, 0xd168f69e, 0x9ed12768, 0x7f8122a3, 0xa37f5d81, 0x66aaee44, 0x446688aa, 0x7e82d654, 0x547ea882, 0xabe6dd3b, 0x3bab76e6, 0x839e950b, 0xb83169e |
|||
, 0xca45c98c, 0x8cca0345, 0x297bbcc7, 0xc729957b, 0xd36e056b, 0x6bd3d66e, 0x3c446c28, 0x283c5044, 0x798b2ca7, 0xa779558b, 0xe23d81bc, 0xbce2633d, 0x1d273116, 0x161d2c27, 0x769a37ad, 0xad76419a |
|||
, 0x3b4d96db, 0xdb3bad4d, 0x56fa9e64, 0x6456c8fa, 0x4ed2a674, 0x744ee8d2, 0x1e223614, 0x141e2822, 0xdb76e492, 0x92db3f76, 0xa1e120c, 0xc0a181e, 0x6cb4fc48, 0x486c90b4, 0xe4378fb8, 0xb8e46b37 |
|||
, 0x5de7789f, 0x9f5d25e7, 0x6eb20fbd, 0xbd6e61b2, 0xef2a6943, 0x43ef862a, 0xa6f135c4, 0xc4a693f1, 0xa8e3da39, 0x39a872e3, 0xa4f7c631, 0x31a462f7, 0x37598ad3, 0xd337bd59, 0x8b8674f2, 0xf28bff86 |
|||
, 0x325683d5, 0xd532b156, 0x43c54e8b, 0x8b430dc5, 0x59eb856e, 0x6e59dceb, 0xb7c218da, 0xdab7afc2, 0x8c8f8e01, 0x18c028f, 0x64ac1db1, 0xb16479ac, 0xd26df19c, 0x9cd2236d, 0xe03b7249, 0x49e0923b |
|||
, 0xb4c71fd8, 0xd8b4abc7, 0xfa15b9ac, 0xacfa4315, 0x709faf3, 0xf307fd09, 0x256fa0cf, 0xcf25856f, 0xafea20ca, 0xcaaf8fea, 0x8e897df4, 0xf48ef389, 0xe9206747, 0x47e98e20, 0x18283810, 0x10182028 |
|||
, 0xd5640b6f, 0x6fd5de64, 0x888373f0, 0xf088fb83, 0x6fb1fb4a, 0x4a6f94b1, 0x7296ca5c, 0x5c72b896, 0x246c5438, 0x3824706c, 0xf1085f57, 0x57f1ae08, 0xc7522173, 0x73c7e652, 0x51f36497, 0x975135f3 |
|||
, 0x2365aecb, 0xcb238d65, 0x7c8425a1, 0xa17c5984, 0x9cbf57e8, 0xe89ccbbf, 0x21635d3e, 0x3e217c63, 0xdd7cea96, 0x96dd377c, 0xdc7f1e61, 0x61dcc27f, 0x86919c0d, 0xd861a91, 0x85949b0f, 0xf851e94 |
|||
, 0x90ab4be0, 0xe090dbab, 0x42c6ba7c, 0x7c42f8c6, 0xc4572671, 0x71c4e257, 0xaae529cc, 0xccaa83e5, 0xd873e390, 0x90d83b73, 0x50f0906, 0x6050c0f, 0x103f4f7, 0xf701f503, 0x12362a1c, 0x1c123836 |
|||
, 0xa3fe3cc2, 0xc2a39ffe, 0x5fe18b6a, 0x6a5fd4e1, 0xf910beae, 0xaef94710, 0xd06b0269, 0x69d0d26b, 0x91a8bf17, 0x17912ea8, 0x58e87199, 0x995829e8, 0x2769533a, 0x3a277469, 0xb9d0f727, 0x27b94ed0 |
|||
, 0x384891d9, 0xd938a948, 0x1335deeb, 0xeb13cd35, 0xb3cee52b, 0x2bb356ce, 0x33557722, 0x22334455, 0xbbd604d2, 0xd2bbbfd6, 0x709039a9, 0xa9704990, 0x89808707, 0x7890e80, 0xa7f2c133, 0x33a766f2 |
|||
, 0xb6c1ec2d, 0x2db65ac1, 0x22665a3c, 0x3c227866, 0x92adb815, 0x15922aad, 0x2060a9c9, 0xc9208960, 0x49db5c87, 0x874915db, 0xff1ab0aa, 0xaaff4f1a, 0x7888d850, 0x5078a088, 0x7a8e2ba5, 0xa57a518e |
|||
, 0x8f8a8903, 0x38f068a, 0xf8134a59, 0x59f8b213, 0x809b9209, 0x980129b, 0x1739231a, 0x1a173439, 0xda751065, 0x65daca75, 0x315384d7, 0xd731b553, 0xc651d584, 0x84c61351, 0xb8d303d0, 0xd0b8bbd3 |
|||
, 0xc35edc82, 0x82c31f5e, 0xb0cbe229, 0x29b052cb, 0x7799c35a, 0x5a77b499, 0x11332d1e, 0x1e113c33, 0xcb463d7b, 0x7bcbf646, 0xfc1fb7a8, 0xa8fc4b1f, 0xd6610c6d, 0x6dd6da61, 0x3a4e622c, 0x2c3a584e}; |
|||
|
|||
#endif /* __tables_h */ |
@ -0,0 +1,24 @@ |
|||
// Copyright (c) 2012-2013 The Cryptonote developers
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include <stddef.h> |
|||
#include <stdint.h> |
|||
#include <string.h> |
|||
|
|||
#include "hash-ops.h" |
|||
#include "c_keccak.h" |
|||
|
|||
void hash_permutation(union hash_state *state) { |
|||
keccakf((uint64_t*)state, 24); |
|||
} |
|||
|
|||
void hash_process(union hash_state *state, const uint8_t *buf, size_t count) { |
|||
keccak1600(buf, count, (uint8_t*)state); |
|||
} |
|||
|
|||
void cn_fast_hash(const void *data, size_t length, char *hash) { |
|||
union hash_state state; |
|||
hash_process(&state, data, length); |
|||
memcpy(hash, &state, HASH_SIZE); |
|||
} |
@ -0,0 +1,5 @@ |
|||
#pragma once |
|||
|
|||
typedef unsigned char BitSequence; |
|||
typedef unsigned long long DataLength; |
|||
typedef enum {SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2} HashReturn; |
@ -0,0 +1,50 @@ |
|||
/*
|
|||
* --------------------------------------------------------------------------- |
|||
* OpenAES License |
|||
* --------------------------------------------------------------------------- |
|||
* Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* - Redistributions of source code must retain the above copyright notice, |
|||
* this list of conditions and the following disclaimer. |
|||
* - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
* --------------------------------------------------------------------------- |
|||
*/ |
|||
|
|||
#ifndef _OAES_CONFIG_H |
|||
#define _OAES_CONFIG_H |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
//#ifndef OAES_HAVE_ISAAC
|
|||
//#define OAES_HAVE_ISAAC 1
|
|||
//#endif // OAES_HAVE_ISAAC
|
|||
|
|||
//#ifndef OAES_DEBUG
|
|||
//#define OAES_DEBUG 0
|
|||
//#endif // OAES_DEBUG
|
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif // _OAES_CONFIG_H
|
File diff suppressed because it is too large
@ -0,0 +1,214 @@ |
|||
/*
|
|||
* --------------------------------------------------------------------------- |
|||
* OpenAES License |
|||
* --------------------------------------------------------------------------- |
|||
* Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* - Redistributions of source code must retain the above copyright notice, |
|||
* this list of conditions and the following disclaimer. |
|||
* - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
* --------------------------------------------------------------------------- |
|||
*/ |
|||
|
|||
#ifndef _OAES_LIB_H |
|||
#define _OAES_LIB_H |
|||
|
|||
#include <stdint.h> |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
#ifdef _WIN32 |
|||
# ifdef OAES_SHARED |
|||
# ifdef oaes_lib_EXPORTS |
|||
# define OAES_API __declspec(dllexport) |
|||
# else |
|||
# define OAES_API __declspec(dllimport) |
|||
# endif |
|||
# else |
|||
# define OAES_API |
|||
# endif |
|||
#else |
|||
# define OAES_API |
|||
#endif // WIN32
|
|||
|
|||
#define OAES_VERSION "0.8.1" |
|||
#define OAES_BLOCK_SIZE 16 |
|||
|
|||
typedef void OAES_CTX; |
|||
|
|||
typedef enum |
|||
{ |
|||
OAES_RET_FIRST = 0, |
|||
OAES_RET_SUCCESS = 0, |
|||
OAES_RET_UNKNOWN, |
|||
OAES_RET_ARG1, |
|||
OAES_RET_ARG2, |
|||
OAES_RET_ARG3, |
|||
OAES_RET_ARG4, |
|||
OAES_RET_ARG5, |
|||
OAES_RET_NOKEY, |
|||
OAES_RET_MEM, |
|||
OAES_RET_BUF, |
|||
OAES_RET_HEADER, |
|||
OAES_RET_COUNT |
|||
} OAES_RET; |
|||
|
|||
/*
|
|||
* oaes_set_option() takes one of these values for its [option] parameter |
|||
* some options accept either an optional or a required [value] parameter |
|||
*/ |
|||
// no option
|
|||
#define OAES_OPTION_NONE 0 |
|||
// enable ECB mode, disable CBC mode
|
|||
#define OAES_OPTION_ECB 1 |
|||
// enable CBC mode, disable ECB mode
|
|||
// value is optional, may pass uint8_t iv[OAES_BLOCK_SIZE] to specify
|
|||
// the value of the initialization vector, iv
|
|||
#define OAES_OPTION_CBC 2 |
|||
|
|||
#ifdef OAES_DEBUG |
|||
typedef int ( * oaes_step_cb ) ( |
|||
const uint8_t state[OAES_BLOCK_SIZE], |
|||
const char * step_name, |
|||
int step_count, |
|||
void * user_data ); |
|||
// enable state stepping mode
|
|||
// value is required, must pass oaes_step_cb to receive the state at each step
|
|||
#define OAES_OPTION_STEP_ON 4 |
|||
// disable state stepping mode
|
|||
#define OAES_OPTION_STEP_OFF 8 |
|||
#endif // OAES_DEBUG
|
|||
|
|||
typedef uint16_t OAES_OPTION; |
|||
|
|||
typedef struct _oaes_key |
|||
{ |
|||
size_t data_len; |
|||
uint8_t *data; |
|||
size_t exp_data_len; |
|||
uint8_t *exp_data; |
|||
size_t num_keys; |
|||
size_t key_base; |
|||
} oaes_key; |
|||
|
|||
typedef struct _oaes_ctx |
|||
{ |
|||
#ifdef OAES_HAVE_ISAAC |
|||
randctx * rctx; |
|||
#endif // OAES_HAVE_ISAAC
|
|||
|
|||
#ifdef OAES_DEBUG |
|||
oaes_step_cb step_cb; |
|||
#endif // OAES_DEBUG
|
|||
|
|||
oaes_key * key; |
|||
OAES_OPTION options; |
|||
uint8_t iv[OAES_BLOCK_SIZE]; |
|||
} oaes_ctx; |
|||
/*
|
|||
* // usage:
|
|||
* |
|||
* OAES_CTX * ctx = oaes_alloc(); |
|||
* . |
|||
* . |
|||
* . |
|||
* { |
|||
* oaes_gen_key_xxx( ctx ); |
|||
* { |
|||
* oaes_key_export( ctx, _buf, &_buf_len ); |
|||
* // or
|
|||
* oaes_key_export_data( ctx, _buf, &_buf_len );\ |
|||
* } |
|||
* } |
|||
* // or
|
|||
* { |
|||
* oaes_key_import( ctx, _buf, _buf_len ); |
|||
* // or
|
|||
* oaes_key_import_data( ctx, _buf, _buf_len ); |
|||
* } |
|||
* . |
|||
* . |
|||
* . |
|||
* oaes_encrypt( ctx, m, m_len, c, &c_len ); |
|||
* . |
|||
* . |
|||
* . |
|||
* oaes_decrypt( ctx, c, c_len, m, &m_len ); |
|||
* . |
|||
* . |
|||
* . |
|||
* oaes_free( &ctx ); |
|||
*/ |
|||
|
|||
OAES_API OAES_CTX * oaes_alloc(void); |
|||
|
|||
OAES_API OAES_RET oaes_free( OAES_CTX ** ctx ); |
|||
|
|||
OAES_API OAES_RET oaes_set_option( OAES_CTX * ctx, |
|||
OAES_OPTION option, const void * value ); |
|||
|
|||
OAES_API OAES_RET oaes_key_gen_128( OAES_CTX * ctx ); |
|||
|
|||
OAES_API OAES_RET oaes_key_gen_192( OAES_CTX * ctx ); |
|||
|
|||
OAES_API OAES_RET oaes_key_gen_256( OAES_CTX * ctx ); |
|||
|
|||
// export key with header information
|
|||
// set data == NULL to get the required data_len
|
|||
OAES_API OAES_RET oaes_key_export( OAES_CTX * ctx, |
|||
uint8_t * data, size_t * data_len ); |
|||
|
|||
// directly export the data from key
|
|||
// set data == NULL to get the required data_len
|
|||
OAES_API OAES_RET oaes_key_export_data( OAES_CTX * ctx, |
|||
uint8_t * data, size_t * data_len ); |
|||
|
|||
// import key with header information
|
|||
OAES_API OAES_RET oaes_key_import( OAES_CTX * ctx, |
|||
const uint8_t * data, size_t data_len ); |
|||
|
|||
// directly import data into key
|
|||
OAES_API OAES_RET oaes_key_import_data( OAES_CTX * ctx, |
|||
const uint8_t * data, size_t data_len ); |
|||
|
|||
// set c == NULL to get the required c_len
|
|||
OAES_API OAES_RET oaes_encrypt( OAES_CTX * ctx, |
|||
const uint8_t * m, size_t m_len, uint8_t * c, size_t * c_len ); |
|||
|
|||
// set m == NULL to get the required m_len
|
|||
OAES_API OAES_RET oaes_decrypt( OAES_CTX * ctx, |
|||
const uint8_t * c, size_t c_len, uint8_t * m, size_t * m_len ); |
|||
|
|||
// set buf == NULL to get the required buf_len
|
|||
OAES_API OAES_RET oaes_sprintf( |
|||
char * buf, size_t * buf_len, const uint8_t * data, size_t data_len ); |
|||
|
|||
OAES_API OAES_RET oaes_encryption_round( const uint8_t * key, uint8_t * c ); |
|||
|
|||
OAES_API OAES_RET oaes_pseudo_encrypt_ecb( OAES_CTX * ctx, uint8_t * c ); |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif // _OAES_LIB_H
|
@ -0,0 +1,187 @@ |
|||
#ifndef _SKEIN_PORT_H_ |
|||
#define _SKEIN_PORT_H_ |
|||
|
|||
#include <limits.h> |
|||
#include <stdint.h> |
|||
|
|||
#ifndef RETURN_VALUES |
|||
# define RETURN_VALUES |
|||
# if defined( DLL_EXPORT ) |
|||
# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) |
|||
# define VOID_RETURN __declspec( dllexport ) void __stdcall |
|||
# define INT_RETURN __declspec( dllexport ) int __stdcall |
|||
# elif defined( __GNUC__ ) |
|||
# define VOID_RETURN __declspec( __dllexport__ ) void |
|||
# define INT_RETURN __declspec( __dllexport__ ) int |
|||
# else |
|||
# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers |
|||
# endif |
|||
# elif defined( DLL_IMPORT ) |
|||
# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) |
|||
# define VOID_RETURN __declspec( dllimport ) void __stdcall |
|||
# define INT_RETURN __declspec( dllimport ) int __stdcall |
|||
# elif defined( __GNUC__ ) |
|||
# define VOID_RETURN __declspec( __dllimport__ ) void |
|||
# define INT_RETURN __declspec( __dllimport__ ) int |
|||
# else |
|||
# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers |
|||
# endif |
|||
# elif defined( __WATCOMC__ ) |
|||
# define VOID_RETURN void __cdecl |
|||
# define INT_RETURN int __cdecl |
|||
# else |
|||
# define VOID_RETURN void |
|||
# define INT_RETURN int |
|||
# 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 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 ptr_cast(x,size) ((ui_type(size)*)(x)) |
|||
|
|||
typedef unsigned int uint_t; /* native unsigned integer */ |
|||
typedef uint8_t u08b_t; /* 8-bit unsigned integer */ |
|||
typedef uint64_t u64b_t; /* 64-bit unsigned integer */ |
|||
|
|||
#ifndef RotL_64 |
|||
#define RotL_64(x,N) (((x) << (N)) | ((x) >> (64-(N)))) |
|||
#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? */ |
|||
|
|||
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ |
|||
#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ |
|||
|
|||
#if BYTE_ORDER == LITTLE_ENDIAN && !defined(PLATFORM_BYTE_ORDER) |
|||
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN |
|||
#endif |
|||
|
|||
#if BYTE_ORDER == BIG_ENDIAN && !defined(PLATFORM_BYTE_ORDER) |
|||
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN |
|||
#endif |
|||
|
|||
/* special handler for IA64, which may be either endianness (?) */ |
|||
/* here we assume little-endian, but this may need to be changed */ |
|||
#if defined(__ia64) || defined(__ia64__) || defined(_M_IA64) |
|||
# define PLATFORM_MUST_ALIGN (1) |
|||
#ifndef PLATFORM_BYTE_ORDER |
|||
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef PLATFORM_MUST_ALIGN |
|||
# define PLATFORM_MUST_ALIGN (0) |
|||
#endif |
|||
|
|||
|
|||
#if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN |
|||
/* here for big-endian CPUs */ |
|||
#define SKEIN_NEED_SWAP (1) |
|||
#elif PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN |
|||
/* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */ |
|||
#define SKEIN_NEED_SWAP (0) |
|||
#if PLATFORM_MUST_ALIGN == 0 /* ok to use "fast" versions? */ |
|||
#define Skein_Put64_LSB_First(dst08,src64,bCnt) memcpy(dst08,src64,bCnt) |
|||
#define Skein_Get64_LSB_First(dst64,src08,wCnt) memcpy(dst64,src08,8*(wCnt)) |
|||
#endif |
|||
#else |
|||
#error "Skein needs endianness setting!" |
|||
#endif |
|||
|
|||
#endif /* ifndef SKEIN_NEED_SWAP */ |
|||
|
|||
/*
|
|||
****************************************************************** |
|||
* Provide any definitions still needed. |
|||
****************************************************************** |
|||
*/ |
|||
#ifndef Skein_Swap64 /* swap for big-endian, nop for little-endian */ |
|||
#if SKEIN_NEED_SWAP |
|||
#define Skein_Swap64(w64) \ |
|||
( (( ((u64b_t)(w64)) & 0xFF) << 56) | \ |
|||
(((((u64b_t)(w64)) >> 8) & 0xFF) << 48) | \ |
|||
(((((u64b_t)(w64)) >>16) & 0xFF) << 40) | \ |
|||
(((((u64b_t)(w64)) >>24) & 0xFF) << 32) | \ |
|||
(((((u64b_t)(w64)) >>32) & 0xFF) << 24) | \ |
|||
(((((u64b_t)(w64)) >>40) & 0xFF) << 16) | \ |
|||
(((((u64b_t)(w64)) >>48) & 0xFF) << 8) | \ |
|||
(((((u64b_t)(w64)) >>56) & 0xFF) ) ) |
|||
#else |
|||
#define Skein_Swap64(w64) (w64) |
|||
#endif |
|||
#endif /* ifndef Skein_Swap64 */ |
|||
|
|||
|
|||
#ifndef Skein_Put64_LSB_First |
|||
void Skein_Put64_LSB_First(u08b_t *dst,const u64b_t *src,size_t bCnt) |
|||
#ifdef SKEIN_PORT_CODE /* instantiate the function code here? */ |
|||
{ /* this version is fully portable (big-endian or little-endian), but slow */ |
|||
size_t n; |
|||
|
|||
for (n=0;n<bCnt;n++) |
|||
dst[n] = (u08b_t) (src[n>>3] >> (8*(n&7))); |
|||
} |
|||
#else |
|||
; /* output only the function prototype */ |
|||
#endif |
|||
#endif /* ifndef Skein_Put64_LSB_First */ |
|||
|
|||
|
|||
#ifndef Skein_Get64_LSB_First |
|||
void Skein_Get64_LSB_First(u64b_t *dst,const u08b_t *src,size_t wCnt) |
|||
#ifdef SKEIN_PORT_CODE /* instantiate the function code here? */ |
|||
{ /* this version is fully portable (big-endian or little-endian), but slow */ |
|||
size_t n; |
|||
|
|||
for (n=0;n<8*wCnt;n+=8) |
|||
dst[n/8] = (((u64b_t) src[n ]) ) + |
|||
(((u64b_t) src[n+1]) << 8) + |
|||
(((u64b_t) src[n+2]) << 16) + |
|||
(((u64b_t) src[n+3]) << 24) + |
|||
(((u64b_t) src[n+4]) << 32) + |
|||
(((u64b_t) src[n+5]) << 40) + |
|||
(((u64b_t) src[n+6]) << 48) + |
|||
(((u64b_t) src[n+7]) << 56) ; |
|||
} |
|||
#else |
|||
; /* output only the function prototype */ |
|||
#endif |
|||
#endif /* ifndef Skein_Get64_LSB_First */ |
|||
|
|||
#endif /* ifndef _SKEIN_PORT_H_ */ |
@ -0,0 +1,29 @@ |
|||
/* 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__ |
|||
#define __DONATE_H__ |
|||
|
|||
#define DONATE_LEVEL 5 |
|||
|
|||
#endif /* __DONATE_H__ */ |
@ -0,0 +1,274 @@ |
|||
/* 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 _LINUX_LIST_H |
|||
#define _LINUX_LIST_H |
|||
|
|||
/*
|
|||
* Simple doubly linked list implementation. |
|||
* |
|||
* Some of the internal functions ("__xxx") are useful when |
|||
* manipulating whole lists rather than single entries, as |
|||
* sometimes we already know the next/prev entries and we can |
|||
* generate better code by using them directly rather than |
|||
* using the generic single-entry routines. |
|||
*/ |
|||
|
|||
struct list_head { |
|||
struct list_head *next, *prev; |
|||
}; |
|||
|
|||
#define LIST_HEAD_INIT(name) { &(name), &(name) } |
|||
|
|||
#define LIST_HEAD(name) \ |
|||
struct list_head name = LIST_HEAD_INIT(name) |
|||
|
|||
#define INIT_LIST_HEAD(ptr) do { \ |
|||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \ |
|||
} while (0) |
|||
|
|||
/*
|
|||
* Insert a new entry between two known consecutive entries. |
|||
* |
|||
* This is only for internal list manipulation where we know |
|||
* the prev/next entries already! |
|||
*/ |
|||
static inline void __list_add(struct list_head *new, |
|||
struct list_head *prev, |
|||
struct list_head *next) |
|||
{ |
|||
next->prev = new; |
|||
new->next = next; |
|||
new->prev = prev; |
|||
prev->next = new; |
|||
} |
|||
|
|||
/**
|
|||
* list_add - add a new entry |
|||
* @new: new entry to be added |
|||
* @head: list head to add it after |
|||
* |
|||
* Insert a new entry after the specified head. |
|||
* This is good for implementing stacks. |
|||
*/ |
|||
static inline void list_add(struct list_head *new, struct list_head *head) |
|||
{ |
|||
__list_add(new, head, head->next); |
|||
} |
|||
|
|||
/**
|
|||
* list_add_tail - add a new entry |
|||
* @new: new entry to be added |
|||
* @head: list head to add it before |
|||
* |
|||
* Insert a new entry before the specified head. |
|||
* This is useful for implementing queues. |
|||
*/ |
|||
static inline void list_add_tail(struct list_head *new, struct list_head *head) |
|||
{ |
|||
__list_add(new, head->prev, head); |
|||
} |
|||
|
|||
/*
|
|||
* Delete a list entry by making the prev/next entries |
|||
* point to each other. |
|||
* |
|||
* This is only for internal list manipulation where we know |
|||
* the prev/next entries already! |
|||
*/ |
|||
static inline void __list_del(struct list_head *prev, struct list_head *next) |
|||
{ |
|||
next->prev = prev; |
|||
prev->next = next; |
|||
} |
|||
|
|||
/**
|
|||
* list_del - deletes entry from list. |
|||
* @entry: the element to delete from the list. |
|||
* Note: list_empty on entry does not return true after this, the entry is in an undefined state. |
|||
*/ |
|||
static inline void list_del(struct list_head *entry) |
|||
{ |
|||
__list_del(entry->prev, entry->next); |
|||
entry->next = (void *) 0; |
|||
entry->prev = (void *) 0; |
|||
} |
|||
|
|||
/**
|
|||
* list_del_init - deletes entry from list and reinitialize it. |
|||
* @entry: the element to delete from the list. |
|||
*/ |
|||
static inline void list_del_init(struct list_head *entry) |
|||
{ |
|||
__list_del(entry->prev, entry->next); |
|||
INIT_LIST_HEAD(entry); |
|||
} |
|||
|
|||
/**
|
|||
* list_move - delete from one list and add as another's head |
|||
* @list: the entry to move |
|||
* @head: the head that will precede our entry |
|||
*/ |
|||
static inline void list_move(struct list_head *list, struct list_head *head) |
|||
{ |
|||
__list_del(list->prev, list->next); |
|||
list_add(list, head); |
|||
} |
|||
|
|||
/**
|
|||
* list_move_tail - delete from one list and add as another's tail |
|||
* @list: the entry to move |
|||
* @head: the head that will follow our entry |
|||
*/ |
|||
static inline void list_move_tail(struct list_head *list, |
|||
struct list_head *head) |
|||
{ |
|||
__list_del(list->prev, list->next); |
|||
list_add_tail(list, head); |
|||
} |
|||
|
|||
/**
|
|||
* list_empty - tests whether a list is empty |
|||
* @head: the list to test. |
|||
*/ |
|||
static inline int list_empty(struct list_head *head) |
|||
{ |
|||
return head->next == head; |
|||
} |
|||
|
|||
static inline void __list_splice(struct list_head *list, |
|||
struct list_head *head) |
|||
{ |
|||
struct list_head *first = list->next; |
|||
struct list_head *last = list->prev; |
|||
struct list_head *at = head->next; |
|||
|
|||
first->prev = head; |
|||
head->next = first; |
|||
|
|||
last->next = at; |
|||
at->prev = last; |
|||
} |
|||
|
|||
/**
|
|||
* list_splice - join two lists |
|||
* @list: the new list to add. |
|||
* @head: the place to add it in the first list. |
|||
*/ |
|||
static inline void list_splice(struct list_head *list, struct list_head *head) |
|||
{ |
|||
if (!list_empty(list)) |
|||
__list_splice(list, head); |
|||
} |
|||
|
|||
/**
|
|||
* list_splice_init - join two lists and reinitialise the emptied list. |
|||
* @list: the new list to add. |
|||
* @head: the place to add it in the first list. |
|||
* |
|||
* The list at @list is reinitialised |
|||
*/ |
|||
static inline void list_splice_init(struct list_head *list, |
|||
struct list_head *head) |
|||
{ |
|||
if (!list_empty(list)) { |
|||
__list_splice(list, head); |
|||
INIT_LIST_HEAD(list); |
|||
} |
|||
} |
|||
|
|||
/**
|
|||
* list_entry - get the struct for this entry |
|||
* @ptr: the &struct list_head pointer. |
|||
* @type: the type of the struct this is embedded in. |
|||
* @member: the name of the list_struct within the struct. |
|||
*/ |
|||
#define list_entry(ptr, type, member) \ |
|||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) |
|||
|
|||
/**
|
|||
* list_for_each - iterate over a list |
|||
* @pos: the &struct list_head to use as a loop counter. |
|||
* @head: the head for your list. |
|||
*/ |
|||
#define list_for_each(pos, head) \ |
|||
for (pos = (head)->next; pos != (head); \ |
|||
pos = pos->next) |
|||
/**
|
|||
* list_for_each_prev - iterate over a list backwards |
|||
* @pos: the &struct list_head to use as a loop counter. |
|||
* @head: the head for your list. |
|||
*/ |
|||
#define list_for_each_prev(pos, head) \ |
|||
for (pos = (head)->prev; pos != (head); \ |
|||
pos = pos->prev) |
|||
|
|||
/**
|
|||
* list_for_each_safe - iterate over a list safe against removal of list entry |
|||
* @pos: the &struct list_head to use as a loop counter. |
|||
* @n: another &struct list_head to use as temporary storage |
|||
* @head: the head for your list. |
|||
*/ |
|||
#define list_for_each_safe(pos, n, head) \ |
|||
for (pos = (head)->next, n = pos->next; pos != (head); \ |
|||
pos = n, n = pos->next) |
|||
|
|||
/**
|
|||
* list_for_each_entry - iterate over list of given type |
|||
* @pos: the type * to use as a loop counter. |
|||
* @head: the head for your list. |
|||
* @member: the name of the list_struct within the struct. |
|||
*/ |
|||
#define list_for_each_entry(pos, head, member) \ |
|||
for (pos = list_entry((head)->next, typeof(*pos), member); \ |
|||
&pos->member != (head); \ |
|||
pos = list_entry(pos->member.next, typeof(*pos), member)) |
|||
|
|||
/**
|
|||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry |
|||
* @pos: the type * to use as a loop counter. |
|||
* @n: another type * to use as temporary storage |
|||
* @head: the head for your list. |
|||
* @member: the name of the list_struct within the struct. |
|||
*/ |
|||
#define list_for_each_entry_safe(pos, n, head, member) \ |
|||
for (pos = list_entry((head)->next, typeof(*pos), member), \ |
|||
n = list_entry(pos->member.next, typeof(*pos), member); \ |
|||
&pos->member != (head); \ |
|||
pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
|||
|
|||
/**
|
|||
* list_for_each_entry_continue - iterate over list of given type |
|||
* continuing after existing point |
|||
* @pos: the type * to use as a loop counter. |
|||
* @head: the head for your list. |
|||
* @member: the name of the list_struct within the struct. |
|||
*/ |
|||
#define list_for_each_entry_continue(pos, head, member) \ |
|||
for (pos = list_entry(pos->member.next, typeof(*pos), member), \ |
|||
prefetch(pos->member.next); \ |
|||
&pos->member != (head); \ |
|||
pos = list_entry(pos->member.next, typeof(*pos), member), \ |
|||
prefetch(pos->member.next)) |
|||
|
|||
#endif |
@ -0,0 +1,38 @@ |
|||
/* 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 "persistent_memory.h" |
|||
|
|||
static size_t offset = 0; |
|||
|
|||
|
|||
void * persistent_calloc(size_t num, size_t size) { |
|||
void *mem = &persistent_memory[offset]; |
|||
offset += (num * size); |
|||
|
|||
memset(mem, 0, num * size); |
|||
|
|||
return mem; |
|||
} |
@ -0,0 +1,441 @@ |
|||
/* 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 <string.h> |
|||
#include <jansson.h> |
|||
#include <curl/curl.h> |
|||
#include <getopt.h> |
|||
|
|||
#include "version.h" |
|||
#include "utils/applog.h" |
|||
#include "options.h" |
|||
#include "cpu.h" |
|||
#include "donate.h" |
|||
#include "algo/cryptonight/cryptonight.h" |
|||
|
|||
|
|||
int64_t opt_affinity = -1L; |
|||
int opt_n_threads = 0; |
|||
int opt_algo_variant = 0; |
|||
int opt_retries = 5; |
|||
int opt_retry_pause = 5; |
|||
int opt_donate_level = DONATE_LEVEL; |
|||
bool opt_colors = true; |
|||
bool opt_keepalive = false; |
|||
bool opt_background = false; |
|||
char *opt_url = NULL; |
|||
char *opt_backup_url = NULL; |
|||
char *opt_userpass = NULL; |
|||
char *opt_user = NULL; |
|||
char *opt_pass = NULL; |
|||
|
|||
|
|||
static char const usage[] = "\
|
|||
Usage: " APP_ID " [OPTIONS]\n\ |
|||
Options:\n\ |
|||
-o, --url=URL URL of mining server\n\ |
|||
-b, --backup-url=URL URL of backup 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\ |
|||
--no-color disable colored output\n\ |
|||
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ |
|||
-B, --background run the miner in the background\n\ |
|||
-c, --config=FILE load a JSON-format configuration file\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:Vb:"; |
|||
|
|||
|
|||
static struct option const options[] = { |
|||
{ "algo", 1, NULL, 'a' }, |
|||
{ "av", 1, NULL, 'v' }, |
|||
{ "background", 0, NULL, 'B' }, |
|||
{ "backup-url", 1, NULL, 'b' }, |
|||
{ "config", 1, NULL, 'c' }, |
|||
{ "cpu-affinity", 1, NULL, 1020 }, |
|||
{ "donate-level", 1, NULL, 1003 }, |
|||
{ "help", 0, NULL, 'h' }, |
|||
{ "keepalive", 0, NULL ,'k' }, |
|||
{ "no-color", 0, NULL, 1002 }, |
|||
{ "pass", 1, NULL, 'p' }, |
|||
{ "retries", 1, NULL, 'r' }, |
|||
{ "retry-pause", 1, NULL, 'R' }, |
|||
{ "threads", 1, NULL, 't' }, |
|||
{ "url", 1, NULL, 'o' }, |
|||
{ "user", 1, NULL, 'u' }, |
|||
{ "userpass", 1, NULL, 'O' }, |
|||
{ "version", 0, NULL, 'V' }, |
|||
{ 0, 0, 0, 0 } |
|||
}; |
|||
|
|||
|
|||
static int get_algo_variant(int variant) { |
|||
if (variant > XMR_VARIANT_AUTO && variant < XMR_VARIANT_MAX) { |
|||
return variant; |
|||
} |
|||
|
|||
if (cpu_info.flags & CPU_FLAG_AES) { |
|||
if (cpu_info.flags & CPU_FLAG_BMI2) { |
|||
return XMR_VARIANT_AESNI_BMI2; |
|||
} |
|||
|
|||
return XMR_VARIANT_AESNI; |
|||
} |
|||
|
|||
return XMR_VARIANT_LEGACY; |
|||
} |
|||
|
|||
|
|||
static void parse_config(json_t *config, char *ref); |
|||
static char *parse_url(const char *arg); |
|||
|
|||
|
|||
static void parse_arg(int key, char *arg) { |
|||
char *p; |
|||
int v; |
|||
uint64_t ul; |
|||
|
|||
switch (key) |
|||
{ |
|||
case 'a': |
|||
break; |
|||
|
|||
case 'O': /* --userpass */ |
|||
p = strchr(arg, ':'); |
|||
if (!p) { |
|||
show_usage_and_exit(1); |
|||
} |
|||
|
|||
free(opt_userpass); |
|||
opt_userpass = strdup(arg); |
|||
free(opt_user); |
|||
opt_user = calloc(p - arg + 1, 1); |
|||
strncpy(opt_user, arg, p - arg); |
|||
free(opt_pass); |
|||
opt_pass = strdup(p + 1); |
|||
break; |
|||
|
|||
case 'o': /* --url */ |
|||
p = parse_url(arg); |
|||
if (p) { |
|||
free(opt_url); |
|||
opt_url = p; |
|||
} |
|||
break; |
|||
|
|||
case 'b': /* --backup-url */ |
|||
p = parse_url(arg); |
|||
if (p) { |
|||
free(opt_backup_url); |
|||
opt_backup_url = p; |
|||
} |
|||
break; |
|||
|
|||
case 'u': /* --user */ |
|||
free(opt_user); |
|||
opt_user = strdup(arg); |
|||
break; |
|||
|
|||
case 'p': /* --pass */ |
|||
free(opt_pass); |
|||
opt_pass = strdup(arg); |
|||
break; |
|||
|
|||
case 'r': /* --retries */ |
|||
v = atoi(arg); |
|||
if (v < 1 || v > 1000) { |
|||
show_usage_and_exit(1); |
|||
} |
|||
|
|||
opt_retries = v; |
|||
break; |
|||
|
|||
case 'R': /* --retry-pause */ |
|||
v = atoi(arg); |
|||
if (v < 1 || v > 3600) { |
|||
show_usage_and_exit(1); |
|||
} |
|||
|
|||
opt_retry_pause = v; |
|||
break; |
|||
|
|||
case 't': /* --threads */ |
|||
v = atoi(arg); |
|||
if (v < 1 || v > 1024) { |
|||
show_usage_and_exit(1); |
|||
} |
|||
|
|||
opt_n_threads = v; |
|||
break; |
|||
|
|||
case 'k': |
|||
opt_keepalive = true; |
|||
break; |
|||
|
|||
case 'V': /* --version */ |
|||
show_version_and_exit(); |
|||
break; |
|||
|
|||
case 'h': /* --help */ |
|||
show_usage_and_exit(0); |
|||
break; |
|||
|
|||
case 'c': { /* --config */ |
|||
json_error_t err; |
|||
json_t *config = json_load_file(arg, 0, &err); |
|||
|
|||
if (!json_is_object(config)) { |
|||
if (err.line < 0) { |
|||
applog(LOG_ERR, "%s\n", err.text); |
|||
} |
|||
else { |
|||
applog(LOG_ERR, "%s:%d: %s\n", arg, err.line, err.text); |
|||
} |
|||
} else { |
|||
parse_config(config, arg); |
|||
json_decref(config); |
|||
} |
|||
break; |
|||
} |
|||
|
|||
case 'B': |
|||
opt_background = true; |
|||
opt_colors = false; |
|||
break; |
|||
|
|||
case 'v': /* --av */ |
|||
v = atoi(arg); |
|||
if (v < 0 || v > XMR_VARIANT_MAX) { |
|||
show_usage_and_exit(1); |
|||
} |
|||
|
|||
opt_algo_variant = v; |
|||
break; |
|||
|
|||
case 1020: /* --cpu-affinity */ |
|||
p = strstr(arg, "0x"); |
|||
ul = p ? strtoul(p, NULL, 16) : atol(arg); |
|||
if (ul > (1UL << cpu_info.count) -1) { |
|||
ul = -1; |
|||
} |
|||
|
|||
opt_affinity = ul; |
|||
break; |
|||
|
|||
case 1002: /* --no-color */ |
|||
opt_colors = false; |
|||
break; |
|||
|
|||
case 1003: |
|||
v = atoi(arg); |
|||
if (v < 1 || v > 99) { |
|||
show_usage_and_exit(1); |
|||
} |
|||
|
|||
opt_donate_level = v; |
|||
break; |
|||
|
|||
default: |
|||
show_usage_and_exit(1); |
|||
} |
|||
} |
|||
|
|||
|
|||
static void parse_config(json_t *config, char *ref) |
|||
{ |
|||
int i; |
|||
char buf[16]; |
|||
json_t *val; |
|||
|
|||
applog(LOG_ERR, ref); |
|||
|
|||
for (i = 0; i < ARRAY_SIZE(options); i++) { |
|||
if (!options[i].name) { |
|||
break; |
|||
} |
|||
|
|||
val = json_object_get(config, options[i].name); |
|||
if (!val) { |
|||
continue; |
|||
} |
|||
|
|||
if (options[i].has_arg && json_is_string(val)) { |
|||
char *s = strdup(json_string_value(val)); |
|||
if (!s) { |
|||
break; |
|||
} |
|||
|
|||
parse_arg(options[i].val, s); |
|||
free(s); |
|||
} |
|||
else if (options[i].has_arg && json_is_integer(val)) { |
|||
sprintf(buf, "%d", (int) json_integer_value(val)); |
|||
parse_arg(options[i].val, buf); |
|||
} |
|||
else if (options[i].has_arg && json_is_real(val)) { |
|||
sprintf(buf, "%f", json_real_value(val)); |
|||
parse_arg(options[i].val, buf); |
|||
} |
|||
else if (!options[i].has_arg) { |
|||
if (json_is_true(val)) { |
|||
parse_arg(options[i].val, ""); |
|||
} |
|||
} |
|||
else { |
|||
applog(LOG_ERR, "JSON option %s invalid", options[i].name); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
static char *parse_url(const char *arg) |
|||
{ |
|||
char *p = strstr(arg, "://"); |
|||
if (p) { |
|||
if (strncasecmp(arg, "stratum+tcp://", 14)) { |
|||
show_usage_and_exit(1); |
|||
} |
|||
|
|||
return strdup(arg); |
|||
} |
|||
|
|||
|
|||
if (!strlen(arg) || *arg == '/') { |
|||
show_usage_and_exit(1); |
|||
} |
|||
|
|||
char *dest = malloc(strlen(arg) + 14); |
|||
sprintf(dest, "stratum+tcp://%s", arg); |
|||
|
|||
return dest; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* Parse application command line via getopt. |
|||
*/ |
|||
void parse_cmdline(int argc, char *argv[]) { |
|||
opt_user = strdup("x"); |
|||
opt_pass = strdup("x"); |
|||
|
|||
int key; |
|||
|
|||
while (1) { |
|||
key = getopt_long(argc, argv, short_options, options, NULL); |
|||
if (key < 0) { |
|||
break; |
|||
} |
|||
|
|||
parse_arg(key, optarg); |
|||
} |
|||
|
|||
if (optind < argc) { |
|||
fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]); |
|||
show_usage_and_exit(1); |
|||
} |
|||
|
|||
if (!opt_url) { |
|||
opt_url = strdup("stratum+tcp://proxy.xmrig.com:443"); |
|||
opt_keepalive = true; |
|||
|
|||
if (!opt_backup_url) { |
|||
opt_backup_url = strdup("stratum+tcp://failover.xmrig.com:80"); |
|||
} |
|||
} |
|||
|
|||
if (!opt_userpass) { |
|||
opt_userpass = malloc(strlen(opt_user) + strlen(opt_pass) + 2); |
|||
if (!opt_userpass) { |
|||
proper_exit(1); |
|||
} |
|||
|
|||
sprintf(opt_userpass, "%s:%s", opt_user, opt_pass); |
|||
} |
|||
|
|||
if (!opt_n_threads) { |
|||
opt_n_threads = get_optimal_threads_count(); |
|||
} |
|||
|
|||
opt_algo_variant = get_algo_variant(opt_algo_variant); |
|||
if (!opt_algo_variant) { |
|||
opt_algo_variant = get_algo_variant(0); |
|||
} |
|||
|
|||
if (opt_donate_level < 1 || opt_donate_level > 99) { |
|||
opt_donate_level = 1; |
|||
} |
|||
|
|||
cryptonight_init(opt_algo_variant); |
|||
} |
|||
|
|||
|
|||
void show_usage_and_exit(int status) { |
|||
if (status) { |
|||
fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n"); |
|||
} |
|||
else { |
|||
printf(usage); |
|||
} |
|||
|
|||
proper_exit(status); |
|||
} |
|||
|
|||
|
|||
void show_version_and_exit(void) { |
|||
printf(APP_NAME " " APP_VERSION "\n built on " __DATE__ |
|||
|
|||
#ifdef __GNUC__ |
|||
" with GCC"); |
|||
printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); |
|||
#endif |
|||
|
|||
printf("\n features:" |
|||
#ifdef __i386__ |
|||
" i386" |
|||
#endif |
|||
#ifdef __x86_64__ |
|||
" x86_64" |
|||
#endif |
|||
#ifdef __AES__ |
|||
" AES-NI" |
|||
#endif |
|||
"\n"); |
|||
|
|||
printf("\n%s\n", curl_version()); |
|||
#ifdef JANSSON_VERSION |
|||
printf("libjansson/%s\n", JANSSON_VERSION); |
|||
#endif |
|||
proper_exit(0); |
|||
} |
@ -0,0 +1,68 @@ |
|||
/* 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__ |
|||
#define __OPTIONS_H__ |
|||
|
|||
#include <stdbool.h> |
|||
#include <stdint.h> |
|||
|
|||
#ifndef ARRAY_SIZE |
|||
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) |
|||
#endif |
|||
|
|||
|
|||
enum xmr_algo_variant { |
|||
XMR_VARIANT_AUTO, |
|||
XMR_VARIANT_AESNI, |
|||
XMR_VARIANT_AESNI_WOLF, |
|||
XMR_VARIANT_AESNI_BMI2, |
|||
XMR_VARIANT_LEGACY, |
|||
XMR_VARIANT_EXPERIMENTAL, |
|||
XMR_VARIANT_MAX |
|||
}; |
|||
|
|||
|
|||
extern bool opt_colors; |
|||
extern bool opt_keepalive; |
|||
extern bool opt_background; |
|||
extern char *opt_url; |
|||
extern char *opt_backup_url; |
|||
extern char *opt_userpass; |
|||
extern char *opt_user; |
|||
extern char *opt_pass; |
|||
extern int opt_n_threads; |
|||
extern int opt_algo_variant; |
|||
extern int opt_retry_pause; |
|||
extern int opt_retries; |
|||
extern int opt_donate_level; |
|||
extern int64_t opt_affinity; |
|||
|
|||
void parse_cmdline(int argc, char *argv[]); |
|||
void show_usage_and_exit(int status); |
|||
void show_version_and_exit(void); |
|||
|
|||
extern void proper_exit(int reason); |
|||
|
|||
|
|||
#endif /* __OPTIONS_H__ */ |
@ -0,0 +1,49 @@ |
|||
/* 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 __PERSISTENT_MEMORY_H__ |
|||
#define __PERSISTENT_MEMORY_H__ |
|||
|
|||
#include <stddef.h> |
|||
|
|||
|
|||
enum memory_flags { |
|||
MEMORY_HUGEPAGES_AVAILABLE = 1, |
|||
MEMORY_HUGEPAGES_ENABLED = 2, |
|||
MEMORY_LOCK = 4 |
|||
}; |
|||
|
|||
|
|||
#define TWO_MB_PAGE 2097152 |
|||
|
|||
|
|||
extern char *persistent_memory; |
|||
extern int persistent_memory_flags; |
|||
|
|||
|
|||
const char * persistent_memory_allocate(); |
|||
void persistent_memory_free(); |
|||
void * persistent_calloc(size_t num, size_t size); |
|||
|
|||
|
|||
#endif /* __PERSISTENT_MEMORY_H__ */ |
@ -0,0 +1,137 @@ |
|||
/* 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 <sys/time.h> |
|||
#include <stdlib.h> |
|||
|
|||
#include "stats.h" |
|||
#include "options.h" |
|||
#include "utils/applog.h" |
|||
#include "persistent_memory.h" |
|||
|
|||
|
|||
static unsigned long accepted_count = 0L; |
|||
static unsigned long rejected_count = 0L; |
|||
static double *thr_hashrates; |
|||
static double *thr_times; |
|||
static uint32_t target = 0; |
|||
|
|||
pthread_mutex_t stats_lock; |
|||
|
|||
|
|||
static int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); |
|||
|
|||
|
|||
/**
|
|||
* @brief stats_init |
|||
*/ |
|||
void stats_init() { |
|||
pthread_mutex_init(&stats_lock, NULL); |
|||
|
|||
thr_hashrates = (double *) persistent_calloc(opt_n_threads, sizeof(double)); |
|||
thr_times = (double *) persistent_calloc(opt_n_threads, sizeof(double)); |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* @brief stats_set_target |
|||
* @param target |
|||
*/ |
|||
void stats_set_target(uint32_t new_target) |
|||
{ |
|||
target = new_target; |
|||
|
|||
applog(LOG_DEBUG, "Pool set diff to %g", ((double) 0xffffffff) / target); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief stats_share_result |
|||
* @param result |
|||
*/ |
|||
void stats_share_result(bool success) |
|||
{ |
|||
double hashrate = 0.0; |
|||
|
|||
pthread_mutex_lock(&stats_lock); |
|||
|
|||
for (int i = 0; i < opt_n_threads; i++) { |
|||
if (thr_times[i] > 0) { |
|||
hashrate += thr_hashrates[i] / thr_times[i]; |
|||
} |
|||
} |
|||
|
|||
success ? accepted_count++ : rejected_count++; |
|||
pthread_mutex_unlock(&stats_lock); |
|||
|
|||
applog(LOG_INFO, "accepted: %lu/%lu (%.2f%%), %.2f H/s at diff %g", |
|||
accepted_count, accepted_count + rejected_count, |
|||
100. * accepted_count / (accepted_count + rejected_count), hashrate, |
|||
(((double) 0xffffffff) / target)); |
|||
} |
|||
|
|||
|
|||
void stats_add_hashes(int thr_id, struct timeval *tv_start, unsigned long hashes_done) |
|||
{ |
|||
struct timeval tv_end, diff; |
|||
|
|||
/* record scanhash elapsed time */ |
|||
gettimeofday(&tv_end, NULL); |
|||
timeval_subtract(&diff, &tv_end, tv_start); |
|||
|
|||
if (diff.tv_usec || diff.tv_sec) { |
|||
pthread_mutex_lock(&stats_lock); |
|||
thr_hashrates[thr_id] = hashes_done; |
|||
thr_times[thr_id] = (diff.tv_sec + 1e-6 * diff.tv_usec); |
|||
pthread_mutex_unlock(&stats_lock); |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Subtract the `struct timeval' values X and Y,
|
|||
storing the result in RESULT. |
|||
Return 1 if the difference is negative, otherwise 0. */ |
|||
static int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) |
|||
{ |
|||
/* Perform the carry for the later subtraction by updating Y. */ |
|||
if (x->tv_usec < y->tv_usec) { |
|||
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; |
|||
y->tv_usec -= 1000000 * nsec; |
|||
y->tv_sec += nsec; |
|||
} |
|||
if (x->tv_usec - y->tv_usec > 1000000) { |
|||
int nsec = (x->tv_usec - y->tv_usec) / 1000000; |
|||
y->tv_usec += 1000000 * nsec; |
|||
y->tv_sec -= nsec; |
|||
} |
|||
|
|||
/* Compute the time remaining to wait.
|
|||
* `tv_usec' is certainly positive. */ |
|||
result->tv_sec = x->tv_sec - y->tv_sec; |
|||
result->tv_usec = x->tv_usec - y->tv_usec; |
|||
|
|||
/* Return 1 if result is negative. */ |
|||
return x->tv_sec < y->tv_sec; |
|||
} |
@ -0,0 +1,37 @@ |
|||
/* 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 __STATS_H__ |
|||
#define __STATS_H__ |
|||
|
|||
#include <stdbool.h> |
|||
#include <inttypes.h> |
|||
|
|||
|
|||
void stats_init(); |
|||
void stats_set_target(uint32_t new_target); |
|||
void stats_share_result(bool success); |
|||
void stats_add_hashes(int thr_id, struct timeval *tv_start, unsigned long hashes_done); |
|||
|
|||
|
|||
#endif /* __STATS_H__ */ |
@ -0,0 +1,707 @@ |
|||
/* 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 <stdlib.h> |
|||
#include <pthread.h> |
|||
#include <jansson.h> |
|||
#include <unistd.h> |
|||
|
|||
#if defined(WIN32) |
|||
# include <winsock2.h> |
|||
# include <mstcpip.h> |
|||
#else |
|||
# include <errno.h> |
|||
# include <netinet/tcp.h> |
|||
# include <poll.h> |
|||
#endif |
|||
|
|||
#include "stratum.h" |
|||
#include "version.h" |
|||
#include "stats.h" |
|||
#include "util.h" |
|||
#include "utils/applog.h" |
|||
|
|||
|
|||
#ifdef WIN32 |
|||
# define socket_blocks() (WSAGetLastError() == WSAEWOULDBLOCK) |
|||
# define poll(fdarray, nfds, timeout) WSAPoll(fdarray, nfds, timeout) |
|||
# define SHUT_RDWR SD_BOTH |
|||
#else |
|||
# define socket_blocks() (errno == EAGAIN || errno == EWOULDBLOCK) |
|||
# define closesocket(x) close((x)) |
|||
#endif |
|||
|
|||
#define RBUFSIZE 2048 |
|||
#define RECVSIZE (RBUFSIZE - 4) |
|||
|
|||
#define unlikely(expr) (__builtin_expect(!!(expr), 0)) |
|||
|
|||
|
|||
static bool send_line(curl_socket_t sock, char *s); |
|||
static bool socket_full(curl_socket_t sock, int timeout); |
|||
static void buffer_append(struct stratum_ctx *sctx, const char *s); |
|||
static bool job(struct stratum_ctx *sctx, json_t *params); |
|||
static int sockopt_keepalive_cb(void *userdata, curl_socket_t fd, curlsocktype purpose); |
|||
static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose, struct curl_sockaddr *addr); |
|||
static int closesocket_cb(void *clientp, curl_socket_t item); |
|||
static bool login_decode(struct stratum_ctx *sctx, const json_t *val); |
|||
static bool job_decode(struct stratum_ctx *sctx, const json_t *job); |
|||
static bool jobj_binary(const json_t *obj, const char *key, void *buf, size_t buflen); |
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_socket_full |
|||
* @param sctx |
|||
* @param timeout |
|||
* @return |
|||
*/ |
|||
bool stratum_socket_full(struct stratum_ctx *sctx, int timeout) |
|||
{ |
|||
return strlen(sctx->sockbuf) || socket_full(sctx->sock, timeout); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_send_line |
|||
* @param sctx |
|||
* @param s |
|||
* @return |
|||
*/ |
|||
bool stratum_send_line(struct stratum_ctx *sctx, char *s) |
|||
{ |
|||
bool ret = false; |
|||
|
|||
pthread_mutex_lock(&sctx->sock_lock); |
|||
ret = send_line(sctx->sock, s); |
|||
pthread_mutex_unlock(&sctx->sock_lock); |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_recv_line |
|||
* @param sctx |
|||
* @return |
|||
*/ |
|||
char *stratum_recv_line(struct stratum_ctx *sctx) |
|||
{ |
|||
if (!strstr(sctx->sockbuf, "\n")) { |
|||
bool ret = true; |
|||
time_t rstart; |
|||
|
|||
time(&rstart); |
|||
|
|||
if (!socket_full(sctx->sock, 60)) { |
|||
applog(LOG_ERR, "stratum_recv_line timed out"); |
|||
return NULL; |
|||
} |
|||
|
|||
do { |
|||
char s[RBUFSIZE]; |
|||
ssize_t n; |
|||
|
|||
memset(s, 0, RBUFSIZE); |
|||
n = recv(sctx->sock, s, RECVSIZE, 0); |
|||
if (!n) { |
|||
ret = false; |
|||
break; |
|||
} |
|||
|
|||
if (n < 0) { |
|||
if (!socket_blocks() || !socket_full(sctx->sock, 1)) { |
|||
ret = false; |
|||
break; |
|||
} |
|||
} else { |
|||
buffer_append(sctx, s); |
|||
} |
|||
} while (time(NULL) - rstart < 60 && !strstr(sctx->sockbuf, "\n")); |
|||
|
|||
if (!ret) { |
|||
applog(LOG_ERR, "stratum_recv_line failed"); |
|||
return NULL; |
|||
} |
|||
} |
|||
|
|||
ssize_t buflen = strlen(sctx->sockbuf); |
|||
char *tok = strtok(sctx->sockbuf, "\n"); |
|||
|
|||
if (!tok) { |
|||
applog(LOG_ERR, "stratum_recv_line failed to parse a newline-terminated string"); |
|||
return NULL; |
|||
} |
|||
|
|||
char *sret = strdup(tok); |
|||
ssize_t len = strlen(sret); |
|||
|
|||
if (buflen > len + 1) { |
|||
memmove(sctx->sockbuf, sctx->sockbuf + len + 1, buflen - len + 1); |
|||
} |
|||
else { |
|||
sctx->sockbuf[0] = '\0'; |
|||
} |
|||
|
|||
return sret; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_disconnect |
|||
* @param sctx |
|||
*/ |
|||
void stratum_disconnect(struct stratum_ctx *sctx) |
|||
{ |
|||
pthread_mutex_lock(&sctx->sock_lock); |
|||
|
|||
sctx->ready = false; |
|||
|
|||
if (sctx->curl) { |
|||
curl_easy_cleanup(sctx->curl); |
|||
sctx->curl = NULL; |
|||
sctx->sockbuf[0] = '\0'; |
|||
} |
|||
|
|||
pthread_mutex_unlock(&sctx->sock_lock); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_handle_method |
|||
* @param sctx |
|||
* @param s |
|||
* @return |
|||
*/ |
|||
bool stratum_handle_method(struct stratum_ctx *sctx, const char *s) |
|||
{ |
|||
bool ret = false; |
|||
const char *method; |
|||
json_t *val = json_decode(s); |
|||
|
|||
if (!val) { |
|||
return false; |
|||
} |
|||
|
|||
if (method = json_string_value(json_object_get(val, "method"))) { |
|||
if (!strcasecmp(method, "job")) { |
|||
ret = job(sctx, json_object_get(val, "params")); |
|||
} |
|||
else { |
|||
applog(LOG_WARNING, "Unknown method: \"%s\"", method); |
|||
} |
|||
} |
|||
|
|||
json_decref(val); |
|||
return ret; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_handle_response |
|||
* @param buf |
|||
* @return |
|||
*/ |
|||
bool stratum_handle_response(char *buf) { |
|||
bool valid = false; |
|||
|
|||
json_t *val = json_decode(buf); |
|||
if (!val) { |
|||
return false; |
|||
} |
|||
|
|||
json_t *res_val = json_object_get(val, "result"); |
|||
json_t *err_val = json_object_get(val, "error"); |
|||
json_t *id_val = json_object_get(val, "id"); |
|||
|
|||
if (!id_val || json_is_null(id_val) || !res_val) { |
|||
json_decref(val); |
|||
return false; |
|||
} |
|||
|
|||
json_t *status = json_object_get(res_val, "status"); |
|||
|
|||
if (!strcmp(json_string_value(status), "KEEPALIVED") ) { |
|||
applog(LOG_DEBUG, "Keepalived receveid"); |
|||
json_decref(val); |
|||
return true; |
|||
} |
|||
|
|||
if (status) { |
|||
valid = !strcmp(json_string_value(status), "OK") && json_is_null(err_val); |
|||
} else { |
|||
valid = json_is_null(err_val); |
|||
} |
|||
|
|||
stats_share_result(valid); |
|||
json_decref(val); |
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_keepalived |
|||
* @param sctx |
|||
* @return |
|||
*/ |
|||
bool stratum_keepalived(struct stratum_ctx *sctx) |
|||
{ |
|||
char *s = malloc(128); |
|||
snprintf(s, 128, "{\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"},\"id\":1}", sctx->id); |
|||
bool ret = stratum_send_line(sctx, s); |
|||
|
|||
free(s); |
|||
return ret; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_authorize |
|||
* @param sctx |
|||
* @param user |
|||
* @param pass |
|||
* @return |
|||
*/ |
|||
bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *pass) |
|||
{ |
|||
char *sret; |
|||
json_error_t err; |
|||
|
|||
char *req = malloc(128 + strlen(user) + strlen(pass)); |
|||
sprintf(req, "{\"method\":\"login\",\"params\":{\"login\":\"%s\",\"pass\":\"%s\",\"agent\":\"%s/%s\"},\"id\":1}", user, pass, APP_NAME, APP_VERSION); |
|||
|
|||
if (!stratum_send_line(sctx, req)) { |
|||
free(req); |
|||
return false; |
|||
} |
|||
|
|||
free(req); |
|||
|
|||
while (1) { |
|||
sret = stratum_recv_line(sctx); |
|||
if (!sret) { |
|||
return false; |
|||
} |
|||
|
|||
if (!stratum_handle_method(sctx, sret)) { |
|||
break; |
|||
} |
|||
|
|||
free(sret); |
|||
} |
|||
|
|||
json_t *val = json_decode(sret); |
|||
free(sret); |
|||
|
|||
if (!val) { |
|||
return false; |
|||
} |
|||
|
|||
json_t *result = json_object_get(val, "result"); |
|||
json_t *error = json_object_get(val, "error"); |
|||
|
|||
if (!result || json_is_false(result) || (error && !json_is_null(error))) { |
|||
applog(LOG_ERR, "Stratum authentication failed"); |
|||
json_decref(val); |
|||
return false; |
|||
} |
|||
|
|||
login_decode(sctx, val); |
|||
json_t *job = json_object_get(result, "job"); |
|||
|
|||
pthread_mutex_lock(&sctx->work_lock); |
|||
if (job) { |
|||
job_decode(sctx, job); |
|||
} |
|||
pthread_mutex_unlock(&sctx->work_lock); |
|||
|
|||
json_decref(val); |
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_connect |
|||
* @param sctx |
|||
* @param url |
|||
* @return |
|||
*/ |
|||
bool stratum_connect(struct stratum_ctx *sctx, const char *url) |
|||
{ |
|||
CURL *curl; |
|||
|
|||
pthread_mutex_lock(&sctx->sock_lock); |
|||
sctx->ready = false; |
|||
|
|||
if (sctx->curl) { |
|||
curl_easy_cleanup(sctx->curl); |
|||
} |
|||
|
|||
sctx->curl = curl_easy_init(); |
|||
if (!sctx->curl) { |
|||
applog(LOG_ERR, "CURL initialization failed"); |
|||
pthread_mutex_unlock(&sctx->sock_lock); |
|||
return false; |
|||
} |
|||
|
|||
curl = sctx->curl; |
|||
if (!sctx->sockbuf) { |
|||
sctx->sockbuf = calloc(RBUFSIZE, 1); |
|||
sctx->sockbuf_size = RBUFSIZE; |
|||
} |
|||
|
|||
sctx->sockbuf[0] = '\0'; |
|||
pthread_mutex_unlock(&sctx->sock_lock); |
|||
|
|||
if (url != sctx->url) { |
|||
free(sctx->url); |
|||
sctx->url = strdup(url); |
|||
} |
|||
|
|||
free(sctx->curl_url); |
|||
sctx->curl_url = malloc(strlen(url)); |
|||
sprintf(sctx->curl_url, "http%s/", strstr(url, "://")); |
|||
|
|||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 0); |
|||
curl_easy_setopt(curl, CURLOPT_URL, sctx->curl_url); |
|||
curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1); |
|||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30); |
|||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, sctx->curl_err_str); |
|||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); |
|||
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1); |
|||
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb); |
|||
curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket_grab_cb); |
|||
curl_easy_setopt(curl, CURLOPT_CLOSESOCKETFUNCTION, closesocket_cb); |
|||
curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sctx->sock); |
|||
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1); |
|||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); |
|||
|
|||
int rc = curl_easy_perform(curl); |
|||
if (rc) { |
|||
applog(LOG_ERR, "Stratum connection failed: code: %d, text: %s", rc, sctx->curl_err_str); |
|||
curl_easy_cleanup(curl); |
|||
sctx->curl = NULL; |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief send_line |
|||
* @param sock |
|||
* @param s |
|||
* @return |
|||
*/ |
|||
static bool send_line(curl_socket_t sock, char *s) |
|||
{ |
|||
ssize_t len, sent = 0; |
|||
|
|||
len = strlen(s); |
|||
s[len++] = '\n'; |
|||
|
|||
while (len > 0) { |
|||
struct pollfd pfd; |
|||
pfd.fd = sock; |
|||
pfd.events = POLLOUT; |
|||
|
|||
if (poll(&pfd, 1, 0) < 1) { |
|||
return false; |
|||
} |
|||
|
|||
ssize_t n = send(sock, s + sent, len, 0); |
|||
if (n < 0) { |
|||
if (!socket_blocks()) { |
|||
return false; |
|||
} |
|||
|
|||
n = 0; |
|||
} |
|||
|
|||
sent += n; |
|||
len -= n; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief socket_full |
|||
* @param sock |
|||
* @param timeout |
|||
* @return |
|||
*/ |
|||
static bool socket_full(curl_socket_t sock, int timeout) |
|||
{ |
|||
struct pollfd pfd; |
|||
pfd.fd = sock; |
|||
pfd.events = POLLIN; |
|||
|
|||
return poll(&pfd, 1, timeout * 1000) > 0; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief buffer_append |
|||
* @param sctx |
|||
* @param s |
|||
*/ |
|||
static void buffer_append(struct stratum_ctx *sctx, const char *s) |
|||
{ |
|||
size_t old, new; |
|||
|
|||
old = strlen(sctx->sockbuf); |
|||
new = old + strlen(s) + 1; |
|||
|
|||
if (new >= sctx->sockbuf_size) { |
|||
sctx->sockbuf_size = new + (RBUFSIZE - (new % RBUFSIZE)); |
|||
sctx->sockbuf = realloc(sctx->sockbuf, sctx->sockbuf_size); |
|||
} |
|||
|
|||
strcpy(sctx->sockbuf + old, s); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief job |
|||
* @param sctx |
|||
* @param params |
|||
* @return |
|||
*/ |
|||
static bool job(struct stratum_ctx *sctx, json_t *params) |
|||
{ |
|||
bool ret = false; |
|||
pthread_mutex_lock(&sctx->work_lock); |
|||
ret = job_decode(sctx, params); |
|||
pthread_mutex_unlock(&sctx->work_lock); |
|||
return ret; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief sockopt_keepalive_cb |
|||
* @param userdata |
|||
* @param fd |
|||
* @param purpose |
|||
* @return |
|||
*/ |
|||
static int sockopt_keepalive_cb(void *userdata, curl_socket_t fd, curlsocktype purpose) |
|||
{ |
|||
int keepalive = 1; |
|||
int tcp_keepcnt = 3; |
|||
int tcp_keepidle = 50; |
|||
int tcp_keepintvl = 50; |
|||
|
|||
#ifndef WIN32 |
|||
if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, |
|||
sizeof(keepalive)))) |
|||
return 1; |
|||
#ifdef __linux |
|||
if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT, |
|||
&tcp_keepcnt, sizeof(tcp_keepcnt)))) |
|||
return 1; |
|||
if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, |
|||
&tcp_keepidle, sizeof(tcp_keepidle)))) |
|||
return 1; |
|||
if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, |
|||
&tcp_keepintvl, sizeof(tcp_keepintvl)))) |
|||
return 1; |
|||
#endif /* __linux */ |
|||
#ifdef __APPLE_CC__ |
|||
if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, |
|||
&tcp_keepintvl, sizeof(tcp_keepintvl)))) |
|||
return 1; |
|||
#endif /* __APPLE_CC__ */ |
|||
#else /* WIN32 */ |
|||
struct tcp_keepalive vals; |
|||
vals.onoff = 1; |
|||
vals.keepalivetime = tcp_keepidle * 1000; |
|||
vals.keepaliveinterval = tcp_keepintvl * 1000; |
|||
DWORD outputBytes; |
|||
if (unlikely(WSAIoctl(fd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals), NULL, 0, &outputBytes, NULL, NULL))) { |
|||
return 1; |
|||
} |
|||
|
|||
#endif /* WIN32 */ |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
static int closesocket_cb(void *clientp, curl_socket_t item) { |
|||
shutdown(item, SHUT_RDWR); |
|||
return closesocket(item); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief opensocket_grab_cb |
|||
* @param clientp |
|||
* @param purpose |
|||
* @param addr |
|||
* @return |
|||
*/ |
|||
static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose, struct curl_sockaddr *addr) |
|||
{ |
|||
curl_socket_t *sock = clientp; |
|||
*sock = socket(addr->family, addr->socktype, addr->protocol); |
|||
return *sock; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief login_decode |
|||
* @param sctx |
|||
* @param val |
|||
* @return |
|||
*/ |
|||
static bool login_decode(struct stratum_ctx *sctx, const json_t *val) { |
|||
json_t *res = json_object_get(val, "result"); |
|||
if (!res) { |
|||
applog(LOG_ERR, "JSON invalid result"); |
|||
return false; |
|||
} |
|||
|
|||
json_t *tmp = json_object_get(res, "id"); |
|||
if (!tmp) { |
|||
applog(LOG_ERR, "JSON invalid id"); |
|||
return false; |
|||
} |
|||
|
|||
const char *id = json_string_value(tmp); |
|||
if (!id) { |
|||
applog(LOG_ERR, "JSON id is not a string"); |
|||
return false; |
|||
} |
|||
|
|||
memcpy(&sctx->id, id, 64); |
|||
|
|||
pthread_mutex_lock(&sctx->sock_lock); |
|||
sctx->ready = true; |
|||
pthread_mutex_unlock(&sctx->sock_lock); |
|||
|
|||
tmp = json_object_get(res, "status"); |
|||
if (!tmp) { |
|||
applog(LOG_ERR, "JSON invalid status"); |
|||
return false; |
|||
} |
|||
|
|||
const char *s = json_string_value(tmp); |
|||
if (!s) { |
|||
applog(LOG_ERR, "JSON status is not a string"); |
|||
return false; |
|||
} |
|||
|
|||
if (strcmp(s, "OK")) { |
|||
applog(LOG_ERR, "JSON returned status \"%s\"", s); |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief job_decode |
|||
* @param sctx |
|||
* @param job |
|||
* @param work |
|||
* @return |
|||
*/ |
|||
static bool job_decode(struct stratum_ctx *sctx, const json_t *job) { |
|||
json_t *tmp = json_object_get(job, "job_id"); |
|||
if (!tmp) { |
|||
applog(LOG_ERR, "JSON invalid job id"); |
|||
return false; |
|||
} |
|||
|
|||
const char *job_id = json_string_value(tmp); |
|||
tmp = json_object_get(job, "blob"); |
|||
if (!tmp) { |
|||
applog(LOG_ERR, "JSON invalid blob"); |
|||
return false; |
|||
} |
|||
|
|||
const char *hexblob = json_string_value(tmp); |
|||
if (!hexblob || strlen(hexblob) != 152) { |
|||
applog(LOG_ERR, "JSON invalid blob length"); |
|||
return false; |
|||
} |
|||
|
|||
if (!hex2bin(sctx->blob, hexblob, 76)) { |
|||
applog(LOG_ERR, "JSON inval blob"); |
|||
return false; |
|||
} |
|||
|
|||
uint32_t target; |
|||
jobj_binary(job, "target", &target, 4); |
|||
|
|||
if (sctx->target != target) { |
|||
stats_set_target(target); |
|||
sctx->target = target; |
|||
} |
|||
|
|||
memcpy(sctx->work.data, sctx->blob, 76); |
|||
memset(sctx->work.target, 0xff, sizeof(sctx->work.target)); |
|||
|
|||
sctx->work.target[7] = sctx->target; |
|||
|
|||
free(sctx->work.job_id); |
|||
sctx->work.job_id = strdup(job_id); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief jobj_binary |
|||
* @param obj |
|||
* @param key |
|||
* @param buf |
|||
* @param buflen |
|||
* @return |
|||
*/ |
|||
static bool jobj_binary(const json_t *obj, const char *key, void *buf, size_t buflen) { |
|||
const char *hexstr; |
|||
json_t *tmp; |
|||
|
|||
tmp = json_object_get(obj, key); |
|||
if (unlikely(!tmp)) { |
|||
applog(LOG_ERR, "JSON key '%s' not found", key); |
|||
return false; |
|||
} |
|||
|
|||
hexstr = json_string_value(tmp); |
|||
if (unlikely(!hexstr)) { |
|||
applog(LOG_ERR, "JSON key '%s' is not a string", key); |
|||
return false; |
|||
} |
|||
|
|||
if (!hex2bin(buf, hexstr, buflen)) { |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
@ -0,0 +1,76 @@ |
|||
/* 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 __STRATUM_H__ |
|||
#define __STRATUM_H__ |
|||
|
|||
#include <stdbool.h> |
|||
#include <inttypes.h> |
|||
#include <curl/curl.h> |
|||
|
|||
|
|||
struct work { |
|||
uint32_t data[19]; |
|||
uint32_t target[8]; |
|||
uint32_t hash[8]; |
|||
|
|||
char *job_id; |
|||
size_t xnonce2_len; |
|||
unsigned char *xnonce2; |
|||
}; |
|||
|
|||
|
|||
struct stratum_ctx { |
|||
char *url; |
|||
|
|||
CURL *curl; |
|||
char *curl_url; |
|||
char curl_err_str[CURL_ERROR_SIZE]; |
|||
curl_socket_t sock; |
|||
size_t sockbuf_size; |
|||
char *sockbuf; |
|||
pthread_mutex_t sock_lock; |
|||
bool ready; |
|||
|
|||
char id[64]; |
|||
char blob[76]; |
|||
uint32_t target; |
|||
|
|||
struct work work; |
|||
struct work g_work; |
|||
time_t g_work_time; |
|||
pthread_mutex_t work_lock; |
|||
}; |
|||
|
|||
|
|||
bool stratum_send_line(struct stratum_ctx *sctx, char *s); |
|||
bool stratum_socket_full(struct stratum_ctx *sctx, int timeout); |
|||
char *stratum_recv_line(struct stratum_ctx *sctx); |
|||
bool stratum_connect(struct stratum_ctx *sctx, const char *url); |
|||
void stratum_disconnect(struct stratum_ctx *sctx); |
|||
bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *pass); |
|||
bool stratum_handle_method(struct stratum_ctx *sctx, const char *s); |
|||
bool stratum_handle_response(char *buf); |
|||
bool stratum_keepalived(struct stratum_ctx *sctx); |
|||
|
|||
#endif /* __STRATUM_H__ */ |
@ -0,0 +1,7 @@ |
|||
project("xmrig-test" C) |
|||
cmake_minimum_required(VERSION 3.0) |
|||
|
|||
include(CTest) |
|||
|
|||
add_subdirectory(unity) |
|||
add_subdirectory(cryptonight) |
@ -0,0 +1,44 @@ |
|||
set(SOURCES |
|||
../../algo/cryptonight/cryptonight.h |
|||
../../algo/cryptonight/cryptonight_common.c |
|||
../../algo/cryptonight/cryptonight_av4_legacy.c |
|||
../../crypto/c_keccak.c |
|||
../../crypto/c_blake256.c |
|||
../../crypto/c_groestl.c |
|||
../../crypto/c_jh.c |
|||
../../crypto/c_skein.c |
|||
../../crypto/oaes_config.h |
|||
../../crypto/oaes_lib.h |
|||
../../crypto/oaes_lib.c |
|||
../../crypto/aesb.c |
|||
) |
|||
|
|||
if (CMAKE_SIZEOF_VOID_P EQUAL 8) |
|||
add_subdirectory(bmi2) |
|||
|
|||
add_executable(cryptonight_app ${SOURCES} |
|||
cryptonight.c |
|||
../../algo/cryptonight/cryptonight_av1_aesni.c |
|||
../../algo/cryptonight/cryptonight_av2_aesni_wolf.c |
|||
../../algo/cryptonight/cryptonight_av5_aesni_experimental.c |
|||
) |
|||
|
|||
target_link_libraries(cryptonight_app unity cryptonight_av3_aesni_bmi2) |
|||
else() |
|||
add_executable(cryptonight_app ${SOURCES} |
|||
cryptonight32.c |
|||
../../algo/cryptonight/cryptonight_av1_aesni32.c |
|||
) |
|||
|
|||
target_link_libraries(cryptonight_app unity) |
|||
endif() |
|||
|
|||
|
|||
|
|||
include_directories(../..) |
|||
|
|||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -fno-strict-aliasing") |
|||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2") |
|||
add_definitions(-DBUILD_TEST) |
|||
|
|||
add_test(cryptonight_test cryptonight_app) |
@ -0,0 +1,3 @@ |
|||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -mbmi2") |
|||
include_directories(../../..) |
|||
add_library(cryptonight_av3_aesni_bmi2 STATIC ../../../algo/cryptonight/cryptonight_av3_aesni_bmi2.c) |
@ -0,0 +1,158 @@ |
|||
#include <unity.h> |
|||
#include <stdbool.h> |
|||
#include <stdlib.h> |
|||
#include <algo/cryptonight/cryptonight.h> |
|||
|
|||
|
|||
void cryptonight_av1_aesni(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
void cryptonight_av2_aesni_wolf(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
void cryptonight_av3_aesni_bmi2(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
void cryptonight_av4_legacy(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
void cryptonight_av5_aesni_experimental(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
|
|||
|
|||
char *bin2hex(const unsigned char *p, size_t len) |
|||
{ |
|||
int i; |
|||
char *s = malloc((len * 2) + 1); |
|||
if (!s) |
|||
return NULL; |
|||
|
|||
for (i = 0; i < len; i++) |
|||
sprintf(s + (i * 2), "%02x", (unsigned int) p[i]); |
|||
|
|||
return s; |
|||
} |
|||
|
|||
bool hex2bin(unsigned char *p, const char *hexstr, size_t len) |
|||
{ |
|||
char hex_byte[3]; |
|||
char *ep; |
|||
|
|||
hex_byte[2] = '\0'; |
|||
|
|||
while (*hexstr && len) { |
|||
if (!hexstr[1]) { |
|||
return false; |
|||
} |
|||
hex_byte[0] = hexstr[0]; |
|||
hex_byte[1] = hexstr[1]; |
|||
*p = (unsigned char) strtol(hex_byte, &ep, 16); |
|||
if (*ep) { |
|||
return false; |
|||
} |
|||
p++; |
|||
hexstr += 2; |
|||
len--; |
|||
} |
|||
|
|||
return (len == 0 && *hexstr == 0) ? true : false; |
|||
} |
|||
|
|||
|
|||
void test_cryptonight_av1_should_CalcHash(void) { |
|||
char hash[32]; |
|||
char data[76]; |
|||
|
|||
hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); |
|||
|
|||
uint8_t *memory = (uint8_t *) malloc(MEMORY); |
|||
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); |
|||
|
|||
cryptonight_av1_aesni(&hash, data, memory, ctx); |
|||
|
|||
free(memory); |
|||
free(ctx); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); |
|||
} |
|||
|
|||
|
|||
void test_cryptonight_av2_should_CalcHash(void) |
|||
{ |
|||
char hash[32]; |
|||
char data[76]; |
|||
|
|||
hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); |
|||
|
|||
uint8_t *memory = (uint8_t *) malloc(MEMORY); |
|||
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); |
|||
|
|||
cryptonight_av2_aesni_wolf(&hash, data, memory, ctx); |
|||
|
|||
free(memory); |
|||
free(ctx); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); |
|||
} |
|||
|
|||
|
|||
void test_cryptonight_av3_should_CalcHash(void) |
|||
{ |
|||
char hash[32]; |
|||
char data[76]; |
|||
|
|||
hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); |
|||
|
|||
uint8_t *memory = (uint8_t *) malloc(MEMORY); |
|||
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); |
|||
|
|||
cryptonight_av3_aesni_bmi2(&hash, data, memory, ctx); |
|||
|
|||
free(memory); |
|||
free(ctx); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); |
|||
} |
|||
|
|||
|
|||
void test_cryptonight_av4_should_CalcHash(void) |
|||
{ |
|||
char hash[32]; |
|||
char data[76]; |
|||
|
|||
hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); |
|||
|
|||
uint8_t *memory = (uint8_t *) malloc(MEMORY); |
|||
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); |
|||
|
|||
cryptonight_av4_legacy(&hash, data, memory, ctx); |
|||
|
|||
free(memory); |
|||
free(ctx); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); |
|||
} |
|||
|
|||
|
|||
void test_cryptonight_av5_should_CalcHash(void) |
|||
{ |
|||
char hash[32]; |
|||
char data[76]; |
|||
|
|||
hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); |
|||
|
|||
uint8_t *memory = (uint8_t *) malloc(MEMORY); |
|||
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); |
|||
|
|||
cryptonight_av5_aesni_experimental(&hash, data, memory, ctx); |
|||
|
|||
free(memory); |
|||
free(ctx); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); |
|||
} |
|||
|
|||
|
|||
int main(void) |
|||
{ |
|||
UNITY_BEGIN(); |
|||
|
|||
RUN_TEST(test_cryptonight_av1_should_CalcHash); |
|||
RUN_TEST(test_cryptonight_av2_should_CalcHash); |
|||
RUN_TEST(test_cryptonight_av3_should_CalcHash); |
|||
RUN_TEST(test_cryptonight_av4_should_CalcHash); |
|||
RUN_TEST(test_cryptonight_av5_should_CalcHash); |
|||
|
|||
return UNITY_END(); |
|||
} |
@ -0,0 +1,95 @@ |
|||
#include <unity.h> |
|||
#include <stdbool.h> |
|||
#include <stdlib.h> |
|||
#include <algo/cryptonight/cryptonight.h> |
|||
|
|||
|
|||
void cryptonight_av1_aesni32(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
void cryptonight_av4_legacy(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); |
|||
|
|||
|
|||
char *bin2hex(const unsigned char *p, size_t len) |
|||
{ |
|||
int i; |
|||
char *s = malloc((len * 2) + 1); |
|||
if (!s) |
|||
return NULL; |
|||
|
|||
for (i = 0; i < len; i++) |
|||
sprintf(s + (i * 2), "%02x", (unsigned int) p[i]); |
|||
|
|||
return s; |
|||
} |
|||
|
|||
bool hex2bin(unsigned char *p, const char *hexstr, size_t len) |
|||
{ |
|||
char hex_byte[3]; |
|||
char *ep; |
|||
|
|||
hex_byte[2] = '\0'; |
|||
|
|||
while (*hexstr && len) { |
|||
if (!hexstr[1]) { |
|||
return false; |
|||
} |
|||
hex_byte[0] = hexstr[0]; |
|||
hex_byte[1] = hexstr[1]; |
|||
*p = (unsigned char) strtol(hex_byte, &ep, 16); |
|||
if (*ep) { |
|||
return false; |
|||
} |
|||
p++; |
|||
hexstr += 2; |
|||
len--; |
|||
} |
|||
|
|||
return (len == 0 && *hexstr == 0) ? true : false; |
|||
} |
|||
|
|||
|
|||
void test_cryptonight_av1_32_should_CalcHash(void) { |
|||
char hash[32]; |
|||
char data[76]; |
|||
|
|||
hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); |
|||
|
|||
uint8_t *memory = (uint8_t *) malloc(MEMORY); |
|||
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); |
|||
|
|||
cryptonight_av1_aesni32(&hash, data, memory, ctx); |
|||
|
|||
free(memory); |
|||
free(ctx); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); |
|||
} |
|||
|
|||
|
|||
void test_cryptonight_av4_should_CalcHash(void) |
|||
{ |
|||
char hash[32]; |
|||
char data[76]; |
|||
|
|||
hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); |
|||
|
|||
uint8_t *memory = (uint8_t *) malloc(MEMORY); |
|||
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); |
|||
|
|||
cryptonight_av4_legacy(&hash, data, memory, ctx); |
|||
|
|||
free(memory); |
|||
free(ctx); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); |
|||
} |
|||
|
|||
|
|||
int main(void) |
|||
{ |
|||
UNITY_BEGIN(); |
|||
|
|||
RUN_TEST(test_cryptonight_av1_32_should_CalcHash); |
|||
RUN_TEST(test_cryptonight_av4_should_CalcHash); |
|||
|
|||
return UNITY_END(); |
|||
} |
@ -0,0 +1,2 @@ |
|||
add_library(unity STATIC unity.c) |
|||
target_include_directories(unity PUBLIC .) |
File diff suppressed because it is too large
@ -0,0 +1,293 @@ |
|||
/* ==========================================
|
|||
Unity Project - A Test Framework for C |
|||
Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams |
|||
[Released under MIT License. Please refer to license.txt for details] |
|||
========================================== */ |
|||
|
|||
#ifndef UNITY_FRAMEWORK_H |
|||
#define UNITY_FRAMEWORK_H |
|||
#define UNITY |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" |
|||
{ |
|||
#endif |
|||
|
|||
#include "unity_internals.h" |
|||
|
|||
void setUp(void); |
|||
void tearDown(void); |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Configuration Options |
|||
*------------------------------------------------------- |
|||
* All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. |
|||
|
|||
* Integers/longs/pointers |
|||
* - Unity attempts to automatically discover your integer sizes |
|||
* - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h> |
|||
* - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h> |
|||
* - If you cannot use the automatic methods above, you can force Unity by using these options: |
|||
* - define UNITY_SUPPORT_64 |
|||
* - set UNITY_INT_WIDTH |
|||
* - set UNITY_LONG_WIDTH |
|||
* - set UNITY_POINTER_WIDTH |
|||
|
|||
* Floats |
|||
* - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons |
|||
* - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT |
|||
* - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats |
|||
* - define UNITY_FLOAT_VERBOSE to print floating point values in errors (uses sprintf) |
|||
* - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons |
|||
* - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) |
|||
* - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE |
|||
* - define UNITY_DOUBLE_TYPE to specify something other than double |
|||
* - define UNITY_DOUBLE_VERBOSE to print floating point values in errors (uses sprintf) |
|||
* - define UNITY_VERBOSE_NUMBER_MAX_LENGTH to change maximum length of printed numbers (used by sprintf) |
|||
|
|||
* Output |
|||
* - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired |
|||
* - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure |
|||
|
|||
* Optimization |
|||
* - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge |
|||
* - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. |
|||
|
|||
* Test Cases |
|||
* - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script |
|||
|
|||
* Parameterized Tests |
|||
* - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing |
|||
|
|||
* Tests with Arguments |
|||
* - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity |
|||
|
|||
*------------------------------------------------------- |
|||
* Basic Fail and Ignore |
|||
*-------------------------------------------------------*/ |
|||
|
|||
#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) |
|||
#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) |
|||
#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) |
|||
#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) |
|||
#define TEST_ONLY() |
|||
|
|||
/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
|
|||
* This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ |
|||
#define TEST_PASS() longjmp(Unity.AbortFrame, 1) |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Test Asserts (simple) |
|||
*-------------------------------------------------------*/ |
|||
|
|||
/* Boolean */ |
|||
#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") |
|||
#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") |
|||
#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") |
|||
#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") |
|||
#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") |
|||
#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") |
|||
|
|||
/* Integers (of all sizes) */ |
|||
#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") |
|||
#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(-1), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(0), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(-1), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(0), (actual), __LINE__, NULL) |
|||
|
|||
/* Integer Ranges (of all sizes) */ |
|||
#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
|
|||
/* Structs and Strings */ |
|||
#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) |
|||
|
|||
/* Arrays */ |
|||
#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) |
|||
|
|||
/* Floating Point (If Enabled) */ |
|||
#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) |
|||
|
|||
/* Double (If Enabled) */ |
|||
#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |
|||
#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) |
|||
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Test Asserts (with additional messages) |
|||
*-------------------------------------------------------*/ |
|||
|
|||
/* Boolean */ |
|||
#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) |
|||
#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) |
|||
#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) |
|||
#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) |
|||
#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) |
|||
#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) |
|||
|
|||
/* Integers (of all sizes) */ |
|||
#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(-1), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(0), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(-1), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(0), (actual), __LINE__, (message)) |
|||
|
|||
/* Integer Ranges (of all sizes) */ |
|||
#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
|
|||
/* Structs and Strings */ |
|||
#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) |
|||
|
|||
/* Arrays */ |
|||
#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) |
|||
|
|||
/* Floating Point (If Enabled) */ |
|||
#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) |
|||
|
|||
/* Double (If Enabled) */ |
|||
#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |
|||
#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) |
|||
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) |
|||
|
|||
/* end of UNITY_FRAMEWORK_H */ |
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
#endif |
@ -0,0 +1,749 @@ |
|||
/* ==========================================
|
|||
Unity Project - A Test Framework for C |
|||
Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams |
|||
[Released under MIT License. Please refer to license.txt for details] |
|||
========================================== */ |
|||
|
|||
#ifndef UNITY_INTERNALS_H |
|||
#define UNITY_INTERNALS_H |
|||
|
|||
#ifdef UNITY_INCLUDE_CONFIG_H |
|||
#include "unity_config.h" |
|||
#endif |
|||
|
|||
#include <setjmp.h> |
|||
|
|||
#ifndef UNITY_EXCLUDE_MATH_H |
|||
#include <math.h> |
|||
#endif |
|||
|
|||
/* Unity Attempts to Auto-Detect Integer Types
|
|||
* Attempt 1: UINT_MAX, ULONG_MAX in <limits.h>, or default to 32 bits |
|||
* Attempt 2: UINTPTR_MAX in <stdint.h>, or default to same size as long |
|||
* The user may override any of these derived constants: |
|||
* UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ |
|||
#ifndef UNITY_EXCLUDE_STDINT_H |
|||
#include <stdint.h> |
|||
#endif |
|||
|
|||
#ifndef UNITY_EXCLUDE_LIMITS_H |
|||
#include <limits.h> |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Guess Widths If Not Specified |
|||
*-------------------------------------------------------*/ |
|||
|
|||
/* Determine the size of an int, if not already specified.
|
|||
* We cannot use sizeof(int), because it is not yet defined |
|||
* at this stage in the translation of the C program. |
|||
* Therefore, infer it from UINT_MAX if possible. */ |
|||
#ifndef UNITY_INT_WIDTH |
|||
#ifdef UINT_MAX |
|||
#if (UINT_MAX == 0xFFFF) |
|||
#define UNITY_INT_WIDTH (16) |
|||
#elif (UINT_MAX == 0xFFFFFFFF) |
|||
#define UNITY_INT_WIDTH (32) |
|||
#elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) |
|||
#define UNITY_INT_WIDTH (64) |
|||
#endif |
|||
#else /* Set to default */ |
|||
#define UNITY_INT_WIDTH (32) |
|||
#endif /* UINT_MAX */ |
|||
#endif |
|||
|
|||
/* Determine the size of a long, if not already specified. */ |
|||
#ifndef UNITY_LONG_WIDTH |
|||
#ifdef ULONG_MAX |
|||
#if (ULONG_MAX == 0xFFFF) |
|||
#define UNITY_LONG_WIDTH (16) |
|||
#elif (ULONG_MAX == 0xFFFFFFFF) |
|||
#define UNITY_LONG_WIDTH (32) |
|||
#elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) |
|||
#define UNITY_LONG_WIDTH (64) |
|||
#endif |
|||
#else /* Set to default */ |
|||
#define UNITY_LONG_WIDTH (32) |
|||
#endif /* ULONG_MAX */ |
|||
#endif |
|||
|
|||
/* Determine the size of a pointer, if not already specified. */ |
|||
#ifndef UNITY_POINTER_WIDTH |
|||
#ifdef UINTPTR_MAX |
|||
#if (UINTPTR_MAX <= 0xFFFF) |
|||
#define UNITY_POINTER_WIDTH (16) |
|||
#elif (UINTPTR_MAX <= 0xFFFFFFFF) |
|||
#define UNITY_POINTER_WIDTH (32) |
|||
#elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) |
|||
#define UNITY_POINTER_WIDTH (64) |
|||
#endif |
|||
#else /* Set to default */ |
|||
#define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH |
|||
#endif /* UINTPTR_MAX */ |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Int Support (Define types based on detected sizes) |
|||
*-------------------------------------------------------*/ |
|||
|
|||
#if (UNITY_INT_WIDTH == 32) |
|||
typedef unsigned char _UU8; |
|||
typedef unsigned short _UU16; |
|||
typedef unsigned int _UU32; |
|||
typedef signed char _US8; |
|||
typedef signed short _US16; |
|||
typedef signed int _US32; |
|||
#elif (UNITY_INT_WIDTH == 16) |
|||
typedef unsigned char _UU8; |
|||
typedef unsigned int _UU16; |
|||
typedef unsigned long _UU32; |
|||
typedef signed char _US8; |
|||
typedef signed int _US16; |
|||
typedef signed long _US32; |
|||
#else |
|||
#error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* 64-bit Support |
|||
*-------------------------------------------------------*/ |
|||
|
|||
#ifndef UNITY_SUPPORT_64 |
|||
#if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 |
|||
#define UNITY_SUPPORT_64 |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef UNITY_SUPPORT_64 |
|||
/* No 64-bit Support */ |
|||
typedef _UU32 _U_UINT; |
|||
typedef _US32 _U_SINT; |
|||
#else |
|||
|
|||
/* 64-bit Support */ |
|||
#if (UNITY_LONG_WIDTH == 32) |
|||
typedef unsigned long long _UU64; |
|||
typedef signed long long _US64; |
|||
#elif (UNITY_LONG_WIDTH == 64) |
|||
typedef unsigned long _UU64; |
|||
typedef signed long _US64; |
|||
#else |
|||
#error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) |
|||
#endif |
|||
typedef _UU64 _U_UINT; |
|||
typedef _US64 _U_SINT; |
|||
|
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Pointer Support |
|||
*-------------------------------------------------------*/ |
|||
|
|||
#if (UNITY_POINTER_WIDTH == 32) |
|||
typedef _UU32 _UP; |
|||
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 |
|||
#elif (UNITY_POINTER_WIDTH == 64) |
|||
typedef _UU64 _UP; |
|||
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 |
|||
#elif (UNITY_POINTER_WIDTH == 16) |
|||
typedef _UU16 _UP; |
|||
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 |
|||
#else |
|||
#error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) |
|||
#endif |
|||
|
|||
#ifndef UNITY_PTR_ATTRIBUTE |
|||
#define UNITY_PTR_ATTRIBUTE |
|||
#endif |
|||
|
|||
#ifndef UNITY_INTERNAL_PTR |
|||
#define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* |
|||
/* #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const _UU8* */ |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Float Support |
|||
*-------------------------------------------------------*/ |
|||
|
|||
#ifdef UNITY_EXCLUDE_FLOAT |
|||
|
|||
/* No Floating Point Support */ |
|||
#undef UNITY_INCLUDE_FLOAT |
|||
#undef UNITY_FLOAT_PRECISION |
|||
#undef UNITY_FLOAT_TYPE |
|||
#undef UNITY_FLOAT_VERBOSE |
|||
|
|||
#else |
|||
|
|||
#ifndef UNITY_INCLUDE_FLOAT |
|||
#define UNITY_INCLUDE_FLOAT |
|||
#endif |
|||
|
|||
/* Floating Point Support */ |
|||
#ifndef UNITY_FLOAT_PRECISION |
|||
#define UNITY_FLOAT_PRECISION (0.00001f) |
|||
#endif |
|||
#ifndef UNITY_FLOAT_TYPE |
|||
#define UNITY_FLOAT_TYPE float |
|||
#endif |
|||
typedef UNITY_FLOAT_TYPE _UF; |
|||
|
|||
#ifndef isinf |
|||
/* The value of Inf - Inf is NaN */ |
|||
#define isinf(n) (isnan((n) - (n)) && !isnan(n)) |
|||
#endif |
|||
|
|||
#ifndef isnan |
|||
/* NaN is the only floating point value that does NOT equal itself.
|
|||
* Therefore if n != n, then it is NaN. */ |
|||
#define isnan(n) ((n != n) ? 1 : 0) |
|||
#endif |
|||
|
|||
#ifndef isneg |
|||
#define isneg(n) ((n < 0.0f) ? 1 : 0) |
|||
#endif |
|||
|
|||
#ifndef ispos |
|||
#define ispos(n) ((n > 0.0f) ? 1 : 0) |
|||
#endif |
|||
|
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Double Float Support |
|||
*-------------------------------------------------------*/ |
|||
|
|||
/* unlike FLOAT, we DON'T include by default */ |
|||
#ifndef UNITY_EXCLUDE_DOUBLE |
|||
#ifndef UNITY_INCLUDE_DOUBLE |
|||
#define UNITY_EXCLUDE_DOUBLE |
|||
#endif |
|||
#endif |
|||
|
|||
#ifdef UNITY_EXCLUDE_DOUBLE |
|||
|
|||
/* No Floating Point Support */ |
|||
#undef UNITY_DOUBLE_PRECISION |
|||
#undef UNITY_DOUBLE_TYPE |
|||
#undef UNITY_DOUBLE_VERBOSE |
|||
|
|||
#ifdef UNITY_INCLUDE_DOUBLE |
|||
#undef UNITY_INCLUDE_DOUBLE |
|||
#endif |
|||
|
|||
#ifdef UNITY_FLOAT_VERBOSE |
|||
typedef _UF _UD; |
|||
/* For parameter in UnityPrintFloat, double promotion required */ |
|||
#endif |
|||
|
|||
#else |
|||
|
|||
/* Double Floating Point Support */ |
|||
#ifndef UNITY_DOUBLE_PRECISION |
|||
#define UNITY_DOUBLE_PRECISION (1e-12f) |
|||
#endif |
|||
|
|||
#ifndef UNITY_DOUBLE_TYPE |
|||
#define UNITY_DOUBLE_TYPE double |
|||
#endif |
|||
typedef UNITY_DOUBLE_TYPE _UD; |
|||
|
|||
#endif |
|||
|
|||
#ifdef UNITY_DOUBLE_VERBOSE |
|||
#ifndef UNITY_FLOAT_VERBOSE |
|||
#define UNITY_FLOAT_VERBOSE |
|||
#endif |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Output Method: stdout (DEFAULT) |
|||
*-------------------------------------------------------*/ |
|||
#ifndef UNITY_OUTPUT_CHAR |
|||
/* Default to using putchar, which is defined in stdio.h */ |
|||
#include <stdio.h> |
|||
#define UNITY_OUTPUT_CHAR(a) (void)putchar(a) |
|||
#else |
|||
/* If defined as something else, make sure we declare it here so it's ready for use */ |
|||
#ifndef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION |
|||
extern void UNITY_OUTPUT_CHAR(int); |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef UNITY_OUTPUT_FLUSH |
|||
/* Default to using fflush, which is defined in stdio.h */ |
|||
#include <stdio.h> |
|||
#define UNITY_OUTPUT_FLUSH (void)fflush(stdout) |
|||
#else |
|||
/* If defined as something else, make sure we declare it here so it's ready for use */ |
|||
#ifndef UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION |
|||
extern void UNITY_OUTPUT_FLUSH(void); |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef UNITY_OUTPUT_FLUSH |
|||
#define UNITY_FLUSH_CALL() |
|||
#else |
|||
#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH |
|||
#endif |
|||
|
|||
#ifndef UNITY_PRINT_EOL |
|||
#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') |
|||
#endif |
|||
|
|||
#ifndef UNITY_OUTPUT_START |
|||
#define UNITY_OUTPUT_START() |
|||
#endif |
|||
|
|||
#ifndef UNITY_OUTPUT_COMPLETE |
|||
#define UNITY_OUTPUT_COMPLETE() |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Footprint |
|||
*-------------------------------------------------------*/ |
|||
|
|||
#ifndef UNITY_LINE_TYPE |
|||
#define UNITY_LINE_TYPE _U_UINT |
|||
#endif |
|||
|
|||
#ifndef UNITY_COUNTER_TYPE |
|||
#define UNITY_COUNTER_TYPE _U_UINT |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Language Features Available |
|||
*-------------------------------------------------------*/ |
|||
#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA) |
|||
# ifdef __GNUC__ /* includes clang */ |
|||
# if !(defined(__WIN32__) && defined(__clang__)) && !defined(__TMS470__) |
|||
# define UNITY_WEAK_ATTRIBUTE __attribute__((weak)) |
|||
# endif |
|||
# endif |
|||
#endif |
|||
|
|||
#ifdef UNITY_NO_WEAK |
|||
# undef UNITY_WEAK_ATTRIBUTE |
|||
# undef UNITY_WEAK_PRAGMA |
|||
#endif |
|||
|
|||
|
|||
/*-------------------------------------------------------
|
|||
* Internal Structs Needed |
|||
*-------------------------------------------------------*/ |
|||
|
|||
typedef void (*UnityTestFunction)(void); |
|||
|
|||
#define UNITY_DISPLAY_RANGE_INT (0x10) |
|||
#define UNITY_DISPLAY_RANGE_UINT (0x20) |
|||
#define UNITY_DISPLAY_RANGE_HEX (0x40) |
|||
#define UNITY_DISPLAY_RANGE_AUTO (0x80) |
|||
|
|||
typedef enum |
|||
{ |
|||
UNITY_DISPLAY_STYLE_INT = sizeof(int)+ UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO, |
|||
UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, |
|||
UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, |
|||
UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, |
|||
#ifdef UNITY_SUPPORT_64 |
|||
UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, |
|||
#endif |
|||
|
|||
UNITY_DISPLAY_STYLE_UINT = sizeof(unsigned) + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO, |
|||
UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, |
|||
UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, |
|||
UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, |
|||
#ifdef UNITY_SUPPORT_64 |
|||
UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, |
|||
#endif |
|||
|
|||
UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, |
|||
UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, |
|||
UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, |
|||
#ifdef UNITY_SUPPORT_64 |
|||
UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, |
|||
#endif |
|||
|
|||
UNITY_DISPLAY_STYLE_UNKNOWN |
|||
} UNITY_DISPLAY_STYLE_T; |
|||
|
|||
#ifndef UNITY_EXCLUDE_FLOAT |
|||
typedef enum _UNITY_FLOAT_TRAIT_T |
|||
{ |
|||
UNITY_FLOAT_IS_NOT_INF = 0, |
|||
UNITY_FLOAT_IS_INF, |
|||
UNITY_FLOAT_IS_NOT_NEG_INF, |
|||
UNITY_FLOAT_IS_NEG_INF, |
|||
UNITY_FLOAT_IS_NOT_NAN, |
|||
UNITY_FLOAT_IS_NAN, |
|||
UNITY_FLOAT_IS_NOT_DET, |
|||
UNITY_FLOAT_IS_DET, |
|||
UNITY_FLOAT_INVALID_TRAIT |
|||
} UNITY_FLOAT_TRAIT_T; |
|||
#endif |
|||
|
|||
struct _Unity |
|||
{ |
|||
const char* TestFile; |
|||
const char* CurrentTestName; |
|||
#ifndef UNITY_EXCLUDE_DETAILS |
|||
const char* CurrentDetail1; |
|||
const char* CurrentDetail2; |
|||
#endif |
|||
UNITY_LINE_TYPE CurrentTestLineNumber; |
|||
UNITY_COUNTER_TYPE NumberOfTests; |
|||
UNITY_COUNTER_TYPE TestFailures; |
|||
UNITY_COUNTER_TYPE TestIgnores; |
|||
UNITY_COUNTER_TYPE CurrentTestFailed; |
|||
UNITY_COUNTER_TYPE CurrentTestIgnored; |
|||
jmp_buf AbortFrame; |
|||
}; |
|||
|
|||
extern struct _Unity Unity; |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Test Suite Management |
|||
*-------------------------------------------------------*/ |
|||
|
|||
void UnityBegin(const char* filename); |
|||
int UnityEnd(void); |
|||
void UnityConcludeTest(void); |
|||
void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Details Support |
|||
*-------------------------------------------------------*/ |
|||
|
|||
#ifdef UNITY_EXCLUDE_DETAILS |
|||
#define UNITY_CLR_DETAILS() |
|||
#define UNITY_SET_DETAIL(d1) |
|||
#define UNITY_SET_DETAILS(d1,d2) |
|||
#else |
|||
#define UNITY_CLR_DETAILS() { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } |
|||
#define UNITY_SET_DETAIL(d1) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = 0; } |
|||
#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = d2; } |
|||
|
|||
#ifndef UNITY_DETAIL1_NAME |
|||
#define UNITY_DETAIL1_NAME "Function" |
|||
#endif |
|||
|
|||
#ifndef UNITY_DETAIL2_NAME |
|||
#define UNITY_DETAIL2_NAME "Argument" |
|||
#endif |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Test Output |
|||
*-------------------------------------------------------*/ |
|||
|
|||
void UnityPrint(const char* string); |
|||
void UnityPrintMask(const _U_UINT mask, const _U_UINT number); |
|||
void UnityPrintNumberByStyle(const _U_SINT number, const UNITY_DISPLAY_STYLE_T style); |
|||
void UnityPrintNumber(const _U_SINT number); |
|||
void UnityPrintNumberUnsigned(const _U_UINT number); |
|||
void UnityPrintNumberHex(const _U_UINT number, const char nibbles); |
|||
|
|||
#ifdef UNITY_FLOAT_VERBOSE |
|||
void UnityPrintFloat(const _UD number); |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Test Assertion Functions |
|||
*------------------------------------------------------- |
|||
* Use the macros below this section instead of calling |
|||
* these directly. The macros have a consistent naming |
|||
* convention and will pull in file and line information |
|||
* for you. */ |
|||
|
|||
void UnityAssertEqualNumber(const _U_SINT expected, |
|||
const _U_SINT actual, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber, |
|||
const UNITY_DISPLAY_STYLE_T style); |
|||
|
|||
void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, |
|||
UNITY_INTERNAL_PTR actual, |
|||
const _UU32 num_elements, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber, |
|||
const UNITY_DISPLAY_STYLE_T style); |
|||
|
|||
void UnityAssertBits(const _U_SINT mask, |
|||
const _U_SINT expected, |
|||
const _U_SINT actual, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber); |
|||
|
|||
void UnityAssertEqualString(const char* expected, |
|||
const char* actual, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber); |
|||
|
|||
void UnityAssertEqualStringLen(const char* expected, |
|||
const char* actual, |
|||
const _UU32 length, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber); |
|||
|
|||
void UnityAssertEqualStringArray( const char** expected, |
|||
const char** actual, |
|||
const _UU32 num_elements, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber); |
|||
|
|||
void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, |
|||
UNITY_INTERNAL_PTR actual, |
|||
const _UU32 length, |
|||
const _UU32 num_elements, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber); |
|||
|
|||
void UnityAssertNumbersWithin(const _U_UINT delta, |
|||
const _U_SINT expected, |
|||
const _U_SINT actual, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber, |
|||
const UNITY_DISPLAY_STYLE_T style); |
|||
|
|||
void UnityFail(const char* message, const UNITY_LINE_TYPE line); |
|||
|
|||
void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); |
|||
|
|||
#ifndef UNITY_EXCLUDE_FLOAT |
|||
void UnityAssertFloatsWithin(const _UF delta, |
|||
const _UF expected, |
|||
const _UF actual, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber); |
|||
|
|||
void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const _UF* expected, |
|||
UNITY_PTR_ATTRIBUTE const _UF* actual, |
|||
const _UU32 num_elements, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber); |
|||
|
|||
void UnityAssertFloatSpecial(const _UF actual, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber, |
|||
const UNITY_FLOAT_TRAIT_T style); |
|||
#endif |
|||
|
|||
#ifndef UNITY_EXCLUDE_DOUBLE |
|||
void UnityAssertDoublesWithin(const _UD delta, |
|||
const _UD expected, |
|||
const _UD actual, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber); |
|||
|
|||
void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const _UD* expected, |
|||
UNITY_PTR_ATTRIBUTE const _UD* actual, |
|||
const _UU32 num_elements, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber); |
|||
|
|||
void UnityAssertDoubleSpecial(const _UD actual, |
|||
const char* msg, |
|||
const UNITY_LINE_TYPE lineNumber, |
|||
const UNITY_FLOAT_TRAIT_T style); |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Error Strings We Might Need |
|||
*-------------------------------------------------------*/ |
|||
|
|||
extern const char UnityStrErrFloat[]; |
|||
extern const char UnityStrErrDouble[]; |
|||
extern const char UnityStrErr64[]; |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Test Running Macros |
|||
*-------------------------------------------------------*/ |
|||
|
|||
#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) |
|||
|
|||
#define TEST_ABORT() {longjmp(Unity.AbortFrame, 1);} |
|||
|
|||
/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ |
|||
#ifndef RUN_TEST |
|||
#ifdef __STDC_VERSION__ |
|||
#if __STDC_VERSION__ >= 199901L |
|||
#define RUN_TEST(...) UnityDefaultTestRun(RUN_TEST_FIRST(__VA_ARGS__), RUN_TEST_SECOND(__VA_ARGS__)) |
|||
#define RUN_TEST_FIRST(...) RUN_TEST_FIRST_HELPER(__VA_ARGS__, throwaway) |
|||
#define RUN_TEST_FIRST_HELPER(first, ...) (first), #first |
|||
#define RUN_TEST_SECOND(...) RUN_TEST_SECOND_HELPER(__VA_ARGS__, __LINE__, throwaway) |
|||
#define RUN_TEST_SECOND_HELPER(first, second, ...) (second) |
|||
#endif |
|||
#endif |
|||
#endif |
|||
|
|||
/* If we can't do the tricky version, we'll just have to require them to always include the line number */ |
|||
#ifndef RUN_TEST |
|||
#ifdef CMOCK |
|||
#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) |
|||
#else |
|||
#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) |
|||
#endif |
|||
#endif |
|||
|
|||
#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) |
|||
#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) |
|||
#define UNITY_NEW_TEST(a) \ |
|||
Unity.CurrentTestName = (a); \ |
|||
Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ |
|||
Unity.NumberOfTests++; |
|||
|
|||
#ifndef UNITY_BEGIN |
|||
#define UNITY_BEGIN() UnityBegin(__FILE__) |
|||
#endif |
|||
|
|||
#ifndef UNITY_END |
|||
#define UNITY_END() UnityEnd() |
|||
#endif |
|||
|
|||
#define UNITY_UNUSED(x) (void)(sizeof(x)) |
|||
|
|||
/*-----------------------------------------------
|
|||
* Command Line Argument Support |
|||
*-----------------------------------------------*/ |
|||
|
|||
#ifdef UNITY_USE_COMMAND_LINE_ARGS |
|||
int UnityParseOptions(int argc, char** argv); |
|||
int UnityTestMatches(void); |
|||
#endif |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Basic Fail and Ignore |
|||
*-------------------------------------------------------*/ |
|||
|
|||
#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) |
|||
#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) |
|||
|
|||
/*-------------------------------------------------------
|
|||
* Test Asserts |
|||
*-------------------------------------------------------*/ |
|||
|
|||
#define UNITY_TEST_ASSERT(condition, line, message) if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));} |
|||
#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message)) |
|||
#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message)) |
|||
|
|||
#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) |
|||
#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) |
|||
#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) |
|||
#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UU8 )(expected), (_U_SINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UU16)(expected), (_U_SINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UU32)(expected), (_U_SINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) |
|||
#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) |
|||
#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) |
|||
#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) |
|||
#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((_U_SINT)(mask), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line)) |
|||
|
|||
#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) |
|||
#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) |
|||
#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) |
|||
#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) |
|||
#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) |
|||
#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_U_UINT)(_UU8 )(expected), (_U_SINT)(_U_UINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) |
|||
#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_U_UINT)(_UU16)(expected), (_U_SINT)(_U_UINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) |
|||
#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_U_UINT)(_UU32)(expected), (_U_SINT)(_U_UINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) |
|||
#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_U_UINT)(_UU8 )(expected), (_U_SINT)(_U_UINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) |
|||
#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_U_UINT)(_UU16)(expected), (_U_SINT)(_U_UINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) |
|||
#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_U_UINT)(_UU32)(expected), (_U_SINT)(_U_UINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) |
|||
|
|||
#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UP)(expected), (_U_SINT)(_UP)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) |
|||
#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) |
|||
#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (_UU32)(len), (message), (UNITY_LINE_TYPE)(line)) |
|||
#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(len), 1, (message), (UNITY_LINE_TYPE)(line)) |
|||
|
|||
#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) |
|||
#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) |
|||
#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) |
|||
#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) |
|||
#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) |
|||
#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) |
|||
#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) |
|||
#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(_UP*)(expected), (UNITY_INTERNAL_PTR)(_UP*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) |
|||
#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((const char**)(expected), (const char**)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line)) |
|||
#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(len), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line)) |
|||
|
|||
#ifdef UNITY_SUPPORT_64 |
|||
#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) |
|||
#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) |
|||
#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) |
|||
#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) |
|||
#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) |
|||
#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) |
|||
#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) |
|||
#else |
|||
#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) |
|||
#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) |
|||
#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) |
|||
#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) |
|||
#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) |
|||
#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) |
|||
#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) |
|||
#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) |
|||
#endif |
|||
|
|||
#ifdef UNITY_EXCLUDE_FLOAT |
|||
#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) |
|||
#else |
|||
#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((_UF)(delta), (_UF)(expected), (_UF)(actual), (message), (UNITY_LINE_TYPE)(line)) |
|||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((_UF)(expected) * (_UF)UNITY_FLOAT_PRECISION, (_UF)(expected), (_UF)(actual), (UNITY_LINE_TYPE)(line), (message)) |
|||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((_UF*)(expected), (_UF*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line)) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) |
|||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) |
|||
#endif |
|||
|
|||
#ifdef UNITY_EXCLUDE_DOUBLE |
|||
#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) |
|||
#else |
|||
#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((_UD)(delta), (_UD)(expected), (_UD)(actual), (message), (UNITY_LINE_TYPE)line) |
|||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((_UD)(expected) * (_UD)UNITY_DOUBLE_PRECISION, (_UD)expected, (_UD)actual, (UNITY_LINE_TYPE)(line), message) |
|||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((_UD*)(expected), (_UD*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)line) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) |
|||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) |
|||
#endif |
|||
|
|||
/* End of UNITY_INTERNALS_H */ |
|||
#endif |
@ -0,0 +1,64 @@ |
|||
/* 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 <unistd.h> |
|||
#include <sched.h> |
|||
#include <pthread.h> |
|||
|
|||
#include "cpu.h" |
|||
|
|||
|
|||
struct cpu_info cpu_info = { 0 }; |
|||
void cpu_init_common(); |
|||
|
|||
|
|||
void cpu_init() { |
|||
cpu_info.count = sysconf(_SC_NPROCESSORS_CONF); |
|||
|
|||
cpu_init_common(); |
|||
} |
|||
|
|||
|
|||
int get_optimal_threads_count() { |
|||
int count = cpu_info.count / 2; |
|||
return count < 1 ? 1 : count; |
|||
} |
|||
|
|||
|
|||
int affine_to_cpu_mask(int id, unsigned long mask) |
|||
{ |
|||
cpu_set_t set; |
|||
CPU_ZERO(&set); |
|||
|
|||
for (unsigned i = 0; i < cpu_info.count; i++) { |
|||
if (mask & (1UL << i)) { |
|||
CPU_SET(i, &set); |
|||
} |
|||
} |
|||
|
|||
if (id == -1) { |
|||
sched_setaffinity(0, sizeof(&set), &set); |
|||
} else { |
|||
pthread_setaffinity_np(pthread_self(), sizeof(&set), &set); |
|||
} |
|||
} |
@ -0,0 +1,81 @@ |
|||
/* 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 __MEMORY_H__ |
|||
#define __MEMORY_H__ |
|||
|
|||
#include <stdlib.h> |
|||
#include <mm_malloc.h> |
|||
#include <sys/mman.h> |
|||
|
|||
#include "persistent_memory.h" |
|||
#include "options.h" |
|||
#include "utils/applog.h" |
|||
|
|||
|
|||
char *persistent_memory; |
|||
int persistent_memory_flags = 0; |
|||
|
|||
|
|||
const char * persistent_memory_allocate() { |
|||
const int size = TWO_MB_PAGE * (opt_n_threads + 1); |
|||
persistent_memory_flags |= MEMORY_HUGEPAGES_AVAILABLE; |
|||
|
|||
persistent_memory = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0); |
|||
|
|||
if (persistent_memory == MAP_FAILED) { |
|||
persistent_memory = _mm_malloc(size, 4096); |
|||
return persistent_memory; |
|||
} |
|||
|
|||
persistent_memory_flags |= MEMORY_HUGEPAGES_ENABLED; |
|||
|
|||
if (madvise(persistent_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0) { |
|||
applog(LOG_ERR, "madvise failed"); |
|||
} |
|||
|
|||
if (mlock(persistent_memory, size) == 0) { |
|||
persistent_memory_flags |= MEMORY_LOCK; |
|||
} |
|||
|
|||
return persistent_memory; |
|||
} |
|||
|
|||
|
|||
void persistent_memory_free() { |
|||
const int size = TWO_MB_PAGE * (opt_n_threads + 1); |
|||
|
|||
if (persistent_memory_flags & MEMORY_HUGEPAGES_ENABLED) { |
|||
if (persistent_memory_flags & MEMORY_LOCK) { |
|||
munlock(persistent_memory, size); |
|||
} |
|||
|
|||
munmap(persistent_memory, size); |
|||
} |
|||
else { |
|||
_mm_free(persistent_memory); |
|||
} |
|||
} |
|||
|
|||
|
|||
#endif /* __MEMORY_H__ */ |
@ -0,0 +1,91 @@ |
|||
/* 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 "options.h" |
|||
#include "cpu.h" |
|||
#include "utils/applog.h" |
|||
|
|||
|
|||
static void signal_handler(int sig) |
|||
{ |
|||
switch (sig) { |
|||
case SIGHUP: |
|||
applog(LOG_WARNING, "SIGHUP received"); |
|||
break; |
|||
|
|||
case SIGINT: |
|||
applog(LOG_WARNING, "SIGINT received, exiting"); |
|||
proper_exit(0); |
|||
break; |
|||
|
|||
case SIGTERM: |
|||
applog(LOG_WARNING, "SIGTERM received, exiting"); |
|||
proper_exit(0); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
|
|||
void proper_exit(int reason) { |
|||
exit(reason); |
|||
} |
|||
|
|||
|
|||
void os_specific_init() |
|||
{ |
|||
if (opt_affinity != -1) { |
|||
affine_to_cpu_mask(-1, opt_affinity); |
|||
} |
|||
|
|||
if (opt_background) { |
|||
int i = fork(); |
|||
if (i < 0) { |
|||
exit(1); |
|||
} |
|||
|
|||
if (i > 0) { |
|||
exit(0); |
|||
} |
|||
|
|||
i = setsid(); |
|||
|
|||
if (i < 0) { |
|||
applog(LOG_ERR, "setsid() failed (errno = %d)", errno); |
|||
} |
|||
|
|||
i = chdir("/"); |
|||
if (i < 0) { |
|||
applog(LOG_ERR, "chdir() failed (errno = %d)", errno); |
|||
} |
|||
|
|||
signal(SIGHUP, signal_handler); |
|||
signal(SIGTERM, signal_handler); |
|||
} |
|||
|
|||
signal(SIGINT, signal_handler); |
|||
} |
@ -0,0 +1,270 @@ |
|||
/* 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 <stdio.h> |
|||
#include <stdbool.h> |
|||
#include <stdlib.h> |
|||
#include <pthread.h> |
|||
|
|||
#include "util.h" |
|||
#include "elist.h" |
|||
#include "utils/applog.h" |
|||
|
|||
|
|||
struct tq_ent { |
|||
void *data; |
|||
struct list_head q_node; |
|||
}; |
|||
|
|||
|
|||
struct thread_q { |
|||
struct list_head q; |
|||
bool frozen; |
|||
pthread_mutex_t mutex; |
|||
pthread_cond_t cond; |
|||
}; |
|||
|
|||
|
|||
json_t *json_decode(const char *s) |
|||
{ |
|||
json_error_t err; |
|||
json_t *val = json_loads(s, 0, &err); |
|||
|
|||
if (!val) { |
|||
applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text); |
|||
} |
|||
|
|||
return val; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief bin2hex |
|||
* @param p |
|||
* @param len |
|||
* @return |
|||
*/ |
|||
char *bin2hex(const unsigned char *p, size_t len) |
|||
{ |
|||
char *s = malloc((len * 2) + 1); |
|||
if (!s) { |
|||
return NULL; |
|||
} |
|||
|
|||
for (int i = 0; i < len; i++) { |
|||
sprintf(s + (i * 2), "%02x", (unsigned int) p[i]); |
|||
} |
|||
|
|||
return s; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief hex2bin |
|||
* @param p |
|||
* @param hexstr |
|||
* @param len |
|||
* @return |
|||
*/ |
|||
bool hex2bin(unsigned char *p, const char *hexstr, size_t len) |
|||
{ |
|||
char hex_byte[3]; |
|||
char *ep; |
|||
|
|||
hex_byte[2] = '\0'; |
|||
|
|||
while (*hexstr && len) { |
|||
if (!hexstr[1]) { |
|||
applog(LOG_ERR, "hex2bin str truncated"); |
|||
return false; |
|||
} |
|||
|
|||
hex_byte[0] = hexstr[0]; |
|||
hex_byte[1] = hexstr[1]; |
|||
*p = (unsigned char) strtol(hex_byte, &ep, 16); |
|||
if (*ep) { |
|||
applog(LOG_ERR, "hex2bin failed on '%s'", hex_byte); |
|||
return false; |
|||
} |
|||
|
|||
p++; |
|||
hexstr += 2; |
|||
len--; |
|||
} |
|||
|
|||
return (len == 0 && *hexstr == 0) ? true : false; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief tq_new |
|||
* @return |
|||
*/ |
|||
struct thread_q *tq_new(void) |
|||
{ |
|||
struct thread_q *tq; |
|||
|
|||
tq = calloc(1, sizeof(*tq)); |
|||
if (!tq) |
|||
return NULL; |
|||
|
|||
INIT_LIST_HEAD(&tq->q); |
|||
pthread_mutex_init(&tq->mutex, NULL); |
|||
pthread_cond_init(&tq->cond, NULL); |
|||
|
|||
return tq; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief tq_free |
|||
* @param tq |
|||
*/ |
|||
void tq_free(struct thread_q *tq) |
|||
{ |
|||
struct tq_ent *ent, *iter; |
|||
|
|||
if (!tq) |
|||
return; |
|||
|
|||
list_for_each_entry_safe(ent, iter, &tq->q, q_node) { |
|||
list_del(&ent->q_node); |
|||
free(ent); |
|||
} |
|||
|
|||
pthread_cond_destroy(&tq->cond); |
|||
pthread_mutex_destroy(&tq->mutex); |
|||
|
|||
memset(tq, 0, sizeof(*tq)); /* poison */ |
|||
free(tq); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief tq_freezethaw |
|||
* @param tq |
|||
* @param frozen |
|||
*/ |
|||
static void tq_freezethaw(struct thread_q *tq, bool frozen) |
|||
{ |
|||
pthread_mutex_lock(&tq->mutex); |
|||
|
|||
tq->frozen = frozen; |
|||
|
|||
pthread_cond_signal(&tq->cond); |
|||
pthread_mutex_unlock(&tq->mutex); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief tq_freeze |
|||
* @param tq |
|||
*/ |
|||
void tq_freeze(struct thread_q *tq) |
|||
{ |
|||
tq_freezethaw(tq, true); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief tq_thaw |
|||
* @param tq |
|||
*/ |
|||
void tq_thaw(struct thread_q *tq) |
|||
{ |
|||
tq_freezethaw(tq, false); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief tq_push |
|||
* @param tq |
|||
* @param data |
|||
* @return |
|||
*/ |
|||
bool tq_push(struct thread_q *tq, void *data) |
|||
{ |
|||
struct tq_ent *ent; |
|||
bool rc = true; |
|||
|
|||
ent = calloc(1, sizeof(*ent)); |
|||
if (!ent) |
|||
return false; |
|||
|
|||
ent->data = data; |
|||
INIT_LIST_HEAD(&ent->q_node); |
|||
|
|||
pthread_mutex_lock(&tq->mutex); |
|||
|
|||
if (!tq->frozen) { |
|||
list_add_tail(&ent->q_node, &tq->q); |
|||
} else { |
|||
free(ent); |
|||
rc = false; |
|||
} |
|||
|
|||
pthread_cond_signal(&tq->cond); |
|||
pthread_mutex_unlock(&tq->mutex); |
|||
|
|||
return rc; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief tq_pop |
|||
* @param tq |
|||
* @param abstime |
|||
* @return |
|||
*/ |
|||
void *tq_pop(struct thread_q *tq, const struct timespec *abstime) |
|||
{ |
|||
struct tq_ent *ent; |
|||
void *rval = NULL; |
|||
int rc; |
|||
|
|||
pthread_mutex_lock(&tq->mutex); |
|||
|
|||
if (!list_empty(&tq->q)) |
|||
goto pop; |
|||
|
|||
if (abstime) |
|||
rc = pthread_cond_timedwait(&tq->cond, &tq->mutex, abstime); |
|||
else |
|||
rc = pthread_cond_wait(&tq->cond, &tq->mutex); |
|||
if (rc) |
|||
goto out; |
|||
if (list_empty(&tq->q)) |
|||
goto out; |
|||
|
|||
pop: |
|||
ent = list_entry(tq->q.next, struct tq_ent, q_node); |
|||
rval = ent->data; |
|||
|
|||
list_del(&ent->q_node); |
|||
free(ent); |
|||
|
|||
out: |
|||
pthread_mutex_unlock(&tq->mutex); |
|||
return rval; |
|||
} |
@ -0,0 +1,43 @@ |
|||
/* 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 __UTIL_H__ |
|||
#define __UTIL_H__ |
|||
|
|||
#include <jansson.h> |
|||
|
|||
|
|||
json_t *json_decode(const char *s); |
|||
|
|||
char *bin2hex(const unsigned char *p, size_t len); |
|||
bool hex2bin(unsigned char *p, const char *hexstr, size_t len); |
|||
|
|||
struct thread_q *tq_new(void); |
|||
void tq_free(struct thread_q *tq); |
|||
bool tq_push(struct thread_q *tq, void *data); |
|||
void *tq_pop(struct thread_q *tq, const struct timespec *abstime); |
|||
void tq_freeze(struct thread_q *tq); |
|||
void tq_thaw(struct thread_q *tq); |
|||
|
|||
|
|||
#endif /* __UTIL_H__ */ |
@ -0,0 +1,146 @@ |
|||
/* 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 "xmrig.h" |
|||
#include "applog.h" |
|||
#include "threads.h" |
|||
#include <sys/time.h> |
|||
#include <string.h> |
|||
|
|||
#ifdef WIN32 |
|||
# include "compat/winansi.h" |
|||
#endif |
|||
|
|||
#include "options.h" |
|||
|
|||
|
|||
MUTEX applog_mutex; |
|||
|
|||
|
|||
void applog_init() |
|||
{ |
|||
MUTEX_INIT(applog_mutex); |
|||
} |
|||
|
|||
|
|||
void applog(int prio, const char *fmt, ...) |
|||
{ |
|||
if (opt_background) { |
|||
return; |
|||
} |
|||
|
|||
va_list ap; |
|||
va_start(ap, fmt); |
|||
|
|||
struct tm tm; |
|||
struct tm *tm_p; |
|||
time_t now = time(NULL); |
|||
|
|||
MUTEX_LOCK(applog_mutex); |
|||
tm_p = localtime(&now); |
|||
memcpy(&tm, tm_p, sizeof(tm)); |
|||
MUTEX_UNLOCK(applog_mutex); |
|||
|
|||
const char* color = ""; |
|||
|
|||
if (opt_colors) { |
|||
switch (prio) { |
|||
case LOG_ERR: color = CL_RED; break; |
|||
case LOG_WARNING: color = CL_YLW; break; |
|||
case LOG_NOTICE: color = CL_WHT; break; |
|||
case LOG_INFO: color = ""; break; |
|||
case LOG_DEBUG: color = CL_GRY; break; |
|||
|
|||
case LOG_BLUE: |
|||
prio = LOG_NOTICE; |
|||
color = CL_CYN; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
const int len = 64 + strlen(fmt) + 2; |
|||
char *f = alloca(len); |
|||
|
|||
sprintf(f, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n", |
|||
tm.tm_year + 1900, |
|||
tm.tm_mon + 1, |
|||
tm.tm_mday, |
|||
tm.tm_hour, |
|||
tm.tm_min, |
|||
tm.tm_sec, |
|||
color, |
|||
fmt, |
|||
opt_colors ? CL_N : "" |
|||
); |
|||
|
|||
MUTEX_LOCK(applog_mutex); |
|||
vfprintf(stderr, f, ap); |
|||
fflush(stderr); |
|||
MUTEX_UNLOCK(applog_mutex); |
|||
|
|||
va_end(ap); |
|||
} |
|||
|
|||
|
|||
void applog_notime(int prio, const char *fmt, ...) |
|||
{ |
|||
if (opt_background) { |
|||
return; |
|||
} |
|||
|
|||
va_list ap; |
|||
va_start(ap, fmt); |
|||
|
|||
const char* color = ""; |
|||
|
|||
if (opt_colors) { |
|||
switch (prio) { |
|||
case LOG_ERR: color = CL_RED; break; |
|||
case LOG_WARNING: color = CL_YLW; break; |
|||
case LOG_NOTICE: color = CL_WHT; break; |
|||
case LOG_INFO: color = ""; break; |
|||
case LOG_DEBUG: color = CL_GRY; break; |
|||
|
|||
case LOG_BLUE: |
|||
prio = LOG_NOTICE; |
|||
color = CL_CYN; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
const int len = 64 + strlen(fmt) + 2; |
|||
char *f = alloca(len); |
|||
|
|||
sprintf(f, "%s%s%s\n", |
|||
color, |
|||
fmt, |
|||
opt_colors ? CL_N : "" |
|||
); |
|||
|
|||
MUTEX_LOCK(applog_mutex); |
|||
vfprintf(stderr, f, ap); |
|||
fflush(stderr); |
|||
MUTEX_UNLOCK(applog_mutex); |
|||
|
|||
va_end(ap); |
|||
} |
@ -0,0 +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/>.
|
|||
*/ |
|||
|
|||
#ifndef __APPLOG_H__ |
|||
#define __APPLOG_H__ |
|||
|
|||
enum { |
|||
LOG_ERR, |
|||
LOG_WARNING, |
|||
LOG_NOTICE, |
|||
LOG_INFO, |
|||
LOG_DEBUG, |
|||
LOG_BLUE = 0x10 |
|||
}; |
|||
|
|||
#define CL_N "\x1B[0m" |
|||
#define CL_RED "\x1B[31m" |
|||
#define CL_GRN "\x1B[32m" |
|||
#define CL_YLW "\x1B[33m" |
|||
#define CL_BLU "\x1B[34m" |
|||
#define CL_MAG "\x1B[35m" |
|||
#define CL_CYN "\x1B[36m" |
|||
|
|||
#define CL_BLK "\x1B[22;30m" /* black */ |
|||
#define CL_RD2 "\x1B[22;31m" /* red */ |
|||
#define CL_GR2 "\x1B[22;32m" /* green */ |
|||
#define CL_BRW "\x1B[22;33m" /* brown */ |
|||
#define CL_BL2 "\x1B[22;34m" /* blue */ |
|||
#define CL_MA2 "\x1B[22;35m" /* magenta */ |
|||
#define CL_CY2 "\x1B[22;36m" /* cyan */ |
|||
#define CL_SIL "\x1B[22;37m" /* gray */ |
|||
|
|||
#ifdef WIN32 |
|||
#define CL_GRY "\x1B[01;30m" /* dark gray */ |
|||
#else |
|||
#define CL_GRY "\x1B[90m" /* dark gray selectable in putty */ |
|||
#endif |
|||
#define CL_LRD "\x1B[01;31m" /* light red */ |
|||
#define CL_LGR "\x1B[01;32m" /* light green */ |
|||
#define CL_YL2 "\x1B[01;33m" /* yellow */ |
|||
#define CL_LBL "\x1B[01;34m" /* light blue */ |
|||
#define CL_LMA "\x1B[01;35m" /* light magenta */ |
|||
#define CL_LCY "\x1B[01;36m" /* light cyan */ |
|||
|
|||
#define CL_WHT "\x1B[01;37m" /* white */ |
|||
|
|||
#define OPT_COLOR(color, text) (opt_colors ? (color text CL_N) : text) |
|||
|
|||
|
|||
void applog_init(); |
|||
void applog(int prio, const char *fmt, ...); |
|||
void applog_notime(int prio, const char *fmt, ...); |
|||
|
|||
#endif /* __APPLOG_H__ */ |
@ -0,0 +1,103 @@ |
|||
/* 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 "options.h" |
|||
#include "applog.h" |
|||
#include "version.h" |
|||
#include "persistent_memory.h" |
|||
#include "cpu.h" |
|||
|
|||
|
|||
static void print_memory() { |
|||
const char *t1 = (persistent_memory_flags & MEMORY_HUGEPAGES_AVAILABLE) ? OPT_COLOR(CL_LGR, "available") : OPT_COLOR(CL_LRD, "unavailable"); |
|||
const char *t2 = (persistent_memory_flags & MEMORY_HUGEPAGES_ENABLED) ? OPT_COLOR(CL_LGR, "enabled") : OPT_COLOR(CL_LRD, "disabled"); |
|||
|
|||
if (opt_colors) { |
|||
applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "HUGE PAGES: %s, %s", t1, t2); |
|||
} |
|||
else { |
|||
applog_notime(LOG_INFO, " * HUGE PAGES: %s, %s", t1, t2); |
|||
} |
|||
} |
|||
|
|||
|
|||
static void print_cpu() { |
|||
const char *t1 = (cpu_info.flags & CPU_FLAG_X86_64) ? OPT_COLOR(CL_LGR, "x86_64") : OPT_COLOR(CL_LRD, "-x86_64"); |
|||
const char *t2 = (cpu_info.flags & CPU_FLAG_AES) ? OPT_COLOR(CL_LGR, "AES-NI") : OPT_COLOR(CL_LRD, "-AES-NI"); |
|||
const char *t3 = (cpu_info.flags & CPU_FLAG_BMI2) ? OPT_COLOR(CL_LGR, "BMI2") : OPT_COLOR(CL_LRD, "-BMI2"); |
|||
|
|||
if (opt_colors) { |
|||
applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "CPU: %s", cpu_info.brand); |
|||
applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "CPU FEATURES: %s %s %s", t1, t2, t3); |
|||
} |
|||
else { |
|||
applog_notime(LOG_INFO, " * CPU: %s", cpu_info.brand); |
|||
applog_notime(LOG_INFO, " * CPU FEATURES: %s %s %s", t1, t2, t3); |
|||
} |
|||
} |
|||
|
|||
|
|||
static void print_threads() { |
|||
if (opt_colors) { |
|||
applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "THREADS: " CL_WHT "%d" CL_WHT ", av=%d, donate=%d%%", opt_n_threads, opt_algo_variant, opt_donate_level); |
|||
} |
|||
else { |
|||
applog_notime(LOG_INFO, " * THREADS: %d, av=%d, donate=%d%%", opt_n_threads, opt_algo_variant, opt_donate_level); |
|||
} |
|||
} |
|||
|
|||
|
|||
static void print_stratum() { |
|||
if (opt_colors) { |
|||
applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "STRATUM URL: " CL_LCY "%s", opt_url); |
|||
|
|||
if (opt_backup_url) { |
|||
applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "FAILOVER URL: " CL_LCY "%s", opt_backup_url); |
|||
} |
|||
else { |
|||
applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "FAILOVER URL: " CL_LRD "none"); |
|||
} |
|||
} |
|||
else { |
|||
applog_notime(LOG_INFO, " * STRATUM URL: %s", opt_url); |
|||
applog_notime(LOG_INFO, " * FAILOVER URL: %s", opt_backup_url ? opt_backup_url : "none"); |
|||
} |
|||
} |
|||
|
|||
|
|||
void print_summary() { |
|||
if (opt_colors) { |
|||
applog_notime(LOG_INFO, CL_LGR " * " CL_WHT APP_NAME " " APP_VERSION " " CL_LCY APP_SITE); |
|||
} |
|||
else { |
|||
applog_notime(LOG_INFO, " * " APP_NAME " " APP_VERSION " " APP_SITE); |
|||
} |
|||
|
|||
print_memory(); |
|||
print_cpu(); |
|||
print_threads(); |
|||
print_stratum(); |
|||
} |
|||
|
|||
|
|||
|
@ -0,0 +1,29 @@ |
|||
/* 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__ |
|||
#define __SUMMARY_H__ |
|||
|
|||
void print_summary(); |
|||
|
|||
#endif /* __SUMMARY_H__ */ |
@ -0,0 +1,41 @@ |
|||
/* 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 __THREADS_H__ |
|||
#define __THREADS_H__ |
|||
|
|||
#if defined(WIN32) && defined(USE_NATIVE_THREADS) |
|||
# include <windows.h> |
|||
# define MUTEX CRITICAL_SECTION |
|||
# define MUTEX_INIT(mutex) InitializeCriticalSection(&mutex) |
|||
# define MUTEX_LOCK(mutex) EnterCriticalSection(&mutex) |
|||
# define MUTEX_UNLOCK(mutex) LeaveCriticalSection(&mutex) |
|||
#else |
|||
# include <pthread.h> |
|||
# define MUTEX pthread_mutex_t |
|||
# define MUTEX_INIT(mutex) pthread_mutex_init(&mutex, NULL) |
|||
# define MUTEX_LOCK(mutex) pthread_mutex_lock(&mutex) |
|||
# define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(&mutex) |
|||
#endif |
|||
|
|||
#endif /* __THREADS_H__ */ |
@ -0,0 +1,39 @@ |
|||
/* 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 __VERSION_H__ |
|||
#define __VERSION_H__ |
|||
|
|||
#define APP_ID "xmrig" |
|||
#define APP_NAME "XMRig" |
|||
#define APP_VERSION "0.5.0" |
|||
#define APP_DOMAIN "xmrig.com" |
|||
#define APP_SITE "www.xmrig.com" |
|||
#define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com" |
|||
|
|||
#define APP_VER_MAJOR 0 |
|||
#define APP_VER_MINOR 5 |
|||
#define APP_VER_BUILD 0 |
|||
#define APP_VER_REV 0 |
|||
|
|||
#endif /* __VERSION_H__ */ |
@ -0,0 +1,58 @@ |
|||
/* 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 <stdbool.h> |
|||
|
|||
#include "cpu.h" |
|||
|
|||
|
|||
struct cpu_info cpu_info = { 0 }; |
|||
void cpu_init_common(); |
|||
|
|||
|
|||
void cpu_init() { |
|||
SYSTEM_INFO sysinfo; |
|||
GetSystemInfo(&sysinfo); |
|||
|
|||
cpu_info.count = sysinfo.dwNumberOfProcessors; |
|||
|
|||
cpu_init_common(); |
|||
} |
|||
|
|||
|
|||
int get_optimal_threads_count(int mining_algo) { |
|||
int count = cpu_info.count / 2; |
|||
return count < 1 ? 1 : count; |
|||
} |
|||
|
|||
|
|||
int affine_to_cpu_mask(int id, unsigned long mask) |
|||
{ |
|||
if (id == -1) { |
|||
SetProcessAffinityMask(GetCurrentProcess(), mask); |
|||
} |
|||
else { |
|||
SetThreadAffinityMask(GetCurrentThread(), mask); |
|||
} |
|||
} |
@ -0,0 +1,116 @@ |
|||
/* 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 __MEMORY_H__ |
|||
#define __MEMORY_H__ |
|||
|
|||
#include <windows.h> |
|||
#include "options.h" |
|||
#include "persistent_memory.h" |
|||
|
|||
|
|||
char *persistent_memory; |
|||
int persistent_memory_flags = 0; |
|||
|
|||
|
|||
/*****************************************************************
|
|||
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(HANDLE hProcess, BOOL bEnable) { |
|||
struct { |
|||
DWORD Count; |
|||
LUID_AND_ATTRIBUTES Privilege[1]; |
|||
} Info; |
|||
|
|||
HANDLE Token; |
|||
BOOL result; |
|||
|
|||
if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &Token) != TRUE) { |
|||
return FALSE; |
|||
} |
|||
|
|||
Info.Count = 1; |
|||
Info.Privilege[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; |
|||
|
|||
if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid)) != TRUE) { |
|||
return FALSE; |
|||
} |
|||
|
|||
if (AdjustTokenPrivileges(Token, FALSE, (PTOKEN_PRIVILEGES) &Info, 0, NULL, NULL) != TRUE) { |
|||
return FALSE; |
|||
} |
|||
|
|||
if (GetLastError() != ERROR_SUCCESS) { |
|||
return FALSE; |
|||
} |
|||
|
|||
CloseHandle(Token); |
|||
|
|||
return TRUE; |
|||
} |
|||
|
|||
|
|||
const char * persistent_memory_allocate() { |
|||
const int size = TWO_MB_PAGE * (opt_n_threads + 1); |
|||
|
|||
if (SetLockPagesPrivilege(GetCurrentProcess(), TRUE)) { |
|||
persistent_memory_flags |= MEMORY_HUGEPAGES_AVAILABLE; |
|||
} |
|||
|
|||
persistent_memory = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE); |
|||
if (!persistent_memory) { |
|||
persistent_memory = _mm_malloc(size, 4096); |
|||
} |
|||
else { |
|||
persistent_memory_flags |= MEMORY_HUGEPAGES_ENABLED; |
|||
} |
|||
|
|||
return persistent_memory; |
|||
} |
|||
|
|||
|
|||
void persistent_memory_free() { |
|||
if (persistent_memory_flags & MEMORY_HUGEPAGES_ENABLED) { |
|||
VirtualFree(persistent_memory, 0, MEM_RELEASE); |
|||
} |
|||
else { |
|||
_mm_free(persistent_memory); |
|||
} |
|||
} |
|||
|
|||
#endif /* __MEMORY_H__ */ |
@ -0,0 +1,84 @@ |
|||
/* 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 "options.h" |
|||
#include "cpu.h" |
|||
#include "utils/applog.h" |
|||
|
|||
|
|||
BOOL WINAPI ConsoleHandler(DWORD dwType) |
|||
{ |
|||
switch (dwType) { |
|||
case CTRL_C_EVENT: |
|||
applog(LOG_WARNING, "CTRL_C_EVENT received, exiting"); |
|||
proper_exit(0); |
|||
break; |
|||
|
|||
case CTRL_BREAK_EVENT: |
|||
applog(LOG_WARNING, "CTRL_BREAK_EVENT received, exiting"); |
|||
proper_exit(0); |
|||
break; |
|||
|
|||
default: |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
void proper_exit(int reason) { |
|||
if (opt_background) { |
|||
HWND hcon = GetConsoleWindow(); |
|||
if (hcon) { |
|||
// unhide parent command line windows
|
|||
ShowWindow(hcon, SW_SHOWMINNOACTIVE); |
|||
} |
|||
} |
|||
|
|||
exit(reason); |
|||
} |
|||
|
|||
|
|||
void os_specific_init() |
|||
{ |
|||
if (opt_affinity != -1) { |
|||
affine_to_cpu_mask(-1, opt_affinity); |
|||
} |
|||
|
|||
SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE); |
|||
|
|||
if (opt_background) { |
|||
HWND hcon = GetConsoleWindow(); |
|||
if (hcon) { |
|||
// this method also hide parent command line window
|
|||
ShowWindow(hcon, SW_HIDE); |
|||
} else { |
|||
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); |
|||
CloseHandle(h); |
|||
FreeConsole(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,610 @@ |
|||
/* 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 <unistd.h> |
|||
#include <jansson.h> |
|||
#include <sys/time.h> |
|||
|
|||
#ifdef WIN32 |
|||
# include <winsock2.h> |
|||
# include <windows.h> |
|||
#endif |
|||
|
|||
#include <jansson.h> |
|||
#include <curl/curl.h> |
|||
#include <pthread.h> |
|||
|
|||
#include "compat.h" |
|||
#include "xmrig.h" |
|||
#include "algo/cryptonight/cryptonight.h" |
|||
#include "options.h" |
|||
#include "cpu.h" |
|||
#include "persistent_memory.h" |
|||
#include "stratum.h" |
|||
#include "stats.h" |
|||
#include "util.h" |
|||
#include "utils/summary.h" |
|||
#include "utils/applog.h" |
|||
|
|||
#define LP_SCANTIME 60 |
|||
#define JSON_BUF_LEN 345 |
|||
|
|||
|
|||
struct workio_cmd { |
|||
struct thr_info *thr; |
|||
struct work *work; |
|||
}; |
|||
|
|||
|
|||
struct thr_info *thr_info; |
|||
static int work_thr_id = -1; |
|||
static int timer_thr_id = -1; |
|||
static int stratum_thr_id = -1; |
|||
struct work_restart *work_restart = NULL; |
|||
static struct stratum_ctx *stratum_ctx = NULL; |
|||
static bool backup_active = false; |
|||
static bool g_want_donate = false; |
|||
|
|||
|
|||
static void workio_cmd_free(struct workio_cmd *wc); |
|||
|
|||
|
|||
/**
|
|||
* @brief work_free |
|||
* @param w |
|||
*/ |
|||
static inline void work_free(struct work *w) { |
|||
free(w->job_id); |
|||
free(w->xnonce2); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief work_copy |
|||
* @param dest |
|||
* @param src |
|||
*/ |
|||
static inline void work_copy(struct work *dest, const struct work *src) { |
|||
memcpy(dest, src, sizeof(struct work)); |
|||
if (src->job_id) { |
|||
dest->job_id = strdup(src->job_id); |
|||
} |
|||
|
|||
if (src->xnonce2) { |
|||
dest->xnonce2 = malloc(src->xnonce2_len); |
|||
memcpy(dest->xnonce2, src->xnonce2, src->xnonce2_len); |
|||
} |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief restart_threads |
|||
*/ |
|||
static inline void restart_threads(void) { |
|||
for (int i = 0; i < opt_n_threads; i++) { |
|||
work_restart[i].restart = 1; |
|||
} |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief gen_workify |
|||
* @param sctx |
|||
* @param work |
|||
*/ |
|||
static inline void gen_workify(struct stratum_ctx *sctx) { |
|||
pthread_mutex_lock(&stratum_ctx->work_lock); |
|||
|
|||
if (stratum_ctx->work.job_id && (!stratum_ctx->g_work_time || strcmp(stratum_ctx->work.job_id, stratum_ctx->g_work.job_id))) { |
|||
free(sctx->g_work.job_id); |
|||
memcpy(&sctx->g_work, &sctx->work, sizeof(struct work)); |
|||
sctx->work.job_id = strdup(sctx->work.job_id); |
|||
time(&stratum_ctx->g_work_time); |
|||
|
|||
pthread_mutex_unlock(&stratum_ctx->work_lock); |
|||
|
|||
applog(LOG_DEBUG, "Stratum detected new block"); |
|||
restart_threads(); |
|||
|
|||
return; |
|||
} |
|||
|
|||
pthread_mutex_unlock(&stratum_ctx->work_lock); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief submit_upstream_work |
|||
* @param work |
|||
* @return |
|||
*/ |
|||
static bool submit_upstream_work(struct work *work) { |
|||
char s[JSON_BUF_LEN]; |
|||
|
|||
/* pass if the previous hash is not the current previous hash */ |
|||
if (memcmp(work->data + 1, stratum_ctx->g_work.data + 1, 32)) { |
|||
return true; |
|||
} |
|||
|
|||
char *noncestr = bin2hex(((const unsigned char*) work->data) + 39, 4); |
|||
char *hashhex = bin2hex((const unsigned char *) work->hash, 32); |
|||
|
|||
snprintf(s, JSON_BUF_LEN, |
|||
"{\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"},\"id\":1}", |
|||
stratum_ctx->id, work->job_id, noncestr, hashhex); |
|||
|
|||
free(hashhex); |
|||
free(noncestr); |
|||
|
|||
if (unlikely(!stratum_send_line(stratum_ctx, s))) { |
|||
return false; |
|||
} |
|||
|
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* @brief workio_cmd_free |
|||
* @param wc |
|||
*/ |
|||
static void workio_cmd_free(struct workio_cmd *wc) { |
|||
if (!wc) { |
|||
return; |
|||
} |
|||
|
|||
work_free(wc->work); |
|||
free(wc->work); |
|||
|
|||
memset(wc, 0, sizeof(*wc)); /* poison */ |
|||
free(wc); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief workio_submit_work |
|||
* @param wc |
|||
* @param curl |
|||
* @return |
|||
*/ |
|||
static bool workio_submit_work(struct workio_cmd *wc) { |
|||
while (!submit_upstream_work(wc->work)) { |
|||
sleep(opt_retry_pause); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief workio_thread |
|||
* @param userdata |
|||
* @return |
|||
*/ |
|||
static void *workio_thread(void *userdata) { |
|||
struct thr_info *mythr = userdata; |
|||
bool ok = true; |
|||
|
|||
while (ok) { |
|||
struct workio_cmd *wc; |
|||
|
|||
/* wait for workio_cmd sent to us, on our queue */ |
|||
wc = tq_pop(mythr->q, NULL ); |
|||
if (!wc) { |
|||
ok = false; |
|||
break; |
|||
} |
|||
|
|||
workio_submit_work(wc); |
|||
workio_cmd_free(wc); |
|||
} |
|||
|
|||
tq_freeze(mythr->q); |
|||
|
|||
return NULL ; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief submit_work |
|||
* @param thr |
|||
* @param work_in |
|||
* @return |
|||
*/ |
|||
static bool submit_work(struct thr_info *thr, const struct work *work_in) { |
|||
struct workio_cmd *wc; |
|||
|
|||
/* fill out work request message */ |
|||
wc = calloc(1, sizeof(*wc)); |
|||
wc->work = malloc(sizeof(*work_in)); |
|||
|
|||
if (likely(wc->work)) { |
|||
wc->thr = thr; |
|||
work_copy(wc->work, work_in); |
|||
|
|||
if (likely(tq_push(thr_info[work_thr_id].q, wc))) { |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
workio_cmd_free(wc); |
|||
return false; |
|||
} |
|||
|
|||
|
|||
static bool should_pause(int thr_id) { |
|||
bool ret = false; |
|||
|
|||
pthread_mutex_lock(&stratum_ctx->sock_lock); |
|||
|
|||
if (!stratum_ctx->ready) { |
|||
ret = true; |
|||
} |
|||
|
|||
pthread_mutex_unlock(&stratum_ctx->sock_lock); |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief miner_thread |
|||
* @param userdata |
|||
* @return |
|||
*/ |
|||
static void *miner_thread(void *userdata) { |
|||
struct thr_info *mythr = userdata; |
|||
int thr_id = mythr->id; |
|||
struct work work = { { 0 } }; |
|||
uint32_t max_nonce; |
|||
uint32_t end_nonce = 0xffffffffU / opt_n_threads * (thr_id + 1) - 0x20; |
|||
|
|||
struct cryptonight_ctx *persistentctx = (struct cryptonight_ctx *) &persistent_memory[TWO_MB_PAGE - sizeof(struct cryptonight_ctx) * (thr_id + 1)]; |
|||
|
|||
if (cpu_info.count > 1 && opt_n_threads > 1 && opt_affinity != -1L) { |
|||
affine_to_cpu_mask(thr_id, (unsigned long) opt_affinity); |
|||
} |
|||
|
|||
uint32_t *nonceptr = (uint32_t*) (((char*)work.data) + 39); |
|||
uint32_t hash[32 / 4] __attribute__((aligned(32))); |
|||
|
|||
while (1) { |
|||
unsigned long hashes_done; |
|||
struct timeval tv_start; |
|||
int64_t max64; |
|||
int rc; |
|||
|
|||
if (should_pause(thr_id)) { |
|||
sleep(1); |
|||
continue; |
|||
} |
|||
|
|||
pthread_mutex_lock(&stratum_ctx->work_lock); |
|||
|
|||
if (memcmp(work.data, stratum_ctx->g_work.data, 39) || memcmp(((uint8_t*) work.data) + 43, ((uint8_t*) stratum_ctx->g_work.data) + 43, 33)) { |
|||
work_free(&work); |
|||
work_copy(&work, &stratum_ctx->g_work); |
|||
nonceptr = (uint32_t*) (((char*)work.data) + 39); |
|||
*nonceptr = 0xffffffffU / opt_n_threads * thr_id; |
|||
} else { |
|||
++(*nonceptr); |
|||
} |
|||
|
|||
pthread_mutex_unlock(&stratum_ctx->work_lock); |
|||
|
|||
work_restart[thr_id].restart = 0; |
|||
|
|||
/* adjust max_nonce to meet target scan time */ |
|||
max64 = LP_SCANTIME; |
|||
|
|||
//max64 *= thr_hashrates[thr_id];
|
|||
if (max64 <= 0) { |
|||
max64 = 0x40LL; |
|||
} |
|||
|
|||
if (*nonceptr + max64 > end_nonce) { |
|||
max_nonce = end_nonce; |
|||
} else { |
|||
max_nonce = *nonceptr + max64; |
|||
} |
|||
|
|||
hashes_done = 0; |
|||
gettimeofday(&tv_start, NULL ); |
|||
|
|||
/* scan nonces for a proof-of-work hash */ |
|||
rc = scanhash_cryptonight(thr_id, hash, work.data, work.target, max_nonce, &hashes_done, &persistent_memory[TWO_MB_PAGE * (thr_id + 1)], persistentctx); |
|||
stats_add_hashes(thr_id, &tv_start, hashes_done); |
|||
|
|||
memcpy(work.hash, hash, 32); |
|||
|
|||
/* if nonce found, submit work */ |
|||
if (rc && !submit_work(mythr, &work)) { |
|||
continue; |
|||
} |
|||
} |
|||
|
|||
tq_freeze(mythr->q); |
|||
return NULL; |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_thread |
|||
* @param userdata |
|||
* @return |
|||
*/ |
|||
static void *timer_thread(void *userdata) { |
|||
const int max_user_time = 100 - opt_donate_level; |
|||
int user_time_remaning = max_user_time; |
|||
int donate_time_remaning = 0; |
|||
|
|||
|
|||
while (1) { |
|||
sleep(60); |
|||
|
|||
if (user_time_remaning > 0) { |
|||
if (--user_time_remaning == 0) { |
|||
g_want_donate = true; |
|||
|
|||
donate_time_remaning = opt_donate_level; |
|||
stratum_disconnect(stratum_ctx); |
|||
continue; |
|||
} |
|||
} |
|||
|
|||
if (donate_time_remaning > 0) { |
|||
if (--donate_time_remaning == 0) { |
|||
g_want_donate = false; |
|||
|
|||
user_time_remaning = max_user_time; |
|||
stratum_disconnect(stratum_ctx); |
|||
continue; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
static void switch_stratum() { |
|||
static bool want_donate = false; |
|||
|
|||
if (g_want_donate && !want_donate) { |
|||
stratum_ctx->url = "stratum+tcp://donate.xmrig.com:443"; |
|||
applog(LOG_NOTICE, "Switching to dev pool"); |
|||
want_donate = true; |
|||
} |
|||
|
|||
if (!g_want_donate && want_donate) { |
|||
stratum_ctx->url = backup_active ? opt_backup_url : opt_url; |
|||
applog(LOG_NOTICE, "Switching to user pool: \"%s\"", stratum_ctx->url); |
|||
want_donate = false; |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* @brief stratum_thread |
|||
* @param userdata |
|||
* @return |
|||
*/ |
|||
static void *stratum_thread(void *userdata) { |
|||
char *s; |
|||
|
|||
stratum_ctx->url = opt_url; |
|||
stratum_ctx->ready = false; |
|||
|
|||
while (1) { |
|||
int failures = 0; |
|||
switch_stratum(); |
|||
|
|||
while (!stratum_ctx->curl) { |
|||
pthread_mutex_lock(&stratum_ctx->work_lock); |
|||
stratum_ctx->g_work_time = 0; |
|||
pthread_mutex_unlock(&stratum_ctx->work_lock); |
|||
|
|||
restart_threads(); |
|||
switch_stratum(); |
|||
|
|||
if (!stratum_connect(stratum_ctx, stratum_ctx->url) || !stratum_authorize(stratum_ctx, opt_user, opt_pass)) { |
|||
stratum_disconnect(stratum_ctx); |
|||
failures++; |
|||
|
|||
if (failures > opt_retries && opt_backup_url) { |
|||
failures = 0; |
|||
|
|||
backup_active = !backup_active; |
|||
stratum_ctx->url = backup_active ? opt_backup_url : opt_url; |
|||
sleep(opt_retry_pause); |
|||
|
|||
applog(LOG_WARNING, "Switch to: \"%s\"", stratum_ctx->url); |
|||
continue; |
|||
} |
|||
|
|||
applog(LOG_ERR, "...retry after %d seconds", opt_retry_pause); |
|||
sleep(opt_retry_pause); |
|||
} |
|||
} |
|||
|
|||
gen_workify(stratum_ctx); |
|||
|
|||
if (opt_keepalive && !stratum_socket_full(stratum_ctx, 90)) { |
|||
stratum_keepalived(stratum_ctx); |
|||
} |
|||
|
|||
if (!stratum_socket_full(stratum_ctx, 300)) { |
|||
applog(LOG_ERR, "Stratum connection timed out"); |
|||
s = NULL; |
|||
} else { |
|||
s = stratum_recv_line(stratum_ctx); |
|||
} |
|||
|
|||
if (!s) { |
|||
stratum_disconnect(stratum_ctx); |
|||
applog(LOG_ERR, "Stratum connection interrupted"); |
|||
continue; |
|||
} |
|||
|
|||
if (!stratum_handle_method(stratum_ctx, s)) { |
|||
stratum_handle_response(s); |
|||
} |
|||
|
|||
free(s); |
|||
} |
|||
|
|||
return NULL ; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief start work I/O thread |
|||
* @return |
|||
*/ |
|||
static bool start_workio() { |
|||
work_thr_id = opt_n_threads; |
|||
|
|||
struct thr_info *thr = &thr_info[work_thr_id]; |
|||
thr->id = work_thr_id; |
|||
thr->q = tq_new(); |
|||
|
|||
if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, workio_thread, thr))) { |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief start_stratum |
|||
* @return |
|||
*/ |
|||
static bool start_stratum() { |
|||
stratum_thr_id = opt_n_threads + 1; |
|||
|
|||
stratum_ctx = persistent_calloc(1, sizeof(struct stratum_ctx)); |
|||
pthread_mutex_init(&stratum_ctx->work_lock, NULL); |
|||
pthread_mutex_init(&stratum_ctx->sock_lock, NULL); |
|||
|
|||
struct thr_info *thr = &thr_info[stratum_thr_id]; |
|||
thr->id = stratum_thr_id; |
|||
thr->q = tq_new(); |
|||
|
|||
if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, stratum_thread, thr))) { |
|||
return false; |
|||
} |
|||
|
|||
tq_push(thr_info[stratum_thr_id].q, strdup(opt_url)); |
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief start_timer |
|||
* @return |
|||
*/ |
|||
static bool start_timer() { |
|||
timer_thr_id = opt_n_threads + 2; |
|||
|
|||
if (opt_donate_level < 1) { |
|||
return true; |
|||
} |
|||
|
|||
struct thr_info *thr = &thr_info[timer_thr_id]; |
|||
thr->id = timer_thr_id; |
|||
thr->q = tq_new(); |
|||
|
|||
if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, timer_thread, thr))) { |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief start_mining |
|||
* @return |
|||
*/ |
|||
static bool start_mining() { |
|||
for (int i = 0; i < opt_n_threads; i++) { |
|||
struct thr_info *thr = &thr_info[i]; |
|||
|
|||
thr->id = i; |
|||
thr->q = tq_new(); |
|||
|
|||
if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, miner_thread, thr))) { |
|||
applog(LOG_ERR, "thread %d create failed", i); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* @brief main |
|||
* @param argc |
|||
* @param argv |
|||
* @return |
|||
*/ |
|||
int main(int argc, char *argv[]) { |
|||
cpu_init(); |
|||
applog_init(); |
|||
parse_cmdline(argc, argv); |
|||
persistent_memory_allocate(); |
|||
print_summary(); |
|||
|
|||
stats_init(); |
|||
os_specific_init(); |
|||
|
|||
work_restart = persistent_calloc(opt_n_threads, sizeof(*work_restart)); |
|||
thr_info = persistent_calloc(opt_n_threads + 3, sizeof(struct thr_info)); |
|||
|
|||
if (!start_workio()) { |
|||
applog(LOG_ERR, "workio thread create failed"); |
|||
return 1; |
|||
} |
|||
|
|||
if (!start_stratum()) { |
|||
applog(LOG_ERR, "stratum thread create failed"); |
|||
return 1; |
|||
} |
|||
|
|||
start_timer(); |
|||
|
|||
if (!start_mining()) { |
|||
return 1; |
|||
} |
|||
|
|||
pthread_join(thr_info[work_thr_id].pth, NULL); |
|||
applog(LOG_INFO, "workio thread dead, exiting."); |
|||
persistent_memory_free(); |
|||
return 0; |
|||
} |
|||
|
@ -0,0 +1,57 @@ |
|||
/* 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 __XMRIG_H__ |
|||
#define __XMRIG_H__ |
|||
|
|||
#include <stdbool.h> |
|||
#include <inttypes.h> |
|||
#include <jansson.h> |
|||
#include <curl/curl.h> |
|||
#include <pthread.h> |
|||
|
|||
#define unlikely(expr) (__builtin_expect(!!(expr), 0)) |
|||
#define likely(expr) (__builtin_expect(!!(expr), 1)) |
|||
|
|||
|
|||
struct thr_info { |
|||
int id; |
|||
pthread_t pth; |
|||
struct thread_q *q; |
|||
}; |
|||
|
|||
|
|||
struct work_restart { |
|||
volatile unsigned long restart; |
|||
char padding[128 - sizeof(unsigned long)]; |
|||
}; |
|||
|
|||
|
|||
struct work; |
|||
|
|||
|
|||
extern struct thr_info *thr_info; |
|||
extern struct work_restart *work_restart; |
|||
extern void os_specific_init(); |
|||
|
|||
#endif /* __XMRIG_H__ */ |
Loading…
Reference in new issue