mirror of
https://github.com/xmrig/xmrig.git
synced 2024-11-16 15:57:38 +00:00
Initial import.
This commit is contained in:
commit
ed320731e9
93 changed files with 21078 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build
|
127
CMakeLists.txt
Normal file
127
CMakeLists.txt
Normal file
|
@ -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})
|
674
LICENSE
Normal file
674
LICENSE
Normal file
|
@ -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>.
|
94
README.md
Normal file
94
README.md
Normal file
|
@ -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).
|
2
algo/cryptonight/bmi2/CMakeLists.txt
Normal file
2
algo/cryptonight/bmi2/CMakeLists.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbmi2")
|
||||||
|
add_library(cryptonight_av3_aesni_bmi2 STATIC ../cryptonight_av3_aesni_bmi2.c)
|
72
algo/cryptonight/cryptonight.h
Normal file
72
algo/cryptonight/cryptonight.h
Normal file
|
@ -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__ */
|
216
algo/cryptonight/cryptonight_av1_aesni.c
Normal file
216
algo/cryptonight/cryptonight_av1_aesni.c
Normal file
|
@ -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);
|
||||||
|
}
|
239
algo/cryptonight/cryptonight_av1_aesni32.c
Normal file
239
algo/cryptonight/cryptonight_av1_aesni32.c
Normal file
|
@ -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);
|
||||||
|
}
|
237
algo/cryptonight/cryptonight_av2_aesni_wolf.c
Normal file
237
algo/cryptonight/cryptonight_av2_aesni_wolf.c
Normal file
|
@ -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);
|
||||||
|
}
|
214
algo/cryptonight/cryptonight_av3_aesni_bmi2.c
Normal file
214
algo/cryptonight/cryptonight_av3_aesni_bmi2.c
Normal file
|
@ -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);
|
||||||
|
}
|
151
algo/cryptonight/cryptonight_av4_legacy.c
Normal file
151
algo/cryptonight/cryptonight_av4_legacy.c
Normal file
|
@ -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);
|
||||||
|
}
|
248
algo/cryptonight/cryptonight_av5_aesni_experimental.c
Normal file
248
algo/cryptonight/cryptonight_av5_aesni_experimental.c
Normal file
|
@ -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);
|
||||||
|
}
|
142
algo/cryptonight/cryptonight_common.c
Normal file
142
algo/cryptonight/cryptonight_common.c
Normal file
|
@ -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
|
47
compat.h
Normal file
47
compat.h
Normal file
|
@ -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__ */
|
23
compat/jansson/CMakeLists.txt
Normal file
23
compat/jansson/CMakeLists.txt
Normal file
|
@ -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})
|
19
compat/jansson/LICENSE
Normal file
19
compat/jansson/LICENSE
Normal file
|
@ -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.
|
446
compat/jansson/dump.c
Normal file
446
compat/jansson/dump.c
Normal file
|
@ -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);
|
||||||
|
}
|
63
compat/jansson/error.c
Normal file
63
compat/jansson/error.c
Normal file
|
@ -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';
|
||||||
|
}
|
356
compat/jansson/hashtable.c
Normal file
356
compat/jansson/hashtable.c
Normal file
|
@ -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;
|
||||||
|
}
|
176
compat/jansson/hashtable.h
Normal file
176
compat/jansson/hashtable.h
Normal file
|
@ -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
|
277
compat/jansson/hashtable_seed.c
Normal file
277
compat/jansson/hashtable_seed.c
Normal file
|
@ -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
|
311
compat/jansson/jansson.h
Normal file
311
compat/jansson/jansson.h
Normal file
|
@ -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
|
43
compat/jansson/jansson_config.h
Normal file
43
compat/jansson/jansson_config.h
Normal file
|
@ -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
|
108
compat/jansson/jansson_private.h
Normal file
108
compat/jansson/jansson_private.h
Normal file
|
@ -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
|
159
compat/jansson/jansson_private_config.h
Normal file
159
compat/jansson/jansson_private_config.h
Normal file
|
@ -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 */
|
1110
compat/jansson/load.c
Normal file
1110
compat/jansson/load.c
Normal file
File diff suppressed because it is too large
Load diff
381
compat/jansson/lookup3.h
Normal file
381
compat/jansson/lookup3.h
Normal file
|
@ -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;
|
||||||
|
}
|
69
compat/jansson/memory.c
Normal file
69
compat/jansson/memory.c
Normal file
|
@ -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;
|
||||||
|
}
|
871
compat/jansson/pack_unpack.c
Normal file
871
compat/jansson/pack_unpack.c
Normal file
|
@ -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;
|
||||||
|
}
|
111
compat/jansson/strbuffer.c
Normal file
111
compat/jansson/strbuffer.c
Normal file
|
@ -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';
|
||||||
|
}
|
34
compat/jansson/strbuffer.h
Normal file
34
compat/jansson/strbuffer.h
Normal file
|
@ -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
|
145
compat/jansson/strconv.c
Normal file
145
compat/jansson/strconv.c
Normal file
|
@ -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;
|
||||||
|
}
|
187
compat/jansson/utf.c
Normal file
187
compat/jansson/utf.c
Normal file
|
@ -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;
|
||||||
|
}
|
27
compat/jansson/utf.h
Normal file
27
compat/jansson/utf.h
Normal file
|
@ -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
|
1045
compat/jansson/value.c
Normal file
1045
compat/jansson/value.c
Normal file
File diff suppressed because it is too large
Load diff
392
compat/winansi.c
Normal file
392
compat/winansi.c
Normal file
|
@ -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;
|
||||||
|
}
|
32
compat/winansi.h
Normal file
32
compat/winansi.h
Normal file
|
@ -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
|
100
cpu.c
Normal file
100
cpu.c
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
48
cpu.h
Normal file
48
cpu.h
Normal file
|
@ -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__ */
|
170
crypto/aesb.c
Normal file
170
crypto/aesb.c
Normal file
|
@ -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
|
10
crypto/aesb.h
Normal file
10
crypto/aesb.h
Normal file
|
@ -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__ */
|
326
crypto/c_blake256.c
Normal file
326
crypto/c_blake256.c
Normal file
|
@ -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);
|
||||||
|
}
|
43
crypto/c_blake256.h
Normal file
43
crypto/c_blake256.h
Normal file
|
@ -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_ */
|
360
crypto/c_groestl.c
Normal file
360
crypto/c_groestl.c
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
60
crypto/c_groestl.h
Normal file
60
crypto/c_groestl.h
Normal file
|
@ -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 */
|
367
crypto/c_jh.c
Normal file
367
crypto/c_jh.c
Normal file
|
@ -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);
|
||||||
|
}
|
19
crypto/c_jh.h
Normal file
19
crypto/c_jh.h
Normal file
|
@ -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);
|
123
crypto/c_keccak.c
Normal file
123
crypto/c_keccak.c
Normal file
|
@ -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);
|
||||||
|
}
|
26
crypto/c_keccak.h
Normal file
26
crypto/c_keccak.h
Normal file
|
@ -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
|
2036
crypto/c_skein.c
Normal file
2036
crypto/c_skein.c
Normal file
File diff suppressed because it is too large
Load diff
47
crypto/c_skein.h
Normal file
47
crypto/c_skein.h
Normal file
|
@ -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_ */
|
38
crypto/groestl_tables.h
Normal file
38
crypto/groestl_tables.h
Normal file
|
@ -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 */
|
24
crypto/hash.c
Normal file
24
crypto/hash.c
Normal file
|
@ -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);
|
||||||
|
}
|
5
crypto/hash.h
Normal file
5
crypto/hash.h
Normal file
|
@ -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;
|
50
crypto/oaes_config.h
Normal file
50
crypto/oaes_config.h
Normal file
|
@ -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
|
1417
crypto/oaes_lib.c
Normal file
1417
crypto/oaes_lib.c
Normal file
File diff suppressed because it is too large
Load diff
214
crypto/oaes_lib.h
Normal file
214
crypto/oaes_lib.h
Normal file
|
@ -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
|
187
crypto/skein_port.h
Normal file
187
crypto/skein_port.h
Normal file
|
@ -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_ */
|
29
donate.h
Normal file
29
donate.h
Normal file
|
@ -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__ */
|
274
elist.h
Normal file
274
elist.h
Normal file
|
@ -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
|
38
memory.c
Normal file
38
memory.c
Normal file
|
@ -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;
|
||||||
|
}
|
441
options.c
Normal file
441
options.c
Normal file
|
@ -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);
|
||||||
|
}
|
68
options.h
Normal file
68
options.h
Normal file
|
@ -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__ */
|
49
persistent_memory.h
Normal file
49
persistent_memory.h
Normal file
|
@ -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__ */
|
137
stats.c
Normal file
137
stats.c
Normal file
|
@ -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;
|
||||||
|
}
|
37
stats.h
Normal file
37
stats.h
Normal file
|
@ -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__ */
|
707
stratum.c
Normal file
707
stratum.c
Normal file
|
@ -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;
|
||||||
|
}
|
76
stratum.h
Normal file
76
stratum.h
Normal file
|
@ -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__ */
|
7
test/CMakeLists.txt
Normal file
7
test/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
project("xmrig-test" C)
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
|
include(CTest)
|
||||||
|
|
||||||
|
add_subdirectory(unity)
|
||||||
|
add_subdirectory(cryptonight)
|
44
test/cryptonight/CMakeLists.txt
Normal file
44
test/cryptonight/CMakeLists.txt
Normal file
|
@ -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)
|
3
test/cryptonight/bmi2/CMakeLists.txt
Normal file
3
test/cryptonight/bmi2/CMakeLists.txt
Normal file
|
@ -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)
|
158
test/cryptonight/cryptonight.c
Normal file
158
test/cryptonight/cryptonight.c
Normal file
|
@ -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();
|
||||||
|
}
|
95
test/cryptonight/cryptonight32.c
Normal file
95
test/cryptonight/cryptonight32.c
Normal file
|
@ -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();
|
||||||
|
}
|
2
test/unity/CMakeLists.txt
Normal file
2
test/unity/CMakeLists.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
add_library(unity STATIC unity.c)
|
||||||
|
target_include_directories(unity PUBLIC .)
|
1446
test/unity/unity.c
Normal file
1446
test/unity/unity.c
Normal file
File diff suppressed because it is too large
Load diff
293
test/unity/unity.h
Normal file
293
test/unity/unity.h
Normal file
|
@ -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
|
749
test/unity/unity_internals.h
Normal file
749
test/unity/unity_internals.h
Normal file
|
@ -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
|
64
unix/cpu_unix.c
Normal file
64
unix/cpu_unix.c
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
81
unix/memory_unix.c
Normal file
81
unix/memory_unix.c
Normal file
|
@ -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__ */
|
91
unix/xmrig_unix.c
Normal file
91
unix/xmrig_unix.c
Normal file
|
@ -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);
|
||||||
|
}
|
270
util.c
Normal file
270
util.c
Normal file
|
@ -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;
|
||||||
|
}
|
43
util.h
Normal file
43
util.h
Normal file
|
@ -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__ */
|
146
utils/applog.c
Normal file
146
utils/applog.c
Normal file
|
@ -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);
|
||||||
|
}
|
74
utils/applog.h
Normal file
74
utils/applog.h
Normal file
|
@ -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__ */
|
103
utils/summary.c
Normal file
103
utils/summary.c
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
29
utils/summary.h
Normal file
29
utils/summary.h
Normal file
|
@ -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__ */
|
41
utils/threads.h
Normal file
41
utils/threads.h
Normal file
|
@ -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__ */
|
39
version.h
Normal file
39
version.h
Normal file
|
@ -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__ */
|
58
win/cpu_win.c
Normal file
58
win/cpu_win.c
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
116
win/memory_win.c
Normal file
116
win/memory_win.c
Normal file
|
@ -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__ */
|
84
win/xmrig_win.c
Normal file
84
win/xmrig_win.c
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
610
xmrig.c
Normal file
610
xmrig.c
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
57
xmrig.h
Normal file
57
xmrig.h
Normal file
|
@ -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 a new issue