From 9ff1e2f044c3d45049c6e5672b776e1c735cf4ef Mon Sep 17 00:00:00 2001 From: Oliver Weichhold Date: Tue, 10 Sep 2019 08:42:37 +0200 Subject: [PATCH 01/36] Create stale.yml --- .github/stale.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 00000000..dc90e5a1 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,17 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security +# Label to use when marking an issue as stale +staleLabel: wontfix +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false From d72db18e797d53c6f80441117c8f0aca348910ef Mon Sep 17 00:00:00 2001 From: Oliver Weichhold Date: Mon, 9 Dec 2019 11:20:31 +0100 Subject: [PATCH 02/36] Dupe prevention. Fixes #710 --- src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs | 2 +- src/Miningcore/Blockchain/Cryptonote/CryptonoteWorkerJob.cs | 3 ++- src/Miningcore/Blockchain/Equihash/EquihashJob.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 68651db4..1f1e617e 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -57,7 +57,7 @@ public class BitcoinJob protected PoolConfig poolConfig; protected BitcoinTemplate coin; private BitcoinTemplate.BitcoinNetworkParams networkParams; - protected readonly HashSet submissions = new HashSet(); + protected readonly HashSet submissions = new HashSet(StringComparer.OrdinalIgnoreCase); protected uint256 blockTargetValue; protected byte[] coinbaseFinal; protected string coinbaseFinalHex; diff --git a/src/Miningcore/Blockchain/Cryptonote/CryptonoteWorkerJob.cs b/src/Miningcore/Blockchain/Cryptonote/CryptonoteWorkerJob.cs index 83d8a3ae..85d2d24d 100644 --- a/src/Miningcore/Blockchain/Cryptonote/CryptonoteWorkerJob.cs +++ b/src/Miningcore/Blockchain/Cryptonote/CryptonoteWorkerJob.cs @@ -18,6 +18,7 @@ portions of the Software. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +using System; using System.Collections.Generic; namespace Miningcore.Blockchain.Cryptonote @@ -35,6 +36,6 @@ public CryptonoteWorkerJob(string jobId, double difficulty) public uint ExtraNonce { get; set; } public double Difficulty { get; set; } - public HashSet Submissions { get; } = new HashSet(); + public HashSet Submissions { get; } = new HashSet(StringComparer.OrdinalIgnoreCase); } } diff --git a/src/Miningcore/Blockchain/Equihash/EquihashJob.cs b/src/Miningcore/Blockchain/Equihash/EquihashJob.cs index dba80155..411eebec 100644 --- a/src/Miningcore/Blockchain/Equihash/EquihashJob.cs +++ b/src/Miningcore/Blockchain/Equihash/EquihashJob.cs @@ -50,7 +50,7 @@ public class EquihashJob protected Network network; protected IDestination poolAddressDestination; - protected readonly HashSet submissions = new HashSet(); + protected readonly HashSet submissions = new HashSet(StringComparer.OrdinalIgnoreCase); protected uint256 blockTargetValue; protected byte[] coinbaseInitial; From 1faa235cda9f3a5d931393139122832a126dc980 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Mon, 2 Mar 2020 19:11:51 +0300 Subject: [PATCH 03/36] Update to .net3 and add x16rv2 --- README.md | 4 +- appveyor.yml | 8 +- src/Miningcore.Tests/Miningcore.Tests.csproj | 8 +- src/Miningcore/Miningcore.csproj | 5 +- src/Miningcore/Program.cs | 2 +- src/Miningcore/linux-build.sh | 2 +- src/Native/libmultihash/sph_tiger.h | 191 +++++ src/Native/libmultihash/tiger.c | 697 +++++++++++++++++++ src/Native/libmultihash/x16r.c | 266 +++---- 9 files changed, 1045 insertions(+), 138 deletions(-) create mode 100644 src/Native/libmultihash/sph_tiger.h create mode 100644 src/Native/libmultihash/tiger.c diff --git a/README.md b/README.md index 53f91749..f867e5fa 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ $ sudo apt-get update -y $ sudo apt-get -y install dotnet-sdk-2.2 git cmake build-essential libssl-dev pkg-config libboost-all-dev libsodium-dev libzmq5 $ git clone https://github.com/coinfoundry/miningcore $ cd miningcore/src/Miningcore -$ dotnet publish -c Release --framework netcoreapp2.2 -o ../../build +$ dotnet publish -c Release --framework netcoreapp3.1 -o ../../build ``` #### Building on Windows @@ -145,7 +145,7 @@ Download and install the [.Net Core 2.2 SDK](https://www.microsoft.com/net/downl ```dosbatch > git clone https://github.com/coinfoundry/miningcore > cd miningcore/src/Miningcore -> dotnet publish -c Release --framework netcoreapp2.2 -o ..\..\build +> dotnet publish -c Release --framework netcoreapp3.1 -o ..\..\build ``` #### Building on Windows - Visual Studio diff --git a/appveyor.yml b/appveyor.yml index 4edf8831..bd750329 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,13 +21,13 @@ build_script: - sh: sudo apt-get update -y && sudo apt-get -y install cmake build-essential libssl-dev pkg-config libboost-all-dev libsodium-dev libzmq5 - # Publish - cd Miningcore - - dotnet publish -c Release --framework netcoreapp2.2 + - dotnet publish -c Release --framework netcoreapp3.1 - # Publish Artifacts - - sh: (cd bin/Release/netcoreapp2.2 && mkdir miningcore && cp -r publish/* miningcore && tar cf miningcore-linux-ubuntu-x64.tar.gz miningcore && appveyor PushArtifact miningcore-linux-ubuntu-x64.tar.gz) - - cmd: cd bin\Release\netcoreapp2.2 && mkdir miningcore && xcopy publish\* miningcore /S && 7z a miningcore-win-x64.zip miningcore && appveyor PushArtifact miningcore-win-x64.zip && cd ..\..\.. + - sh: (cd bin/Release/netcoreapp3.1 && mkdir miningcore && cp -r publish/* miningcore && tar cf miningcore-linux-ubuntu-x64.tar.gz miningcore && appveyor PushArtifact miningcore-linux-ubuntu-x64.tar.gz) + - cmd: cd bin\Release\netcoreapp3.1 && mkdir miningcore && xcopy publish\* miningcore /S && 7z a miningcore-win-x64.zip miningcore && appveyor PushArtifact miningcore-win-x64.zip && cd ..\..\.. - # Build Tests - cd ../Miningcore.Tests - - dotnet build -c Release --framework netcoreapp2.2 + - dotnet build -c Release --framework netcoreapp3.1 #---------------------------------# # tests configuration # diff --git a/src/Miningcore.Tests/Miningcore.Tests.csproj b/src/Miningcore.Tests/Miningcore.Tests.csproj index 2ea5169a..8977ebbd 100644 --- a/src/Miningcore.Tests/Miningcore.Tests.csproj +++ b/src/Miningcore.Tests/Miningcore.Tests.csproj @@ -10,7 +10,7 @@ - netcoreapp2.2 + netcoreapp3.1 false AnyCPU Miningcore.Tests @@ -35,7 +35,7 @@ - + all @@ -56,7 +56,7 @@ - + @@ -65,7 +65,7 @@ - + diff --git a/src/Miningcore/Miningcore.csproj b/src/Miningcore/Miningcore.csproj index 7f46795d..141bc85e 100644 --- a/src/Miningcore/Miningcore.csproj +++ b/src/Miningcore/Miningcore.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.2 + netcoreapp3.1 Miningcore Miningcore AnyCPU @@ -58,7 +58,8 @@ - + + diff --git a/src/Miningcore/Program.cs b/src/Miningcore/Program.cs index 97f460a7..8f45c8d6 100644 --- a/src/Miningcore/Program.cs +++ b/src/Miningcore/Program.cs @@ -730,7 +730,7 @@ private static void StartApi() services.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .AddControllersAsServices() - .AddJsonOptions(options => + .AddNewtonsoftJson(options => { options.SerializerSettings.Formatting = Formatting.Indented; }); diff --git a/src/Miningcore/linux-build.sh b/src/Miningcore/linux-build.sh index a3889448..782ae4ec 100755 --- a/src/Miningcore/linux-build.sh +++ b/src/Miningcore/linux-build.sh @@ -5,4 +5,4 @@ BUILDIR=${1:-../../build} echo "Building into $BUILDIR" -dotnet publish -c Release --framework netcoreapp2.2 -o $BUILDIR +dotnet publish -c Release --framework netcoreapp3.1 -o $BUILDIR diff --git a/src/Native/libmultihash/sph_tiger.h b/src/Native/libmultihash/sph_tiger.h new file mode 100644 index 00000000..1a586853 --- /dev/null +++ b/src/Native/libmultihash/sph_tiger.h @@ -0,0 +1,191 @@ +/* $Id: sph_tiger.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * Tiger / Tiger-2 interface. + * + * Tiger has been published in: R. Anderson, E. Biham, "Tiger: A Fast + * New Hash Function", Fast Software Encryption - FSE'96, LNCS 1039, + * Springer (1996), pp. 89--97. + * + * Tiger2 has never been formally published, but it was described as + * identical to Tiger, except for the padding which is the same in + * Tiger2 as it is in MD4. Fortunately, an implementation of Tiger2 + * was submitted to NESSIE, which produced test vectors; the sphlib + * implementation of Tiger2 is compatible with the NESSIE test vectors. + * + * ==========================(LICENSE BEGIN)============================ + * + * Copyright (c) 2007-2010 Projet RNRT SAPHIR + * + * 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. + * + * ===========================(LICENSE END)============================= + * + * @file sph_tiger.h + * @author Thomas Pornin + */ + +#ifndef SPH_TIGER_H__ +#define SPH_TIGER_H__ + +#include +#include "sph_types.h" + +#if SPH_64 + +/** + * Output size (in bits) for Tiger. + */ +#define SPH_SIZE_tiger 192 + +/** + * Output size (in bits) for Tiger2. + */ +#define SPH_SIZE_tiger2 192 + +/** + * This structure is a context for Tiger computations: it contains the + * intermediate values and some data from the last entered block. Once + * a Tiger computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running Tiger computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + sph_u64 val[3]; + sph_u64 count; +#endif +} sph_tiger_context; + +/** + * Initialize a Tiger context. This process performs no memory allocation. + * + * @param cc the Tiger context (pointer to + * a sph_tiger_context) + */ +void sph_tiger_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Tiger context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_tiger(void *cc, const void *data, size_t len); + +/** + * Terminate the current Tiger computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (24 bytes). The context is automatically + * reinitialized. + * + * @param cc the Tiger context + * @param dst the destination buffer + */ +void sph_tiger_close(void *cc, void *dst); + +/** + * Apply the Tiger compression function on the provided data. The + * msg parameter contains the 8 64-bit input blocks, + * as numerical values (hence after the little-endian decoding). The + * val parameter contains the 3 64-bit input blocks for + * the compression function; the output is written in place in this + * array. + * + * @param msg the message block (8 values) + * @param val the function 192-bit input and output + */ +void sph_tiger_comp(const sph_u64 msg[8], sph_u64 val[3]); + +/** + * This structure is a context for Tiger2 computations. It is identical + * to the Tiger context, and they may be freely exchanged, since the + * difference between Tiger and Tiger2 resides solely in the padding, which + * is computed only in the last computation step. + */ +typedef sph_tiger_context sph_tiger2_context; + +#ifdef DOXYGEN_IGNORE +/** + * Initialize a Tiger2 context. This function is identical to + * sph_tiger_init(). + * + * @param cc the Tiger2 context (pointer to + * a sph_tiger2_context) + */ +void sph_tiger2_init(void *cc); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_tiger2_init sph_tiger_init +#endif + +#ifdef DOXYGEN_IGNORE +/** + * Process some data bytes. This function is identical to + * sph_tiger(). + * + * @param cc the Tiger2 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_tiger2(void *cc, const void *data, size_t len); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_tiger2 sph_tiger +#endif + +/** + * Terminate the current Tiger2 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (24 bytes). The context is automatically + * reinitialized. Note that this function is NOT identical to + * sph_tiger2_close(): this is the exact and unique point + * where Tiger and Tiger2 differ. + * + * @param cc the Tiger context + * @param dst the destination buffer + */ +void sph_tiger2_close(void *cc, void *dst); + +#ifdef DOXYGEN_IGNORE +/** + * Apply the Tiger2 compression function, which is identical to the Tiger + * compression function. + * + * @param msg the message block (8 values) + * @param val the function 192-bit input and output + */ +void sph_tiger2_comp(const sph_u64 msg[8], sph_u64 val[3]); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_tiger2_comp sph_tiger_comp +#endif + +#endif + +#endif \ No newline at end of file diff --git a/src/Native/libmultihash/tiger.c b/src/Native/libmultihash/tiger.c new file mode 100644 index 00000000..f22fcb97 --- /dev/null +++ b/src/Native/libmultihash/tiger.c @@ -0,0 +1,697 @@ +/* $Id: tiger.c 216 2010-06-08 09:46:57Z tp $ */ +/* + * Tiger / Tiger2 implementation. + * + * ==========================(LICENSE BEGIN)============================ + * + * Copyright (c) 2007-2010 Projet RNRT SAPHIR + * + * 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. + * + * ===========================(LICENSE END)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_tiger.h" + +#if SPH_64 + +static const sph_u64 T1[256] = { + SPH_C64(0x02AAB17CF7E90C5E), SPH_C64(0xAC424B03E243A8EC), + SPH_C64(0x72CD5BE30DD5FCD3), SPH_C64(0x6D019B93F6F97F3A), + SPH_C64(0xCD9978FFD21F9193), SPH_C64(0x7573A1C9708029E2), + SPH_C64(0xB164326B922A83C3), SPH_C64(0x46883EEE04915870), + SPH_C64(0xEAACE3057103ECE6), SPH_C64(0xC54169B808A3535C), + SPH_C64(0x4CE754918DDEC47C), SPH_C64(0x0AA2F4DFDC0DF40C), + SPH_C64(0x10B76F18A74DBEFA), SPH_C64(0xC6CCB6235AD1AB6A), + SPH_C64(0x13726121572FE2FF), SPH_C64(0x1A488C6F199D921E), + SPH_C64(0x4BC9F9F4DA0007CA), SPH_C64(0x26F5E6F6E85241C7), + SPH_C64(0x859079DBEA5947B6), SPH_C64(0x4F1885C5C99E8C92), + SPH_C64(0xD78E761EA96F864B), SPH_C64(0x8E36428C52B5C17D), + SPH_C64(0x69CF6827373063C1), SPH_C64(0xB607C93D9BB4C56E), + SPH_C64(0x7D820E760E76B5EA), SPH_C64(0x645C9CC6F07FDC42), + SPH_C64(0xBF38A078243342E0), SPH_C64(0x5F6B343C9D2E7D04), + SPH_C64(0xF2C28AEB600B0EC6), SPH_C64(0x6C0ED85F7254BCAC), + SPH_C64(0x71592281A4DB4FE5), SPH_C64(0x1967FA69CE0FED9F), + SPH_C64(0xFD5293F8B96545DB), SPH_C64(0xC879E9D7F2A7600B), + SPH_C64(0x860248920193194E), SPH_C64(0xA4F9533B2D9CC0B3), + SPH_C64(0x9053836C15957613), SPH_C64(0xDB6DCF8AFC357BF1), + SPH_C64(0x18BEEA7A7A370F57), SPH_C64(0x037117CA50B99066), + SPH_C64(0x6AB30A9774424A35), SPH_C64(0xF4E92F02E325249B), + SPH_C64(0x7739DB07061CCAE1), SPH_C64(0xD8F3B49CECA42A05), + SPH_C64(0xBD56BE3F51382F73), SPH_C64(0x45FAED5843B0BB28), + SPH_C64(0x1C813D5C11BF1F83), SPH_C64(0x8AF0E4B6D75FA169), + SPH_C64(0x33EE18A487AD9999), SPH_C64(0x3C26E8EAB1C94410), + SPH_C64(0xB510102BC0A822F9), SPH_C64(0x141EEF310CE6123B), + SPH_C64(0xFC65B90059DDB154), SPH_C64(0xE0158640C5E0E607), + SPH_C64(0x884E079826C3A3CF), SPH_C64(0x930D0D9523C535FD), + SPH_C64(0x35638D754E9A2B00), SPH_C64(0x4085FCCF40469DD5), + SPH_C64(0xC4B17AD28BE23A4C), SPH_C64(0xCAB2F0FC6A3E6A2E), + SPH_C64(0x2860971A6B943FCD), SPH_C64(0x3DDE6EE212E30446), + SPH_C64(0x6222F32AE01765AE), SPH_C64(0x5D550BB5478308FE), + SPH_C64(0xA9EFA98DA0EDA22A), SPH_C64(0xC351A71686C40DA7), + SPH_C64(0x1105586D9C867C84), SPH_C64(0xDCFFEE85FDA22853), + SPH_C64(0xCCFBD0262C5EEF76), SPH_C64(0xBAF294CB8990D201), + SPH_C64(0xE69464F52AFAD975), SPH_C64(0x94B013AFDF133E14), + SPH_C64(0x06A7D1A32823C958), SPH_C64(0x6F95FE5130F61119), + SPH_C64(0xD92AB34E462C06C0), SPH_C64(0xED7BDE33887C71D2), + SPH_C64(0x79746D6E6518393E), SPH_C64(0x5BA419385D713329), + SPH_C64(0x7C1BA6B948A97564), SPH_C64(0x31987C197BFDAC67), + SPH_C64(0xDE6C23C44B053D02), SPH_C64(0x581C49FED002D64D), + SPH_C64(0xDD474D6338261571), SPH_C64(0xAA4546C3E473D062), + SPH_C64(0x928FCE349455F860), SPH_C64(0x48161BBACAAB94D9), + SPH_C64(0x63912430770E6F68), SPH_C64(0x6EC8A5E602C6641C), + SPH_C64(0x87282515337DDD2B), SPH_C64(0x2CDA6B42034B701B), + SPH_C64(0xB03D37C181CB096D), SPH_C64(0xE108438266C71C6F), + SPH_C64(0x2B3180C7EB51B255), SPH_C64(0xDF92B82F96C08BBC), + SPH_C64(0x5C68C8C0A632F3BA), SPH_C64(0x5504CC861C3D0556), + SPH_C64(0xABBFA4E55FB26B8F), SPH_C64(0x41848B0AB3BACEB4), + SPH_C64(0xB334A273AA445D32), SPH_C64(0xBCA696F0A85AD881), + SPH_C64(0x24F6EC65B528D56C), SPH_C64(0x0CE1512E90F4524A), + SPH_C64(0x4E9DD79D5506D35A), SPH_C64(0x258905FAC6CE9779), + SPH_C64(0x2019295B3E109B33), SPH_C64(0xF8A9478B73A054CC), + SPH_C64(0x2924F2F934417EB0), SPH_C64(0x3993357D536D1BC4), + SPH_C64(0x38A81AC21DB6FF8B), SPH_C64(0x47C4FBF17D6016BF), + SPH_C64(0x1E0FAADD7667E3F5), SPH_C64(0x7ABCFF62938BEB96), + SPH_C64(0xA78DAD948FC179C9), SPH_C64(0x8F1F98B72911E50D), + SPH_C64(0x61E48EAE27121A91), SPH_C64(0x4D62F7AD31859808), + SPH_C64(0xECEBA345EF5CEAEB), SPH_C64(0xF5CEB25EBC9684CE), + SPH_C64(0xF633E20CB7F76221), SPH_C64(0xA32CDF06AB8293E4), + SPH_C64(0x985A202CA5EE2CA4), SPH_C64(0xCF0B8447CC8A8FB1), + SPH_C64(0x9F765244979859A3), SPH_C64(0xA8D516B1A1240017), + SPH_C64(0x0BD7BA3EBB5DC726), SPH_C64(0xE54BCA55B86ADB39), + SPH_C64(0x1D7A3AFD6C478063), SPH_C64(0x519EC608E7669EDD), + SPH_C64(0x0E5715A2D149AA23), SPH_C64(0x177D4571848FF194), + SPH_C64(0xEEB55F3241014C22), SPH_C64(0x0F5E5CA13A6E2EC2), + SPH_C64(0x8029927B75F5C361), SPH_C64(0xAD139FABC3D6E436), + SPH_C64(0x0D5DF1A94CCF402F), SPH_C64(0x3E8BD948BEA5DFC8), + SPH_C64(0xA5A0D357BD3FF77E), SPH_C64(0xA2D12E251F74F645), + SPH_C64(0x66FD9E525E81A082), SPH_C64(0x2E0C90CE7F687A49), + SPH_C64(0xC2E8BCBEBA973BC5), SPH_C64(0x000001BCE509745F), + SPH_C64(0x423777BBE6DAB3D6), SPH_C64(0xD1661C7EAEF06EB5), + SPH_C64(0xA1781F354DAACFD8), SPH_C64(0x2D11284A2B16AFFC), + SPH_C64(0xF1FC4F67FA891D1F), SPH_C64(0x73ECC25DCB920ADA), + SPH_C64(0xAE610C22C2A12651), SPH_C64(0x96E0A810D356B78A), + SPH_C64(0x5A9A381F2FE7870F), SPH_C64(0xD5AD62EDE94E5530), + SPH_C64(0xD225E5E8368D1427), SPH_C64(0x65977B70C7AF4631), + SPH_C64(0x99F889B2DE39D74F), SPH_C64(0x233F30BF54E1D143), + SPH_C64(0x9A9675D3D9A63C97), SPH_C64(0x5470554FF334F9A8), + SPH_C64(0x166ACB744A4F5688), SPH_C64(0x70C74CAAB2E4AEAD), + SPH_C64(0xF0D091646F294D12), SPH_C64(0x57B82A89684031D1), + SPH_C64(0xEFD95A5A61BE0B6B), SPH_C64(0x2FBD12E969F2F29A), + SPH_C64(0x9BD37013FEFF9FE8), SPH_C64(0x3F9B0404D6085A06), + SPH_C64(0x4940C1F3166CFE15), SPH_C64(0x09542C4DCDF3DEFB), + SPH_C64(0xB4C5218385CD5CE3), SPH_C64(0xC935B7DC4462A641), + SPH_C64(0x3417F8A68ED3B63F), SPH_C64(0xB80959295B215B40), + SPH_C64(0xF99CDAEF3B8C8572), SPH_C64(0x018C0614F8FCB95D), + SPH_C64(0x1B14ACCD1A3ACDF3), SPH_C64(0x84D471F200BB732D), + SPH_C64(0xC1A3110E95E8DA16), SPH_C64(0x430A7220BF1A82B8), + SPH_C64(0xB77E090D39DF210E), SPH_C64(0x5EF4BD9F3CD05E9D), + SPH_C64(0x9D4FF6DA7E57A444), SPH_C64(0xDA1D60E183D4A5F8), + SPH_C64(0xB287C38417998E47), SPH_C64(0xFE3EDC121BB31886), + SPH_C64(0xC7FE3CCC980CCBEF), SPH_C64(0xE46FB590189BFD03), + SPH_C64(0x3732FD469A4C57DC), SPH_C64(0x7EF700A07CF1AD65), + SPH_C64(0x59C64468A31D8859), SPH_C64(0x762FB0B4D45B61F6), + SPH_C64(0x155BAED099047718), SPH_C64(0x68755E4C3D50BAA6), + SPH_C64(0xE9214E7F22D8B4DF), SPH_C64(0x2ADDBF532EAC95F4), + SPH_C64(0x32AE3909B4BD0109), SPH_C64(0x834DF537B08E3450), + SPH_C64(0xFA209DA84220728D), SPH_C64(0x9E691D9B9EFE23F7), + SPH_C64(0x0446D288C4AE8D7F), SPH_C64(0x7B4CC524E169785B), + SPH_C64(0x21D87F0135CA1385), SPH_C64(0xCEBB400F137B8AA5), + SPH_C64(0x272E2B66580796BE), SPH_C64(0x3612264125C2B0DE), + SPH_C64(0x057702BDAD1EFBB2), SPH_C64(0xD4BABB8EACF84BE9), + SPH_C64(0x91583139641BC67B), SPH_C64(0x8BDC2DE08036E024), + SPH_C64(0x603C8156F49F68ED), SPH_C64(0xF7D236F7DBEF5111), + SPH_C64(0x9727C4598AD21E80), SPH_C64(0xA08A0896670A5FD7), + SPH_C64(0xCB4A8F4309EBA9CB), SPH_C64(0x81AF564B0F7036A1), + SPH_C64(0xC0B99AA778199ABD), SPH_C64(0x959F1EC83FC8E952), + SPH_C64(0x8C505077794A81B9), SPH_C64(0x3ACAAF8F056338F0), + SPH_C64(0x07B43F50627A6778), SPH_C64(0x4A44AB49F5ECCC77), + SPH_C64(0x3BC3D6E4B679EE98), SPH_C64(0x9CC0D4D1CF14108C), + SPH_C64(0x4406C00B206BC8A0), SPH_C64(0x82A18854C8D72D89), + SPH_C64(0x67E366B35C3C432C), SPH_C64(0xB923DD61102B37F2), + SPH_C64(0x56AB2779D884271D), SPH_C64(0xBE83E1B0FF1525AF), + SPH_C64(0xFB7C65D4217E49A9), SPH_C64(0x6BDBE0E76D48E7D4), + SPH_C64(0x08DF828745D9179E), SPH_C64(0x22EA6A9ADD53BD34), + SPH_C64(0xE36E141C5622200A), SPH_C64(0x7F805D1B8CB750EE), + SPH_C64(0xAFE5C7A59F58E837), SPH_C64(0xE27F996A4FB1C23C), + SPH_C64(0xD3867DFB0775F0D0), SPH_C64(0xD0E673DE6E88891A), + SPH_C64(0x123AEB9EAFB86C25), SPH_C64(0x30F1D5D5C145B895), + SPH_C64(0xBB434A2DEE7269E7), SPH_C64(0x78CB67ECF931FA38), + SPH_C64(0xF33B0372323BBF9C), SPH_C64(0x52D66336FB279C74), + SPH_C64(0x505F33AC0AFB4EAA), SPH_C64(0xE8A5CD99A2CCE187), + SPH_C64(0x534974801E2D30BB), SPH_C64(0x8D2D5711D5876D90), + SPH_C64(0x1F1A412891BC038E), SPH_C64(0xD6E2E71D82E56648), + SPH_C64(0x74036C3A497732B7), SPH_C64(0x89B67ED96361F5AB), + SPH_C64(0xFFED95D8F1EA02A2), SPH_C64(0xE72B3BD61464D43D), + SPH_C64(0xA6300F170BDC4820), SPH_C64(0xEBC18760ED78A77A), +}; + +static const sph_u64 T2[256] = { + SPH_C64(0xE6A6BE5A05A12138), SPH_C64(0xB5A122A5B4F87C98), + SPH_C64(0x563C6089140B6990), SPH_C64(0x4C46CB2E391F5DD5), + SPH_C64(0xD932ADDBC9B79434), SPH_C64(0x08EA70E42015AFF5), + SPH_C64(0xD765A6673E478CF1), SPH_C64(0xC4FB757EAB278D99), + SPH_C64(0xDF11C6862D6E0692), SPH_C64(0xDDEB84F10D7F3B16), + SPH_C64(0x6F2EF604A665EA04), SPH_C64(0x4A8E0F0FF0E0DFB3), + SPH_C64(0xA5EDEEF83DBCBA51), SPH_C64(0xFC4F0A2A0EA4371E), + SPH_C64(0xE83E1DA85CB38429), SPH_C64(0xDC8FF882BA1B1CE2), + SPH_C64(0xCD45505E8353E80D), SPH_C64(0x18D19A00D4DB0717), + SPH_C64(0x34A0CFEDA5F38101), SPH_C64(0x0BE77E518887CAF2), + SPH_C64(0x1E341438B3C45136), SPH_C64(0xE05797F49089CCF9), + SPH_C64(0xFFD23F9DF2591D14), SPH_C64(0x543DDA228595C5CD), + SPH_C64(0x661F81FD99052A33), SPH_C64(0x8736E641DB0F7B76), + SPH_C64(0x15227725418E5307), SPH_C64(0xE25F7F46162EB2FA), + SPH_C64(0x48A8B2126C13D9FE), SPH_C64(0xAFDC541792E76EEA), + SPH_C64(0x03D912BFC6D1898F), SPH_C64(0x31B1AAFA1B83F51B), + SPH_C64(0xF1AC2796E42AB7D9), SPH_C64(0x40A3A7D7FCD2EBAC), + SPH_C64(0x1056136D0AFBBCC5), SPH_C64(0x7889E1DD9A6D0C85), + SPH_C64(0xD33525782A7974AA), SPH_C64(0xA7E25D09078AC09B), + SPH_C64(0xBD4138B3EAC6EDD0), SPH_C64(0x920ABFBE71EB9E70), + SPH_C64(0xA2A5D0F54FC2625C), SPH_C64(0xC054E36B0B1290A3), + SPH_C64(0xF6DD59FF62FE932B), SPH_C64(0x3537354511A8AC7D), + SPH_C64(0xCA845E9172FADCD4), SPH_C64(0x84F82B60329D20DC), + SPH_C64(0x79C62CE1CD672F18), SPH_C64(0x8B09A2ADD124642C), + SPH_C64(0xD0C1E96A19D9E726), SPH_C64(0x5A786A9B4BA9500C), + SPH_C64(0x0E020336634C43F3), SPH_C64(0xC17B474AEB66D822), + SPH_C64(0x6A731AE3EC9BAAC2), SPH_C64(0x8226667AE0840258), + SPH_C64(0x67D4567691CAECA5), SPH_C64(0x1D94155C4875ADB5), + SPH_C64(0x6D00FD985B813FDF), SPH_C64(0x51286EFCB774CD06), + SPH_C64(0x5E8834471FA744AF), SPH_C64(0xF72CA0AEE761AE2E), + SPH_C64(0xBE40E4CDAEE8E09A), SPH_C64(0xE9970BBB5118F665), + SPH_C64(0x726E4BEB33DF1964), SPH_C64(0x703B000729199762), + SPH_C64(0x4631D816F5EF30A7), SPH_C64(0xB880B5B51504A6BE), + SPH_C64(0x641793C37ED84B6C), SPH_C64(0x7B21ED77F6E97D96), + SPH_C64(0x776306312EF96B73), SPH_C64(0xAE528948E86FF3F4), + SPH_C64(0x53DBD7F286A3F8F8), SPH_C64(0x16CADCE74CFC1063), + SPH_C64(0x005C19BDFA52C6DD), SPH_C64(0x68868F5D64D46AD3), + SPH_C64(0x3A9D512CCF1E186A), SPH_C64(0x367E62C2385660AE), + SPH_C64(0xE359E7EA77DCB1D7), SPH_C64(0x526C0773749ABE6E), + SPH_C64(0x735AE5F9D09F734B), SPH_C64(0x493FC7CC8A558BA8), + SPH_C64(0xB0B9C1533041AB45), SPH_C64(0x321958BA470A59BD), + SPH_C64(0x852DB00B5F46C393), SPH_C64(0x91209B2BD336B0E5), + SPH_C64(0x6E604F7D659EF19F), SPH_C64(0xB99A8AE2782CCB24), + SPH_C64(0xCCF52AB6C814C4C7), SPH_C64(0x4727D9AFBE11727B), + SPH_C64(0x7E950D0C0121B34D), SPH_C64(0x756F435670AD471F), + SPH_C64(0xF5ADD442615A6849), SPH_C64(0x4E87E09980B9957A), + SPH_C64(0x2ACFA1DF50AEE355), SPH_C64(0xD898263AFD2FD556), + SPH_C64(0xC8F4924DD80C8FD6), SPH_C64(0xCF99CA3D754A173A), + SPH_C64(0xFE477BACAF91BF3C), SPH_C64(0xED5371F6D690C12D), + SPH_C64(0x831A5C285E687094), SPH_C64(0xC5D3C90A3708A0A4), + SPH_C64(0x0F7F903717D06580), SPH_C64(0x19F9BB13B8FDF27F), + SPH_C64(0xB1BD6F1B4D502843), SPH_C64(0x1C761BA38FFF4012), + SPH_C64(0x0D1530C4E2E21F3B), SPH_C64(0x8943CE69A7372C8A), + SPH_C64(0xE5184E11FEB5CE66), SPH_C64(0x618BDB80BD736621), + SPH_C64(0x7D29BAD68B574D0B), SPH_C64(0x81BB613E25E6FE5B), + SPH_C64(0x071C9C10BC07913F), SPH_C64(0xC7BEEB7909AC2D97), + SPH_C64(0xC3E58D353BC5D757), SPH_C64(0xEB017892F38F61E8), + SPH_C64(0xD4EFFB9C9B1CC21A), SPH_C64(0x99727D26F494F7AB), + SPH_C64(0xA3E063A2956B3E03), SPH_C64(0x9D4A8B9A4AA09C30), + SPH_C64(0x3F6AB7D500090FB4), SPH_C64(0x9CC0F2A057268AC0), + SPH_C64(0x3DEE9D2DEDBF42D1), SPH_C64(0x330F49C87960A972), + SPH_C64(0xC6B2720287421B41), SPH_C64(0x0AC59EC07C00369C), + SPH_C64(0xEF4EAC49CB353425), SPH_C64(0xF450244EEF0129D8), + SPH_C64(0x8ACC46E5CAF4DEB6), SPH_C64(0x2FFEAB63989263F7), + SPH_C64(0x8F7CB9FE5D7A4578), SPH_C64(0x5BD8F7644E634635), + SPH_C64(0x427A7315BF2DC900), SPH_C64(0x17D0C4AA2125261C), + SPH_C64(0x3992486C93518E50), SPH_C64(0xB4CBFEE0A2D7D4C3), + SPH_C64(0x7C75D6202C5DDD8D), SPH_C64(0xDBC295D8E35B6C61), + SPH_C64(0x60B369D302032B19), SPH_C64(0xCE42685FDCE44132), + SPH_C64(0x06F3DDB9DDF65610), SPH_C64(0x8EA4D21DB5E148F0), + SPH_C64(0x20B0FCE62FCD496F), SPH_C64(0x2C1B912358B0EE31), + SPH_C64(0xB28317B818F5A308), SPH_C64(0xA89C1E189CA6D2CF), + SPH_C64(0x0C6B18576AAADBC8), SPH_C64(0xB65DEAA91299FAE3), + SPH_C64(0xFB2B794B7F1027E7), SPH_C64(0x04E4317F443B5BEB), + SPH_C64(0x4B852D325939D0A6), SPH_C64(0xD5AE6BEEFB207FFC), + SPH_C64(0x309682B281C7D374), SPH_C64(0xBAE309A194C3B475), + SPH_C64(0x8CC3F97B13B49F05), SPH_C64(0x98A9422FF8293967), + SPH_C64(0x244B16B01076FF7C), SPH_C64(0xF8BF571C663D67EE), + SPH_C64(0x1F0D6758EEE30DA1), SPH_C64(0xC9B611D97ADEB9B7), + SPH_C64(0xB7AFD5887B6C57A2), SPH_C64(0x6290AE846B984FE1), + SPH_C64(0x94DF4CDEACC1A5FD), SPH_C64(0x058A5BD1C5483AFF), + SPH_C64(0x63166CC142BA3C37), SPH_C64(0x8DB8526EB2F76F40), + SPH_C64(0xE10880036F0D6D4E), SPH_C64(0x9E0523C9971D311D), + SPH_C64(0x45EC2824CC7CD691), SPH_C64(0x575B8359E62382C9), + SPH_C64(0xFA9E400DC4889995), SPH_C64(0xD1823ECB45721568), + SPH_C64(0xDAFD983B8206082F), SPH_C64(0xAA7D29082386A8CB), + SPH_C64(0x269FCD4403B87588), SPH_C64(0x1B91F5F728BDD1E0), + SPH_C64(0xE4669F39040201F6), SPH_C64(0x7A1D7C218CF04ADE), + SPH_C64(0x65623C29D79CE5CE), SPH_C64(0x2368449096C00BB1), + SPH_C64(0xAB9BF1879DA503BA), SPH_C64(0xBC23ECB1A458058E), + SPH_C64(0x9A58DF01BB401ECC), SPH_C64(0xA070E868A85F143D), + SPH_C64(0x4FF188307DF2239E), SPH_C64(0x14D565B41A641183), + SPH_C64(0xEE13337452701602), SPH_C64(0x950E3DCF3F285E09), + SPH_C64(0x59930254B9C80953), SPH_C64(0x3BF299408930DA6D), + SPH_C64(0xA955943F53691387), SPH_C64(0xA15EDECAA9CB8784), + SPH_C64(0x29142127352BE9A0), SPH_C64(0x76F0371FFF4E7AFB), + SPH_C64(0x0239F450274F2228), SPH_C64(0xBB073AF01D5E868B), + SPH_C64(0xBFC80571C10E96C1), SPH_C64(0xD267088568222E23), + SPH_C64(0x9671A3D48E80B5B0), SPH_C64(0x55B5D38AE193BB81), + SPH_C64(0x693AE2D0A18B04B8), SPH_C64(0x5C48B4ECADD5335F), + SPH_C64(0xFD743B194916A1CA), SPH_C64(0x2577018134BE98C4), + SPH_C64(0xE77987E83C54A4AD), SPH_C64(0x28E11014DA33E1B9), + SPH_C64(0x270CC59E226AA213), SPH_C64(0x71495F756D1A5F60), + SPH_C64(0x9BE853FB60AFEF77), SPH_C64(0xADC786A7F7443DBF), + SPH_C64(0x0904456173B29A82), SPH_C64(0x58BC7A66C232BD5E), + SPH_C64(0xF306558C673AC8B2), SPH_C64(0x41F639C6B6C9772A), + SPH_C64(0x216DEFE99FDA35DA), SPH_C64(0x11640CC71C7BE615), + SPH_C64(0x93C43694565C5527), SPH_C64(0xEA038E6246777839), + SPH_C64(0xF9ABF3CE5A3E2469), SPH_C64(0x741E768D0FD312D2), + SPH_C64(0x0144B883CED652C6), SPH_C64(0xC20B5A5BA33F8552), + SPH_C64(0x1AE69633C3435A9D), SPH_C64(0x97A28CA4088CFDEC), + SPH_C64(0x8824A43C1E96F420), SPH_C64(0x37612FA66EEEA746), + SPH_C64(0x6B4CB165F9CF0E5A), SPH_C64(0x43AA1C06A0ABFB4A), + SPH_C64(0x7F4DC26FF162796B), SPH_C64(0x6CBACC8E54ED9B0F), + SPH_C64(0xA6B7FFEFD2BB253E), SPH_C64(0x2E25BC95B0A29D4F), + SPH_C64(0x86D6A58BDEF1388C), SPH_C64(0xDED74AC576B6F054), + SPH_C64(0x8030BDBC2B45805D), SPH_C64(0x3C81AF70E94D9289), + SPH_C64(0x3EFF6DDA9E3100DB), SPH_C64(0xB38DC39FDFCC8847), + SPH_C64(0x123885528D17B87E), SPH_C64(0xF2DA0ED240B1B642), + SPH_C64(0x44CEFADCD54BF9A9), SPH_C64(0x1312200E433C7EE6), + SPH_C64(0x9FFCC84F3A78C748), SPH_C64(0xF0CD1F72248576BB), + SPH_C64(0xEC6974053638CFE4), SPH_C64(0x2BA7B67C0CEC4E4C), + SPH_C64(0xAC2F4DF3E5CE32ED), SPH_C64(0xCB33D14326EA4C11), + SPH_C64(0xA4E9044CC77E58BC), SPH_C64(0x5F513293D934FCEF), + SPH_C64(0x5DC9645506E55444), SPH_C64(0x50DE418F317DE40A), + SPH_C64(0x388CB31A69DDE259), SPH_C64(0x2DB4A83455820A86), + SPH_C64(0x9010A91E84711AE9), SPH_C64(0x4DF7F0B7B1498371), + SPH_C64(0xD62A2EABC0977179), SPH_C64(0x22FAC097AA8D5C0E), +}; + +static const sph_u64 T3[256] = { + SPH_C64(0xF49FCC2FF1DAF39B), SPH_C64(0x487FD5C66FF29281), + SPH_C64(0xE8A30667FCDCA83F), SPH_C64(0x2C9B4BE3D2FCCE63), + SPH_C64(0xDA3FF74B93FBBBC2), SPH_C64(0x2FA165D2FE70BA66), + SPH_C64(0xA103E279970E93D4), SPH_C64(0xBECDEC77B0E45E71), + SPH_C64(0xCFB41E723985E497), SPH_C64(0xB70AAA025EF75017), + SPH_C64(0xD42309F03840B8E0), SPH_C64(0x8EFC1AD035898579), + SPH_C64(0x96C6920BE2B2ABC5), SPH_C64(0x66AF4163375A9172), + SPH_C64(0x2174ABDCCA7127FB), SPH_C64(0xB33CCEA64A72FF41), + SPH_C64(0xF04A4933083066A5), SPH_C64(0x8D970ACDD7289AF5), + SPH_C64(0x8F96E8E031C8C25E), SPH_C64(0xF3FEC02276875D47), + SPH_C64(0xEC7BF310056190DD), SPH_C64(0xF5ADB0AEBB0F1491), + SPH_C64(0x9B50F8850FD58892), SPH_C64(0x4975488358B74DE8), + SPH_C64(0xA3354FF691531C61), SPH_C64(0x0702BBE481D2C6EE), + SPH_C64(0x89FB24057DEDED98), SPH_C64(0xAC3075138596E902), + SPH_C64(0x1D2D3580172772ED), SPH_C64(0xEB738FC28E6BC30D), + SPH_C64(0x5854EF8F63044326), SPH_C64(0x9E5C52325ADD3BBE), + SPH_C64(0x90AA53CF325C4623), SPH_C64(0xC1D24D51349DD067), + SPH_C64(0x2051CFEEA69EA624), SPH_C64(0x13220F0A862E7E4F), + SPH_C64(0xCE39399404E04864), SPH_C64(0xD9C42CA47086FCB7), + SPH_C64(0x685AD2238A03E7CC), SPH_C64(0x066484B2AB2FF1DB), + SPH_C64(0xFE9D5D70EFBF79EC), SPH_C64(0x5B13B9DD9C481854), + SPH_C64(0x15F0D475ED1509AD), SPH_C64(0x0BEBCD060EC79851), + SPH_C64(0xD58C6791183AB7F8), SPH_C64(0xD1187C5052F3EEE4), + SPH_C64(0xC95D1192E54E82FF), SPH_C64(0x86EEA14CB9AC6CA2), + SPH_C64(0x3485BEB153677D5D), SPH_C64(0xDD191D781F8C492A), + SPH_C64(0xF60866BAA784EBF9), SPH_C64(0x518F643BA2D08C74), + SPH_C64(0x8852E956E1087C22), SPH_C64(0xA768CB8DC410AE8D), + SPH_C64(0x38047726BFEC8E1A), SPH_C64(0xA67738B4CD3B45AA), + SPH_C64(0xAD16691CEC0DDE19), SPH_C64(0xC6D4319380462E07), + SPH_C64(0xC5A5876D0BA61938), SPH_C64(0x16B9FA1FA58FD840), + SPH_C64(0x188AB1173CA74F18), SPH_C64(0xABDA2F98C99C021F), + SPH_C64(0x3E0580AB134AE816), SPH_C64(0x5F3B05B773645ABB), + SPH_C64(0x2501A2BE5575F2F6), SPH_C64(0x1B2F74004E7E8BA9), + SPH_C64(0x1CD7580371E8D953), SPH_C64(0x7F6ED89562764E30), + SPH_C64(0xB15926FF596F003D), SPH_C64(0x9F65293DA8C5D6B9), + SPH_C64(0x6ECEF04DD690F84C), SPH_C64(0x4782275FFF33AF88), + SPH_C64(0xE41433083F820801), SPH_C64(0xFD0DFE409A1AF9B5), + SPH_C64(0x4325A3342CDB396B), SPH_C64(0x8AE77E62B301B252), + SPH_C64(0xC36F9E9F6655615A), SPH_C64(0x85455A2D92D32C09), + SPH_C64(0xF2C7DEA949477485), SPH_C64(0x63CFB4C133A39EBA), + SPH_C64(0x83B040CC6EBC5462), SPH_C64(0x3B9454C8FDB326B0), + SPH_C64(0x56F56A9E87FFD78C), SPH_C64(0x2DC2940D99F42BC6), + SPH_C64(0x98F7DF096B096E2D), SPH_C64(0x19A6E01E3AD852BF), + SPH_C64(0x42A99CCBDBD4B40B), SPH_C64(0xA59998AF45E9C559), + SPH_C64(0x366295E807D93186), SPH_C64(0x6B48181BFAA1F773), + SPH_C64(0x1FEC57E2157A0A1D), SPH_C64(0x4667446AF6201AD5), + SPH_C64(0xE615EBCACFB0F075), SPH_C64(0xB8F31F4F68290778), + SPH_C64(0x22713ED6CE22D11E), SPH_C64(0x3057C1A72EC3C93B), + SPH_C64(0xCB46ACC37C3F1F2F), SPH_C64(0xDBB893FD02AAF50E), + SPH_C64(0x331FD92E600B9FCF), SPH_C64(0xA498F96148EA3AD6), + SPH_C64(0xA8D8426E8B6A83EA), SPH_C64(0xA089B274B7735CDC), + SPH_C64(0x87F6B3731E524A11), SPH_C64(0x118808E5CBC96749), + SPH_C64(0x9906E4C7B19BD394), SPH_C64(0xAFED7F7E9B24A20C), + SPH_C64(0x6509EADEEB3644A7), SPH_C64(0x6C1EF1D3E8EF0EDE), + SPH_C64(0xB9C97D43E9798FB4), SPH_C64(0xA2F2D784740C28A3), + SPH_C64(0x7B8496476197566F), SPH_C64(0x7A5BE3E6B65F069D), + SPH_C64(0xF96330ED78BE6F10), SPH_C64(0xEEE60DE77A076A15), + SPH_C64(0x2B4BEE4AA08B9BD0), SPH_C64(0x6A56A63EC7B8894E), + SPH_C64(0x02121359BA34FEF4), SPH_C64(0x4CBF99F8283703FC), + SPH_C64(0x398071350CAF30C8), SPH_C64(0xD0A77A89F017687A), + SPH_C64(0xF1C1A9EB9E423569), SPH_C64(0x8C7976282DEE8199), + SPH_C64(0x5D1737A5DD1F7ABD), SPH_C64(0x4F53433C09A9FA80), + SPH_C64(0xFA8B0C53DF7CA1D9), SPH_C64(0x3FD9DCBC886CCB77), + SPH_C64(0xC040917CA91B4720), SPH_C64(0x7DD00142F9D1DCDF), + SPH_C64(0x8476FC1D4F387B58), SPH_C64(0x23F8E7C5F3316503), + SPH_C64(0x032A2244E7E37339), SPH_C64(0x5C87A5D750F5A74B), + SPH_C64(0x082B4CC43698992E), SPH_C64(0xDF917BECB858F63C), + SPH_C64(0x3270B8FC5BF86DDA), SPH_C64(0x10AE72BB29B5DD76), + SPH_C64(0x576AC94E7700362B), SPH_C64(0x1AD112DAC61EFB8F), + SPH_C64(0x691BC30EC5FAA427), SPH_C64(0xFF246311CC327143), + SPH_C64(0x3142368E30E53206), SPH_C64(0x71380E31E02CA396), + SPH_C64(0x958D5C960AAD76F1), SPH_C64(0xF8D6F430C16DA536), + SPH_C64(0xC8FFD13F1BE7E1D2), SPH_C64(0x7578AE66004DDBE1), + SPH_C64(0x05833F01067BE646), SPH_C64(0xBB34B5AD3BFE586D), + SPH_C64(0x095F34C9A12B97F0), SPH_C64(0x247AB64525D60CA8), + SPH_C64(0xDCDBC6F3017477D1), SPH_C64(0x4A2E14D4DECAD24D), + SPH_C64(0xBDB5E6D9BE0A1EEB), SPH_C64(0x2A7E70F7794301AB), + SPH_C64(0xDEF42D8A270540FD), SPH_C64(0x01078EC0A34C22C1), + SPH_C64(0xE5DE511AF4C16387), SPH_C64(0x7EBB3A52BD9A330A), + SPH_C64(0x77697857AA7D6435), SPH_C64(0x004E831603AE4C32), + SPH_C64(0xE7A21020AD78E312), SPH_C64(0x9D41A70C6AB420F2), + SPH_C64(0x28E06C18EA1141E6), SPH_C64(0xD2B28CBD984F6B28), + SPH_C64(0x26B75F6C446E9D83), SPH_C64(0xBA47568C4D418D7F), + SPH_C64(0xD80BADBFE6183D8E), SPH_C64(0x0E206D7F5F166044), + SPH_C64(0xE258A43911CBCA3E), SPH_C64(0x723A1746B21DC0BC), + SPH_C64(0xC7CAA854F5D7CDD3), SPH_C64(0x7CAC32883D261D9C), + SPH_C64(0x7690C26423BA942C), SPH_C64(0x17E55524478042B8), + SPH_C64(0xE0BE477656A2389F), SPH_C64(0x4D289B5E67AB2DA0), + SPH_C64(0x44862B9C8FBBFD31), SPH_C64(0xB47CC8049D141365), + SPH_C64(0x822C1B362B91C793), SPH_C64(0x4EB14655FB13DFD8), + SPH_C64(0x1ECBBA0714E2A97B), SPH_C64(0x6143459D5CDE5F14), + SPH_C64(0x53A8FBF1D5F0AC89), SPH_C64(0x97EA04D81C5E5B00), + SPH_C64(0x622181A8D4FDB3F3), SPH_C64(0xE9BCD341572A1208), + SPH_C64(0x1411258643CCE58A), SPH_C64(0x9144C5FEA4C6E0A4), + SPH_C64(0x0D33D06565CF620F), SPH_C64(0x54A48D489F219CA1), + SPH_C64(0xC43E5EAC6D63C821), SPH_C64(0xA9728B3A72770DAF), + SPH_C64(0xD7934E7B20DF87EF), SPH_C64(0xE35503B61A3E86E5), + SPH_C64(0xCAE321FBC819D504), SPH_C64(0x129A50B3AC60BFA6), + SPH_C64(0xCD5E68EA7E9FB6C3), SPH_C64(0xB01C90199483B1C7), + SPH_C64(0x3DE93CD5C295376C), SPH_C64(0xAED52EDF2AB9AD13), + SPH_C64(0x2E60F512C0A07884), SPH_C64(0xBC3D86A3E36210C9), + SPH_C64(0x35269D9B163951CE), SPH_C64(0x0C7D6E2AD0CDB5FA), + SPH_C64(0x59E86297D87F5733), SPH_C64(0x298EF221898DB0E7), + SPH_C64(0x55000029D1A5AA7E), SPH_C64(0x8BC08AE1B5061B45), + SPH_C64(0xC2C31C2B6C92703A), SPH_C64(0x94CC596BAF25EF42), + SPH_C64(0x0A1D73DB22540456), SPH_C64(0x04B6A0F9D9C4179A), + SPH_C64(0xEFFDAFA2AE3D3C60), SPH_C64(0xF7C8075BB49496C4), + SPH_C64(0x9CC5C7141D1CD4E3), SPH_C64(0x78BD1638218E5534), + SPH_C64(0xB2F11568F850246A), SPH_C64(0xEDFABCFA9502BC29), + SPH_C64(0x796CE5F2DA23051B), SPH_C64(0xAAE128B0DC93537C), + SPH_C64(0x3A493DA0EE4B29AE), SPH_C64(0xB5DF6B2C416895D7), + SPH_C64(0xFCABBD25122D7F37), SPH_C64(0x70810B58105DC4B1), + SPH_C64(0xE10FDD37F7882A90), SPH_C64(0x524DCAB5518A3F5C), + SPH_C64(0x3C9E85878451255B), SPH_C64(0x4029828119BD34E2), + SPH_C64(0x74A05B6F5D3CECCB), SPH_C64(0xB610021542E13ECA), + SPH_C64(0x0FF979D12F59E2AC), SPH_C64(0x6037DA27E4F9CC50), + SPH_C64(0x5E92975A0DF1847D), SPH_C64(0xD66DE190D3E623FE), + SPH_C64(0x5032D6B87B568048), SPH_C64(0x9A36B7CE8235216E), + SPH_C64(0x80272A7A24F64B4A), SPH_C64(0x93EFED8B8C6916F7), + SPH_C64(0x37DDBFF44CCE1555), SPH_C64(0x4B95DB5D4B99BD25), + SPH_C64(0x92D3FDA169812FC0), SPH_C64(0xFB1A4A9A90660BB6), + SPH_C64(0x730C196946A4B9B2), SPH_C64(0x81E289AA7F49DA68), + SPH_C64(0x64669A0F83B1A05F), SPH_C64(0x27B3FF7D9644F48B), + SPH_C64(0xCC6B615C8DB675B3), SPH_C64(0x674F20B9BCEBBE95), + SPH_C64(0x6F31238275655982), SPH_C64(0x5AE488713E45CF05), + SPH_C64(0xBF619F9954C21157), SPH_C64(0xEABAC46040A8EAE9), + SPH_C64(0x454C6FE9F2C0C1CD), SPH_C64(0x419CF6496412691C), + SPH_C64(0xD3DC3BEF265B0F70), SPH_C64(0x6D0E60F5C3578A9E), +}; + +static const sph_u64 T4[256] = { + SPH_C64(0x5B0E608526323C55), SPH_C64(0x1A46C1A9FA1B59F5), + SPH_C64(0xA9E245A17C4C8FFA), SPH_C64(0x65CA5159DB2955D7), + SPH_C64(0x05DB0A76CE35AFC2), SPH_C64(0x81EAC77EA9113D45), + SPH_C64(0x528EF88AB6AC0A0D), SPH_C64(0xA09EA253597BE3FF), + SPH_C64(0x430DDFB3AC48CD56), SPH_C64(0xC4B3A67AF45CE46F), + SPH_C64(0x4ECECFD8FBE2D05E), SPH_C64(0x3EF56F10B39935F0), + SPH_C64(0x0B22D6829CD619C6), SPH_C64(0x17FD460A74DF2069), + SPH_C64(0x6CF8CC8E8510ED40), SPH_C64(0xD6C824BF3A6ECAA7), + SPH_C64(0x61243D581A817049), SPH_C64(0x048BACB6BBC163A2), + SPH_C64(0xD9A38AC27D44CC32), SPH_C64(0x7FDDFF5BAAF410AB), + SPH_C64(0xAD6D495AA804824B), SPH_C64(0xE1A6A74F2D8C9F94), + SPH_C64(0xD4F7851235DEE8E3), SPH_C64(0xFD4B7F886540D893), + SPH_C64(0x247C20042AA4BFDA), SPH_C64(0x096EA1C517D1327C), + SPH_C64(0xD56966B4361A6685), SPH_C64(0x277DA5C31221057D), + SPH_C64(0x94D59893A43ACFF7), SPH_C64(0x64F0C51CCDC02281), + SPH_C64(0x3D33BCC4FF6189DB), SPH_C64(0xE005CB184CE66AF1), + SPH_C64(0xFF5CCD1D1DB99BEA), SPH_C64(0xB0B854A7FE42980F), + SPH_C64(0x7BD46A6A718D4B9F), SPH_C64(0xD10FA8CC22A5FD8C), + SPH_C64(0xD31484952BE4BD31), SPH_C64(0xC7FA975FCB243847), + SPH_C64(0x4886ED1E5846C407), SPH_C64(0x28CDDB791EB70B04), + SPH_C64(0xC2B00BE2F573417F), SPH_C64(0x5C9590452180F877), + SPH_C64(0x7A6BDDFFF370EB00), SPH_C64(0xCE509E38D6D9D6A4), + SPH_C64(0xEBEB0F00647FA702), SPH_C64(0x1DCC06CF76606F06), + SPH_C64(0xE4D9F28BA286FF0A), SPH_C64(0xD85A305DC918C262), + SPH_C64(0x475B1D8732225F54), SPH_C64(0x2D4FB51668CCB5FE), + SPH_C64(0xA679B9D9D72BBA20), SPH_C64(0x53841C0D912D43A5), + SPH_C64(0x3B7EAA48BF12A4E8), SPH_C64(0x781E0E47F22F1DDF), + SPH_C64(0xEFF20CE60AB50973), SPH_C64(0x20D261D19DFFB742), + SPH_C64(0x16A12B03062A2E39), SPH_C64(0x1960EB2239650495), + SPH_C64(0x251C16FED50EB8B8), SPH_C64(0x9AC0C330F826016E), + SPH_C64(0xED152665953E7671), SPH_C64(0x02D63194A6369570), + SPH_C64(0x5074F08394B1C987), SPH_C64(0x70BA598C90B25CE1), + SPH_C64(0x794A15810B9742F6), SPH_C64(0x0D5925E9FCAF8C6C), + SPH_C64(0x3067716CD868744E), SPH_C64(0x910AB077E8D7731B), + SPH_C64(0x6A61BBDB5AC42F61), SPH_C64(0x93513EFBF0851567), + SPH_C64(0xF494724B9E83E9D5), SPH_C64(0xE887E1985C09648D), + SPH_C64(0x34B1D3C675370CFD), SPH_C64(0xDC35E433BC0D255D), + SPH_C64(0xD0AAB84234131BE0), SPH_C64(0x08042A50B48B7EAF), + SPH_C64(0x9997C4EE44A3AB35), SPH_C64(0x829A7B49201799D0), + SPH_C64(0x263B8307B7C54441), SPH_C64(0x752F95F4FD6A6CA6), + SPH_C64(0x927217402C08C6E5), SPH_C64(0x2A8AB754A795D9EE), + SPH_C64(0xA442F7552F72943D), SPH_C64(0x2C31334E19781208), + SPH_C64(0x4FA98D7CEAEE6291), SPH_C64(0x55C3862F665DB309), + SPH_C64(0xBD0610175D53B1F3), SPH_C64(0x46FE6CB840413F27), + SPH_C64(0x3FE03792DF0CFA59), SPH_C64(0xCFE700372EB85E8F), + SPH_C64(0xA7BE29E7ADBCE118), SPH_C64(0xE544EE5CDE8431DD), + SPH_C64(0x8A781B1B41F1873E), SPH_C64(0xA5C94C78A0D2F0E7), + SPH_C64(0x39412E2877B60728), SPH_C64(0xA1265EF3AFC9A62C), + SPH_C64(0xBCC2770C6A2506C5), SPH_C64(0x3AB66DD5DCE1CE12), + SPH_C64(0xE65499D04A675B37), SPH_C64(0x7D8F523481BFD216), + SPH_C64(0x0F6F64FCEC15F389), SPH_C64(0x74EFBE618B5B13C8), + SPH_C64(0xACDC82B714273E1D), SPH_C64(0xDD40BFE003199D17), + SPH_C64(0x37E99257E7E061F8), SPH_C64(0xFA52626904775AAA), + SPH_C64(0x8BBBF63A463D56F9), SPH_C64(0xF0013F1543A26E64), + SPH_C64(0xA8307E9F879EC898), SPH_C64(0xCC4C27A4150177CC), + SPH_C64(0x1B432F2CCA1D3348), SPH_C64(0xDE1D1F8F9F6FA013), + SPH_C64(0x606602A047A7DDD6), SPH_C64(0xD237AB64CC1CB2C7), + SPH_C64(0x9B938E7225FCD1D3), SPH_C64(0xEC4E03708E0FF476), + SPH_C64(0xFEB2FBDA3D03C12D), SPH_C64(0xAE0BCED2EE43889A), + SPH_C64(0x22CB8923EBFB4F43), SPH_C64(0x69360D013CF7396D), + SPH_C64(0x855E3602D2D4E022), SPH_C64(0x073805BAD01F784C), + SPH_C64(0x33E17A133852F546), SPH_C64(0xDF4874058AC7B638), + SPH_C64(0xBA92B29C678AA14A), SPH_C64(0x0CE89FC76CFAADCD), + SPH_C64(0x5F9D4E0908339E34), SPH_C64(0xF1AFE9291F5923B9), + SPH_C64(0x6E3480F60F4A265F), SPH_C64(0xEEBF3A2AB29B841C), + SPH_C64(0xE21938A88F91B4AD), SPH_C64(0x57DFEFF845C6D3C3), + SPH_C64(0x2F006B0BF62CAAF2), SPH_C64(0x62F479EF6F75EE78), + SPH_C64(0x11A55AD41C8916A9), SPH_C64(0xF229D29084FED453), + SPH_C64(0x42F1C27B16B000E6), SPH_C64(0x2B1F76749823C074), + SPH_C64(0x4B76ECA3C2745360), SPH_C64(0x8C98F463B91691BD), + SPH_C64(0x14BCC93CF1ADE66A), SPH_C64(0x8885213E6D458397), + SPH_C64(0x8E177DF0274D4711), SPH_C64(0xB49B73B5503F2951), + SPH_C64(0x10168168C3F96B6B), SPH_C64(0x0E3D963B63CAB0AE), + SPH_C64(0x8DFC4B5655A1DB14), SPH_C64(0xF789F1356E14DE5C), + SPH_C64(0x683E68AF4E51DAC1), SPH_C64(0xC9A84F9D8D4B0FD9), + SPH_C64(0x3691E03F52A0F9D1), SPH_C64(0x5ED86E46E1878E80), + SPH_C64(0x3C711A0E99D07150), SPH_C64(0x5A0865B20C4E9310), + SPH_C64(0x56FBFC1FE4F0682E), SPH_C64(0xEA8D5DE3105EDF9B), + SPH_C64(0x71ABFDB12379187A), SPH_C64(0x2EB99DE1BEE77B9C), + SPH_C64(0x21ECC0EA33CF4523), SPH_C64(0x59A4D7521805C7A1), + SPH_C64(0x3896F5EB56AE7C72), SPH_C64(0xAA638F3DB18F75DC), + SPH_C64(0x9F39358DABE9808E), SPH_C64(0xB7DEFA91C00B72AC), + SPH_C64(0x6B5541FD62492D92), SPH_C64(0x6DC6DEE8F92E4D5B), + SPH_C64(0x353F57ABC4BEEA7E), SPH_C64(0x735769D6DA5690CE), + SPH_C64(0x0A234AA642391484), SPH_C64(0xF6F9508028F80D9D), + SPH_C64(0xB8E319A27AB3F215), SPH_C64(0x31AD9C1151341A4D), + SPH_C64(0x773C22A57BEF5805), SPH_C64(0x45C7561A07968633), + SPH_C64(0xF913DA9E249DBE36), SPH_C64(0xDA652D9B78A64C68), + SPH_C64(0x4C27A97F3BC334EF), SPH_C64(0x76621220E66B17F4), + SPH_C64(0x967743899ACD7D0B), SPH_C64(0xF3EE5BCAE0ED6782), + SPH_C64(0x409F753600C879FC), SPH_C64(0x06D09A39B5926DB6), + SPH_C64(0x6F83AEB0317AC588), SPH_C64(0x01E6CA4A86381F21), + SPH_C64(0x66FF3462D19F3025), SPH_C64(0x72207C24DDFD3BFB), + SPH_C64(0x4AF6B6D3E2ECE2EB), SPH_C64(0x9C994DBEC7EA08DE), + SPH_C64(0x49ACE597B09A8BC4), SPH_C64(0xB38C4766CF0797BA), + SPH_C64(0x131B9373C57C2A75), SPH_C64(0xB1822CCE61931E58), + SPH_C64(0x9D7555B909BA1C0C), SPH_C64(0x127FAFDD937D11D2), + SPH_C64(0x29DA3BADC66D92E4), SPH_C64(0xA2C1D57154C2ECBC), + SPH_C64(0x58C5134D82F6FE24), SPH_C64(0x1C3AE3515B62274F), + SPH_C64(0xE907C82E01CB8126), SPH_C64(0xF8ED091913E37FCB), + SPH_C64(0x3249D8F9C80046C9), SPH_C64(0x80CF9BEDE388FB63), + SPH_C64(0x1881539A116CF19E), SPH_C64(0x5103F3F76BD52457), + SPH_C64(0x15B7E6F5AE47F7A8), SPH_C64(0xDBD7C6DED47E9CCF), + SPH_C64(0x44E55C410228BB1A), SPH_C64(0xB647D4255EDB4E99), + SPH_C64(0x5D11882BB8AAFC30), SPH_C64(0xF5098BBB29D3212A), + SPH_C64(0x8FB5EA14E90296B3), SPH_C64(0x677B942157DD025A), + SPH_C64(0xFB58E7C0A390ACB5), SPH_C64(0x89D3674C83BD4A01), + SPH_C64(0x9E2DA4DF4BF3B93B), SPH_C64(0xFCC41E328CAB4829), + SPH_C64(0x03F38C96BA582C52), SPH_C64(0xCAD1BDBD7FD85DB2), + SPH_C64(0xBBB442C16082AE83), SPH_C64(0xB95FE86BA5DA9AB0), + SPH_C64(0xB22E04673771A93F), SPH_C64(0x845358C9493152D8), + SPH_C64(0xBE2A488697B4541E), SPH_C64(0x95A2DC2DD38E6966), + SPH_C64(0xC02C11AC923C852B), SPH_C64(0x2388B1990DF2A87B), + SPH_C64(0x7C8008FA1B4F37BE), SPH_C64(0x1F70D0C84D54E503), + SPH_C64(0x5490ADEC7ECE57D4), SPH_C64(0x002B3C27D9063A3A), + SPH_C64(0x7EAEA3848030A2BF), SPH_C64(0xC602326DED2003C0), + SPH_C64(0x83A7287D69A94086), SPH_C64(0xC57A5FCB30F57A8A), + SPH_C64(0xB56844E479EBE779), SPH_C64(0xA373B40F05DCBCE9), + SPH_C64(0xD71A786E88570EE2), SPH_C64(0x879CBACDBDE8F6A0), + SPH_C64(0x976AD1BCC164A32F), SPH_C64(0xAB21E25E9666D78B), + SPH_C64(0x901063AAE5E5C33C), SPH_C64(0x9818B34448698D90), + SPH_C64(0xE36487AE3E1E8ABB), SPH_C64(0xAFBDF931893BDCB4), + SPH_C64(0x6345A0DC5FBBD519), SPH_C64(0x8628FE269B9465CA), + SPH_C64(0x1E5D01603F9C51EC), SPH_C64(0x4DE44006A15049B7), + SPH_C64(0xBF6C70E5F776CBB1), SPH_C64(0x411218F2EF552BED), + SPH_C64(0xCB0C0708705A36A3), SPH_C64(0xE74D14754F986044), + SPH_C64(0xCD56D9430EA8280E), SPH_C64(0xC12591D7535F5065), + SPH_C64(0xC83223F1720AEF96), SPH_C64(0xC3A0396F7363A51F), +}; + +#define PASS(a, b, c, mul) do { \ + ROUND(a, b, c, X0, mul); \ + ROUND(b, c, a, X1, mul); \ + ROUND(c, a, b, X2, mul); \ + ROUND(a, b, c, X3, mul); \ + ROUND(b, c, a, X4, mul); \ + ROUND(c, a, b, X5, mul); \ + ROUND(a, b, c, X6, mul); \ + ROUND(b, c, a, X7, mul); \ + } while (0) + +#define ROUND(a, b, c, x, mul) do { \ + c ^= x; \ + a = SPH_T64(a - (T1[c & 0xFF] ^ T2[(c >> 16) & 0xFF] \ + ^ T3[(c >> 32) & 0xFF] ^ T4[(c >> 48) & 0xFF])); \ + b = SPH_T64(b + (T4[(c >> 8) & 0xFF] ^ T3[(c >> 24) & 0xFF] \ + ^ T2[(c >> 40) & 0xFF] ^ T1[(c >> 56) & 0xFF])); \ + b = mul(b); \ + } while (0) + +#define MUL5(x) SPH_T64((x) * SPH_C64(5)) +#define MUL7(x) SPH_T64((x) * SPH_C64(7)) +#define MUL9(x) SPH_T64((x) * SPH_C64(9)) + +#define KSCHED do { \ + X0 = SPH_T64(X0 - (X7 ^ SPH_C64(0xA5A5A5A5A5A5A5A5))); \ + X1 ^= X0; \ + X2 = SPH_T64(X2 + X1); \ + X3 = SPH_T64(X3 - (X2 ^ (~X1 << 19))); \ + X4 ^= X3; \ + X5 = SPH_T64(X5 + X4); \ + X6 = SPH_T64(X6 - (X5 ^ (~X4 >> 23))); \ + X7 ^= X6; \ + X0 = SPH_T64(X0 + X7); \ + X1 = SPH_T64(X1 - (X0 ^ (~X7 << 19))); \ + X2 ^= X1; \ + X3 = SPH_T64(X3 + X2); \ + X4 = SPH_T64(X4 - (X3 ^ (~X2 >> 23))); \ + X5 ^= X4; \ + X6 = SPH_T64(X6 + X5); \ + X7 = SPH_T64(X7 - (X6 ^ SPH_C64(0x0123456789ABCDEF))); \ + } while (0) + +#define TIGER_ROUND_BODY(in, r) do { \ + sph_u64 A, B, C; \ + sph_u64 X0, X1, X2, X3, X4, X5, X6, X7; \ + \ + A = (r)[0]; \ + B = (r)[1]; \ + C = (r)[2]; \ + \ + X0 = (in(0)); \ + X1 = (in(1)); \ + X2 = (in(2)); \ + X3 = (in(3)); \ + X4 = (in(4)); \ + X5 = (in(5)); \ + X6 = (in(6)); \ + X7 = (in(7)); \ + PASS(A, B, C, MUL5); \ + KSCHED; \ + PASS(C, A, B, MUL7); \ + KSCHED; \ + PASS(B, C, A, MUL9); \ + \ + (r)[0] ^= A; \ + (r)[1] = SPH_T64(B - (r)[1]); \ + (r)[2] = SPH_T64(C + (r)[2]); \ + } while (0) + +/* + * One round of Tiger. The data must be aligned for 64-bit access. + */ +static void +tiger_round(const unsigned char *data, sph_u64 r[3]) +{ +#define TIGER_IN(i) sph_dec64le_aligned(data + 8 * (i)) + TIGER_ROUND_BODY(TIGER_IN, r); +#undef TIGER_IN +} + +/* see sph_tiger.h */ +void +sph_tiger_init(void *cc) +{ + sph_tiger_context *sc; + + sc = (sph_tiger_context*)cc; + sc->val[0] = SPH_C64(0x0123456789ABCDEF); + sc->val[1] = SPH_C64(0xFEDCBA9876543210); + sc->val[2] = SPH_C64(0xF096A5B4C3B2E187); + sc->count = 0; +} + +#define RFUN tiger_round +#define HASH tiger +#define LE64 1 +#define BLEN 64U +#define PW01 1 +#define PLW1 1 +#include "md_helper.c" + +/* see sph_tiger.h */ +void +sph_tiger_close(void *cc, void *dst) +{ + tiger_close(cc, dst, 3); + sph_tiger_init(cc); +} + +/* see sph_tiger.h */ +void +sph_tiger_comp(const sph_u64 msg[8], sph_u64 val[3]) +{ +#define TIGER_IN(i) msg[i] + TIGER_ROUND_BODY(TIGER_IN, val); +#undef TIGER_IN +} + +#undef HASH +#define HASH tiger2 +#undef PW01 +#define CLOSE_ONLY 1 +#include "md_helper.c" + +/* see sph_tiger.h */ +void +sph_tiger2_close(void *cc, void *dst) +{ + tiger2_close(cc, dst, 3); + sph_tiger2_init(cc); +} + +#endif \ No newline at end of file diff --git a/src/Native/libmultihash/x16r.c b/src/Native/libmultihash/x16r.c index 4d116b83..965fd7a5 100644 --- a/src/Native/libmultihash/x16r.c +++ b/src/Native/libmultihash/x16r.c @@ -19,6 +19,7 @@ #include "sha3/sph_shabal.h" #include "sha3/sph_whirlpool.h" #include "sha3/sph_sha2.h" +#include "sha3/sph_tiger.h" enum Algo { BLAKE = 0, @@ -42,136 +43,153 @@ enum Algo { static void getAlgoString(const uint8_t* prevblock, char *output) { - char *sptr = output; + char *sptr = output; + int j; - for (int j = 0; j < HASH_FUNC_COUNT; j++) { - char b = (15 - j) >> 1; // 16 ascii hex chars, reversed - uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4; - if (algoDigit >= 10) - sprintf(sptr, "%c", 'A' + (algoDigit - 10)); - else - sprintf(sptr, "%u", (uint32_t) algoDigit); - sptr++; - } - *sptr = '\0'; + for (j = 0; j < HASH_FUNC_COUNT; j++) { + char b = (15 - j) >> 1; // 16 ascii hex chars, reversed + uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4; + if (algoDigit >= 10) + sprintf(sptr, "%c", 'A' + (algoDigit - 10)); + else + sprintf(sptr, "%u", (uint32_t) algoDigit); + sptr++; + } + *sptr = '\0'; } - -void x16r_hash(const char* input, char* output, uint32_t len) +void x16r_hash(const char* input, char* output,uint32_t len) { - uint32_t hash[64/4]; - char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; + uint32_t hash[64/4]; + char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + sph_tiger_context ctx_tiger; + + void *in = (void*) input; + int size = 80; + int i; + int j; + + getAlgoString(&input[4], hashOrder); - sph_blake512_context ctx_blake; - sph_bmw512_context ctx_bmw; - sph_groestl512_context ctx_groestl; - sph_skein512_context ctx_skein; - sph_jh512_context ctx_jh; - sph_keccak512_context ctx_keccak; - sph_luffa512_context ctx_luffa; - sph_cubehash512_context ctx_cubehash; - sph_shavite512_context ctx_shavite; - sph_simd512_context ctx_simd; - sph_echo512_context ctx_echo; - sph_hamsi512_context ctx_hamsi; - sph_fugue512_context ctx_fugue; - sph_shabal512_context ctx_shabal; - sph_whirlpool_context ctx_whirlpool; - sph_sha512_context ctx_sha512; + for (i = 0; i < 16; i++) { + const char elem = hashOrder[i]; + const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; - void *in = (void*) input; - int size = len; + switch (algo) { + case BLAKE: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case BMW: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case GROESTL: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + case SKEIN: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case JH: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case KECCAK: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes - getAlgoString(&input[4], hashOrder); + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + break; + case LUFFA: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes - for (int i = 0; i < 16; i++) - { - const char elem = hashOrder[i]; - const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + break; + case CUBEHASH: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case SHAVITE: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case SIMD: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + case ECHO: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case HAMSI: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case FUGUE: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case SHABAL: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case WHIRLPOOL: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case SHA512: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes - switch (algo) { - case BLAKE: - sph_blake512_init(&ctx_blake); - sph_blake512(&ctx_blake, in, size); - sph_blake512_close(&ctx_blake, hash); - break; - case BMW: - sph_bmw512_init(&ctx_bmw); - sph_bmw512(&ctx_bmw, in, size); - sph_bmw512_close(&ctx_bmw, hash); - break; - case GROESTL: - sph_groestl512_init(&ctx_groestl); - sph_groestl512(&ctx_groestl, in, size); - sph_groestl512_close(&ctx_groestl, hash); - break; - case SKEIN: - sph_skein512_init(&ctx_skein); - sph_skein512(&ctx_skein, in, size); - sph_skein512_close(&ctx_skein, hash); - break; - case JH: - sph_jh512_init(&ctx_jh); - sph_jh512(&ctx_jh, in, size); - sph_jh512_close(&ctx_jh, hash); - break; - case KECCAK: - sph_keccak512_init(&ctx_keccak); - sph_keccak512(&ctx_keccak, in, size); - sph_keccak512_close(&ctx_keccak, hash); - break; - case LUFFA: - sph_luffa512_init(&ctx_luffa); - sph_luffa512(&ctx_luffa, in, size); - sph_luffa512_close(&ctx_luffa, hash); - break; - case CUBEHASH: - sph_cubehash512_init(&ctx_cubehash); - sph_cubehash512(&ctx_cubehash, in, size); - sph_cubehash512_close(&ctx_cubehash, hash); - break; - case SHAVITE: - sph_shavite512_init(&ctx_shavite); - sph_shavite512(&ctx_shavite, in, size); - sph_shavite512_close(&ctx_shavite, hash); - break; - case SIMD: - sph_simd512_init(&ctx_simd); - sph_simd512(&ctx_simd, in, size); - sph_simd512_close(&ctx_simd, hash); - break; - case ECHO: - sph_echo512_init(&ctx_echo); - sph_echo512(&ctx_echo, in, size); - sph_echo512_close(&ctx_echo, hash); - break; - case HAMSI: - sph_hamsi512_init(&ctx_hamsi); - sph_hamsi512(&ctx_hamsi, in, size); - sph_hamsi512_close(&ctx_hamsi, hash); - break; - case FUGUE: - sph_fugue512_init(&ctx_fugue); - sph_fugue512(&ctx_fugue, in, size); - sph_fugue512_close(&ctx_fugue, hash); - break; - case SHABAL: - sph_shabal512_init(&ctx_shabal); - sph_shabal512(&ctx_shabal, in, size); - sph_shabal512_close(&ctx_shabal, hash); - break; - case WHIRLPOOL: - sph_whirlpool_init(&ctx_whirlpool); - sph_whirlpool(&ctx_whirlpool, in, size); - sph_whirlpool_close(&ctx_whirlpool, hash); - break; - case SHA512: - sph_sha512_init(&ctx_sha512); - sph_sha512(&ctx_sha512,(const void*) in, size); - sph_sha512_close(&ctx_sha512,(void*) hash); - break; - } - in = (void*) hash; - size = 64; - } - memcpy(output, hash, 32); + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) hash, 64); + sph_sha512_close(&ctx_sha512,(void*) hash); + break; + } + in = (void*) hash; + size = 64; + } + memcpy(output, hash, 32); } From fef5d8fb187cea9ca6ef259ee62bd479ce0cbe68 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Mon, 2 Mar 2020 19:13:17 +0300 Subject: [PATCH 04/36] add IndexChain --- src/Miningcore/coins.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 6701fb11..68fb495e 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -286,6 +286,26 @@ "explorerTxLink": "https://bchain.info/GLT/tx/{0}", "explorerAccountLink": "https://bchain.info/GLT/addr/{0}" }, + "indexchain": { + "name": "IndexChain", + "symbol": "IDX", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "sha256d" + }, + "headerHasher": { + "hash": "x16r" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "x16r" } ] + }, + "hasMasterNodes": true, + "shareMultiplier": 256, + "explorerBlockLink": "https://chainz.cryptoid.info/dash/block.dws?$height$.htm", + "explorerTxLink": "https://chainz.cryptoid.info/dash/tx.dws?{0}.htm", + "explorerAccountLink": "https://chainz.cryptoid.info/dash/address.dws?{0}.htm" + }, "mooncoin": { "name": "MoonCoin", "symbol": "MOON", From f200fdb6b0f8bc8f7e38c9484dc1ecfa4509f8bf Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Mon, 2 Mar 2020 19:31:54 +0300 Subject: [PATCH 05/36] Refactor x16rv2 implementation --- src/Miningcore/Native/LibMultihash.cs | 3 + src/Native/libmultihash/exports.cpp | 5 + src/Native/libmultihash/libmultihash.vcxproj | 2 + .../libmultihash/libmultihash.vcxproj.filters | 6 + src/Native/libmultihash/sha3/sph_tiger.h | 2 +- src/Native/libmultihash/sph_tiger.h | 191 ----------------- src/Native/libmultihash/x16rv2.c | 195 ++++++++++++++++++ src/Native/libmultihash/x16rv2.h | 16 ++ 8 files changed, 228 insertions(+), 192 deletions(-) delete mode 100644 src/Native/libmultihash/sph_tiger.h create mode 100644 src/Native/libmultihash/x16rv2.c create mode 100644 src/Native/libmultihash/x16rv2.h diff --git a/src/Miningcore/Native/LibMultihash.cs b/src/Miningcore/Native/LibMultihash.cs index cc452b8c..67b82cf4 100644 --- a/src/Miningcore/Native/LibMultihash.cs +++ b/src/Miningcore/Native/LibMultihash.cs @@ -115,6 +115,9 @@ public static unsafe class LibMultihash [DllImport("libmultihash", EntryPoint = "x16r_export", CallingConvention = CallingConvention.Cdecl)] public static extern int x16r(byte* input, void* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "x16rv2_export", CallingConvention = CallingConvention.Cdecl)] + public static extern int x16rv2_export(byte* input, void* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "x16s_export", CallingConvention = CallingConvention.Cdecl)] public static extern int x16s(byte* input, void* output, uint inputLength); diff --git a/src/Native/libmultihash/exports.cpp b/src/Native/libmultihash/exports.cpp index 02194b73..25130e0a 100644 --- a/src/Native/libmultihash/exports.cpp +++ b/src/Native/libmultihash/exports.cpp @@ -44,6 +44,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "Lyra2RE.h" #include "Lyra2.h" #include "x16r.h" +#include "x16rv2.h" #include "x16s.h" #include "x21s.h" #include "x25x.h" @@ -217,6 +218,10 @@ extern "C" MODULE_API void x16r_export(const char* input, char* output, uint32_t { x16r_hash(input, output, input_len); } +extern "C" MODULE_API void x16rv2_export(const char* input, char* output, uint32_t input_len) +{ + x16rv2_hash(input, output, input_len); +} extern "C" MODULE_API void x21s_export(const char* input, char* output, uint32_t input_len) { diff --git a/src/Native/libmultihash/libmultihash.vcxproj b/src/Native/libmultihash/libmultihash.vcxproj index 7522da19..e2a55f9b 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj +++ b/src/Native/libmultihash/libmultihash.vcxproj @@ -261,6 +261,7 @@ + @@ -348,6 +349,7 @@ + diff --git a/src/Native/libmultihash/libmultihash.vcxproj.filters b/src/Native/libmultihash/libmultihash.vcxproj.filters index 0ec24faa..dd59d9c1 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj.filters +++ b/src/Native/libmultihash/libmultihash.vcxproj.filters @@ -205,6 +205,9 @@ Header Files + + + Header Files Header Files @@ -481,6 +484,9 @@ Source Files + + Source Files + Source Files diff --git a/src/Native/libmultihash/sha3/sph_tiger.h b/src/Native/libmultihash/sha3/sph_tiger.h index 10191f3d..1a586853 100644 --- a/src/Native/libmultihash/sha3/sph_tiger.h +++ b/src/Native/libmultihash/sha3/sph_tiger.h @@ -188,4 +188,4 @@ void sph_tiger2_comp(const sph_u64 msg[8], sph_u64 val[3]); #endif -#endif +#endif \ No newline at end of file diff --git a/src/Native/libmultihash/sph_tiger.h b/src/Native/libmultihash/sph_tiger.h deleted file mode 100644 index 1a586853..00000000 --- a/src/Native/libmultihash/sph_tiger.h +++ /dev/null @@ -1,191 +0,0 @@ -/* $Id: sph_tiger.h 216 2010-06-08 09:46:57Z tp $ */ -/** - * Tiger / Tiger-2 interface. - * - * Tiger has been published in: R. Anderson, E. Biham, "Tiger: A Fast - * New Hash Function", Fast Software Encryption - FSE'96, LNCS 1039, - * Springer (1996), pp. 89--97. - * - * Tiger2 has never been formally published, but it was described as - * identical to Tiger, except for the padding which is the same in - * Tiger2 as it is in MD4. Fortunately, an implementation of Tiger2 - * was submitted to NESSIE, which produced test vectors; the sphlib - * implementation of Tiger2 is compatible with the NESSIE test vectors. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2007-2010 Projet RNRT SAPHIR - * - * 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. - * - * ===========================(LICENSE END)============================= - * - * @file sph_tiger.h - * @author Thomas Pornin - */ - -#ifndef SPH_TIGER_H__ -#define SPH_TIGER_H__ - -#include -#include "sph_types.h" - -#if SPH_64 - -/** - * Output size (in bits) for Tiger. - */ -#define SPH_SIZE_tiger 192 - -/** - * Output size (in bits) for Tiger2. - */ -#define SPH_SIZE_tiger2 192 - -/** - * This structure is a context for Tiger computations: it contains the - * intermediate values and some data from the last entered block. Once - * a Tiger computation has been performed, the context can be reused for - * another computation. - * - * The contents of this structure are private. A running Tiger computation - * can be cloned by copying the context (e.g. with a simple - * memcpy()). - */ -typedef struct { -#ifndef DOXYGEN_IGNORE - unsigned char buf[64]; /* first field, for alignment */ - sph_u64 val[3]; - sph_u64 count; -#endif -} sph_tiger_context; - -/** - * Initialize a Tiger context. This process performs no memory allocation. - * - * @param cc the Tiger context (pointer to - * a sph_tiger_context) - */ -void sph_tiger_init(void *cc); - -/** - * Process some data bytes. It is acceptable that len is zero - * (in which case this function does nothing). - * - * @param cc the Tiger context - * @param data the input data - * @param len the input data length (in bytes) - */ -void sph_tiger(void *cc, const void *data, size_t len); - -/** - * Terminate the current Tiger computation and output the result into the - * provided buffer. The destination buffer must be wide enough to - * accomodate the result (24 bytes). The context is automatically - * reinitialized. - * - * @param cc the Tiger context - * @param dst the destination buffer - */ -void sph_tiger_close(void *cc, void *dst); - -/** - * Apply the Tiger compression function on the provided data. The - * msg parameter contains the 8 64-bit input blocks, - * as numerical values (hence after the little-endian decoding). The - * val parameter contains the 3 64-bit input blocks for - * the compression function; the output is written in place in this - * array. - * - * @param msg the message block (8 values) - * @param val the function 192-bit input and output - */ -void sph_tiger_comp(const sph_u64 msg[8], sph_u64 val[3]); - -/** - * This structure is a context for Tiger2 computations. It is identical - * to the Tiger context, and they may be freely exchanged, since the - * difference between Tiger and Tiger2 resides solely in the padding, which - * is computed only in the last computation step. - */ -typedef sph_tiger_context sph_tiger2_context; - -#ifdef DOXYGEN_IGNORE -/** - * Initialize a Tiger2 context. This function is identical to - * sph_tiger_init(). - * - * @param cc the Tiger2 context (pointer to - * a sph_tiger2_context) - */ -void sph_tiger2_init(void *cc); -#endif - -#ifndef DOXYGEN_IGNORE -#define sph_tiger2_init sph_tiger_init -#endif - -#ifdef DOXYGEN_IGNORE -/** - * Process some data bytes. This function is identical to - * sph_tiger(). - * - * @param cc the Tiger2 context - * @param data the input data - * @param len the input data length (in bytes) - */ -void sph_tiger2(void *cc, const void *data, size_t len); -#endif - -#ifndef DOXYGEN_IGNORE -#define sph_tiger2 sph_tiger -#endif - -/** - * Terminate the current Tiger2 computation and output the result into the - * provided buffer. The destination buffer must be wide enough to - * accomodate the result (24 bytes). The context is automatically - * reinitialized. Note that this function is NOT identical to - * sph_tiger2_close(): this is the exact and unique point - * where Tiger and Tiger2 differ. - * - * @param cc the Tiger context - * @param dst the destination buffer - */ -void sph_tiger2_close(void *cc, void *dst); - -#ifdef DOXYGEN_IGNORE -/** - * Apply the Tiger2 compression function, which is identical to the Tiger - * compression function. - * - * @param msg the message block (8 values) - * @param val the function 192-bit input and output - */ -void sph_tiger2_comp(const sph_u64 msg[8], sph_u64 val[3]); -#endif - -#ifndef DOXYGEN_IGNORE -#define sph_tiger2_comp sph_tiger_comp -#endif - -#endif - -#endif \ No newline at end of file diff --git a/src/Native/libmultihash/x16rv2.c b/src/Native/libmultihash/x16rv2.c new file mode 100644 index 00000000..5db8e7b2 --- /dev/null +++ b/src/Native/libmultihash/x16rv2.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include + +#include "sha3/sph_blake.h" +#include "sha3/sph_bmw.h" +#include "sha3/sph_groestl.h" +#include "sha3/sph_jh.h" +#include "sha3/sph_keccak.h" +#include "sha3/sph_skein.h" +#include "sha3/sph_luffa.h" +#include "sha3/sph_cubehash.h" +#include "sha3/sph_shavite.h" +#include "sha3/sph_simd.h" +#include "sha3/sph_echo.h" +#include "sha3/sph_hamsi.h" +#include "sha3/sph_fugue.h" +#include "sha3/sph_shabal.h" +#include "sha3/sph_whirlpool.h" +#include "sha3/sph_sha2.h" +#include "sha3/sph_tiger.h" + +enum Algo { + BLAKE = 0, + BMW, + GROESTL, + JH, + KECCAK, + SKEIN, + LUFFA, + CUBEHASH, + SHAVITE, + SIMD, + ECHO, + HAMSI, + FUGUE, + SHABAL, + WHIRLPOOL, + SHA512, + HASH_FUNC_COUNT +}; + +static void getAlgoString(const uint8_t* prevblock, char *output) +{ + char *sptr = output; + int j; + + for (j = 0; j < HASH_FUNC_COUNT; j++) { + char b = (15 - j) >> 1; // 16 ascii hex chars, reversed + uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4; + if (algoDigit >= 10) + sprintf(sptr, "%c", 'A' + (algoDigit - 10)); + else + sprintf(sptr, "%u", (uint32_t) algoDigit); + sptr++; + } + *sptr = '\0'; +} +void x16rv2_hash(const char* input, char* output,uint32_t len) +{ + uint32_t hash[64/4]; + char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + sph_tiger_context ctx_tiger; + + void *in = (void*) input; + int size = 80; + int i; + int j; + + getAlgoString(&input[4], hashOrder); + + for (i = 0; i < 16; i++) { + const char elem = hashOrder[i]; + const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; + + switch (algo) { + case BLAKE: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case BMW: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case GROESTL: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + case SKEIN: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case JH: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case KECCAK: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + break; + case LUFFA: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + break; + case CUBEHASH: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case SHAVITE: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case SIMD: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + case ECHO: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case HAMSI: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case FUGUE: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case SHABAL: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case WHIRLPOOL: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case SHA512: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) hash, 64); + sph_sha512_close(&ctx_sha512,(void*) hash); + break; + } + in = (void*) hash; + size = 64; + } + memcpy(output, hash, 32); +} diff --git a/src/Native/libmultihash/x16rv2.h b/src/Native/libmultihash/x16rv2.h new file mode 100644 index 00000000..9ff2bf4a --- /dev/null +++ b/src/Native/libmultihash/x16rv2.h @@ -0,0 +1,16 @@ +#ifndef X16RV2_H +#define X16RV2_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void x16rv2_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif From 1e7462bde091316bb4e437e005e770c157497243 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Mon, 2 Mar 2020 19:33:59 +0300 Subject: [PATCH 06/36] Add back orignal x16r code --- src/Native/libmultihash/x16r.c | 268 +++++++++++++++------------------ src/Native/libmultihash/x16r.h | 2 +- 2 files changed, 126 insertions(+), 144 deletions(-) diff --git a/src/Native/libmultihash/x16r.c b/src/Native/libmultihash/x16r.c index 965fd7a5..b271798a 100644 --- a/src/Native/libmultihash/x16r.c +++ b/src/Native/libmultihash/x16r.c @@ -19,7 +19,6 @@ #include "sha3/sph_shabal.h" #include "sha3/sph_whirlpool.h" #include "sha3/sph_sha2.h" -#include "sha3/sph_tiger.h" enum Algo { BLAKE = 0, @@ -43,153 +42,136 @@ enum Algo { static void getAlgoString(const uint8_t* prevblock, char *output) { - char *sptr = output; - int j; + char *sptr = output; - for (j = 0; j < HASH_FUNC_COUNT; j++) { - char b = (15 - j) >> 1; // 16 ascii hex chars, reversed - uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4; - if (algoDigit >= 10) - sprintf(sptr, "%c", 'A' + (algoDigit - 10)); - else - sprintf(sptr, "%u", (uint32_t) algoDigit); - sptr++; - } - *sptr = '\0'; + for (int j = 0; j < HASH_FUNC_COUNT; j++) { + char b = (15 - j) >> 1; // 16 ascii hex chars, reversed + uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4; + if (algoDigit >= 10) + sprintf(sptr, "%c", 'A' + (algoDigit - 10)); + else + sprintf(sptr, "%u", (uint32_t) algoDigit); + sptr++; + } + *sptr = '\0'; } -void x16r_hash(const char* input, char* output,uint32_t len) -{ - uint32_t hash[64/4]; - char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; - - sph_blake512_context ctx_blake; - sph_bmw512_context ctx_bmw; - sph_groestl512_context ctx_groestl; - sph_skein512_context ctx_skein; - sph_jh512_context ctx_jh; - sph_keccak512_context ctx_keccak; - sph_luffa512_context ctx_luffa; - sph_cubehash512_context ctx_cubehash; - sph_shavite512_context ctx_shavite; - sph_simd512_context ctx_simd; - sph_echo512_context ctx_echo; - sph_hamsi512_context ctx_hamsi; - sph_fugue512_context ctx_fugue; - sph_shabal512_context ctx_shabal; - sph_whirlpool_context ctx_whirlpool; - sph_sha512_context ctx_sha512; - sph_tiger_context ctx_tiger; - - void *in = (void*) input; - int size = 80; - int i; - int j; - getAlgoString(&input[4], hashOrder); +void x16r_hash(const char* input, char* output, uint32_t len) +{ + uint32_t hash[64/4]; + char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; - for (i = 0; i < 16; i++) { - const char elem = hashOrder[i]; - const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; - switch (algo) { - case BLAKE: - sph_blake512_init(&ctx_blake); - sph_blake512(&ctx_blake, in, size); - sph_blake512_close(&ctx_blake, hash); - break; - case BMW: - sph_bmw512_init(&ctx_bmw); - sph_bmw512(&ctx_bmw, in, size); - sph_bmw512_close(&ctx_bmw, hash); - break; - case GROESTL: - sph_groestl512_init(&ctx_groestl); - sph_groestl512(&ctx_groestl, in, size); - sph_groestl512_close(&ctx_groestl, hash); - break; - case SKEIN: - sph_skein512_init(&ctx_skein); - sph_skein512(&ctx_skein, in, size); - sph_skein512_close(&ctx_skein, hash); - break; - case JH: - sph_jh512_init(&ctx_jh); - sph_jh512(&ctx_jh, in, size); - sph_jh512_close(&ctx_jh, hash); - break; - case KECCAK: - sph_tiger_init(&ctx_tiger); - sph_tiger(&ctx_tiger, (const void*) in, size); - sph_tiger_close(&ctx_tiger, (void*) hash); - for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + void *in = (void*) input; + int size = len; - sph_keccak512_init(&ctx_keccak); - sph_keccak512(&ctx_keccak, hash, 64); - sph_keccak512_close(&ctx_keccak, hash); - break; - case LUFFA: - sph_tiger_init(&ctx_tiger); - sph_tiger(&ctx_tiger, (const void*) in, size); - sph_tiger_close(&ctx_tiger, (void*) hash); - for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + getAlgoString(&input[4], hashOrder); - sph_luffa512_init(&ctx_luffa); - sph_luffa512(&ctx_luffa, hash, 64); - sph_luffa512_close(&ctx_luffa, hash); - break; - case CUBEHASH: - sph_cubehash512_init(&ctx_cubehash); - sph_cubehash512(&ctx_cubehash, in, size); - sph_cubehash512_close(&ctx_cubehash, hash); - break; - case SHAVITE: - sph_shavite512_init(&ctx_shavite); - sph_shavite512(&ctx_shavite, in, size); - sph_shavite512_close(&ctx_shavite, hash); - break; - case SIMD: - sph_simd512_init(&ctx_simd); - sph_simd512(&ctx_simd, in, size); - sph_simd512_close(&ctx_simd, hash); - break; - case ECHO: - sph_echo512_init(&ctx_echo); - sph_echo512(&ctx_echo, in, size); - sph_echo512_close(&ctx_echo, hash); - break; - case HAMSI: - sph_hamsi512_init(&ctx_hamsi); - sph_hamsi512(&ctx_hamsi, in, size); - sph_hamsi512_close(&ctx_hamsi, hash); - break; - case FUGUE: - sph_fugue512_init(&ctx_fugue); - sph_fugue512(&ctx_fugue, in, size); - sph_fugue512_close(&ctx_fugue, hash); - break; - case SHABAL: - sph_shabal512_init(&ctx_shabal); - sph_shabal512(&ctx_shabal, in, size); - sph_shabal512_close(&ctx_shabal, hash); - break; - case WHIRLPOOL: - sph_whirlpool_init(&ctx_whirlpool); - sph_whirlpool(&ctx_whirlpool, in, size); - sph_whirlpool_close(&ctx_whirlpool, hash); - break; - case SHA512: - sph_tiger_init(&ctx_tiger); - sph_tiger(&ctx_tiger, (const void*) in, size); - sph_tiger_close(&ctx_tiger, (void*) hash); - for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + for (int i = 0; i < 16; i++) + { + const char elem = hashOrder[i]; + const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; - sph_sha512_init(&ctx_sha512); - sph_sha512(&ctx_sha512,(const void*) hash, 64); - sph_sha512_close(&ctx_sha512,(void*) hash); - break; - } - in = (void*) hash; - size = 64; - } - memcpy(output, hash, 32); -} + switch (algo) { + case BLAKE: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case BMW: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case GROESTL: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + case SKEIN: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case JH: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case KECCAK: + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, in, size); + sph_keccak512_close(&ctx_keccak, hash); + break; + case LUFFA: + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, in, size); + sph_luffa512_close(&ctx_luffa, hash); + break; + case CUBEHASH: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case SHAVITE: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case SIMD: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + case ECHO: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case HAMSI: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case FUGUE: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case SHABAL: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case WHIRLPOOL: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case SHA512: + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) in, size); + sph_sha512_close(&ctx_sha512,(void*) hash); + break; + } + in = (void*) hash; + size = 64; + } + memcpy(output, hash, 32); +} \ No newline at end of file diff --git a/src/Native/libmultihash/x16r.h b/src/Native/libmultihash/x16r.h index 4a41ec85..dddc7cec 100644 --- a/src/Native/libmultihash/x16r.h +++ b/src/Native/libmultihash/x16r.h @@ -13,4 +13,4 @@ void x16r_hash(const char* input, char* output, uint32_t len); } #endif -#endif +#endif \ No newline at end of file From cdabce0fa06ac5008e3127ba9437c37fb4268831 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Mon, 2 Mar 2020 19:37:12 +0300 Subject: [PATCH 07/36] Update AppVeyor to use Visual Studio 2019 --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index bd750329..e414a726 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ # Build worker image (VM template) image: -- Visual Studio 2017 +- Visual Studio 2019 - Ubuntu #---------------------------------# From db2db42dcf157fef1fecd92b5c2754b8e35b450e Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Mon, 2 Mar 2020 22:36:25 +0300 Subject: [PATCH 08/36] Fix hash type for IndexChain --- src/Miningcore/coins.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 68fb495e..2b07ff7f 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -294,11 +294,11 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "x16r" + "hash": "x16rv2" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x16r" } ] + "args": [ { "hash": "x16rv2" } ] }, "hasMasterNodes": true, "shareMultiplier": 256, From 963d7042a0b2216596bd940362569170ab94499e Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Mon, 2 Mar 2020 23:09:37 +0300 Subject: [PATCH 09/36] Fixes for x16rv2 code --- .../Crypto/Hashing/Algorithms/X16RV2.cs | 42 +++++++++++++++++++ src/Miningcore/Native/LibMultihash.cs | 2 +- src/Miningcore/coins.json | 8 ++++ src/Native/libmultihash/Makefile | 2 +- src/Native/libmultihash/exports.cpp | 2 +- src/Native/libmultihash/x16rv2.c | 2 +- src/Native/libmultihash/x16rv2.h | 2 +- 7 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 src/Miningcore/Crypto/Hashing/Algorithms/X16RV2.cs diff --git a/src/Miningcore/Crypto/Hashing/Algorithms/X16RV2.cs b/src/Miningcore/Crypto/Hashing/Algorithms/X16RV2.cs new file mode 100644 index 00000000..e2c9fe8a --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Algorithms/X16RV2.cs @@ -0,0 +1,42 @@ +/* +Copyright 2017 Coin Foundry (coinfoundry.org) +Authors: Oliver Weichhold (oliver@weichhold.com) + +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. +*/ + +using System; +using Miningcore.Contracts; +using Miningcore.Native; + +namespace Miningcore.Crypto.Hashing.Algorithms +{ + public unsafe class X16RV2 : IHashAlgorithm + { + public void Digest(ReadOnlySpan data, Span result, params object[] extra) + { + Contract.Requires(result.Length >= 32, $"{nameof(result)} must be greater or equal 32 bytes"); + + fixed (byte* input = data) + { + fixed (byte* output = result) + { + LibMultihash.x16rv2(input, output, (uint) data.Length); + } + } + } + } +} diff --git a/src/Miningcore/Native/LibMultihash.cs b/src/Miningcore/Native/LibMultihash.cs index 67b82cf4..d2fa2a96 100644 --- a/src/Miningcore/Native/LibMultihash.cs +++ b/src/Miningcore/Native/LibMultihash.cs @@ -116,7 +116,7 @@ public static unsafe class LibMultihash public static extern int x16r(byte* input, void* output, uint inputLength); [DllImport("libmultihash", EntryPoint = "x16rv2_export", CallingConvention = CallingConvention.Cdecl)] - public static extern int x16rv2_export(byte* input, void* output, uint inputLength); + public static extern int x16rv2(byte* input, void* output, uint inputLength); [DllImport("libmultihash", EntryPoint = "x16s_export", CallingConvention = CallingConvention.Cdecl)] public static extern int x16s(byte* input, void* output, uint inputLength); diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 2b07ff7f..45e28fd8 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -300,6 +300,14 @@ "hash": "reverse", "args": [ { "hash": "x16rv2" } ] }, + "posBlockHasher": { + "hash": "reverse", + "args": [ + { + "hash": "x16rv2" + } + ] + }, "hasMasterNodes": true, "shareMultiplier": 256, "explorerBlockLink": "https://chainz.cryptoid.info/dash/block.dws?$height$.htm", diff --git a/src/Native/libmultihash/Makefile b/src/Native/libmultihash/Makefile index 0c1a2e26..0c01ea6c 100644 --- a/src/Native/libmultihash/Makefile +++ b/src/Native/libmultihash/Makefile @@ -12,7 +12,7 @@ OBJECTS = bcrypt.o blake.o blake2s.o c11.o dcrypt.o fresh.o lane.o \ sha3/sph_luffa.o sha3/sph_shabal.o sha3/sph_shavite.o sha3/sph_simd.o sha3/sph_skein.o sha3/sph_whirlpool.o \ sha3/sph_haval.o sha3/sph_sha2.o sha3/sph_sha2big.o sha3/sph_blake2s.o sha3/sm3.o sha3/panama.o \ sha3/extra.o sha3/gost_streebog.o sha3/sph_tiger.o sha3/SWIFFTX.o KeccakP-800-reference.o \ - shavite3.o skein.o x11.o x13.o x15.o x17.o x16r.o x16s.o x21s.o odocrypt.o x25x.o \ + shavite3.o skein.o x11.o x13.o x15.o x17.o x16r.o x16rv2.o x16s.o x21s.o odocrypt.o x25x.o \ Lyra2.o Lyra2RE.o Sponge.o geek.o \ equi/util.o equi/support/cleanse.o equi/random.o \ equi/uint256.o equi/arith_uint256.o equi/crypto/hmac_sha512.o \ diff --git a/src/Native/libmultihash/exports.cpp b/src/Native/libmultihash/exports.cpp index 25130e0a..91ceaf3d 100644 --- a/src/Native/libmultihash/exports.cpp +++ b/src/Native/libmultihash/exports.cpp @@ -220,7 +220,7 @@ extern "C" MODULE_API void x16r_export(const char* input, char* output, uint32_t } extern "C" MODULE_API void x16rv2_export(const char* input, char* output, uint32_t input_len) { - x16rv2_hash(input, output, input_len); + x16rv2_hash(input, output); } extern "C" MODULE_API void x21s_export(const char* input, char* output, uint32_t input_len) diff --git a/src/Native/libmultihash/x16rv2.c b/src/Native/libmultihash/x16rv2.c index 5db8e7b2..fcd67509 100644 --- a/src/Native/libmultihash/x16rv2.c +++ b/src/Native/libmultihash/x16rv2.c @@ -57,7 +57,7 @@ static void getAlgoString(const uint8_t* prevblock, char *output) } *sptr = '\0'; } -void x16rv2_hash(const char* input, char* output,uint32_t len) +void x16rv2_hash(const char* input, char* output) { uint32_t hash[64/4]; char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; diff --git a/src/Native/libmultihash/x16rv2.h b/src/Native/libmultihash/x16rv2.h index 9ff2bf4a..64f7ca69 100644 --- a/src/Native/libmultihash/x16rv2.h +++ b/src/Native/libmultihash/x16rv2.h @@ -7,7 +7,7 @@ extern "C" { #include -void x16rv2_hash(const char* input, char* output, uint32_t len); +void x16rv2_hash(const char* input, char* output); #ifdef __cplusplus } From e117e1f75bf7b2dd9d2584ff105b6ba2940090fe Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Wed, 4 Mar 2020 00:30:31 +0300 Subject: [PATCH 10/36] Changes for indexchain and general upgrades --- .../Blockchain/Bitcoin/BitcoinJob.cs | 15 +- .../Blockchain/Bitcoin/BitcoinJobManager.cs | 4 +- .../Bitcoin/BitcoinJobManagerBase.cs | 12 +- .../Blockchain/Bitcoin/IndexBlockHeader.cs | 344 ++++++++++++++++++ src/Miningcore/Program.cs | 4 +- src/Native/libmultihash/exports.cpp | 2 +- src/Native/libmultihash/x16rv2.c | 253 +++++++------ src/Native/libmultihash/x16rv2.h | 2 +- 8 files changed, 491 insertions(+), 145 deletions(-) create mode 100644 src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 1f1e617e..7bc4925d 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -124,7 +124,7 @@ protected virtual void BuildCoinbase() // version bs.ReadWrite(ref txVersion); - // timestamp for POS coins + // // timestamp for POS coins if(isPoS) { var timestamp = BlockTemplate.CurTime; @@ -320,7 +320,7 @@ protected byte[] SerializeHeader(Span coinbaseHash, uint nTime, uint nonce version = (version & ~versionMask.Value) | (versionBits.Value & versionMask.Value); #pragma warning disable 618 - var blockHeader = new BlockHeader + var blockHeader = new IndexBlockHeader #pragma warning restore 618 { Version = unchecked((int) version), @@ -328,7 +328,8 @@ protected byte[] SerializeHeader(Span coinbaseHash, uint nTime, uint nonce HashPrevBlock = uint256.Parse(BlockTemplate.PreviousBlockhash), HashMerkleRoot = new uint256(merkleRoot), BlockTime = DateTimeOffset.FromUnixTimeSeconds(nTime), - Nonce = nonce + Nonce = nonce, + ProofOfStake = false }; return blockHeader.ToBytes(); @@ -432,9 +433,9 @@ protected virtual byte[] SerializeBlock(byte[] header, byte[] coinbase) bs.ReadWrite(ref coinbase); bs.ReadWrite(ref rawTransactionBuffer); - // POS coins require a zero byte appended to block which the daemon replaces with the signature - if(isPoS) - bs.ReadWrite((byte) 0); + // // POS coins require a zero byte appended to block which the daemon replaces with the signature + // if(isPoS) + // bs.ReadWrite((byte) 0); return stream.ToArray(); } @@ -566,7 +567,7 @@ public void Init(BlockTemplate blockTemplate, string jobId, JobId = jobId; Difficulty = new Target(new NBitcoin.BouncyCastle.Math.BigInteger(BlockTemplate.Target, 16)).Difficulty; extraNoncePlaceHolderLength = BitcoinConstants.ExtranoncePlaceHolderLength; - this.isPoS = isPoS; + this.isPoS = false; this.shareMultiplier = shareMultiplier; txComment = !string.IsNullOrEmpty(extraPoolConfig?.CoinbaseTxComment) ? diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManager.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManager.cs index 49825f69..4019b09d 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManager.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManager.cs @@ -120,9 +120,9 @@ await GetBlockTemplateAsync() : job = CreateJob(); job.Init(blockTemplate, NextJobId(), - poolConfig, extraPoolConfig, clusterConfig, clock, poolAddressDestination, network, isPoS, + poolConfig, extraPoolConfig, clusterConfig, clock, poolAddressDestination, network, false, ShareMultiplier, coin.CoinbaseHasherValue, coin.HeaderHasherValue, - !isPoS ? coin.BlockHasherValue : coin.PoSBlockHasherValue ?? coin.BlockHasherValue); + coin.BlockHasherValue); lock(jobLock) { diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs index b5d5ed46..54c1c547 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs @@ -498,13 +498,13 @@ protected override async Task PostStartInitAsync(CancellationToken ct) if(validateAddressResponse == null || !validateAddressResponse.IsValid) logger.ThrowLogPoolStartupException($"Daemon reports pool-address '{poolConfig.Address}' as invalid"); - isPoS = difficultyResponse.Values().Any(x => x.Path == "proof-of-stake"); + // isPoS = difficultyResponse.Values().Any(x => x.Path == "proof-of-stake"); - // Create pool address script from response - if(!isPoS) + // // Create pool address script from response + // if(!isPoS) poolAddressDestination = AddressToDestination(poolConfig.Address, extraPoolConfig?.AddressType); - else - poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); + // else + // poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); // Payment-processing setup if(clusterConfig.PaymentProcessing?.Enabled == true && poolConfig.PaymentProcessing?.Enabled == true) @@ -518,7 +518,7 @@ protected override async Task PostStartInitAsync(CancellationToken ct) // update stats BlockchainStats.NetworkType = network.Name; - BlockchainStats.RewardType = isPoS ? "POS" : "POW"; + BlockchainStats.RewardType = "POW"; // block submission RPC method if(submitBlockResponse.Error?.Message?.ToLower() == "method not found") diff --git a/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs b/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs new file mode 100644 index 00000000..301279a3 --- /dev/null +++ b/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs @@ -0,0 +1,344 @@ +using NBitcoin.BouncyCastle.Math; +using NBitcoin.Crypto; +using NBitcoin.DataEncoders; +using NBitcoin.RPC; +#if !NOJSONNET +using Newtonsoft.Json.Linq; +#endif +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace NBitcoin +{ + /// + /// Nodes collect new transactions into a block, hash them into a hash tree, + /// and scan through nonce values to make the block's hash satisfy proof-of-work + /// requirements. When they solve the proof-of-work, they broadcast the block + /// to everyone and the block is added to the block chain. The first transaction + /// in the block is a special one that creates a new coin owned by the creator + /// of the block. + /// + public class IndexBlockHeader : IBitcoinSerializable + { + internal const int Size = 81; + + + public static IndexBlockHeader Parse(string hex, Network network) + { + if (network == null) + throw new ArgumentNullException(nameof(network)); + return Parse(hex, network.Consensus.ConsensusFactory); + } + + public static IndexBlockHeader Parse(string hex, Consensus consensus) + { + if (consensus == null) + throw new ArgumentNullException(nameof(consensus)); + return Parse(hex, consensus.ConsensusFactory); + } + + public static IndexBlockHeader Parse(string hex, ConsensusFactory consensusFactory) + { + if (consensusFactory == null) + throw new ArgumentNullException(nameof(consensusFactory)); + return new IndexBlockHeader(Encoders.Hex.DecodeData(hex), consensusFactory); + } + + + [Obsolete("Use Parse(string hex, Network|Consensus|ConsensusFactory) instead")] + public static IndexBlockHeader Parse(string hex) + { + return Parse(hex, Consensus.Main.ConsensusFactory); + } + + [Obsolete("You should instantiate IndexBlockHeader from ConsensusFactory.CreateIndexBlockHeader")] + public IndexBlockHeader() + { + SetNull(); + } + + public IndexBlockHeader(string hex, Network network) + : this(hex, network?.Consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(network))) + { + + } + + public IndexBlockHeader(string hex, Consensus consensus) + : this(hex, consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(consensus))) + { + + } + + public IndexBlockHeader(string hex, ConsensusFactory consensusFactory) + { + if (hex == null) + throw new ArgumentNullException(nameof(hex)); + if (consensusFactory == null) + throw new ArgumentNullException(nameof(consensusFactory)); + BitcoinStream bs = new BitcoinStream(Encoders.Hex.DecodeData(hex)) + { + ConsensusFactory = consensusFactory + }; + this.ReadWrite(bs); + } + + [Obsolete("Use new IndexBlockHeader(string hex, Network|Consensus|ConsensusFactory) instead")] + public IndexBlockHeader(string hex) + : this(Encoders.Hex.DecodeData(hex)) + { + + } + + + public IndexBlockHeader(byte[] data, Network network) + : this(data, network?.Consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(network))) + { + + } + + public IndexBlockHeader(byte[] data, Consensus consensus) + : this(data, consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(consensus))) + { + + } + + public IndexBlockHeader(byte[] data, ConsensusFactory consensusFactory) + { + if (data == null) + throw new ArgumentNullException(nameof(data)); + if (consensusFactory == null) + throw new ArgumentNullException(nameof(consensusFactory)); + BitcoinStream bs = new BitcoinStream(data) + { + ConsensusFactory = consensusFactory + }; + this.ReadWrite(bs); + } + + + [Obsolete("Use new IndexBlockHeader(byte[] hex, Network|Consensus|ConsensusFactory) instead")] + public IndexBlockHeader(byte[] bytes) + { + this.ReadWrite(bytes); + } + + + // header + const int CURRENT_VERSION = 3; + + protected uint256 hashPrevBlock; + + public uint256 HashPrevBlock + { + get + { + return hashPrevBlock; + } + set + { + hashPrevBlock = value; + } + } + protected uint256 hashMerkleRoot; + + protected uint nTime; + protected uint nBits; + + public Target Bits + { + get + { + return nBits; + } + set + { + nBits = value; + } + } + + protected int nVersion; + + public int Version + { + get + { + return nVersion; + } + set + { + nVersion = value; + } + } + + protected uint nNonce; + + public uint Nonce + { + get + { + return nNonce; + } + set + { + nNonce = value; + } + } + public uint256 HashMerkleRoot + { + get + { + return hashMerkleRoot; + } + set + { + hashMerkleRoot = value; + } + } + protected bool fProofOfStake; + public bool ProofOfStake + { + get + { + return fProofOfStake; + } + set + { + fProofOfStake = value; + } + } + // protected byte[] posBlockSig; + // public byte[] PosBlockSig + // { + // get + // { + // return posBlockSig; + // } + // set + // { + // posBlockSig = value; + // } + // } + + protected internal virtual void SetNull() + { + nVersion = CURRENT_VERSION; + hashPrevBlock = 0; + hashMerkleRoot = 0; + nTime = 0; + nBits = 0; + nNonce = 0; + fProofOfStake = false; + // posBlockSig = Array.Empty(); + } + + public virtual bool IsNull + { + get + { + return (nBits == 0); + } + } + #region IBitcoinSerializable Members + + public virtual void ReadWrite(BitcoinStream stream) + { + stream.ReadWrite(ref nVersion); + stream.ReadWrite(ref hashPrevBlock); + stream.ReadWrite(ref hashMerkleRoot); + stream.ReadWrite(ref nTime); + stream.ReadWrite(ref nBits); + stream.ReadWrite(ref nNonce); + stream.ReadWrite(ref fProofOfStake); + // stream.ReadWrite(ref posBlockSig); + + } + + + #endregion + + + public virtual uint256 GetPoWHash() + { + return GetHash(); + } + + public uint256 GetHash() + { + uint256 h = null; + var hashes = _Hashes; + if (hashes != null) + { + h = hashes[0]; + } + if (h != null) + return h; + + using (var hs = CreateHashStream()) + { + var stream = new BitcoinStream(hs, true); + stream.SerializationTypeScope(SerializationType.Hash); + this.ReadWrite(stream); + h = hs.GetHash(); + } + + hashes = _Hashes; + if (hashes != null) + { + hashes[0] = h; + } + return h; + } + + protected virtual HashStreamBase CreateHashStream() + { + return new HashStream(); + } + + [Obsolete("Call PrecomputeHash(true, true) instead")] + public void CacheHashes() + { + PrecomputeHash(true, true); + } + + /// + /// Precompute the block header hash so that later calls to GetHash() will returns the precomputed hash + /// + /// If true, the previous precomputed hash is thrown away, else it is reused + /// If true, the hash will be calculated and cached at the first call to GetHash(), else it will be immediately + public void PrecomputeHash(bool invalidateExisting, bool lazily) + { + _Hashes = invalidateExisting ? new uint256[1] : _Hashes ?? new uint256[1]; + if (!lazily && _Hashes[0] == null) + _Hashes[0] = GetHash(); + } + + + uint256[] _Hashes; + + public DateTimeOffset BlockTime + { + get + { + return Utils.UnixTimeToDateTime(nTime); + } + set + { + this.nTime = Utils.DateTimeToUnixTime(value); + } + } + + static BigInteger Pow256 = BigInteger.ValueOf(2).Pow(256); + public bool CheckProofOfWork() + { + var bits = Bits.ToBigInteger(); + if (bits.CompareTo(BigInteger.Zero) <= 0 || bits.CompareTo(Pow256) >= 0) + return false; + // Check proof of work matches claimed amount + return GetPoWHash() <= Bits.ToUInt256(); + } + + + } +} \ No newline at end of file diff --git a/src/Miningcore/Program.cs b/src/Miningcore/Program.cs index 8f45c8d6..671d48d8 100644 --- a/src/Miningcore/Program.cs +++ b/src/Miningcore/Program.cs @@ -734,6 +734,7 @@ private static void StartApi() { options.SerializerSettings.Formatting = Formatting.Indented; }); + services.AddMvc(option => option.EnableEndpointRouting = false); // Gzip Compression services.AddResponseCompression(); @@ -755,10 +756,11 @@ private static void StartApi() UseIpWhiteList(app, true, new[] { "/metrics" }, clusterConfig.Api?.MetricsIpWhitelist); app.UseResponseCompression(); - app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials()); + app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); app.UseWebSockets(); app.MapWebSocketManager("/notifications", app.ApplicationServices.GetService()); app.UseMetricServer(); + app.UseMvc(); }) .UseKestrel(options => diff --git a/src/Native/libmultihash/exports.cpp b/src/Native/libmultihash/exports.cpp index 91ceaf3d..7574bc2e 100644 --- a/src/Native/libmultihash/exports.cpp +++ b/src/Native/libmultihash/exports.cpp @@ -220,7 +220,7 @@ extern "C" MODULE_API void x16r_export(const char* input, char* output, uint32_t } extern "C" MODULE_API void x16rv2_export(const char* input, char* output, uint32_t input_len) { - x16rv2_hash(input, output); + x16rv2_hash(input, output,input_len); } extern "C" MODULE_API void x21s_export(const char* input, char* output, uint32_t input_len) diff --git a/src/Native/libmultihash/x16rv2.c b/src/Native/libmultihash/x16rv2.c index fcd67509..539dbcc9 100644 --- a/src/Native/libmultihash/x16rv2.c +++ b/src/Native/libmultihash/x16rv2.c @@ -57,139 +57,138 @@ static void getAlgoString(const uint8_t* prevblock, char *output) } *sptr = '\0'; } -void x16rv2_hash(const char* input, char* output) +void x16rv2_hash(const char* input, char* output, uint32_t len) { - uint32_t hash[64/4]; - char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; + uint32_t hash[64/4]; + char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; - sph_blake512_context ctx_blake; - sph_bmw512_context ctx_bmw; - sph_groestl512_context ctx_groestl; - sph_skein512_context ctx_skein; - sph_jh512_context ctx_jh; - sph_keccak512_context ctx_keccak; - sph_luffa512_context ctx_luffa; - sph_cubehash512_context ctx_cubehash; - sph_shavite512_context ctx_shavite; - sph_simd512_context ctx_simd; - sph_echo512_context ctx_echo; - sph_hamsi512_context ctx_hamsi; - sph_fugue512_context ctx_fugue; - sph_shabal512_context ctx_shabal; - sph_whirlpool_context ctx_whirlpool; - sph_sha512_context ctx_sha512; - sph_tiger_context ctx_tiger; + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + sph_tiger_context ctx_tiger; - void *in = (void*) input; - int size = 80; - int i; - int j; + void *in = (void*) input; + int size = len; - getAlgoString(&input[4], hashOrder); + getAlgoString(&input[4], hashOrder); - for (i = 0; i < 16; i++) { - const char elem = hashOrder[i]; - const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; + for (int i = 0; i < 16; i++) + { + const char elem = hashOrder[i]; + const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; - switch (algo) { - case BLAKE: - sph_blake512_init(&ctx_blake); - sph_blake512(&ctx_blake, in, size); - sph_blake512_close(&ctx_blake, hash); - break; - case BMW: - sph_bmw512_init(&ctx_bmw); - sph_bmw512(&ctx_bmw, in, size); - sph_bmw512_close(&ctx_bmw, hash); - break; - case GROESTL: - sph_groestl512_init(&ctx_groestl); - sph_groestl512(&ctx_groestl, in, size); - sph_groestl512_close(&ctx_groestl, hash); - break; - case SKEIN: - sph_skein512_init(&ctx_skein); - sph_skein512(&ctx_skein, in, size); - sph_skein512_close(&ctx_skein, hash); - break; - case JH: - sph_jh512_init(&ctx_jh); - sph_jh512(&ctx_jh, in, size); - sph_jh512_close(&ctx_jh, hash); - break; - case KECCAK: - sph_tiger_init(&ctx_tiger); - sph_tiger(&ctx_tiger, (const void*) in, size); - sph_tiger_close(&ctx_tiger, (void*) hash); - for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + switch (algo) { + case BLAKE: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case BMW: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case GROESTL: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + case SKEIN: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case JH: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case KECCAK: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (int j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes - sph_keccak512_init(&ctx_keccak); - sph_keccak512(&ctx_keccak, hash, 64); - sph_keccak512_close(&ctx_keccak, hash); - break; - case LUFFA: - sph_tiger_init(&ctx_tiger); - sph_tiger(&ctx_tiger, (const void*) in, size); - sph_tiger_close(&ctx_tiger, (void*) hash); - for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + break; + case LUFFA: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (int j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes - sph_luffa512_init(&ctx_luffa); - sph_luffa512(&ctx_luffa, hash, 64); - sph_luffa512_close(&ctx_luffa, hash); - break; - case CUBEHASH: - sph_cubehash512_init(&ctx_cubehash); - sph_cubehash512(&ctx_cubehash, in, size); - sph_cubehash512_close(&ctx_cubehash, hash); - break; - case SHAVITE: - sph_shavite512_init(&ctx_shavite); - sph_shavite512(&ctx_shavite, in, size); - sph_shavite512_close(&ctx_shavite, hash); - break; - case SIMD: - sph_simd512_init(&ctx_simd); - sph_simd512(&ctx_simd, in, size); - sph_simd512_close(&ctx_simd, hash); - break; - case ECHO: - sph_echo512_init(&ctx_echo); - sph_echo512(&ctx_echo, in, size); - sph_echo512_close(&ctx_echo, hash); - break; - case HAMSI: - sph_hamsi512_init(&ctx_hamsi); - sph_hamsi512(&ctx_hamsi, in, size); - sph_hamsi512_close(&ctx_hamsi, hash); - break; - case FUGUE: - sph_fugue512_init(&ctx_fugue); - sph_fugue512(&ctx_fugue, in, size); - sph_fugue512_close(&ctx_fugue, hash); - break; - case SHABAL: - sph_shabal512_init(&ctx_shabal); - sph_shabal512(&ctx_shabal, in, size); - sph_shabal512_close(&ctx_shabal, hash); - break; - case WHIRLPOOL: - sph_whirlpool_init(&ctx_whirlpool); - sph_whirlpool(&ctx_whirlpool, in, size); - sph_whirlpool_close(&ctx_whirlpool, hash); - break; - case SHA512: - sph_tiger_init(&ctx_tiger); - sph_tiger(&ctx_tiger, (const void*) in, size); - sph_tiger_close(&ctx_tiger, (void*) hash); - for (j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + break; + case CUBEHASH: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case SHAVITE: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case SIMD: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + case ECHO: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case HAMSI: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case FUGUE: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case SHABAL: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case WHIRLPOOL: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case SHA512: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (int j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes - sph_sha512_init(&ctx_sha512); - sph_sha512(&ctx_sha512,(const void*) hash, 64); - sph_sha512_close(&ctx_sha512,(void*) hash); - break; - } - in = (void*) hash; - size = 64; - } - memcpy(output, hash, 32); -} + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) hash, 64); + sph_sha512_close(&ctx_sha512,(void*) hash); + break; + } + in = (void*) hash; + size = 64; + } + memcpy(output, hash, 32); +} \ No newline at end of file diff --git a/src/Native/libmultihash/x16rv2.h b/src/Native/libmultihash/x16rv2.h index 64f7ca69..9ff2bf4a 100644 --- a/src/Native/libmultihash/x16rv2.h +++ b/src/Native/libmultihash/x16rv2.h @@ -7,7 +7,7 @@ extern "C" { #include -void x16rv2_hash(const char* input, char* output); +void x16rv2_hash(const char* input, char* output, uint32_t len); #ifdef __cplusplus } From a8d32c6b5013586e160c6f48d4ce0f4136bb8c3d Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Wed, 4 Mar 2020 15:27:42 +0300 Subject: [PATCH 11/36] Updates for testing --- .../Blockchain/Bitcoin/BitcoinJob.cs | 15 ++++++---- .../Bitcoin/BitcoinJobManagerBase.cs | 8 +++--- .../Blockchain/Bitcoin/IndexBlockHeader.cs | 28 +++++++++---------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 7bc4925d..1e65c322 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -37,7 +37,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using Newtonsoft.Json.Linq; using Contract = Miningcore.Contracts.Contract; using Transaction = NBitcoin.Transaction; - +using Miningcore.Crypto.Hashing.Algorithms; namespace Miningcore.Blockchain.Bitcoin { public class BitcoinJob @@ -329,7 +329,8 @@ protected byte[] SerializeHeader(Span coinbaseHash, uint nTime, uint nonce HashMerkleRoot = new uint256(merkleRoot), BlockTime = DateTimeOffset.FromUnixTimeSeconds(nTime), Nonce = nonce, - ProofOfStake = false + ProofOfStake = false, + PosBlockSig = Array.Empty() }; return blockHeader.ToBytes(); @@ -349,7 +350,9 @@ protected virtual (Share Share, string BlockHex) ProcessShareInternal( // hash block-header var headerBytes = SerializeHeader(coinbaseHash, nTime, nonce, context.VersionRollingMask, versionBits); Span headerHash = stackalloc byte[32]; - headerHasher.Digest(headerBytes, headerHash, (ulong) nTime, BlockTemplate, coin, networkParams); + var hasher = new X16RV2(); + + hasher.Digest(headerBytes, headerHash, (ulong) nTime, BlockTemplate, coin, networkParams); var headerValue = new uint256(headerHash); // calc share-diff @@ -434,8 +437,8 @@ protected virtual byte[] SerializeBlock(byte[] header, byte[] coinbase) bs.ReadWrite(ref rawTransactionBuffer); // // POS coins require a zero byte appended to block which the daemon replaces with the signature - // if(isPoS) - // bs.ReadWrite((byte) 0); + if(isPoS) + bs.ReadWrite((byte) 0); return stream.ToArray(); } @@ -567,7 +570,7 @@ public void Init(BlockTemplate blockTemplate, string jobId, JobId = jobId; Difficulty = new Target(new NBitcoin.BouncyCastle.Math.BigInteger(BlockTemplate.Target, 16)).Difficulty; extraNoncePlaceHolderLength = BitcoinConstants.ExtranoncePlaceHolderLength; - this.isPoS = false; + this.isPoS = isPoS; this.shareMultiplier = shareMultiplier; txComment = !string.IsNullOrEmpty(extraPoolConfig?.CoinbaseTxComment) ? diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs index 54c1c547..455ce74e 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs @@ -498,13 +498,13 @@ protected override async Task PostStartInitAsync(CancellationToken ct) if(validateAddressResponse == null || !validateAddressResponse.IsValid) logger.ThrowLogPoolStartupException($"Daemon reports pool-address '{poolConfig.Address}' as invalid"); - // isPoS = difficultyResponse.Values().Any(x => x.Path == "proof-of-stake"); + isPoS = difficultyResponse.Values().Any(x => x.Path == "proof-of-stake"); // // Create pool address script from response - // if(!isPoS) + if(!isPoS) poolAddressDestination = AddressToDestination(poolConfig.Address, extraPoolConfig?.AddressType); - // else - // poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); + else + poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); // Payment-processing setup if(clusterConfig.PaymentProcessing?.Enabled == true && poolConfig.PaymentProcessing?.Enabled == true) diff --git a/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs b/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs index 301279a3..e7909a3f 100644 --- a/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs +++ b/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs @@ -208,18 +208,18 @@ public bool ProofOfStake fProofOfStake = value; } } - // protected byte[] posBlockSig; - // public byte[] PosBlockSig - // { - // get - // { - // return posBlockSig; - // } - // set - // { - // posBlockSig = value; - // } - // } + protected byte[] posBlockSig; + public byte[] PosBlockSig + { + get + { + return posBlockSig; + } + set + { + posBlockSig = value; + } + } protected internal virtual void SetNull() { @@ -230,7 +230,7 @@ protected internal virtual void SetNull() nBits = 0; nNonce = 0; fProofOfStake = false; - // posBlockSig = Array.Empty(); + posBlockSig = Array.Empty(); } public virtual bool IsNull @@ -251,7 +251,7 @@ public virtual void ReadWrite(BitcoinStream stream) stream.ReadWrite(ref nBits); stream.ReadWrite(ref nNonce); stream.ReadWrite(ref fProofOfStake); - // stream.ReadWrite(ref posBlockSig); + stream.ReadWrite(ref posBlockSig); } From eac84ebf5d983b07143e76ae0dc0d4995597f15b Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Wed, 4 Mar 2020 19:21:41 +0300 Subject: [PATCH 12/36] Minor fixes for Header hash --- src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs | 8 +++----- .../Blockchain/Bitcoin/IndexBlockHeader.cs | 14 -------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 1e65c322..5cca3bb7 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -329,8 +329,7 @@ protected byte[] SerializeHeader(Span coinbaseHash, uint nTime, uint nonce HashMerkleRoot = new uint256(merkleRoot), BlockTime = DateTimeOffset.FromUnixTimeSeconds(nTime), Nonce = nonce, - ProofOfStake = false, - PosBlockSig = Array.Empty() + ProofOfStake = false }; return blockHeader.ToBytes(); @@ -350,9 +349,8 @@ protected virtual (Share Share, string BlockHex) ProcessShareInternal( // hash block-header var headerBytes = SerializeHeader(coinbaseHash, nTime, nonce, context.VersionRollingMask, versionBits); Span headerHash = stackalloc byte[32]; - var hasher = new X16RV2(); - hasher.Digest(headerBytes, headerHash, (ulong) nTime, BlockTemplate, coin, networkParams); + headerHasher.Digest(headerBytes, headerHash, (ulong) nTime, BlockTemplate, coin, networkParams); var headerValue = new uint256(headerHash); // calc share-diff @@ -372,7 +370,7 @@ protected virtual (Share Share, string BlockHex) ProcessShareInternal( ratio = shareDiff / context.PreviousDifficulty.Value; if(ratio < 0.99) - throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})"); + throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share given ({shareDiff})"); // use previous difficulty stratumDifficulty = context.PreviousDifficulty.Value; diff --git a/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs b/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs index e7909a3f..32b0fd77 100644 --- a/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs +++ b/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs @@ -208,18 +208,6 @@ public bool ProofOfStake fProofOfStake = value; } } - protected byte[] posBlockSig; - public byte[] PosBlockSig - { - get - { - return posBlockSig; - } - set - { - posBlockSig = value; - } - } protected internal virtual void SetNull() { @@ -230,7 +218,6 @@ protected internal virtual void SetNull() nBits = 0; nNonce = 0; fProofOfStake = false; - posBlockSig = Array.Empty(); } public virtual bool IsNull @@ -251,7 +238,6 @@ public virtual void ReadWrite(BitcoinStream stream) stream.ReadWrite(ref nBits); stream.ReadWrite(ref nNonce); stream.ReadWrite(ref fProofOfStake); - stream.ReadWrite(ref posBlockSig); } From 92186830f47bc46e6e03b7a4d08915ce542aadfb Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Fri, 20 Mar 2020 17:22:33 +0300 Subject: [PATCH 13/36] Working IDX mining code --- src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs | 5 ++--- src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs | 6 +++--- src/Miningcore/coins.json | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 5cca3bb7..47ecd3da 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -320,7 +320,7 @@ protected byte[] SerializeHeader(Span coinbaseHash, uint nTime, uint nonce version = (version & ~versionMask.Value) | (versionBits.Value & versionMask.Value); #pragma warning disable 618 - var blockHeader = new IndexBlockHeader + var blockHeader = new BlockHeader #pragma warning restore 618 { Version = unchecked((int) version), @@ -328,8 +328,7 @@ protected byte[] SerializeHeader(Span coinbaseHash, uint nTime, uint nonce HashPrevBlock = uint256.Parse(BlockTemplate.PreviousBlockhash), HashMerkleRoot = new uint256(merkleRoot), BlockTime = DateTimeOffset.FromUnixTimeSeconds(nTime), - Nonce = nonce, - ProofOfStake = false + Nonce = nonce }; return blockHeader.ToBytes(); diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs index 455ce74e..76b881cf 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs @@ -501,10 +501,10 @@ protected override async Task PostStartInitAsync(CancellationToken ct) isPoS = difficultyResponse.Values().Any(x => x.Path == "proof-of-stake"); // // Create pool address script from response - if(!isPoS) + //if(!isPoS) poolAddressDestination = AddressToDestination(poolConfig.Address, extraPoolConfig?.AddressType); - else - poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); + // else + // poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); // Payment-processing setup if(clusterConfig.PaymentProcessing?.Enabled == true && poolConfig.PaymentProcessing?.Enabled == true) diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 45e28fd8..c2d96b33 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -309,7 +309,7 @@ ] }, "hasMasterNodes": true, - "shareMultiplier": 256, + "shareMultiplier": 4096, "explorerBlockLink": "https://chainz.cryptoid.info/dash/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/dash/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/dash/address.dws?{0}.htm" From 8d95a93b327bbb48a4e2c84360a53c21c93e8b49 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Sat, 21 Mar 2020 03:12:16 +0300 Subject: [PATCH 14/36] More modifications to api for react-admin --- .../Api/Controllers/PoolApiController.cs | 28 +++++++-- .../Api/Responses/GetBlocksResponse.cs | 1 + .../Api/Responses/GetMinerStatsResponse.cs | 1 + .../Model/MinerWorkerPerformanceStats.cs | 1 + .../Postgres/Repositories/BlockRepository.cs | 31 +++++++--- .../Postgres/Repositories/StatsRepository.cs | 58 +++++++++---------- .../Repositories/IBlockRepository.cs | 4 +- src/Miningcore/Program.cs | 2 +- 8 files changed, 81 insertions(+), 45 deletions(-) diff --git a/src/Miningcore/Api/Controllers/PoolApiController.cs b/src/Miningcore/Api/Controllers/PoolApiController.cs index 8dca3454..3d384b93 100644 --- a/src/Miningcore/Api/Controllers/PoolApiController.cs +++ b/src/Miningcore/Api/Controllers/PoolApiController.cs @@ -160,28 +160,37 @@ public async Task PagePoolMinersAsync( con, pool.Id, start, page, pageSize))) .Select(mapper.Map) .ToArray(); - + Response.Headers.Add("x-total-count",miners.Length.ToString()); return miners; } [HttpGet("{poolId}/blocks")] public async Task PagePoolBlocksPagedAsync( - string poolId, [FromQuery] int page, [FromQuery] int pageSize = 15, [FromQuery] BlockStatus[] state = null) + string poolId, [FromQuery] int page, [FromQuery] int _start ,[FromQuery] int _end ,[FromQuery] String _order ,[FromQuery] String _sort,[FromQuery] int perPage = 0,[FromQuery] int pageSize = 15, [FromQuery] BlockStatus[] state = null) { + //http://192.168.2.2:4000/api/pools/indexchain/blocks?_end=10&_order=ASC&_sort=id&_start=0 var pool = GetPool(poolId); + if(perPage != 0){ + pageSize = perPage; + } + bool shouldlimitbyid = _end > 0; var blockStates = state != null && state.Length > 0 ? state : new[] { BlockStatus.Confirmed, BlockStatus.Pending, BlockStatus.Orphaned }; - var blocks = (await cf.Run(con => blocksRepo.PageBlocksAsync(con, pool.Id, blockStates, page, pageSize))) + var blocks = shouldlimitbyid ? (await cf.Run(con => blocksRepo.PageBlocksAsyncPaged(con, pool.Id, blockStates, page, pageSize,_start,_end,_order,_sort))) + .Select(mapper.Map) + .ToArray():(await cf.Run(con => blocksRepo.PageBlocksAsync(con, pool.Id, blockStates, page, pageSize))) .Select(mapper.Map) .ToArray(); - + var totalcount = (await cf.Run(con => blocksRepo.PageBlocksAsync(con, pool.Id, blockStates, page, 100000000))) + .Select(mapper.Map) + .ToArray().Length; // enrich blocks var blockInfobaseDict = pool.Template.ExplorerBlockLinks; - - foreach(var block in blocks) + if (_start == 0 && _end < _start) + foreach(var block in blocks) { // compute infoLink if(blockInfobaseDict != null) @@ -197,6 +206,8 @@ public async Task PagePoolMinersAsync( } } } + + Response.Headers.Add("x-total-count",totalcount.ToString()); return blocks; } @@ -226,6 +237,7 @@ public async Task PagePoolMinersAsync( if(!string.IsNullOrEmpty(addressInfobaseUrl)) payment.AddressInfoLink = string.Format(addressInfobaseUrl, payment.Address); } + Response.Headers.Add("x-total-count",payments.Length.ToString()); return payments; } @@ -294,6 +306,7 @@ public async Task PagePoolMinersAsync( if(!string.IsNullOrEmpty(addressInfobaseUrl)) payment.AddressInfoLink = string.Format(addressInfobaseUrl, payment.Address); } + Response.Headers.Add("x-total-count",payments.Length.ToString()); return payments; } @@ -311,6 +324,7 @@ public async Task PagePoolMinersAsync( con, pool.Id, address, page, pageSize))) .Select(mapper.Map) .ToArray(); + Response.Headers.Add("x-total-count",balanceChanges.Length.ToString()); return balanceChanges; } @@ -327,6 +341,7 @@ public async Task PageMinerEarningsByDayAsync( var earnings = (await cf.Run(con => paymentsRepo.PageMinerPaymentsByDayAsync( con, pool.Id, address, page, pageSize))) .ToArray(); + Response.Headers.Add("x-total-count",earnings.Length.ToString()); return earnings; } @@ -341,6 +356,7 @@ public async Task PageMinerEarningsByDayAsync( throw new ApiException($"Invalid or missing miner address", HttpStatusCode.NotFound); var result = await GetMinerPerformanceInternal(mode, pool, address); + Response.Headers.Add("x-total-count",result.Length.ToString()); return result; } diff --git a/src/Miningcore/Api/Responses/GetBlocksResponse.cs b/src/Miningcore/Api/Responses/GetBlocksResponse.cs index aee3cd04..fbd00594 100644 --- a/src/Miningcore/Api/Responses/GetBlocksResponse.cs +++ b/src/Miningcore/Api/Responses/GetBlocksResponse.cs @@ -24,6 +24,7 @@ namespace Miningcore.Api.Responses { public class Block { + public long Id { get; set; } public string PoolId { get; set; } public ulong BlockHeight { get; set; } public double NetworkDifficulty { get; set; } diff --git a/src/Miningcore/Api/Responses/GetMinerStatsResponse.cs b/src/Miningcore/Api/Responses/GetMinerStatsResponse.cs index b459d311..2464145b 100644 --- a/src/Miningcore/Api/Responses/GetMinerStatsResponse.cs +++ b/src/Miningcore/Api/Responses/GetMinerStatsResponse.cs @@ -25,6 +25,7 @@ namespace Miningcore.Api.Responses { public class MinerPerformanceStats { + public long Id { get; set; } public string Miner { get; set; } public double Hashrate { get; set; } public double SharesPerSecond { get; set; } diff --git a/src/Miningcore/Persistence/Model/MinerWorkerPerformanceStats.cs b/src/Miningcore/Persistence/Model/MinerWorkerPerformanceStats.cs index 7b48efcd..bc394e8a 100644 --- a/src/Miningcore/Persistence/Model/MinerWorkerPerformanceStats.cs +++ b/src/Miningcore/Persistence/Model/MinerWorkerPerformanceStats.cs @@ -4,6 +4,7 @@ namespace Miningcore.Persistence.Model { public class MinerWorkerPerformanceStats { + public long Id { get; set; } public string PoolId { get; set; } public string Miner { get; set; } public string Worker { get; set; } diff --git a/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs b/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs index eb855c79..a086527c 100644 --- a/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs +++ b/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs @@ -21,7 +21,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; using System.Data; using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; using AutoMapper; using Dapper; using Miningcore.Extensions; @@ -89,18 +89,33 @@ public async Task PageBlocksAsync(IDbConnection con, string poolId, Blo })) .Select(mapper.Map) .ToArray(); - } - + } + public async Task PageBlocksAsyncPaged(IDbConnection con, string poolId, BlockStatus[] status, int page, int pageSize,int _start,int _end,string _order,string _sort) + { + logger.LogInvoke(new[] { poolId }); + string query = "SELECT * FROM blocks WHERE poolid = @poolid AND status = ANY(@status) AND id <= " + _end + + " ORDER BY " + _sort + " " + _order + " OFFSET @offset FETCH NEXT (@pageSize) ROWS ONLY"; + + return (await con.QueryAsync(query, new + { + poolId, + status = status.Select(x => x.ToString().ToLower()).ToArray(), + offset = page * pageSize, + pageSize + })) + .Select(mapper.Map) + .ToArray(); + } public async Task PageBlocksAsync(IDbConnection con, BlockStatus[] status, int page, int pageSize) { const string query = "SELECT * FROM blocks WHERE status = ANY(@status) " + "ORDER BY created DESC OFFSET @offset FETCH NEXT (@pageSize) ROWS ONLY"; - return (await con.QueryAsync(query, new - { - status = status.Select(x => x.ToString().ToLower()).ToArray(), - offset = page * pageSize, - pageSize + return (await con.QueryAsync(query, new + { + status = status.Select(x => x.ToString().ToLower()).ToArray(), + offset = page * pageSize, + pageSize })) .Select(mapper.Map) .ToArray(); diff --git a/src/Miningcore/Persistence/Postgres/Repositories/StatsRepository.cs b/src/Miningcore/Persistence/Postgres/Repositories/StatsRepository.cs index 50f13484..ca9656ac 100644 --- a/src/Miningcore/Persistence/Postgres/Repositories/StatsRepository.cs +++ b/src/Miningcore/Persistence/Postgres/Repositories/StatsRepository.cs @@ -21,7 +21,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; using System.Data; using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; using AutoMapper; using Dapper; using Miningcore.Extensions; @@ -104,15 +104,15 @@ public async Task GetPoolPerformanceBetweenAsync(IDbConnection con, string trunc = null; - switch(interval) - { - case SampleInterval.Hour: - trunc = "hour"; - break; - - case SampleInterval.Day: - trunc = "day"; - break; + switch(interval) + { + case SampleInterval.Hour: + trunc = "hour"; + break; + + case SampleInterval.Day: + trunc = "day"; + break; } var query = $"SELECT date_trunc('{trunc}', created) AS created, " + @@ -200,20 +200,20 @@ public async Task GetPoolMinerWorkerHashratesAsync(IDbCon logger.LogInvoke(); const string query = - "SELECT s.miner, s.worker, s.hashrate FROM " + - "(" + - " WITH cte AS" + - " (" + - " SELECT" + - " ROW_NUMBER() OVER (partition BY miner, worker ORDER BY created DESC) as rk," + - " miner, worker, hashrate" + - " FROM minerstats" + - " WHERE poolid = @poolId" + - " )" + - " SELECT miner, worker, hashrate" + - " FROM cte" + - " WHERE rk = 1" + - ") s " + + "SELECT s.miner, s.worker, s.hashrate FROM " + + "(" + + " WITH cte AS" + + " (" + + " SELECT" + + " ROW_NUMBER() OVER (partition BY miner, worker ORDER BY created DESC) as rk," + + " miner, worker, hashrate" + + " FROM minerstats" + + " WHERE poolid = @poolId" + + " )" + + " SELECT miner, worker, hashrate" + + " FROM cte" + + " WHERE rk = 1" + + ") s " + "WHERE s.hashrate > 0;"; return (await con.QueryAsync(query, new { poolId })) @@ -320,20 +320,20 @@ public async Task PagePoolMinersByHashrateAsync(I const string query = "WITH tmp AS " + "( " + " SELECT " + - " ms.miner, " + + " ms.miner, " + + " ms.id, " + " ms.hashrate, " + " ms.sharespersecond, " + " ROW_NUMBER() OVER(PARTITION BY ms.miner ORDER BY ms.hashrate DESC) AS rk " + - " FROM (SELECT miner, SUM(hashrate) AS hashrate, SUM(sharespersecond) AS sharespersecond " + + " FROM (SELECT miner, id , SUM(hashrate) AS hashrate, SUM(sharespersecond) AS sharespersecond " + " FROM minerstats " + - " WHERE poolid = @poolid AND created >= @from GROUP BY miner, created) ms " + + " WHERE poolid = @poolid AND created >= @from GROUP BY id, created) ms " + ") " + - "SELECT t.miner, t.hashrate, t.sharespersecond " + + "SELECT t.id, t.miner, t.hashrate, t.sharespersecond " + "FROM tmp t " + "WHERE t.rk = 1 " + "ORDER by t.hashrate DESC " + "OFFSET @offset FETCH NEXT (@pageSize) ROWS ONLY"; - return (await con.QueryAsync(query, new { poolId, from, offset = page * pageSize, pageSize })) .Select(mapper.Map) .ToArray(); diff --git a/src/Miningcore/Persistence/Repositories/IBlockRepository.cs b/src/Miningcore/Persistence/Repositories/IBlockRepository.cs index 3dda0018..210b0005 100644 --- a/src/Miningcore/Persistence/Repositories/IBlockRepository.cs +++ b/src/Miningcore/Persistence/Repositories/IBlockRepository.cs @@ -20,7 +20,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; using System.Data; -using System.Threading.Tasks; +using System.Threading.Tasks; using Miningcore.Persistence.Model; namespace Miningcore.Persistence.Repositories @@ -32,6 +32,8 @@ public interface IBlockRepository Task UpdateBlockAsync(IDbConnection con, IDbTransaction tx, Block block); Task PageBlocksAsync(IDbConnection con, string poolId, BlockStatus[] status, int page, int pageSize); + Task PageBlocksAsyncPaged(IDbConnection con, string poolId, BlockStatus[] status, int page, int pageSize,int _start,int _end,string _order,string _sort); + Task PageBlocksAsync(IDbConnection con, BlockStatus[] status, int page, int pageSize); Task GetPendingBlocksForPoolAsync(IDbConnection con, string poolId); Task GetBlockBeforeAsync(IDbConnection con, string poolId, BlockStatus[] status, DateTime before); diff --git a/src/Miningcore/Program.cs b/src/Miningcore/Program.cs index 671d48d8..5d3bc037 100644 --- a/src/Miningcore/Program.cs +++ b/src/Miningcore/Program.cs @@ -756,7 +756,7 @@ private static void StartApi() UseIpWhiteList(app, true, new[] { "/metrics" }, clusterConfig.Api?.MetricsIpWhitelist); app.UseResponseCompression(); - app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); + app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().WithExposedHeaders("x-total-count")); app.UseWebSockets(); app.MapWebSocketManager("/notifications", app.ApplicationServices.GetService()); app.UseMetricServer(); From 3f080fdc4a5676a0827a8639236714de09a1c28b Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Sat, 21 Mar 2020 17:12:59 +0300 Subject: [PATCH 15/36] Fix Quarkhash --- .../Crypto/Hashing/Algorithms/Quark.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/Miningcore/Crypto/Hashing/Algorithms/Quark.cs diff --git a/src/Miningcore/Crypto/Hashing/Algorithms/Quark.cs b/src/Miningcore/Crypto/Hashing/Algorithms/Quark.cs new file mode 100644 index 00000000..18667762 --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Algorithms/Quark.cs @@ -0,0 +1,42 @@ +/* +Copyright 2017 Coin Foundry (coinfoundry.org) +Authors: Oliver Weichhold (oliver@weichhold.com) + +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. +*/ + +using System; +using Miningcore.Contracts; +using Miningcore.Native; + +namespace Miningcore.Crypto.Hashing.Algorithms +{ + public unsafe class Quark : IHashAlgorithm + { + public void Digest(ReadOnlySpan data, Span result, params object[] extra) + { + Contract.Requires(result.Length >= 32, $"{nameof(result)} must be greater or equal 32 bytes"); + + fixed (byte* input = data) + { + fixed (byte* output = result) + { + LibMultihash.quark(input, output, (uint) data.Length); + } + } + } + } +} From 3ddb15cc169a0b5bf461b3ca0545931b04a6b5ea Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Sun, 22 Mar 2020 23:43:24 +0300 Subject: [PATCH 16/36] log only each 1000 shares --- src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs index f5636ea6..e97337a7 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs @@ -42,7 +42,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NLog; - namespace Miningcore.Blockchain.Bitcoin { [CoinFamily(CoinFamily.Bitcoin)] @@ -62,7 +61,7 @@ public BitcoinPool(IComponentContext ctx, protected object currentJobParams; protected BitcoinJobManager manager; private BitcoinTemplate coin; - + public int submitcount = 0; protected virtual async Task OnSubscribeAsync(StratumClient client, Timestamped tsRequest) { var request = tsRequest.Value; @@ -196,8 +195,10 @@ protected virtual async Task OnSubmitAsync(StratumClient client, Timestamped $"[{client.ConnectionId}] Share accepted: D={Math.Round(share.Difficulty * coin.ShareMultiplier, 3)}"); + submitcount+=1; + if(submitcount % 1000 == 0){ + logger.Info(() => $"[{client.ConnectionId}] {submitcount} Shares accepted: D={Math.Round(share.Difficulty * coin.ShareMultiplier, 3)}"); + } // update pool stats if(share.IsBlockCandidate) From ec205e94069573579746ed97f8244d68354aa620 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Tue, 24 Mar 2020 14:03:09 +0000 Subject: [PATCH 17/36] Add Yespower_sugar hash,Add CashAddr support and DVT. --- .../Blockchain/Bitcoin/BitcoinConstants.cs | 5 + .../Bitcoin/BitcoinJobManagerBase.cs | 5 +- .../Bitcoin/BitcoinPayoutHandler.cs | 4 +- .../Blockchain/Bitcoin/BitcoinPool.cs | 4 +- .../Blockchain/Bitcoin/BitcoinUtils.cs | 8 + src/Miningcore/Blockchain/Bitcoin/CashAddr.cs | 674 ++++++++++++++++++ .../Hashing/Algorithms/YesPower_SugarChain.cs | 42 ++ src/Miningcore/Native/LibMultihash.cs | 3 + src/Miningcore/coins.json | 21 + src/Native/libmultihash/Makefile | 2 +- src/Native/libmultihash/exports.cpp | 7 + src/Native/libmultihash/libmultihash.vcxproj | 3 + src/Native/libmultihash/yespower_ref.c | 580 +++++++++++++++ src/Native/libmultihash/yespower_sugarchain.c | 15 + src/Native/libmultihash/yespower_sugarchain.h | 130 ++++ 15 files changed, 1496 insertions(+), 7 deletions(-) create mode 100644 src/Miningcore/Blockchain/Bitcoin/CashAddr.cs create mode 100644 src/Miningcore/Crypto/Hashing/Algorithms/YesPower_SugarChain.cs create mode 100644 src/Native/libmultihash/yespower_ref.c create mode 100644 src/Native/libmultihash/yespower_sugarchain.c create mode 100644 src/Native/libmultihash/yespower_sugarchain.h diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs index c7c55330..7790d9f2 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs @@ -35,6 +35,11 @@ public enum BitcoinAddressType /// Bech encoded, segwit /// BechSegwit, + /// + /// Bcash custom bech encoded + /// + CashAddr, + } public enum BitcoinTransactionCategory diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs index 76b881cf..af70bbd0 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs @@ -502,7 +502,7 @@ protected override async Task PostStartInitAsync(CancellationToken ct) // // Create pool address script from response //if(!isPoS) - poolAddressDestination = AddressToDestination(poolConfig.Address, extraPoolConfig?.AddressType); + poolAddressDestination = AddressToDestination(poolConfig.Address, poolConfig.Template.Symbol == "DVT" ? BitcoinAddressType.CashAddr : extraPoolConfig?.AddressType); // else // poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); @@ -564,6 +564,9 @@ protected virtual IDestination AddressToDestination(string address, BitcoinAddre case BitcoinAddressType.BechSegwit: return BitcoinUtils.BechSegwitAddressToDestination(poolConfig.Address, network); + case BitcoinAddressType.CashAddr: + return BitcoinUtils.CashAddrToDestination(poolConfig.Address, network); + default: return BitcoinUtils.AddressToDestination(poolConfig.Address, network); } diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs index af61c880..c3dcffed 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs @@ -208,11 +208,11 @@ public virtual Task CalculateBlockEffortAsync(Block block, double accumulatedBlo public virtual async Task PayoutAsync(Balance[] balances) { Contract.RequiresNonNull(balances, nameof(balances)); - + var roundnum = poolConfig.Template.Symbol == "DVT" ? 3:4; // build args var amounts = balances .Where(x => x.Amount > 0) - .ToDictionary(x => x.Address, x => Math.Round(x.Amount, 4)); + .ToDictionary(x => x.Address, x => Math.Round(x.Amount, roundnum)); if(amounts.Count == 0) return; diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs index e97337a7..93fc5929 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs @@ -196,9 +196,7 @@ protected virtual async Task OnSubmitAsync(StratumClient client, Timestamped $"[{client.ConnectionId}] {submitcount} Shares accepted: D={Math.Round(share.Difficulty * coin.ShareMultiplier, 3)}"); - } + logger.Info(() => $"[{client.ConnectionId}] Total Shares:{submitcount} Share accepted: D={Math.Round(share.Difficulty * coin.ShareMultiplier, 3)}"); // update pool stats if(share.IsBlockCandidate) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs index 1119f262..444b89de 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs @@ -23,6 +23,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System.Linq; using NBitcoin; using NBitcoin.DataEncoders; +using static Miningcore.Blockchain.Bitcoin.CashAddr; +using static Miningcore.Blockchain.Bitcoin.BchAddr; namespace Miningcore.Blockchain.Bitcoin { @@ -56,5 +58,11 @@ public static IDestination BechSegwitAddressToDestination(string address, Networ Debug.Assert(result.GetAddress(expectedNetwork).ToString() == address); return result; } + public static IDestination CashAddrToDestination(string address, Network expectedNetwork) + { + BchAddr.BchAddrData bchAddr = BchAddr.DecodeCashAddressWithPrefix(address); + var result = new KeyId(bchAddr.Hash); + return result; + } } } diff --git a/src/Miningcore/Blockchain/Bitcoin/CashAddr.cs b/src/Miningcore/Blockchain/Bitcoin/CashAddr.cs new file mode 100644 index 00000000..6727db58 --- /dev/null +++ b/src/Miningcore/Blockchain/Bitcoin/CashAddr.cs @@ -0,0 +1,674 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NBitcoin.DataEncoders; +namespace Miningcore.Blockchain.Bitcoin{ + + // https://github.com/bitcoincashjs/bchaddrjs + public static class BchAddr + { + public enum CashFormat + { + Legacy, + Bitpay, + Cashaddr + } + + public enum CashNetwork + { + Mainnet, + Testnet, + RegTest, + DevaultMainnet + } + + public enum CashType + { + P2PKH, + P2SH + } + + public class BchAddrData + { + public CashFormat Format { get; set; } + public CashNetwork Network { get; set; } + public CashType Type { get; set; } + public byte[] Hash { get; set; } + + public string GetHash() + { + if (Hash == null) return null; + return Encoders.Hex.EncodeData(Hash); + } + + public string AsLegacyAddress => EncodeAsLegacy(this); + public string AsBitpayAddress => EncodeAsBitpay(this); + public string AsCashaddrAddress => EncodeAsCashaddr(this); + public string AsCashaddrAddressNoPrefix => EncodeAsCashaddrNoPrefix(this); + + public static BchAddrData Create(CashFormat format, CashNetwork network, CashType type, byte[] hash) + { + return new BchAddrData + { + Format = format, + Network = network, + Type = type, + Hash = hash, + }; + } + } + + /// + /// Encodes the given decoded address into legacy format + /// + /// + /// + public static string EncodeAsLegacy(BchAddrData decoded) + { + var versionByte = GetVersionByte(CashFormat.Legacy, decoded.Network, decoded.Type); + var buffer = new byte[1] { versionByte }; + buffer = buffer.Concat(decoded.Hash).ToArray(); + return Encoders.Base58Check.EncodeData(buffer); + } + + /// + /// Encodes the given decoded address into bitpay format + /// + /// + /// + public static string EncodeAsBitpay(BchAddrData decoded) + { + var versionByte = GetVersionByte(CashFormat.Bitpay, decoded.Network, decoded.Type); + var buffer = new byte[1] { versionByte }; + buffer = buffer.Concat(decoded.Hash).ToArray(); + return Encoders.Base58Check.EncodeData(buffer); + } + + /// + /// Encodes the given decoded address into cashaddr format + /// + /// + /// + public static string EncodeAsCashaddr(BchAddrData decoded) + { + var prefix = GetCashaddrkPrefix(decoded); + var type = decoded.Type == CashType.P2PKH ? "P2PKH" : "P2SH"; + var hash = decoded.Hash; + return CashAddr.Encode(prefix, type, hash); + } + + /// + /// Encodes the given decoded address into cashaddr format without a prefix + /// + /// + /// + public static string EncodeAsCashaddrNoPrefix(BchAddrData decoded) + { + var address = EncodeAsCashaddr(decoded); + if (address.IndexOf(":") != -1) + { + return address.Split(':')[1]; + } + throw new Validation.ValidationError($"Invalid BchAddrData"); + } + + public static string GetCashaddrkPrefix(BchAddrData data) + { + switch (data.Network) + { + case CashNetwork.Mainnet: + return "bitcoincash"; + case CashNetwork.DevaultMainnet: + return "devault"; + case CashNetwork.Testnet: + return "bchtest"; + case CashNetwork.RegTest: + return "bchreg"; + } + throw new Validation.ValidationError($"Invalid BchAddrData"); + } + + /// + /// Detects what is the given address' format + /// + /// + /// + public static BchAddrData DecodeAddress(string address) + { + try + { + return DecodeBase58Address(address); + } + catch { } + try + { + return DecodeCashAddress(address); + } + catch { } + throw new Validation.ValidationError($"Invalid address {address}"); + } + + /// + /// returns the Version byte for base58 formats + /// + /// + /// + /// + /// + private static byte GetVersionByte(CashFormat format, CashNetwork network, CashType type) + { + switch (format) + { + case CashFormat.Legacy: + if (network == CashNetwork.Mainnet && type == CashType.P2PKH) return 0; + else if (network == CashNetwork.Mainnet && type == CashType.P2SH) return 5; + break; + case CashFormat.Bitpay: + if (network == CashNetwork.Mainnet && type == CashType.P2PKH) return 28; + else if (network == CashNetwork.Mainnet && type == CashType.P2SH) return 40; + break; + } + if (network == CashNetwork.Testnet && type == CashType.P2PKH) return 111; + else if (network == CashNetwork.Testnet && type == CashType.P2SH) return 196; + else if (network == CashNetwork.RegTest && type == CashType.P2PKH) return 111; + else if (network == CashNetwork.RegTest && type == CashType.P2SH) return 196; + throw new Validation.ValidationError("Invalid parameters"); + } + + /// + /// Decodes the given address into its constituting hash, format, network and type + /// + /// A valid Bitcoin Cash address in any format + /// + private static BchAddrData DecodeBase58Address(string address) + { + var payload = Encoders.Base58Check.DecodeData(address); + var versionByte = payload[0]; + var hash = payload.Skip(1).ToArray(); + switch (versionByte) + { + case 0: + return BchAddrData.Create(CashFormat.Legacy, CashNetwork.Mainnet, CashType.P2PKH, hash); + case 5: + return BchAddrData.Create(CashFormat.Legacy, CashNetwork.Mainnet, CashType.P2SH, hash); + case 111: + return BchAddrData.Create(CashFormat.Legacy, CashNetwork.Testnet, CashType.P2PKH, hash); + case 196: + return BchAddrData.Create(CashFormat.Legacy, CashNetwork.Testnet, CashType.P2SH, hash); + case 28: + return BchAddrData.Create(CashFormat.Bitpay, CashNetwork.Mainnet, CashType.P2PKH, hash); + case 40: + return BchAddrData.Create(CashFormat.Bitpay, CashNetwork.Mainnet, CashType.P2SH, hash); + default: + throw new Validation.ValidationError($"Invalid address type in version byte: {versionByte}"); + } + } + + /// + /// Attempts to decode the given address assuming it is a cashaddr address + /// + /// A valid Bitcoin Cash address in any format + /// + private static BchAddrData DecodeCashAddress(string address) + { + if (address.IndexOf(":") != -1) + { + return DecodeCashAddressWithPrefix(address); + } + else + { + var prefixes = new string[] { "bitcoincash", "bchtest", "bchreg" }; + foreach (var prefix in prefixes) + { + try + { + var result = DecodeCashAddressWithPrefix(prefix + ":" + address); + return result; + } + catch { } + } + } + throw new Validation.ValidationError($"Invalid address {address}"); + } + + /// + /// Attempts to decode the given address assuming it is a cashaddr address with explicit prefix + /// + /// A valid Bitcoin Cash address in any format + /// + public static BchAddrData DecodeCashAddressWithPrefix(string address) + { + var decoded = CashAddr.Decode(address); + var type = decoded.Type == "P2PKH" ? CashType.P2PKH : CashType.P2SH; + switch (decoded.Prefix) + { + case "bitcoincash": + return BchAddrData.Create(CashFormat.Cashaddr, CashNetwork.Mainnet, type, decoded.Hash); + case "devault": + return BchAddrData.Create(CashFormat.Cashaddr, CashNetwork.DevaultMainnet, type, decoded.Hash); + case "bchtest": + return BchAddrData.Create(CashFormat.Cashaddr, CashNetwork.Testnet, type, decoded.Hash); + case "regtest": + return BchAddrData.Create(CashFormat.Cashaddr, CashNetwork.RegTest, type, decoded.Hash); + } + throw new Validation.ValidationError($"Invalid address {address}"); + } + } + + // https://github.com/bitcoincashjs/cashaddrjs + public static class CashAddr + { + public class CashAddrData + { + public string Prefix { get; set; } + public string Type { get; set; } + public byte[] Hash { get; set; } + } + + static string[] VALID_PREFIXES = new string[] { "devault","bitcoincash", "bchtest", "bchreg" }; + + /// + /// Encodes a hash from a given type into a Bitcoin Cash address with the given prefix + /// + /// prefix Network prefix. E.g.: 'bitcoincash' + /// type Type of address to generate. Either 'P2PKH' or 'P2SH' + /// hash Hash to encode represented as an array of 8-bit integers + /// + public static string Encode(string prefix, string type, byte[] hash) + { + Validation.Validate(IsValidPrefix(prefix), $"Invalid prefix: {prefix}"); + var prefixData = Concat(PrefixToByte5Array(prefix), new byte[1]); + var versionByte = GetTypeBits(type) + GetHashSizeBits(hash); + var payloadData = ToByte5Array(Concat(new byte[1] { (byte)versionByte }, hash)); + var checksumData = Concat(Concat(prefixData, payloadData), new byte[8]); + var payload = Concat(payloadData, ChecksumToByte5Array(Polymod(checksumData))); + return prefix + ':' + Base32.Encode(payload); + } + + /// + /// Decodes the given address into its constituting prefix, type and hash + /// + /// Address to decode. E.g.: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a' + /// DecodeData + public static CashAddrData Decode(string address) + { + var pieces = address.ToLower().Split(':'); + Validation.Validate(pieces.Length == 2, $"Missing prefix: {address}"); + var prefix = pieces[0]; + var payload = Base32.Decode(pieces[1]); + Validation.Validate(ValidChecksum(prefix, payload), $"Invalid checksum: {address}"); + var data = payload.Take(payload.Length - 8).ToArray(); + var payloadData = FromByte5Array(data); + var versionByte = payloadData[0]; + var hash = payloadData.Skip(1).ToArray(); + Validation.Validate(GetHashSize((byte)versionByte) == hash.Length * 8, $"Invalid hash size: {address}"); + var type = GetType((byte)versionByte); + return new CashAddrData + { + Prefix = prefix, + Type = type, + Hash = hash + }; + } + + /// + /// Retrieves the address type from its bit representation within the version byte + /// + /// + /// + public static string GetType(byte versionByte) + { + switch (versionByte & 120) + { + case 0: + return "P2PKH"; + case 8: + return "P2SH"; + default: + throw new Validation.ValidationError($"Invalid address type in version byte: {versionByte}"); + } + } + + /// + /// Verify that the payload has not been corrupted by checking that the checksum is valid + /// + /// + /// + /// + public static bool ValidChecksum(string prefix, byte[] payload) + { + var prefixData = Concat(PrefixToByte5Array(prefix), new byte[1]); + var checksumData = Concat(prefixData, payload); + return Polymod(checksumData).Equals(0); + } + + + /// + /// Returns the concatenation a and b + /// + public static byte[] Concat(byte[] a, byte[] b) + { + return a.Concat(b).ToArray(); + } + + /// + /// Returns an array representation of the given checksum to be encoded within the address' payload + /// + /// + /// + public static byte[] ChecksumToByte5Array(long checksum) + { + var result = new byte[8]; + for (var i = 0; i < 8; ++i) + { + result[7 - i] = (byte)(checksum & 31); + checksum = checksum >> 5; + } + return result; + } + + /// + /// Computes a checksum from the given input data as specified for the CashAddr + /// + /// + /// + public static long Polymod(byte[] data) + { + var GENERATOR = new long[] { 0x98f2bc8e61, 0x79b76d99e2, 0xf33e5fb3c4, 0xae2eabe2a8, 0x1e4f43e470 }; + long checksum = 1; + for (var i = 0; i < data.Length; ++i) + { + var value = data[i]; + var topBits = checksum >> 35; + checksum = ((checksum & 0x07ffffffff) << 5) ^ value; + for (var j = 0; j < GENERATOR.Length; ++j) + { + if (((topBits >> j) & 1).Equals(1)) + { + checksum = checksum ^ GENERATOR[j]; + } + } + } + return checksum ^ 1; + } + + /// + /// Checks whether a string is a valid prefix; ie., it has a single letter case + /// and is one of 'bitcoincash', 'bchtest', or 'bchreg'. + /// + /// + /// + public static bool IsValidPrefix(string prefix) + { + return HasSingleCase(prefix) && VALID_PREFIXES.Contains(prefix.ToLower()); + } + + /// + /// Derives an array from the given prefix to be used in the computation of the address checksum + /// + /// Network prefix. E.g.: 'bitcoincash' + /// + public static byte[] PrefixToByte5Array(string prefix) + { + var result = new byte[prefix.Length]; + int i = 0; + foreach (char c in prefix.ToCharArray()) + { + result[i++] = (byte)(c & 31); + } + return result; + } + + /// + /// Returns true if, and only if, the given string contains either uppercase or lowercase letters, but not both + /// + /// + /// + public static bool HasSingleCase(string str) + { + return str == str.ToLower() || str == str.ToUpper(); + } + + /// + /// Returns the bit representation of the length in bits of the given hash within the version byte + /// + /// Hash to encode represented as an array of 8-bit integers + /// + public static byte GetHashSizeBits(byte[] hash) + { + switch (hash.Length * 8) + { + case 160: + return 0; + case 192: + return 1; + case 224: + return 2; + case 256: + return 3; + case 320: + return 4; + case 384: + return 5; + case 448: + return 6; + case 512: + return 7; + default: + throw new Validation.ValidationError($"Invalid hash size: {hash.Length}"); + } + } + + /// + /// Retrieves the the length in bits of the encoded hash from its bit representation within the version byte + /// + /// + /// + public static int GetHashSize(byte versionByte) + { + switch (versionByte & 7) + { + case 0: + return 160; + case 1: + return 192; + case 2: + return 224; + case 3: + return 256; + case 4: + return 320; + case 5: + return 384; + case 6: + return 448; + case 7: + return 512; + default: + throw new Validation.ValidationError($"Invalid versionByte: {versionByte}"); + } + } + + /// + /// Returns the bit representation of the given type within the version byte + /// + /// Address type. Either 'P2PKH' or 'P2SH' + /// + public static byte GetTypeBits(string type) + { + switch (type) + { + case "P2PKH": + return 0; + case "P2SH": + return 8; + default: + throw new Validation.ValidationError($"Invalid type: {type}"); + } + } + + /// + /// Converts an array of 8-bit integers into an array of 5-bit integers, right-padding with zeroes if necessary + /// + /// + /// + public static byte[] ToByte5Array(byte[] data) + { + return ConvertBits.Convert(data, 8, 5); + } + + /// + /// Converts an array of 5-bit integers back into an array of 8-bit integers + /// removing extra zeroes left from padding if necessary. + /// Throws a ValidationError if input is not a zero-padded array of 8-bit integers + /// + /// + /// + public static byte[] FromByte5Array(byte[] data) + { + return ConvertBits.Convert(data, 5, 8, true); + } + + } + + internal static class ConvertBits + { + /// + /// Converts an array of integers made up of 'from' bits into an + /// array of integers made up of 'to' bits.The output array is + /// zero-padded if necessary, unless strict mode is true. + /// + /// data Array of integers made up of 'from' bits + /// from Length in bits of elements in the input array + /// to Length in bits of elements in the output array + /// strictMode Require the conversion to be completed without padding + /// + public static byte[] Convert(byte[] data, int from, int to, bool strictMode = false) + { + Validation.Validate(from > 0, "Invald 'from' parameter"); + Validation.Validate(to > 0, "Invald 'to' parameter"); + Validation.Validate(data.Length > 0, "Invald data"); + var d = data.Length * from / (double)to; + var length = strictMode ? (int)Math.Floor(d) : (int)Math.Ceiling(d); + var mask = (1 << to) - 1; + var result = new byte[length]; + var index = 0; + var accumulator = 0; + var bits = 0; + for (var i = 0; i < data.Length; ++i) + { + var value = data[i]; + Validation.Validate(0 <= value && (value >> from) == 0, $"Invalid value: {value}"); + accumulator = (accumulator << from) | value; + bits += from; + while (bits >= to) + { + bits -= to; + result[index] = (byte)((accumulator >> bits) & mask); + ++index; + } + } + if (!strictMode) + { + if (bits > 0) + { + result[index] = (byte)((accumulator << (to - bits)) & mask); + ++index; + } + } + else + { + Validation.Validate( + bits < from && ((accumulator << (to - bits)) & mask) == 0, + $"Input cannot be converted to {to} bits without padding, but strict mode was used" + ); + } + return result; + } + } + + internal static class Base32 + { + private static readonly char[] DIGITS; + private static Dictionary CHAR_MAP = new Dictionary(); + + static Base32() + { + DIGITS = "qpzry9x8gf2tvdw0s3jn54khce6mua7l".ToCharArray(); + for (int i = 0; i < DIGITS.Length; i++) CHAR_MAP[DIGITS[i]] = i; + } + + /// + /// Decodes the given base32-encoded string into an array of 5-bit integers + /// + /// + /// + public static byte[] Decode(string encoded) + { + if (encoded.Length == 0) + { + throw new CashaddrBase32EncoderException("Invalid encoded string"); + } + var result = new byte[encoded.Length]; + int next = 0; + foreach (char c in encoded.ToCharArray()) + { + if (!CHAR_MAP.ContainsKey(c)) + { + throw new CashaddrBase32EncoderException($"Invalid character: {c}"); + } + result[next++] = (byte)CHAR_MAP[c]; + } + return result; + } + + /// + /// Encodes the given array of 5-bit integers as a base32-encoded string + /// + /// data Array of integers between 0 and 31 inclusive + /// + public static string Encode(byte[] data) + { + if (data.Length == 0) + { + throw new CashaddrBase32EncoderException("Invalid data"); + } + string base32 = String.Empty; + for (var i = 0; i < data.Length; ++i) + { + var value = data[i]; + if (0 <= value && value < 32) + base32 += DIGITS[value]; + else + throw new CashaddrBase32EncoderException($"Invalid value: {value}"); + } + return base32; + } + + private class CashaddrBase32EncoderException : Exception + { + public CashaddrBase32EncoderException(string message) : base(message) + { + } + } + } + + internal static class Validation + { + public static void Validate(bool condition, string message) + { + if (!condition) + { + throw new ValidationError(message); + } + } + + internal class ValidationError : Exception + { + public ValidationError(string message) : base(message) + { + } + } + } + +} \ No newline at end of file diff --git a/src/Miningcore/Crypto/Hashing/Algorithms/YesPower_SugarChain.cs b/src/Miningcore/Crypto/Hashing/Algorithms/YesPower_SugarChain.cs new file mode 100644 index 00000000..bdee801d --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Algorithms/YesPower_SugarChain.cs @@ -0,0 +1,42 @@ +/* +Copyright 2017 Coin Foundry (coinfoundry.org) +Authors: Oliver Weichhold (oliver@weichhold.com) + +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. +*/ + +using System; +using Miningcore.Contracts; +using Miningcore.Native; + +namespace Miningcore.Crypto.Hashing.Algorithms +{ + public unsafe class YesPower_Sugarchain : IHashAlgorithm + { + public void Digest(ReadOnlySpan data, Span result, params object[] extra) + { + Contract.Requires(result.Length >= 32, $"{nameof(result)} must be greater or equal 32 bytes"); + + fixed (byte* input = data) + { + fixed (byte* output = result) + { + LibMultihash.yespower_sugarchain(input, output, (uint) data.Length); + } + } + } + } +} diff --git a/src/Miningcore/Native/LibMultihash.cs b/src/Miningcore/Native/LibMultihash.cs index d2fa2a96..c92ce919 100644 --- a/src/Miningcore/Native/LibMultihash.cs +++ b/src/Miningcore/Native/LibMultihash.cs @@ -112,6 +112,9 @@ public static unsafe class LibMultihash [DllImport("libmultihash", EntryPoint = "c11_export", CallingConvention = CallingConvention.Cdecl)] public static extern int c11(byte* input, void* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "yespower_sugarchain_export", CallingConvention = CallingConvention.Cdecl)] + public static extern int yespower_sugarchain(byte* input, void* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "x16r_export", CallingConvention = CallingConvention.Cdecl)] public static extern int x16r(byte* input, void* output, uint inputLength); diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index c2d96b33..4d988e46 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -35,6 +35,27 @@ "explorerTxLink": "https://www.blocktrail.com/BCC/tx/{0}", "explorerAccountLink": "https://www.blocktrail.com/BCC/address/{0}" }, + "devault": { + "name": "DeVault", + "symbol": "DVT", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "sha256d" + }, + "headerHasher": { + "hash": "sha256d" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "sha256d" } ] + }, + "extraPoolConfig":{ + "AddressType":"BechSegwit" + }, + "explorerBlockLink": "https://devault.llama.network/block/$height$", + "explorerTxLink": "https://devault.llama.network/tx/{0}", + "explorerAccountLink": "https://www.blocktrail.com/address/devault:{0}" + }, "namecoin": { "name": "Namecoin", "symbol": "NMC", diff --git a/src/Native/libmultihash/Makefile b/src/Native/libmultihash/Makefile index 0c01ea6c..f67c6d3a 100644 --- a/src/Native/libmultihash/Makefile +++ b/src/Native/libmultihash/Makefile @@ -12,7 +12,7 @@ OBJECTS = bcrypt.o blake.o blake2s.o c11.o dcrypt.o fresh.o lane.o \ sha3/sph_luffa.o sha3/sph_shabal.o sha3/sph_shavite.o sha3/sph_simd.o sha3/sph_skein.o sha3/sph_whirlpool.o \ sha3/sph_haval.o sha3/sph_sha2.o sha3/sph_sha2big.o sha3/sph_blake2s.o sha3/sm3.o sha3/panama.o \ sha3/extra.o sha3/gost_streebog.o sha3/sph_tiger.o sha3/SWIFFTX.o KeccakP-800-reference.o \ - shavite3.o skein.o x11.o x13.o x15.o x17.o x16r.o x16rv2.o x16s.o x21s.o odocrypt.o x25x.o \ + shavite3.o skein.o yespower_sugarchain.o x11.o x13.o x15.o x17.o x16r.o x16rv2.o x16s.o x21s.o odocrypt.o x25x.o \ Lyra2.o Lyra2RE.o Sponge.o geek.o \ equi/util.o equi/support/cleanse.o equi/random.o \ equi/uint256.o equi/arith_uint256.o equi/crypto/hmac_sha512.o \ diff --git a/src/Native/libmultihash/exports.cpp b/src/Native/libmultihash/exports.cpp index 7574bc2e..efdeed46 100644 --- a/src/Native/libmultihash/exports.cpp +++ b/src/Native/libmultihash/exports.cpp @@ -43,6 +43,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "c11.h" #include "Lyra2RE.h" #include "Lyra2.h" +#include "yespower_sugarchain.h" #include "x16r.h" #include "x16rv2.h" #include "x16s.h" @@ -214,10 +215,16 @@ extern "C" MODULE_API void lyra2rev3_export(const char* input, char* output) lyra2re3_hash(input, output); } +extern "C" MODULE_API void yespower_sugarchain_export(const char* input, char* output, uint32_t input_len) +{ + yespower_hash(input, output); +} + extern "C" MODULE_API void x16r_export(const char* input, char* output, uint32_t input_len) { x16r_hash(input, output, input_len); } + extern "C" MODULE_API void x16rv2_export(const char* input, char* output, uint32_t input_len) { x16rv2_hash(input, output,input_len); diff --git a/src/Native/libmultihash/libmultihash.vcxproj b/src/Native/libmultihash/libmultihash.vcxproj index e2a55f9b..9a227db1 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj +++ b/src/Native/libmultihash/libmultihash.vcxproj @@ -256,6 +256,7 @@ + @@ -344,6 +345,8 @@ + + diff --git a/src/Native/libmultihash/yespower_ref.c b/src/Native/libmultihash/yespower_ref.c new file mode 100644 index 00000000..6e61e5f0 --- /dev/null +++ b/src/Native/libmultihash/yespower_ref.c @@ -0,0 +1,580 @@ +/*- + * Copyright 2009 Colin Percival + * Copyright 2013-2018 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + * + * This is a proof-of-work focused fork of yescrypt, including reference and + * cut-down implementation of the obsolete yescrypt 0.5 (based off its first + * submission to PHC back in 2014) and a new proof-of-work specific variation + * known as yespower 1.0. The former is intended as an upgrade for + * cryptocurrencies that already use yescrypt 0.5 and the latter may be used + * as a further upgrade (hard fork) by those and other cryptocurrencies. The + * version of algorithm to use is requested through parameters, allowing for + * both algorithms to co-exist in client and miner implementations (such as in + * preparation for a hard-fork). + * + * This is the reference implementation. Its purpose is to provide a simple + * human- and machine-readable specification that implementations intended + * for actual use should be tested against. It is deliberately mostly not + * optimized, and it is not meant to be used in production. Instead, use + * yespower-opt.c. + */ + +#warning "This reference implementation is deliberately mostly not optimized. Use yespower-opt.c instead unless you're testing (against) the reference implementation on purpose." + +#include +#include +#include +#include + +#include "sha256.h" +#include "sysendian.h" + +#include "yespower.h" + +static void blkcpy(uint32_t *dst, const uint32_t *src, size_t count) +{ + do { + *dst++ = *src++; + } while (--count); +} + +static void blkxor(uint32_t *dst, const uint32_t *src, size_t count) +{ + do { + *dst++ ^= *src++; + } while (--count); +} + +/** + * salsa20(B): + * Apply the Salsa20 core to the provided block. + */ +static void salsa20(uint32_t B[16], uint32_t rounds) +{ + uint32_t x[16]; + size_t i; + + /* SIMD unshuffle */ + for (i = 0; i < 16; i++) + x[i * 5 % 16] = B[i]; + + for (i = 0; i < rounds; i += 2) { +#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) + /* Operate on columns */ + x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); + x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); + + x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); + x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); + + x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); + x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); + + x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); + x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); + + /* Operate on rows */ + x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); + x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); + + x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); + x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); + + x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); + x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); + + x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); + x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); +#undef R + } + + /* SIMD shuffle */ + for (i = 0; i < 16; i++) + B[i] += x[i * 5 % 16]; +} + +/** + * blockmix_salsa(B): + * Compute B = BlockMix_{salsa20, 1}(B). The input B must be 128 bytes in + * length. + */ +static void blockmix_salsa(uint32_t *B, uint32_t rounds) +{ + uint32_t X[16]; + size_t i; + + /* 1: X <-- B_{2r - 1} */ + blkcpy(X, &B[16], 16); + + /* 2: for i = 0 to 2r - 1 do */ + for (i = 0; i < 2; i++) { + /* 3: X <-- H(X xor B_i) */ + blkxor(X, &B[i * 16], 16); + salsa20(X, rounds); + + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + blkcpy(&B[i * 16], X, 16); + } +} + +/* + * These are tunable, but they must meet certain constraints and are part of + * what defines a yespower version. + */ +#define PWXsimple 2 +#define PWXgather 4 +/* Version 0.5 */ +#define PWXrounds_0_5 6 +#define Swidth_0_5 8 +/* Version 1.0 */ +#define PWXrounds_1_0 3 +#define Swidth_1_0 11 + +/* Derived values. Not tunable on their own. */ +#define PWXbytes (PWXgather * PWXsimple * 8) +#define PWXwords (PWXbytes / sizeof(uint32_t)) +#define rmin ((PWXbytes + 127) / 128) + +/* Runtime derived values. Not tunable on their own. */ +#define Swidth_to_Sbytes1(Swidth) ((1 << Swidth) * PWXsimple * 8) +#define Swidth_to_Smask(Swidth) (((1 << Swidth) - 1) * PWXsimple * 8) + +typedef struct { + yespower_version_t version; + uint32_t salsa20_rounds; + uint32_t PWXrounds, Swidth, Sbytes, Smask; + uint32_t *S; + uint32_t (*S0)[2], (*S1)[2], (*S2)[2]; + size_t w; +} pwxform_ctx_t; + +/** + * pwxform(B): + * Transform the provided block using the provided S-boxes. + */ +static void pwxform(uint32_t *B, pwxform_ctx_t *ctx) +{ + uint32_t (*X)[PWXsimple][2] = (uint32_t (*)[PWXsimple][2])B; + uint32_t (*S0)[2] = ctx->S0, (*S1)[2] = ctx->S1, (*S2)[2] = ctx->S2; + uint32_t Smask = ctx->Smask; + size_t w = ctx->w; + size_t i, j, k; + + /* 1: for i = 0 to PWXrounds - 1 do */ + for (i = 0; i < ctx->PWXrounds; i++) { + /* 2: for j = 0 to PWXgather - 1 do */ + for (j = 0; j < PWXgather; j++) { + uint32_t xl = X[j][0][0]; + uint32_t xh = X[j][0][1]; + uint32_t (*p0)[2], (*p1)[2]; + + /* 3: p0 <-- (lo(B_{j,0}) & Smask) / (PWXsimple * 8) */ + p0 = S0 + (xl & Smask) / sizeof(*S0); + /* 4: p1 <-- (hi(B_{j,0}) & Smask) / (PWXsimple * 8) */ + p1 = S1 + (xh & Smask) / sizeof(*S1); + + /* 5: for k = 0 to PWXsimple - 1 do */ + for (k = 0; k < PWXsimple; k++) { + uint64_t x, s0, s1; + + /* 6: B_{j,k} <-- (hi(B_{j,k}) * lo(B_{j,k}) + S0_{p0,k}) xor S1_{p1,k} */ + s0 = ((uint64_t)p0[k][1] << 32) + p0[k][0]; + s1 = ((uint64_t)p1[k][1] << 32) + p1[k][0]; + + xl = X[j][k][0]; + xh = X[j][k][1]; + + x = (uint64_t)xh * xl; + x += s0; + x ^= s1; + + X[j][k][0] = x; + X[j][k][1] = x >> 32; + } + + if (ctx->version != YESPOWER_0_5 && + (i == 0 || j < PWXgather / 2)) { + if (j & 1) { + for (k = 0; k < PWXsimple; k++) { + S1[w][0] = X[j][k][0]; + S1[w][1] = X[j][k][1]; + w++; + } + } else { + for (k = 0; k < PWXsimple; k++) { + S0[w + k][0] = X[j][k][0]; + S0[w + k][1] = X[j][k][1]; + } + } + } + } + } + + if (ctx->version != YESPOWER_0_5) { + /* 14: (S0, S1, S2) <-- (S2, S0, S1) */ + ctx->S0 = S2; + ctx->S1 = S0; + ctx->S2 = S1; + /* 15: w <-- w mod 2^Swidth */ + ctx->w = w & ((1 << ctx->Swidth) * PWXsimple - 1); + } +} + +/** + * blockmix_pwxform(B, ctx, r): + * Compute B = BlockMix_pwxform{salsa20, ctx, r}(B). The input B must be + * 128r bytes in length. + */ +static void blockmix_pwxform(uint32_t *B, pwxform_ctx_t *ctx, size_t r) +{ + uint32_t X[PWXwords]; + size_t r1, i; + + /* Convert 128-byte blocks to PWXbytes blocks */ + /* 1: r_1 <-- 128r / PWXbytes */ + r1 = 128 * r / PWXbytes; + + /* 2: X <-- B'_{r_1 - 1} */ + blkcpy(X, &B[(r1 - 1) * PWXwords], PWXwords); + + /* 3: for i = 0 to r_1 - 1 do */ + for (i = 0; i < r1; i++) { + /* 4: if r_1 > 1 */ + if (r1 > 1) { + /* 5: X <-- X xor B'_i */ + blkxor(X, &B[i * PWXwords], PWXwords); + } + + /* 7: X <-- pwxform(X) */ + pwxform(X, ctx); + + /* 8: B'_i <-- X */ + blkcpy(&B[i * PWXwords], X, PWXwords); + } + + /* 10: i <-- floor((r_1 - 1) * PWXbytes / 64) */ + i = (r1 - 1) * PWXbytes / 64; + + /* 11: B_i <-- H(B_i) */ + salsa20(&B[i * 16], ctx->salsa20_rounds); + +#if 1 /* No-op with our current pwxform settings, but do it to make sure */ + /* 12: for i = i + 1 to 2r - 1 do */ + for (i++; i < 2 * r; i++) { + /* 13: B_i <-- H(B_i xor B_{i-1}) */ + blkxor(&B[i * 16], &B[(i - 1) * 16], 16); + salsa20(&B[i * 16], ctx->salsa20_rounds); + } +#endif +} + +/** + * integerify(B, r): + * Return the result of parsing B_{2r-1} as a little-endian integer. + */ +static uint32_t integerify(const uint32_t *B, size_t r) +{ +/* + * Our 32-bit words are in host byte order. Also, they are SIMD-shuffled, but + * we only care about the least significant 32 bits anyway. + */ + const uint32_t *X = &B[(2 * r - 1) * 16]; + return X[0]; +} + +/** + * p2floor(x): + * Largest power of 2 not greater than argument. + */ +static uint32_t p2floor(uint32_t x) +{ + uint32_t y; + while ((y = x & (x - 1))) + x = y; + return x; +} + +/** + * wrap(x, i): + * Wrap x to the range 0 to i-1. + */ +static uint32_t wrap(uint32_t x, uint32_t i) +{ + uint32_t n = p2floor(i); + return (x & (n - 1)) + (i - n); +} + +/** + * smix1(B, r, N, V, X, ctx): + * Compute first loop of B = SMix_r(B, N). The input B must be 128r bytes in + * length; the temporary storage V must be 128rN bytes in length; the temporary + * storage X must be 128r bytes in length. + */ +static void smix1(uint32_t *B, size_t r, uint32_t N, + uint32_t *V, uint32_t *X, pwxform_ctx_t *ctx) +{ + size_t s = 32 * r; + uint32_t i, j; + size_t k; + + /* 1: X <-- B */ + for (k = 0; k < 2 * r; k++) + for (i = 0; i < 16; i++) + X[k * 16 + i] = le32dec(&B[k * 16 + (i * 5 % 16)]); + + if (ctx->version != YESPOWER_0_5) { + for (k = 1; k < r; k++) { + blkcpy(&X[k * 32], &X[(k - 1) * 32], 32); + blockmix_pwxform(&X[k * 32], ctx, 1); + } + } + + /* 2: for i = 0 to N - 1 do */ + for (i = 0; i < N; i++) { + /* 3: V_i <-- X */ + blkcpy(&V[i * s], X, s); + + if (i > 1) { + /* j <-- Wrap(Integerify(X), i) */ + j = wrap(integerify(X, r), i); + + /* X <-- X xor V_j */ + blkxor(X, &V[j * s], s); + } + + /* 4: X <-- H(X) */ + if (V != ctx->S) + blockmix_pwxform(X, ctx, r); + else + blockmix_salsa(X, ctx->salsa20_rounds); + } + + /* B' <-- X */ + for (k = 0; k < 2 * r; k++) + for (i = 0; i < 16; i++) + le32enc(&B[k * 16 + (i * 5 % 16)], X[k * 16 + i]); +} + +/** + * smix2(B, r, N, Nloop, V, X, ctx): + * Compute second loop of B = SMix_r(B, N). The input B must be 128r bytes in + * length; the temporary storage V must be 128rN bytes in length; the temporary + * storage X must be 128r bytes in length. The value N must be a power of 2 + * greater than 1. + */ +static void smix2(uint32_t *B, size_t r, uint32_t N, uint32_t Nloop, + uint32_t *V, uint32_t *X, pwxform_ctx_t *ctx) +{ + size_t s = 32 * r; + uint32_t i, j; + size_t k; + + /* X <-- B */ + for (k = 0; k < 2 * r; k++) + for (i = 0; i < 16; i++) + X[k * 16 + i] = le32dec(&B[k * 16 + (i * 5 % 16)]); + + /* 6: for i = 0 to N - 1 do */ + for (i = 0; i < Nloop; i++) { + /* 7: j <-- Integerify(X) mod N */ + j = integerify(X, r) & (N - 1); + + /* 8.1: X <-- X xor V_j */ + blkxor(X, &V[j * s], s); + /* V_j <-- X */ + if (Nloop != 2) + blkcpy(&V[j * s], X, s); + + /* 8.2: X <-- H(X) */ + blockmix_pwxform(X, ctx, r); + } + + /* 10: B' <-- X */ + for (k = 0; k < 2 * r; k++) + for (i = 0; i < 16; i++) + le32enc(&B[k * 16 + (i * 5 % 16)], X[k * 16 + i]); +} + +/** + * smix(B, r, N, p, t, V, X, ctx): + * Compute B = SMix_r(B, N). The input B must be 128rp bytes in length; the + * temporary storage V must be 128rN bytes in length; the temporary storage + * X must be 128r bytes in length. The value N must be a power of 2 and at + * least 16. + */ +static void smix(uint32_t *B, size_t r, uint32_t N, + uint32_t *V, uint32_t *X, pwxform_ctx_t *ctx) +{ + uint32_t Nloop_all = (N + 2) / 3; /* 1/3, round up */ + uint32_t Nloop_rw = Nloop_all; + + Nloop_all++; Nloop_all &= ~(uint32_t)1; /* round up to even */ + if (ctx->version == YESPOWER_0_5) { + Nloop_rw &= ~(uint32_t)1; /* round down to even */ + } else { + Nloop_rw++; Nloop_rw &= ~(uint32_t)1; /* round up to even */ + } + + smix1(B, 1, ctx->Sbytes / 128, ctx->S, X, ctx); + smix1(B, r, N, V, X, ctx); + smix2(B, r, N, Nloop_rw /* must be > 2 */, V, X, ctx); + smix2(B, r, N, Nloop_all - Nloop_rw /* 0 or 2 */, V, X, ctx); +} + +/** + * yespower(local, src, srclen, params, dst): + * Compute yespower(src[0 .. srclen - 1], N, r), to be checked for "< target". + * + * Return 0 on success; or -1 on error. + */ +int yespower(yespower_local_t *local, + const uint8_t *src, size_t srclen, + const yespower_params_t *params, yespower_binary_t *dst) +{ + yespower_version_t version = params->version; + uint32_t N = params->N; + uint32_t r = params->r; + const uint8_t *pers = params->pers; + size_t perslen = params->perslen; + int retval = -1; + size_t B_size, V_size; + uint32_t *B, *V, *X, *S; + pwxform_ctx_t ctx; + uint32_t sha256[8]; + + /* Sanity-check parameters */ + if ((version != YESPOWER_0_5 && version != YESPOWER_1_0) || + N < 1024 || N > 512 * 1024 || r < 8 || r > 32 || + (N & (N - 1)) != 0 || r < rmin || + (!pers && perslen)) { + errno = EINVAL; + return -1; + } + + /* Allocate memory */ + B_size = (size_t)128 * r; + V_size = B_size * N; + if ((V = malloc(V_size)) == NULL) + return -1; + if ((B = malloc(B_size)) == NULL) + goto free_V; + if ((X = malloc(B_size)) == NULL) + goto free_B; + ctx.version = version; + if (version == YESPOWER_0_5) { + ctx.salsa20_rounds = 8; + ctx.PWXrounds = PWXrounds_0_5; + ctx.Swidth = Swidth_0_5; + ctx.Sbytes = 2 * Swidth_to_Sbytes1(ctx.Swidth); + } else { + ctx.salsa20_rounds = 2; + ctx.PWXrounds = PWXrounds_1_0; + ctx.Swidth = Swidth_1_0; + ctx.Sbytes = 3 * Swidth_to_Sbytes1(ctx.Swidth); + } + if ((S = malloc(ctx.Sbytes)) == NULL) + goto free_X; + ctx.S = S; + ctx.S0 = (uint32_t (*)[2])S; + ctx.S1 = ctx.S0 + (1 << ctx.Swidth) * PWXsimple; + ctx.S2 = ctx.S1 + (1 << ctx.Swidth) * PWXsimple; + ctx.Smask = Swidth_to_Smask(ctx.Swidth); + ctx.w = 0; + + SHA256_Buf(src, srclen, (uint8_t *)sha256); + + if (version != YESPOWER_0_5) { + if (pers) { + src = pers; + srclen = perslen; + } else { + srclen = 0; + } + } + + /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ + PBKDF2_SHA256((uint8_t *)sha256, sizeof(sha256), + src, srclen, 1, (uint8_t *)B, B_size); + + blkcpy(sha256, B, sizeof(sha256) / sizeof(sha256[0])); + + /* 3: B_i <-- MF(B_i, N) */ + smix(B, r, N, V, X, &ctx); + + if (version == YESPOWER_0_5) { + /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ + PBKDF2_SHA256((uint8_t *)sha256, sizeof(sha256), + (uint8_t *)B, B_size, 1, (uint8_t *)dst, sizeof(*dst)); + + if (pers) { + HMAC_SHA256_Buf(dst, sizeof(*dst), pers, perslen, + (uint8_t *)sha256); + SHA256_Buf(sha256, sizeof(sha256), (uint8_t *)dst); + } + } else { + HMAC_SHA256_Buf((uint8_t *)B + B_size - 64, 64, + sha256, sizeof(sha256), (uint8_t *)dst); + } + + /* Success! */ + retval = 0; + + /* Free memory */ + free(S); +free_X: + free(X); +free_B: + free(B); +free_V: + free(V); + + return retval; +} + +int yespower_tls(const uint8_t *src, size_t srclen, + const yespower_params_t *params, yespower_binary_t *dst) +{ +/* The reference implementation doesn't use thread-local storage */ + return yespower(NULL, src, srclen, params, dst); +} + +int yespower_init_local(yespower_local_t *local) +{ +/* The reference implementation doesn't use the local structure */ + local->base = local->aligned = NULL; + local->base_size = local->aligned_size = 0; + return 0; +} + +int yespower_free_local(yespower_local_t *local) +{ +/* The reference implementation frees its memory in yespower() */ + (void)local; /* unused */ + return 0; +} \ No newline at end of file diff --git a/src/Native/libmultihash/yespower_sugarchain.c b/src/Native/libmultihash/yespower_sugarchain.c new file mode 100644 index 00000000..fc87fdbe --- /dev/null +++ b/src/Native/libmultihash/yespower_sugarchain.c @@ -0,0 +1,15 @@ +#include "yespower_sugarchain.h" +/* + * yespower for sugarchain + */ +int yespower_hash(const char *input, char *output) +{ + yespower_params_t params = { + .version = YESPOWER_1_0, + .N = 2048, + .r = 32, + .pers = "Satoshi Nakamoto 31/Oct/2008 Proof-of-work is essentially one-CPU-one-vote", + .perslen = 74 + }; + return yespower_tls(input, 80, ¶ms, (yespower_binary_t *) output); +} \ No newline at end of file diff --git a/src/Native/libmultihash/yespower_sugarchain.h b/src/Native/libmultihash/yespower_sugarchain.h new file mode 100644 index 00000000..3d29d152 --- /dev/null +++ b/src/Native/libmultihash/yespower_sugarchain.h @@ -0,0 +1,130 @@ +/*- + * Copyright 2009 Colin Percival + * Copyright 2013-2018 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + */ +#ifndef _YESPOWER_H_ +#define _YESPOWER_H_ + +#include +#include /* for size_t */ + +#ifdef __cplusplus +extern "C" { +#endif +int yespower_hash(const char *input, char *output); +/** + * Internal type used by the memory allocator. Please do not use it directly. + * Use yespower_local_t instead. + */ +typedef struct { + void *base, *aligned; + size_t base_size, aligned_size; +} yespower_region_t; + +/** + * Type for thread-local (RAM) data structure. + */ +typedef yespower_region_t yespower_local_t; + +/* + * Type for yespower algorithm version numbers. + */ +typedef enum { YESPOWER_0_5 = 5, YESPOWER_1_0 = 10 } yespower_version_t; + +/** + * yespower parameters combined into one struct. + */ +typedef struct { + yespower_version_t version; + uint32_t N, r; + const uint8_t *pers; + size_t perslen; +} yespower_params_t; + +/** + * A 256-bit yespower hash. + */ +typedef struct { + unsigned char uc[32]; +} yespower_binary_t; + +/** + * yespower_init_local(local): + * Initialize the thread-local (RAM) data structure. Actual memory allocation + * is currently fully postponed until a call to yespower(). + * + * Return 0 on success; or -1 on error. + * + * MT-safe as long as local is local to the thread. + */ +extern int yespower_init_local(yespower_local_t *local); + +/** + * yespower_free_local(local): + * Free memory that may have been allocated for an initialized thread-local + * (RAM) data structure. + * + * Return 0 on success; or -1 on error. + * + * MT-safe as long as local is local to the thread. + */ +extern int yespower_free_local(yespower_local_t *local); + +/** + * yespower(local, src, srclen, params, dst): + * Compute yespower(src[0 .. srclen - 1], N, r), to be checked for "< target". + * local is the thread-local data structure, allowing to preserve and reuse a + * memory allocation across calls, thereby reducing processing overhead. + * + * Return 0 on success; or -1 on error. + * + * local must be initialized with yespower_init_local(). + * + * MT-safe as long as local and dst are local to the thread. + */ +extern int yespower(yespower_local_t *local, + const uint8_t *src, size_t srclen, + const yespower_params_t *params, yespower_binary_t *dst); + +/** + * yespower_tls(src, srclen, params, dst): + * Compute yespower(src[0 .. srclen - 1], N, r), to be checked for "< target". + * The memory allocation is maintained internally using thread-local storage. + * + * Return 0 on success; or -1 on error. + * + * MT-safe as long as dst is local to the thread. + */ +extern int yespower_tls(const uint8_t *src, size_t srclen, + const yespower_params_t *params, yespower_binary_t *dst); + +#ifdef __cplusplus +} +#endif + +#endif /* !_YESPOWER_H_ */ \ No newline at end of file From 37cf7507fd4cf3df22fb63b33928dcc5bb88515e Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Tue, 24 Mar 2020 14:57:41 +0000 Subject: [PATCH 18/36] Set default addr type as cashaddr for dvt and bchabc --- src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs index af70bbd0..50ba6585 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs @@ -502,7 +502,7 @@ protected override async Task PostStartInitAsync(CancellationToken ct) // // Create pool address script from response //if(!isPoS) - poolAddressDestination = AddressToDestination(poolConfig.Address, poolConfig.Template.Symbol == "DVT" ? BitcoinAddressType.CashAddr : extraPoolConfig?.AddressType); + poolAddressDestination = AddressToDestination(poolConfig.Address, (poolConfig.Template.Symbol == "DVT" || poolConfig.Template.Symbol == "BCHABC" || poolConfig.Template.Symbol == "BCH" ) ? BitcoinAddressType.CashAddr : extraPoolConfig?.AddressType); // else // poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); From e042e9266bb49776dfd120776848ceed5cf1939c Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Tue, 24 Mar 2020 16:26:57 +0000 Subject: [PATCH 19/36] Add support for DVT coinbase_payload --- .../Blockchain/Bitcoin/BitcoinJob.cs | 76 ++++++++++++++++++- .../DaemonResponses/DevaultCoinbasePayload.cs | 22 ++++++ src/Miningcore/Configuration/ClusterConfig.cs | 3 + src/Miningcore/coins.json | 4 +- 4 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 src/Miningcore/Blockchain/Bitcoin/DaemonResponses/DevaultCoinbasePayload.cs diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 47ecd3da..e3028e5b 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -112,10 +112,11 @@ protected virtual void BuildCoinbase() scriptSigFinalBytes.Length); // output transaction - txOut = coin.HasMasterNodes ? - CreateMasternodeOutputTransaction() : - (coin.HasPayee ? CreatePayeeOutputTransaction() : CreateOutputTransaction()); - + txOut = coin.HasMasterNodes ? CreateMasternodeOutputTransaction() : (coin.HasPayee ? CreatePayeeOutputTransaction() : CreateOutputTransaction()); + if(coin.HasCoinbasePayload){ + //Build txOut with superblock and cold reward payees for DVT + txOut = CreatePayloadOutputTransaction(); + } // build coinbase initial using(var stream = new MemoryStream()) { @@ -532,6 +533,67 @@ protected virtual Money CreateMasternodeOutputs(Transaction tx, Money reward) #endregion // Masternodes + #region DevaultCoinbasePayload + + protected CoinbasePayloadBlockTemplateExtra coinbasepayloadParameters; + + protected virtual Transaction CreatePayloadOutputTransaction() + { + var blockReward = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); + rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); + + var tx = Transaction.Create(network); + + // outputs + rewardToPool = CreatePayloadOutputs(tx, blockReward); + + // Finally distribute remaining funds to pool + tx.Outputs.Insert(0, new TxOut(rewardToPool, poolAddressDestination)); + + return tx; + } + + protected virtual Money CreatePayloadOutputs(Transaction tx, Money reward) + { + if(coinbasepayloadParameters.CoinbasePayload != null) + { + CoinbasePayload[] coinbasepayloads; + if(coinbasepayloadParameters.CoinbasePayload.Type == JTokenType.Array) + coinbasepayloads = coinbasepayloadParameters.CoinbasePayload.ToObject(); + else + coinbasepayloads = new[] { coinbasepayloadParameters.CoinbasePayload.ToObject() }; + + foreach(var CoinbasePayee in coinbasepayloads) + { + if(!string.IsNullOrEmpty(CoinbasePayee.Payee)) + { + var payeeAddress = BitcoinUtils.AddressToDestination(CoinbasePayee.Payee, network); + var payeeReward = CoinbasePayee.Amount; + + reward -= payeeReward; + rewardToPool -= payeeReward; + + tx.Outputs.Add(payeeReward, payeeAddress); + } + } + } + + if(!string.IsNullOrEmpty(coinbasepayloadParameters.Payee)) + { + var payeeAddress = BitcoinUtils.AddressToDestination(coinbasepayloadParameters.Payee, network); + var payeeReward = coinbasepayloadParameters.PayeeAmount ?? (reward / 5); + + reward -= payeeReward; + rewardToPool -= payeeReward; + + tx.Outputs.Add(payeeReward, payeeAddress); + } + + return reward; + } + + #endregion // DevaultCoinbasePayload + #region API-Surface public BlockTemplate BlockTemplate { get; protected set; } @@ -584,6 +646,12 @@ public void Init(BlockTemplate blockTemplate, string jobId, txVersion = txVersion + ((uint) (txType << 16)); } } + if(coin.HasCoinbasePayload){ + + coinbasepayloadParameters = BlockTemplate.Extra.SafeExtensionDataAs(); + + + } if(coin.HasPayee) payeeParameters = BlockTemplate.Extra.SafeExtensionDataAs(); diff --git a/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/DevaultCoinbasePayload.cs b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/DevaultCoinbasePayload.cs new file mode 100644 index 00000000..63f01047 --- /dev/null +++ b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/DevaultCoinbasePayload.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Miningcore.Blockchain.Bitcoin.DaemonResponses +{ + public class CoinbasePayload + { + public string Payee { get; set; } + public string Script { get; set; } + public long Amount { get; set; } + } + + public class CoinbasePayloadBlockTemplateExtra : PayeeBlockTemplateExtra + { + [JsonProperty("coinbase_payload")] + public JToken CoinbasePayload { get; set; } + } + +} diff --git a/src/Miningcore/Configuration/ClusterConfig.cs b/src/Miningcore/Configuration/ClusterConfig.cs index 2ee4d099..67d064aa 100644 --- a/src/Miningcore/Configuration/ClusterConfig.cs +++ b/src/Miningcore/Configuration/ClusterConfig.cs @@ -164,6 +164,9 @@ public partial class BitcoinNetworkParams [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public bool HasMasterNodes { get; set; } + [JsonProperty("hasCoinbasePayload")] + public bool HasCoinbasePayload { get; set; } + [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] [DefaultValue(1.0d)] public double ShareMultiplier { get; set; } = 1.0d; diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 4d988e46..c879affd 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -49,9 +49,7 @@ "hash": "reverse", "args": [ { "hash": "sha256d" } ] }, - "extraPoolConfig":{ - "AddressType":"BechSegwit" - }, + "hasCoinbasePayload" : true, "explorerBlockLink": "https://devault.llama.network/block/$height$", "explorerTxLink": "https://devault.llama.network/tx/{0}", "explorerAccountLink": "https://www.blocktrail.com/address/devault:{0}" From 9b4c63c7b4a9fe928ef0bf44d5b37b3f7fb254e2 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Tue, 24 Mar 2020 16:33:36 +0000 Subject: [PATCH 20/36] Use CashAddrToDestination for DVT coinbase_payload txes --- src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index e3028e5b..911d2dd1 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -567,7 +567,7 @@ protected virtual Money CreatePayloadOutputs(Transaction tx, Money reward) { if(!string.IsNullOrEmpty(CoinbasePayee.Payee)) { - var payeeAddress = BitcoinUtils.AddressToDestination(CoinbasePayee.Payee, network); + var payeeAddress = BitcoinUtils.CashAddrToDestination(CoinbasePayee.Payee, network); var payeeReward = CoinbasePayee.Amount; reward -= payeeReward; @@ -580,7 +580,7 @@ protected virtual Money CreatePayloadOutputs(Transaction tx, Money reward) if(!string.IsNullOrEmpty(coinbasepayloadParameters.Payee)) { - var payeeAddress = BitcoinUtils.AddressToDestination(coinbasepayloadParameters.Payee, network); + var payeeAddress = BitcoinUtils.CashAddrToDestination(coinbasepayloadParameters.Payee, network); var payeeReward = coinbasepayloadParameters.PayeeAmount ?? (reward / 5); reward -= payeeReward; From 33f215159a4c0d84f4918c811ad43fe219628a65 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Tue, 24 Mar 2020 17:04:25 +0000 Subject: [PATCH 21/36] Remove extra payee code --- src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 911d2dd1..8e8b3d38 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -578,17 +578,6 @@ protected virtual Money CreatePayloadOutputs(Transaction tx, Money reward) } } - if(!string.IsNullOrEmpty(coinbasepayloadParameters.Payee)) - { - var payeeAddress = BitcoinUtils.CashAddrToDestination(coinbasepayloadParameters.Payee, network); - var payeeReward = coinbasepayloadParameters.PayeeAmount ?? (reward / 5); - - reward -= payeeReward; - rewardToPool -= payeeReward; - - tx.Outputs.Add(payeeReward, payeeAddress); - } - return reward; } From 2b638b4b43df986cd7a92b708280ecedec5e912d Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Fri, 17 Apr 2020 01:09:13 +0000 Subject: [PATCH 22/36] Add IDX handler and hashrate fix for x16v2 --- .../Api/Responses/GetPaymentsResponse.cs | 1 + .../Blockchain/Bitcoin/BitcoinConstants.cs | 3 +- .../Blockchain/Bitcoin/BitcoinJob.cs | 13 ++++---- .../Bitcoin/BitcoinPayoutHandler.cs | 12 +++---- .../Bitcoin/DaemonResponses/Founder.cs | 22 +++++++++++++ .../Bitcoin/DaemonResponses/Masternode.cs | 3 ++ src/Miningcore/Mining/StatsRecorder.cs | 33 +++++++++++-------- src/Miningcore/coins.json | 31 ++++++++++++++--- 8 files changed, 86 insertions(+), 32 deletions(-) create mode 100644 src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs diff --git a/src/Miningcore/Api/Responses/GetPaymentsResponse.cs b/src/Miningcore/Api/Responses/GetPaymentsResponse.cs index 459c43f3..f18035bf 100644 --- a/src/Miningcore/Api/Responses/GetPaymentsResponse.cs +++ b/src/Miningcore/Api/Responses/GetPaymentsResponse.cs @@ -25,6 +25,7 @@ namespace Miningcore.Api.Responses { public class Payment { + public long Id { get; set; } public string Coin { get; set; } public string Address { get; set; } public string AddressInfoLink { get; set; } diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs index 7790d9f2..cf345e8f 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs @@ -75,8 +75,9 @@ public class BitcoinConstants public const int ExtranoncePlaceHolderLength = 8; public const decimal SatoshisPerBitcoin = 100000000; public static double Pow2x32 = Math.Pow(2, 32); + public static double Pow2x42 = Math.Pow(2, 42); public static readonly BigInteger Diff1 = BigInteger.Parse("00ffff0000000000000000000000000000000000000000000000000000", NumberStyles.HexNumber); - public const int CoinbaseMinConfimations = 102; + public const int CoinbaseMinConfimations = 101; /// /// Pool-side mask for version-rolling (Overt ASIC-Boost) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 8e8b3d38..e8871e3d 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -494,10 +494,10 @@ protected virtual Money CreateMasternodeOutputs(Transaction tx, Money reward) { var payeeAddress = BitcoinUtils.AddressToDestination(masterNode.Payee, network); var payeeReward = masterNode.Amount; - - reward -= payeeReward; - rewardToPool -= payeeReward; - + if(!(poolConfig.Template.Symbol == "IDX" ||poolConfig.Template.Symbol == "XZC")){ + reward -= payeeReward; + rewardToPool -= payeeReward; + } tx.Outputs.Add(payeeReward, payeeAddress); } } @@ -520,10 +520,11 @@ protected virtual Money CreateMasternodeOutputs(Transaction tx, Money reward) if(!string.IsNullOrEmpty(masterNodeParameters.Payee)) { var payeeAddress = BitcoinUtils.AddressToDestination(masterNodeParameters.Payee, network); - var payeeReward = masterNodeParameters.PayeeAmount ?? (reward / 5); - + var payeeReward = masterNodeParameters.PayeeAmount; + if(!(poolConfig.Template.Symbol == "IDX" ||poolConfig.Template.Symbol == "XZC")){ reward -= payeeReward; rewardToPool -= payeeReward; + } tx.Outputs.Add(payeeReward, payeeAddress); } diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs index c3dcffed..1f1af0bc 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs @@ -163,7 +163,7 @@ public virtual async Task ClassifyBlocksAsync(Block[] blocks) // update progress var minConfirmations = extraPoolConfig?.MinimumConfirmations ?? BitcoinConstants.CoinbaseMinConfimations; block.ConfirmationProgress = Math.Min(1.0d, (double) transactionInfo.Confirmations / minConfirmations); - block.Reward = transactionInfo.Amount; // update actual block-reward from coinbase-tx + block.Reward = transactionInfo.Details[0].Amount; // update actual block-reward from coinbase-tx result.Add(block); messageBus.NotifyBlockConfirmationProgress(poolConfig.Id, block, coin); @@ -173,7 +173,7 @@ public virtual async Task ClassifyBlocksAsync(Block[] blocks) // matured and spendable coinbase transaction block.Status = BlockStatus.Confirmed; block.ConfirmationProgress = 1; - block.Reward = transactionInfo.Amount; // update actual block-reward from coinbase-tx + block.Reward = transactionInfo.Details[0].Amount; // update actual block-reward from coinbase-tx result.Add(block); logger.Info(() => $"[{LogCategory}] Unlocked block {block.BlockHeight} worth {FormatAmount(block.Reward)}"); @@ -242,14 +242,14 @@ public virtual async Task PayoutAsync(Balance[] balances) { args = new object[] { - string.Empty, // default account + "", // default account amounts, // addresses and associated amounts 1, // only spend funds covered by this many confirmations false, // Whether to add confirmations to transactions locked via InstantSend comment, // tx comment - subtractFeesFrom, // distribute transaction fee equally over all recipients - false, // use_is: Send this transaction as InstantSend - false, // Use anonymized funds only + subtractFeesFrom // distribute transaction fee equally over all recipients + // false, // use_is: Send this transaction as InstantSend + // false, // Use anonymized funds only }; } } diff --git a/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs new file mode 100644 index 00000000..f13d19ca --- /dev/null +++ b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Miningcore.Blockchain.Bitcoin.DaemonResponses +{ + public class Founder + { + public string Payee { get; set; } + public string Script { get; set; } + public long Amount { get; set; } + } + + public class FounderBlockTemplateExtra : PayeeBlockTemplateExtra + { + + [JsonProperty("founder")] + public Founder Founder { get; set; } + } +} diff --git a/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Masternode.cs b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Masternode.cs index 31f7e018..24dd7dd1 100644 --- a/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Masternode.cs +++ b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Masternode.cs @@ -23,6 +23,9 @@ public class MasterNodeBlockTemplateExtra : PayeeBlockTemplateExtra { public JToken Masternode { get; set; } + [JsonProperty("indexnode")] + private JToken Indexnode { set { Masternode = value; } } + [JsonProperty("masternode_payments_started")] public bool MasternodePaymentsStarted { get; set; } diff --git a/src/Miningcore/Mining/StatsRecorder.cs b/src/Miningcore/Mining/StatsRecorder.cs index 35a9e88d..0ac67b7e 100644 --- a/src/Miningcore/Mining/StatsRecorder.cs +++ b/src/Miningcore/Mining/StatsRecorder.cs @@ -5,13 +5,13 @@ using System.Linq; using System.Net.Sockets; using System.Threading; -using System.Threading.Tasks; +using System.Threading.Tasks; using Autofac; using AutoMapper; using Miningcore.Configuration; using Miningcore.Contracts; using Miningcore.Extensions; -using Miningcore.Messaging; +using Miningcore.Messaging; using Miningcore.Persistence; using Miningcore.Persistence.Model; using Miningcore.Persistence.Repositories; @@ -33,8 +33,8 @@ public StatsRecorder(IComponentContext ctx, { Contract.RequiresNonNull(ctx, nameof(ctx)); Contract.RequiresNonNull(clock, nameof(clock)); - Contract.RequiresNonNull(cf, nameof(cf)); - Contract.RequiresNonNull(messageBus, nameof(messageBus)); + Contract.RequiresNonNull(cf, nameof(cf)); + Contract.RequiresNonNull(messageBus, nameof(messageBus)); Contract.RequiresNonNull(mapper, nameof(mapper)); Contract.RequiresNonNull(shareRepo, nameof(shareRepo)); Contract.RequiresNonNull(statsRepo, nameof(statsRepo)); @@ -58,8 +58,8 @@ public StatsRecorder(IComponentContext ctx, private readonly IComponentContext ctx; private readonly IShareRepository shareRepo; private readonly CancellationTokenSource cts = new CancellationTokenSource(); - private readonly ConcurrentDictionary pools = new ConcurrentDictionary(); - private readonly TimeSpan interval = TimeSpan.FromMinutes(5); + private readonly ConcurrentDictionary pools = new ConcurrentDictionary(); + private readonly TimeSpan interval = TimeSpan.FromMinutes(1); private const int HashrateCalculationWindow = 1200; // seconds private const int MinHashrateCalculationWindow = 300; // seconds private const double HashrateBoostFactor = 1.1d; @@ -84,7 +84,7 @@ public void AttachPool(IMiningPool pool) public void Start() { Task.Run(async () => - { + { logger.Info(() => "Online"); // warm-up delay @@ -153,7 +153,9 @@ private async Task UpdatePoolHashratesAsync() var poolHashesAccumulated = result.Sum(x => x.Sum); var poolHashesCountAccumulated = result.Sum(x => x.Count); var poolHashrate = pool.HashrateFromShares(poolHashesAccumulated, windowActual) * HashrateBoostFactor; - + if(poolId == "indexchain"){ + poolHashrate *= 11.2; + } // update pool.PoolStats.ConnectedMiners = byMiner.Length; pool.PoolStats.PoolHashrate = (ulong) Math.Ceiling(poolHashrate); @@ -211,7 +213,7 @@ string buildKey(string miner, string worker = null) // calculate & update miner, worker hashrates foreach(var minerHashes in byMiner) - { + { double minerTotalHashrate = 0; await cf.RunTx(async (con, tx) => @@ -229,13 +231,16 @@ await cf.RunTx(async (con, tx) => if(windowActual >= MinHashrateCalculationWindow) { var hashrate = pool.HashrateFromShares(item.Sum, windowActual) * HashrateBoostFactor; + if(poolId == "indexchain"){ + hashrate *= 11.2; + } minerTotalHashrate += hashrate; // update stats.Hashrate = hashrate; stats.Worker = item.Worker; - stats.SharesPerSecond = (double) item.Count / windowActual; - + stats.SharesPerSecond = (double) item.Count / windowActual; + // persist await statsRepo.InsertMinerWorkerPerformanceStatsAsync(con, tx, stats); @@ -245,9 +250,9 @@ await cf.RunTx(async (con, tx) => // book keeping currentNonZeroMinerWorkers.Add(buildKey(stats.Miner, stats.Worker)); } - } - }); - + } + }); + messageBus.NotifyHashrateUpdated(pool.Config.Id, minerTotalHashrate, stats.Miner, null); } diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index c879affd..865246e3 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -327,11 +327,12 @@ } ] }, + "hasPayees":true, "hasMasterNodes": true, "shareMultiplier": 4096, - "explorerBlockLink": "https://chainz.cryptoid.info/dash/block.dws?$height$.htm", - "explorerTxLink": "https://chainz.cryptoid.info/dash/tx.dws?{0}.htm", - "explorerAccountLink": "https://chainz.cryptoid.info/dash/address.dws?{0}.htm" + "explorerBlockLink": "http://202.182.107.84/block/$hash$", + "explorerTxLink": "http://202.182.107.84/tx/{0}", + "explorerAccountLink": "http://202.182.107.84/address/{0}" }, "mooncoin": { "name": "MoonCoin", @@ -436,12 +437,32 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "x16s" + "hash": "x21s" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "x21s" } ] + }, + "shareMultiplier": 256, + "explorerBlockLink": "http://explorer.pigeoncoin.org/block/$hash$", + "explorerTxLink": "http://explorer.pigeoncoin.org/tx/{0}", + "explorerAccountLink": "http://explorer.pigeoncoin.org/address/{0}" + }, + "pigeoncoin-testnet": { + "name": "Pigeoncoin", + "symbol": "PGN", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "sha256d" + }, + "headerHasher": { + "hash": "x21s" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x16s" } ] + "args": [ { "hash": "x21s" } ] }, + "hasMasterNodes":true, "shareMultiplier": 256, "explorerBlockLink": "http://explorer.pigeoncoin.org/block/$hash$", "explorerTxLink": "http://explorer.pigeoncoin.org/tx/{0}", From 5f47bb62edfa8d22999d74c1f60400380df1ecfb Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Fri, 17 Apr 2020 21:44:57 +0000 Subject: [PATCH 23/36] Add PigeonCoin testnet code. --- .../Blockchain/Bitcoin/BitcoinJob.cs | 55 +++++++++++++++++-- .../Bitcoin/DaemonResponses/Founder.cs | 4 +- src/Miningcore/Configuration/ClusterConfig.cs | 3 + src/Miningcore/coins.json | 6 +- 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index e8871e3d..b1982f25 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -38,6 +38,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using Contract = Miningcore.Contracts.Contract; using Transaction = NBitcoin.Transaction; using Miningcore.Crypto.Hashing.Algorithms; + namespace Miningcore.Blockchain.Bitcoin { public class BitcoinJob @@ -112,7 +113,7 @@ protected virtual void BuildCoinbase() scriptSigFinalBytes.Length); // output transaction - txOut = coin.HasMasterNodes ? CreateMasternodeOutputTransaction() : (coin.HasPayee ? CreatePayeeOutputTransaction() : CreateOutputTransaction()); + txOut = (coin.HasMasterNodes) ? CreateMasternodeOutputTransaction() : (coin.HasPayee ? CreatePayeeOutputTransaction() : CreateOutputTransaction()); if(coin.HasCoinbasePayload){ //Build txOut with superblock and cold reward payees for DVT txOut = CreatePayloadOutputTransaction(); @@ -464,12 +465,13 @@ protected virtual Transaction CreateMasternodeOutputTransaction() { var blockReward = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); - var tx = Transaction.Create(network); // outputs rewardToPool = CreateMasternodeOutputs(tx, blockReward); - + //Now check if we need to pay founder fees Re PGN + if(coin.HasFounderFee) + rewardToPool = CreateFounderOutputs(tx,rewardToPool); // Finally distribute remaining funds to pool tx.Outputs.Insert(0, new TxOut(rewardToPool, poolAddressDestination)); @@ -583,6 +585,47 @@ protected virtual Money CreatePayloadOutputs(Transaction tx, Money reward) } #endregion // DevaultCoinbasePayload + + #region PigeoncoinDevFee + + protected FounderBlockTemplateExtra FounderParameters; + + protected virtual Money CreateFounderOutputs(Transaction tx, Money reward) + { + if(FounderParameters.Founder != null) + { + Founder[] founders; + if(FounderParameters.Founder.Type == JTokenType.Array) + founders = FounderParameters.Founder.ToObject(); + else + founders = new[] { FounderParameters.Founder.ToObject() }; + + foreach(var Founder in founders) + { + if(!string.IsNullOrEmpty(Founder.Payee)) + { + var payeeAddress = BitcoinUtils.AddressToDestination(Founder.Payee, network); + var payeeReward = Founder.Amount; + reward -= payeeReward; + rewardToPool -= payeeReward; + tx.Outputs.Add(payeeReward, payeeAddress); + } + } + } + + if(!string.IsNullOrEmpty(FounderParameters.Payee)) + { + var payeeAddress = BitcoinUtils.AddressToDestination(FounderParameters.Payee, network); + var payeeReward = FounderParameters.PayeeAmount; + reward -= payeeReward; + rewardToPool -= payeeReward; + tx.Outputs.Add(payeeReward, payeeAddress); + } + + return reward; + } + + #endregion // PigeoncoinDevFee #region API-Surface @@ -636,12 +679,12 @@ public void Init(BlockTemplate blockTemplate, string jobId, txVersion = txVersion + ((uint) (txType << 16)); } } - if(coin.HasCoinbasePayload){ - + if(coin.HasCoinbasePayload) coinbasepayloadParameters = BlockTemplate.Extra.SafeExtensionDataAs(); + if(coin.HasFounderFee) + FounderParameters = BlockTemplate.Extra.SafeExtensionDataAs(); - } if(coin.HasPayee) payeeParameters = BlockTemplate.Extra.SafeExtensionDataAs(); diff --git a/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs index f13d19ca..a75f1e34 100644 --- a/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs +++ b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs @@ -15,8 +15,6 @@ public class Founder public class FounderBlockTemplateExtra : PayeeBlockTemplateExtra { - - [JsonProperty("founder")] - public Founder Founder { get; set; } + public JToken Founder { get; set; } } } diff --git a/src/Miningcore/Configuration/ClusterConfig.cs b/src/Miningcore/Configuration/ClusterConfig.cs index 67d064aa..8b686267 100644 --- a/src/Miningcore/Configuration/ClusterConfig.cs +++ b/src/Miningcore/Configuration/ClusterConfig.cs @@ -167,6 +167,9 @@ public partial class BitcoinNetworkParams [JsonProperty("hasCoinbasePayload")] public bool HasCoinbasePayload { get; set; } + [JsonProperty("hasFounderFee")] + public bool HasFounderFee { get; set; } + [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] [DefaultValue(1.0d)] public double ShareMultiplier { get; set; } = 1.0d; diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 865246e3..3ff8c84b 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -327,7 +327,6 @@ } ] }, - "hasPayees":true, "hasMasterNodes": true, "shareMultiplier": 4096, "explorerBlockLink": "http://202.182.107.84/block/$hash$", @@ -449,8 +448,8 @@ "explorerAccountLink": "http://explorer.pigeoncoin.org/address/{0}" }, "pigeoncoin-testnet": { - "name": "Pigeoncoin", - "symbol": "PGN", + "name": "PigeoncoinTest", + "symbol": "PGNt", "family": "bitcoin", "coinbaseHasher": { "hash": "sha256d" @@ -462,6 +461,7 @@ "hash": "reverse", "args": [ { "hash": "x21s" } ] }, + "hasFounderFee":true, "hasMasterNodes":true, "shareMultiplier": 256, "explorerBlockLink": "http://explorer.pigeoncoin.org/block/$hash$", From fe6750cb3c14468b1338c0b70d756a5cabbf3532 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Thu, 23 Apr 2020 22:13:58 +0000 Subject: [PATCH 24/36] Add support for current PGN Mainnet --- src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs | 5 ++++- src/Miningcore/coins.json | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index b1982f25..c023a079 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -263,7 +263,10 @@ protected virtual Script GenerateScriptSigInitial() protected virtual Transaction CreateOutputTransaction() { rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); - + //Now check if we need to pay founder fees Re PGN pre-dash fork + if(coin.HasFounderFee) + rewardToPool = CreateFounderOutputs(tx,rewardToPool); + var tx = Transaction.Create(network); tx.Outputs.Add(rewardToPool, poolAddressDestination); diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 3ff8c84b..3b980c78 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -442,6 +442,7 @@ "hash": "reverse", "args": [ { "hash": "x21s" } ] }, + "hasFounderFee":true, "shareMultiplier": 256, "explorerBlockLink": "http://explorer.pigeoncoin.org/block/$hash$", "explorerTxLink": "http://explorer.pigeoncoin.org/tx/{0}", From be506132fa94e31a5144b8d1b71b5e544ca5d50a Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Thu, 23 Apr 2020 22:17:23 +0000 Subject: [PATCH 25/36] Fix error on devfee code for PGN Mainnet --- src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index c023a079..e4325de6 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -263,11 +263,11 @@ protected virtual Script GenerateScriptSigInitial() protected virtual Transaction CreateOutputTransaction() { rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); + + var tx = Transaction.Create(network); //Now check if we need to pay founder fees Re PGN pre-dash fork if(coin.HasFounderFee) rewardToPool = CreateFounderOutputs(tx,rewardToPool); - - var tx = Transaction.Create(network); tx.Outputs.Add(rewardToPool, poolAddressDestination); From 6c6b146de5347e815c9d386012388f62d48f251d Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Fri, 24 Apr 2020 16:31:50 +0000 Subject: [PATCH 26/36] Fix coinbase payload code --- src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index e4325de6..2ee215f9 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -576,14 +576,17 @@ protected virtual Money CreatePayloadOutputs(Transaction tx, Money reward) var payeeAddress = BitcoinUtils.CashAddrToDestination(CoinbasePayee.Payee, network); var payeeReward = CoinbasePayee.Amount; - reward -= payeeReward; - rewardToPool -= payeeReward; - tx.Outputs.Add(payeeReward, payeeAddress); } } } + if(!string.IsNullOrEmpty(coinbasepayloadParameters.Payee)) + { + var payeeAddress = BitcoinUtils.AddressToDestination(coinbasepayloadParameters.Payee, network); + var payeeReward = coinbasepayloadParameters.PayeeAmount; + tx.Outputs.Add(payeeReward, payeeAddress); + } return reward; } From 36dddcb28faf9616e478483af9db362608ec7c62 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Fri, 24 Apr 2020 20:01:26 +0000 Subject: [PATCH 27/36] use CashAddr for payee on coinbasepayload for DVT --- src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 2ee215f9..62981b87 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -582,7 +582,7 @@ protected virtual Money CreatePayloadOutputs(Transaction tx, Money reward) } if(!string.IsNullOrEmpty(coinbasepayloadParameters.Payee)) { - var payeeAddress = BitcoinUtils.AddressToDestination(coinbasepayloadParameters.Payee, network); + var payeeAddress = BitcoinUtils.CashAddrToDestination(coinbasepayloadParameters.Payee, network); var payeeReward = coinbasepayloadParameters.PayeeAmount; tx.Outputs.Add(payeeReward, payeeAddress); From 852cfde4ac220f40a2fb8d873a93d11aa32d47cc Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Fri, 24 Apr 2020 20:37:26 +0000 Subject: [PATCH 28/36] Dont hardcode addrtypes and minor fixes --- src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs index 50ba6585..0ff6ed7b 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs @@ -502,7 +502,7 @@ protected override async Task PostStartInitAsync(CancellationToken ct) // // Create pool address script from response //if(!isPoS) - poolAddressDestination = AddressToDestination(poolConfig.Address, (poolConfig.Template.Symbol == "DVT" || poolConfig.Template.Symbol == "BCHABC" || poolConfig.Template.Symbol == "BCH" ) ? BitcoinAddressType.CashAddr : extraPoolConfig?.AddressType); + poolAddressDestination = AddressToDestination(poolConfig.Address,extraPoolConfig?.AddressType); // else // poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); @@ -510,8 +510,8 @@ protected override async Task PostStartInitAsync(CancellationToken ct) if(clusterConfig.PaymentProcessing?.Enabled == true && poolConfig.PaymentProcessing?.Enabled == true) { // ensure pool owns wallet - //if (!validateAddressResponse.IsMine) - // logger.ThrowLogPoolStartupException($"Daemon does not own pool-address '{poolConfig.Address}'"); + if (!validateAddressResponse.IsMine) + logger.ThrowLogPoolStartupException($"Daemon does not own pool-address '{poolConfig.Address}'"); ConfigureRewards(); } From 7dd1c41d2412aa13fe64877470adc2dd47e92b0e Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Fri, 24 Apr 2020 21:18:49 +0000 Subject: [PATCH 29/36] Fix DVT address url and add sugarchain to coins --- src/Miningcore/coins.json | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 3b980c78..986d93cf 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -52,7 +52,25 @@ "hasCoinbasePayload" : true, "explorerBlockLink": "https://devault.llama.network/block/$height$", "explorerTxLink": "https://devault.llama.network/tx/{0}", - "explorerAccountLink": "https://www.blocktrail.com/address/devault:{0}" + "explorerAccountLink": "https://devault.llama.network/address/{0}" + }, + "sugarchain": { + "name": "Sugarchain", + "symbol": "SUGAR", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "yespower_sugarchain" + }, + "headerHasher": { + "hash": "sha256d" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "yespower_sugarchain" } ] + }, + "explorerBlockLink": "https://1explorer.sugarchain.org/block/$hash$", + "explorerTxLink": "https://1explorer.sugarchain.org/tx/{0}", + "explorerAccountLink": "https://1explorer.sugarchain.org/address/{0}" }, "namecoin": { "name": "Namecoin", From 7fcc663e7080696955335c6a2ccca62235c28fb4 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Fri, 24 Apr 2020 21:19:31 +0000 Subject: [PATCH 30/36] Fix coinbase hasher for sugarchain to sha256 --- src/Miningcore/coins.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 986d93cf..fbe62ffa 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -59,7 +59,7 @@ "symbol": "SUGAR", "family": "bitcoin", "coinbaseHasher": { - "hash": "yespower_sugarchain" + "hash": "sha256d" }, "headerHasher": { "hash": "sha256d" From 7994b2cddba2bf47f1d65b7ac429c99fabd18405 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Fri, 24 Apr 2020 23:50:26 +0000 Subject: [PATCH 31/36] Fix hashtype for Sugarchain --- src/Miningcore/coins.json | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index fbe62ffa..b3b7fef5 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -62,11 +62,19 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "sha256d" + "hash": "yespower_sugarchain" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "yespower_sugarchain" } ] + "args": [ { "hash": "sha256d" } ] + }, + "posBlockHasher": { + "hash": "reverse", + "args": [ + { + "hash": "yespower_sugarchain" + } + ] }, "explorerBlockLink": "https://1explorer.sugarchain.org/block/$hash$", "explorerTxLink": "https://1explorer.sugarchain.org/tx/{0}", From 2cf060db8b400563e3dbaea8fe23c95154f1d63a Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Sat, 25 Apr 2020 00:28:20 +0000 Subject: [PATCH 32/36] add sugarchain testnet as seperate entry --- src/Miningcore/coins.json | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index b3b7fef5..59d64619 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -80,6 +80,32 @@ "explorerTxLink": "https://1explorer.sugarchain.org/tx/{0}", "explorerAccountLink": "https://1explorer.sugarchain.org/address/{0}" }, + "sugarchain-testnet": { + "name": "TSugarchain", + "symbol": "tSUGAR", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "sha256d" + }, + "headerHasher": { + "hash": "yespower_sugarchain" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "sha256d" } ] + }, + "posBlockHasher": { + "hash": "reverse", + "args": [ + { + "hash": "yespower_sugarchain" + } + ] + }, + "explorerBlockLink": "https://1explorer.sugarchain.org/block/$hash$", + "explorerTxLink": "https://1explorer.sugarchain.org/tx/{0}", + "explorerAccountLink": "https://1explorer.sugarchain.org/address/{0}" + }, "namecoin": { "name": "Namecoin", "symbol": "NMC", From d56dc7bb0970293acb19ce7a403796649bd39c65 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Sat, 25 Apr 2020 12:15:13 +0000 Subject: [PATCH 33/36] add BechPrefix to extrapoolconfig --- src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs | 2 +- src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs | 4 ++-- .../Bitcoin/Configuration/BitcoinPoolConfigExtra.cs | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs index 0ff6ed7b..8f797f80 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs @@ -562,7 +562,7 @@ protected virtual IDestination AddressToDestination(string address, BitcoinAddre switch(addressType.Value) { case BitcoinAddressType.BechSegwit: - return BitcoinUtils.BechSegwitAddressToDestination(poolConfig.Address, network); + return BitcoinUtils.BechSegwitAddressToDestination(poolConfig.Address, network,extraPoolConfig?.BechPrefix); case BitcoinAddressType.CashAddr: return BitcoinUtils.CashAddrToDestination(poolConfig.Address, network); diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs index 444b89de..7635074e 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs @@ -49,9 +49,9 @@ public static IDestination AddressToDestination(string address, Network expected return result; } - public static IDestination BechSegwitAddressToDestination(string address, Network expectedNetwork) + public static IDestination BechSegwitAddressToDestination(string address, Network expectedNetwork,string bechPrefix) { - var encoder = expectedNetwork.GetBech32Encoder(Bech32Type.WITNESS_PUBKEY_ADDRESS, true); + var encoder = Encoders.Bech32(bechPrefix); var decoded = encoder.Decode(address, out var witVersion); var result = new WitKeyId(decoded); diff --git a/src/Miningcore/Blockchain/Bitcoin/Configuration/BitcoinPoolConfigExtra.cs b/src/Miningcore/Blockchain/Bitcoin/Configuration/BitcoinPoolConfigExtra.cs index d3dbed7b..9f89d71a 100644 --- a/src/Miningcore/Blockchain/Bitcoin/Configuration/BitcoinPoolConfigExtra.cs +++ b/src/Miningcore/Blockchain/Bitcoin/Configuration/BitcoinPoolConfigExtra.cs @@ -27,6 +27,11 @@ public class BitcoinPoolConfigExtra { public BitcoinAddressType AddressType { get; set; } = BitcoinAddressType.Legacy; + /// + /// Set bech32 prefix if it is not the standard bech prefix of btc + /// + public string BechPrefix {get;set;} = "bc"; + /// /// Maximum number of tracked jobs. /// Default: 12 - you should increase this value if your blockrefreshinterval is higher than 300ms From 6ee34db7e5e3c3a1ea115b1f2880e67034fd9f58 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Sat, 25 Apr 2020 14:04:50 +0000 Subject: [PATCH 34/36] Fix yesPower_sugarchain hash code --- src/Miningcore/coins.json | 2 + src/Native/libmultihash/Makefile | 2 +- src/Native/libmultihash/exports.cpp | 2 +- src/Native/libmultihash/libmultihash.vcxproj | 9 +- src/Native/libmultihash/sha256.c | 646 ++++++++++++++++++ src/Native/libmultihash/sha256.h | 511 +++----------- src/Native/libmultihash/yespower/sysendian.h | 94 +++ .../yespower-opt.c} | 19 +- .../libmultihash/yespower/yespower-platform.c | 107 +++ .../{ => yespower}/yespower_sugarchain.c | 0 .../{ => yespower}/yespower_sugarchain.h | 0 11 files changed, 966 insertions(+), 426 deletions(-) create mode 100644 src/Native/libmultihash/sha256.c create mode 100644 src/Native/libmultihash/yespower/sysendian.h rename src/Native/libmultihash/{yespower_ref.c => yespower/yespower-opt.c} (97%) create mode 100644 src/Native/libmultihash/yespower/yespower-platform.c rename src/Native/libmultihash/{ => yespower}/yespower_sugarchain.c (100%) rename src/Native/libmultihash/{ => yespower}/yespower_sugarchain.h (100%) diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 59d64619..cf649ea5 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -76,6 +76,7 @@ } ] }, + "shareMultipler":4194304, "explorerBlockLink": "https://1explorer.sugarchain.org/block/$hash$", "explorerTxLink": "https://1explorer.sugarchain.org/tx/{0}", "explorerAccountLink": "https://1explorer.sugarchain.org/address/{0}" @@ -102,6 +103,7 @@ } ] }, + "shareMultipler":4194304, "explorerBlockLink": "https://1explorer.sugarchain.org/block/$hash$", "explorerTxLink": "https://1explorer.sugarchain.org/tx/{0}", "explorerAccountLink": "https://1explorer.sugarchain.org/address/{0}" diff --git a/src/Native/libmultihash/Makefile b/src/Native/libmultihash/Makefile index f67c6d3a..42079841 100644 --- a/src/Native/libmultihash/Makefile +++ b/src/Native/libmultihash/Makefile @@ -12,7 +12,7 @@ OBJECTS = bcrypt.o blake.o blake2s.o c11.o dcrypt.o fresh.o lane.o \ sha3/sph_luffa.o sha3/sph_shabal.o sha3/sph_shavite.o sha3/sph_simd.o sha3/sph_skein.o sha3/sph_whirlpool.o \ sha3/sph_haval.o sha3/sph_sha2.o sha3/sph_sha2big.o sha3/sph_blake2s.o sha3/sm3.o sha3/panama.o \ sha3/extra.o sha3/gost_streebog.o sha3/sph_tiger.o sha3/SWIFFTX.o KeccakP-800-reference.o \ - shavite3.o skein.o yespower_sugarchain.o x11.o x13.o x15.o x17.o x16r.o x16rv2.o x16s.o x21s.o odocrypt.o x25x.o \ + shavite3.o skein.o sha256.o yespower/yespower_sugarchain.o yespower/yespower-opt.o yespower/yespower-platform.o x11.o x13.o x15.o x17.o x16r.o x16rv2.o x16s.o x21s.o odocrypt.o x25x.o \ Lyra2.o Lyra2RE.o Sponge.o geek.o \ equi/util.o equi/support/cleanse.o equi/random.o \ equi/uint256.o equi/arith_uint256.o equi/crypto/hmac_sha512.o \ diff --git a/src/Native/libmultihash/exports.cpp b/src/Native/libmultihash/exports.cpp index efdeed46..7c4b0f4f 100644 --- a/src/Native/libmultihash/exports.cpp +++ b/src/Native/libmultihash/exports.cpp @@ -43,7 +43,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "c11.h" #include "Lyra2RE.h" #include "Lyra2.h" -#include "yespower_sugarchain.h" +#include "yespower/yespower_sugarchain.h" #include "x16r.h" #include "x16rv2.h" #include "x16s.h" diff --git a/src/Native/libmultihash/libmultihash.vcxproj b/src/Native/libmultihash/libmultihash.vcxproj index 9a227db1..b7092505 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj +++ b/src/Native/libmultihash/libmultihash.vcxproj @@ -256,7 +256,8 @@ - + + @@ -314,6 +315,7 @@ + @@ -345,8 +347,9 @@ - - + + + diff --git a/src/Native/libmultihash/sha256.c b/src/Native/libmultihash/sha256.c new file mode 100644 index 00000000..8a1b26d1 --- /dev/null +++ b/src/Native/libmultihash/sha256.c @@ -0,0 +1,646 @@ +/*- + * Copyright 2005-2016 Colin Percival + * Copyright 2016-2018 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#define insecure_memzero(buf, len) /* empty */ +#include "yespower/sysendian.h" + +#include "sha256.h" + +#ifdef __ICC +/* Miscompile with icc 14.0.0 (at least), so don't use restrict there */ +#define restrict +#elif __STDC_VERSION__ >= 199901L +/* Have restrict */ +#elif defined(__GNUC__) +#define restrict __restrict +#else +#define restrict +#endif + +/* + * Encode a length len*2 vector of (uint32_t) into a length len*8 vector of + * (uint8_t) in big-endian form. + */ +static void +be32enc_vect(uint8_t * dst, const uint32_t * src, size_t len) +{ + + /* Encode vector, two words at a time. */ + do { + be32enc(&dst[0], src[0]); + be32enc(&dst[4], src[1]); + src += 2; + dst += 8; + } while (--len); +} + +/* + * Decode a big-endian length len*8 vector of (uint8_t) into a length + * len*2 vector of (uint32_t). + */ +static void +be32dec_vect(uint32_t * dst, const uint8_t * src, size_t len) +{ + + /* Decode vector, two words at a time. */ + do { + dst[0] = be32dec(&src[0]); + dst[1] = be32dec(&src[4]); + src += 8; + dst += 2; + } while (--len); +} + +/* SHA256 round constants. */ +static const uint32_t Krnd[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/* Elementary functions used by SHA256 */ +#define Ch(x, y, z) ((x & (y ^ z)) ^ z) +#define Maj(x, y, z) ((x & (y | z)) | (y & z)) +#define SHR(x, n) (x >> n) +#define ROTR(x, n) ((x >> n) | (x << (32 - n))) +#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) +#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) + +/* SHA256 round function */ +#define RND(a, b, c, d, e, f, g, h, k) \ + h += S1(e) + Ch(e, f, g) + k; \ + d += h; \ + h += S0(a) + Maj(a, b, c); + +/* Adjusted round function for rotating state */ +#define RNDr(S, W, i, ii) \ + RND(S[(64 - i) % 8], S[(65 - i) % 8], \ + S[(66 - i) % 8], S[(67 - i) % 8], \ + S[(68 - i) % 8], S[(69 - i) % 8], \ + S[(70 - i) % 8], S[(71 - i) % 8], \ + W[i + ii] + Krnd[i + ii]) + +/* Message schedule computation */ +#define MSCH(W, ii, i) \ + W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii] + +/* + * SHA256 block compression function. The 256-bit state is transformed via + * the 512-bit input block to produce a new state. + */ +static void +SHA256_Transform(uint32_t state[static restrict 8], + const uint8_t block[static restrict 64], + uint32_t W[static restrict 64], uint32_t S[static restrict 8]) +{ + int i; + + /* 1. Prepare the first part of the message schedule W. */ + be32dec_vect(W, block, 8); + + /* 2. Initialize working variables. */ + memcpy(S, state, 32); + + /* 3. Mix. */ + for (i = 0; i < 64; i += 16) { + RNDr(S, W, 0, i); + RNDr(S, W, 1, i); + RNDr(S, W, 2, i); + RNDr(S, W, 3, i); + RNDr(S, W, 4, i); + RNDr(S, W, 5, i); + RNDr(S, W, 6, i); + RNDr(S, W, 7, i); + RNDr(S, W, 8, i); + RNDr(S, W, 9, i); + RNDr(S, W, 10, i); + RNDr(S, W, 11, i); + RNDr(S, W, 12, i); + RNDr(S, W, 13, i); + RNDr(S, W, 14, i); + RNDr(S, W, 15, i); + + if (i == 48) + break; + MSCH(W, 0, i); + MSCH(W, 1, i); + MSCH(W, 2, i); + MSCH(W, 3, i); + MSCH(W, 4, i); + MSCH(W, 5, i); + MSCH(W, 6, i); + MSCH(W, 7, i); + MSCH(W, 8, i); + MSCH(W, 9, i); + MSCH(W, 10, i); + MSCH(W, 11, i); + MSCH(W, 12, i); + MSCH(W, 13, i); + MSCH(W, 14, i); + MSCH(W, 15, i); + } + + /* 4. Mix local working variables into global state. */ + state[0] += S[0]; + state[1] += S[1]; + state[2] += S[2]; + state[3] += S[3]; + state[4] += S[4]; + state[5] += S[5]; + state[6] += S[6]; + state[7] += S[7]; +} + +static const uint8_t PAD[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* Add padding and terminating bit-count. */ +static void +SHA256_Pad(SHA256_CTX * ctx, uint32_t tmp32[static restrict 72]) +{ + size_t r; + + /* Figure out how many bytes we have buffered. */ + r = (ctx->count >> 3) & 0x3f; + + /* Pad to 56 mod 64, transforming if we finish a block en route. */ + if (r < 56) { + /* Pad to 56 mod 64. */ + memcpy(&ctx->buf[r], PAD, 56 - r); + } else { + /* Finish the current block and mix. */ + memcpy(&ctx->buf[r], PAD, 64 - r); + SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]); + + /* The start of the final block is all zeroes. */ + memset(&ctx->buf[0], 0, 56); + } + + /* Add the terminating bit-count. */ + be64enc(&ctx->buf[56], ctx->count); + + /* Mix in the final block. */ + SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]); +} + +/* Magic initialization constants. */ +static const uint32_t initial_state[8] = { + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 +}; + +/** + * SHA256_Init(ctx): + * Initialize the SHA256 context ${ctx}. + */ +void +SHA256_Init(SHA256_CTX * ctx) +{ + + /* Zero bits processed so far. */ + ctx->count = 0; + + /* Initialize state. */ + memcpy(ctx->state, initial_state, sizeof(initial_state)); +} + +/** + * SHA256_Update(ctx, in, len): + * Input ${len} bytes from ${in} into the SHA256 context ${ctx}. + */ +static void +_SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len, + uint32_t tmp32[static restrict 72]) +{ + uint32_t r; + const uint8_t * src = in; + + /* Return immediately if we have nothing to do. */ + if (len == 0) + return; + + /* Number of bytes left in the buffer from previous updates. */ + r = (ctx->count >> 3) & 0x3f; + + /* Update number of bits. */ + ctx->count += (uint64_t)(len) << 3; + + /* Handle the case where we don't need to perform any transforms. */ + if (len < 64 - r) { + memcpy(&ctx->buf[r], src, len); + return; + } + + /* Finish the current block. */ + memcpy(&ctx->buf[r], src, 64 - r); + SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]); + src += 64 - r; + len -= 64 - r; + + /* Perform complete blocks. */ + while (len >= 64) { + SHA256_Transform(ctx->state, src, &tmp32[0], &tmp32[64]); + src += 64; + len -= 64; + } + + /* Copy left over data into buffer. */ + memcpy(ctx->buf, src, len); +} + +/* Wrapper function for intermediate-values sanitization. */ +void +SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len) +{ + uint32_t tmp32[72]; + + /* Call the real function. */ + _SHA256_Update(ctx, in, len, tmp32); + + /* Clean the stack. */ + insecure_memzero(tmp32, 288); +} + +/** + * SHA256_Final(digest, ctx): + * Output the SHA256 hash of the data input to the context ${ctx} into the + * buffer ${digest}. + */ +static void +_SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx, + uint32_t tmp32[static restrict 72]) +{ + + /* Add padding. */ + SHA256_Pad(ctx, tmp32); + + /* Write the hash. */ + be32enc_vect(digest, ctx->state, 4); +} + +/* Wrapper function for intermediate-values sanitization. */ +void +SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx) +{ + uint32_t tmp32[72]; + + /* Call the real function. */ + _SHA256_Final(digest, ctx, tmp32); + + /* Clear the context state. */ + insecure_memzero(ctx, sizeof(SHA256_CTX)); + + /* Clean the stack. */ + insecure_memzero(tmp32, 288); +} + +/** + * SHA256_Buf(in, len, digest): + * Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}. + */ +void +SHA256_Buf(const void * in, size_t len, uint8_t digest[32]) +{ + SHA256_CTX ctx; + uint32_t tmp32[72]; + + SHA256_Init(&ctx); + _SHA256_Update(&ctx, in, len, tmp32); + _SHA256_Final(digest, &ctx, tmp32); + + /* Clean the stack. */ + insecure_memzero(&ctx, sizeof(SHA256_CTX)); + insecure_memzero(tmp32, 288); +} + +/** + * HMAC_SHA256_Init(ctx, K, Klen): + * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from + * ${K}. + */ +static void +_HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen, + uint32_t tmp32[static restrict 72], uint8_t pad[static restrict 64], + uint8_t khash[static restrict 32]) +{ + const uint8_t * K = _K; + size_t i; + + /* If Klen > 64, the key is really SHA256(K). */ + if (Klen > 64) { + SHA256_Init(&ctx->ictx); + _SHA256_Update(&ctx->ictx, K, Klen, tmp32); + _SHA256_Final(khash, &ctx->ictx, tmp32); + K = khash; + Klen = 32; + } + + /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ + SHA256_Init(&ctx->ictx); + memset(pad, 0x36, 64); + for (i = 0; i < Klen; i++) + pad[i] ^= K[i]; + _SHA256_Update(&ctx->ictx, pad, 64, tmp32); + + /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ + SHA256_Init(&ctx->octx); + memset(pad, 0x5c, 64); + for (i = 0; i < Klen; i++) + pad[i] ^= K[i]; + _SHA256_Update(&ctx->octx, pad, 64, tmp32); +} + +/* Wrapper function for intermediate-values sanitization. */ +void +HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) +{ + uint32_t tmp32[72]; + uint8_t pad[64]; + uint8_t khash[32]; + + /* Call the real function. */ + _HMAC_SHA256_Init(ctx, _K, Klen, tmp32, pad, khash); + + /* Clean the stack. */ + insecure_memzero(tmp32, 288); + insecure_memzero(khash, 32); + insecure_memzero(pad, 64); +} + +/** + * HMAC_SHA256_Update(ctx, in, len): + * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}. + */ +static void +_HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len, + uint32_t tmp32[static restrict 72]) +{ + + /* Feed data to the inner SHA256 operation. */ + _SHA256_Update(&ctx->ictx, in, len, tmp32); +} + +/* Wrapper function for intermediate-values sanitization. */ +void +HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len) +{ + uint32_t tmp32[72]; + + /* Call the real function. */ + _HMAC_SHA256_Update(ctx, in, len, tmp32); + + /* Clean the stack. */ + insecure_memzero(tmp32, 288); +} + +/** + * HMAC_SHA256_Final(digest, ctx): + * Output the HMAC-SHA256 of the data input to the context ${ctx} into the + * buffer ${digest}. + */ +static void +_HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx, + uint32_t tmp32[static restrict 72], uint8_t ihash[static restrict 32]) +{ + + /* Finish the inner SHA256 operation. */ + _SHA256_Final(ihash, &ctx->ictx, tmp32); + + /* Feed the inner hash to the outer SHA256 operation. */ + _SHA256_Update(&ctx->octx, ihash, 32, tmp32); + + /* Finish the outer SHA256 operation. */ + _SHA256_Final(digest, &ctx->octx, tmp32); +} + +/* Wrapper function for intermediate-values sanitization. */ +void +HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx) +{ + uint32_t tmp32[72]; + uint8_t ihash[32]; + + /* Call the real function. */ + _HMAC_SHA256_Final(digest, ctx, tmp32, ihash); + + /* Clean the stack. */ + insecure_memzero(tmp32, 288); + insecure_memzero(ihash, 32); +} + +/** + * HMAC_SHA256_Buf(K, Klen, in, len, digest): + * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of + * length ${Klen}, and write the result to ${digest}. + */ +void +HMAC_SHA256_Buf(const void * K, size_t Klen, const void * in, size_t len, + uint8_t digest[32]) +{ + HMAC_SHA256_CTX ctx; + uint32_t tmp32[72]; + uint8_t tmp8[96]; + + _HMAC_SHA256_Init(&ctx, K, Klen, tmp32, &tmp8[0], &tmp8[64]); + _HMAC_SHA256_Update(&ctx, in, len, tmp32); + _HMAC_SHA256_Final(digest, &ctx, tmp32, &tmp8[0]); + + /* Clean the stack. */ + insecure_memzero(&ctx, sizeof(HMAC_SHA256_CTX)); + insecure_memzero(tmp32, 288); + insecure_memzero(tmp8, 96); +} + +/* Add padding and terminating bit-count, but don't invoke Transform yet. */ +static int +SHA256_Pad_Almost(SHA256_CTX * ctx, uint8_t len[static restrict 8], + uint32_t tmp32[static restrict 72]) +{ + uint32_t r; + + r = (ctx->count >> 3) & 0x3f; + if (r >= 56) + return -1; + + /* + * Convert length to a vector of bytes -- we do this now rather + * than later because the length will change after we pad. + */ + be64enc(len, ctx->count); + + /* Add 1--56 bytes so that the resulting length is 56 mod 64. */ + _SHA256_Update(ctx, PAD, 56 - r, tmp32); + + /* Add the terminating bit-count. */ + ctx->buf[63] = len[7]; + _SHA256_Update(ctx, len, 7, tmp32); + + return 0; +} + +/** + * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): + * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and + * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). + */ +void +PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, + size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) +{ + HMAC_SHA256_CTX Phctx, PShctx, hctx; + uint32_t tmp32[72]; + union { + uint8_t tmp8[96]; + uint32_t state[8]; + } u; + size_t i; + uint8_t ivec[4]; + uint8_t U[32]; + uint8_t T[32]; + uint64_t j; + int k; + size_t clen; + + /* Sanity-check. */ + assert(dkLen <= 32 * (size_t)(UINT32_MAX)); + + if (c == 1 && (dkLen & 31) == 0 && (saltlen & 63) <= 51) { + uint32_t oldcount; + uint8_t * ivecp; + + /* Compute HMAC state after processing P and S. */ + _HMAC_SHA256_Init(&hctx, passwd, passwdlen, + tmp32, &u.tmp8[0], &u.tmp8[64]); + _HMAC_SHA256_Update(&hctx, salt, saltlen, tmp32); + + /* Prepare ictx padding. */ + oldcount = hctx.ictx.count & (0x3f << 3); + _HMAC_SHA256_Update(&hctx, "\0\0\0", 4, tmp32); + if ((hctx.ictx.count & (0x3f << 3)) < oldcount || + SHA256_Pad_Almost(&hctx.ictx, u.tmp8, tmp32)) + goto generic; /* Can't happen due to saltlen check */ + ivecp = hctx.ictx.buf + (oldcount >> 3); + + /* Prepare octx padding. */ + hctx.octx.count += 32 << 3; + SHA256_Pad_Almost(&hctx.octx, u.tmp8, tmp32); + + /* Iterate through the blocks. */ + for (i = 0; i * 32 < dkLen; i++) { + /* Generate INT(i + 1). */ + be32enc(ivecp, (uint32_t)(i + 1)); + + /* Compute U_1 = PRF(P, S || INT(i)). */ + memcpy(u.state, hctx.ictx.state, sizeof(u.state)); + SHA256_Transform(u.state, hctx.ictx.buf, + &tmp32[0], &tmp32[64]); + be32enc_vect(hctx.octx.buf, u.state, 4); + memcpy(u.state, hctx.octx.state, sizeof(u.state)); + SHA256_Transform(u.state, hctx.octx.buf, + &tmp32[0], &tmp32[64]); + be32enc_vect(&buf[i * 32], u.state, 4); + } + + goto cleanup; + } + +generic: + /* Compute HMAC state after processing P. */ + _HMAC_SHA256_Init(&Phctx, passwd, passwdlen, + tmp32, &u.tmp8[0], &u.tmp8[64]); + + /* Compute HMAC state after processing P and S. */ + memcpy(&PShctx, &Phctx, sizeof(HMAC_SHA256_CTX)); + _HMAC_SHA256_Update(&PShctx, salt, saltlen, tmp32); + + /* Iterate through the blocks. */ + for (i = 0; i * 32 < dkLen; i++) { + /* Generate INT(i + 1). */ + be32enc(ivec, (uint32_t)(i + 1)); + + /* Compute U_1 = PRF(P, S || INT(i)). */ + memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); + _HMAC_SHA256_Update(&hctx, ivec, 4, tmp32); + _HMAC_SHA256_Final(T, &hctx, tmp32, u.tmp8); + + if (c > 1) { + /* T_i = U_1 ... */ + memcpy(U, T, 32); + + for (j = 2; j <= c; j++) { + /* Compute U_j. */ + memcpy(&hctx, &Phctx, sizeof(HMAC_SHA256_CTX)); + _HMAC_SHA256_Update(&hctx, U, 32, tmp32); + _HMAC_SHA256_Final(U, &hctx, tmp32, u.tmp8); + + /* ... xor U_j ... */ + for (k = 0; k < 32; k++) + T[k] ^= U[k]; + } + } + + /* Copy as many bytes as necessary into buf. */ + clen = dkLen - i * 32; + if (clen > 32) + clen = 32; + memcpy(&buf[i * 32], T, clen); + } + + /* Clean the stack. */ + insecure_memzero(&Phctx, sizeof(HMAC_SHA256_CTX)); + insecure_memzero(&PShctx, sizeof(HMAC_SHA256_CTX)); + insecure_memzero(U, 32); + insecure_memzero(T, 32); + +cleanup: + insecure_memzero(&hctx, sizeof(HMAC_SHA256_CTX)); + insecure_memzero(tmp32, 288); + insecure_memzero(&u, sizeof(u)); +} \ No newline at end of file diff --git a/src/Native/libmultihash/sha256.h b/src/Native/libmultihash/sha256.h index 5858f659..4b909912 100644 --- a/src/Native/libmultihash/sha256.h +++ b/src/Native/libmultihash/sha256.h @@ -1,440 +1,129 @@ -#ifndef SHA256_H -#define SHA256_H - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include "stdint.h" -#else -#include -#endif - -#include - -static __inline uint32_t -be32dec(const void *pp) -{ - const uint8_t *p = (uint8_t const *)pp; - - return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + - ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); -} +/*- + * Copyright 2005-2016 Colin Percival + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ -static __inline void -be32enc(void *pp, uint32_t x) -{ - uint8_t * p = (uint8_t *)pp; +#ifndef _SHA256_H_ +#define _SHA256_H_ - p[3] = x & 0xff; - p[2] = (x >> 8) & 0xff; - p[1] = (x >> 16) & 0xff; - p[0] = (x >> 24) & 0xff; -} +#include +#include -static __inline uint32_t -le32dec(const void *pp) -{ - const uint8_t *p = (uint8_t const *)pp; +#ifdef __cplusplus +extern "C" { +#endif - return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + - ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); -} +/* + * Use #defines in order to avoid namespace collisions with anyone else's + * SHA256 code (e.g., the code in OpenSSL). + */ +#define SHA256_Init libcperciva_SHA256_Init +#define SHA256_Update libcperciva_SHA256_Update +#define SHA256_Final libcperciva_SHA256_Final +#define SHA256_Buf libcperciva_SHA256_Buf +#define SHA256_CTX libcperciva_SHA256_CTX +#define HMAC_SHA256_Init libcperciva_HMAC_SHA256_Init +#define HMAC_SHA256_Update libcperciva_HMAC_SHA256_Update +#define HMAC_SHA256_Final libcperciva_HMAC_SHA256_Final +#define HMAC_SHA256_Buf libcperciva_HMAC_SHA256_Buf +#define HMAC_SHA256_CTX libcperciva_HMAC_SHA256_CTX + +/* Context structure for SHA256 operations. */ +typedef struct { + uint32_t state[8]; + uint64_t count; + uint8_t buf[64]; +} SHA256_CTX; -static __inline void -le32enc(void *pp, uint32_t x) -{ - uint8_t * p = (uint8_t *)pp; +/** + * SHA256_Init(ctx): + * Initialize the SHA256 context ${ctx}. + */ +void SHA256_Init(SHA256_CTX *); - p[0] = x & 0xff; - p[1] = (x >> 8) & 0xff; - p[2] = (x >> 16) & 0xff; - p[3] = (x >> 24) & 0xff; -} +/** + * SHA256_Update(ctx, in, len): + * Input ${len} bytes from ${in} into the SHA256 context ${ctx}. + */ +void SHA256_Update(SHA256_CTX *, const void *, size_t); +/** + * SHA256_Final(digest, ctx): + * Output the SHA256 hash of the data input to the context ${ctx} into the + * buffer ${digest}. + */ +void SHA256_Final(uint8_t[32], SHA256_CTX *); -typedef struct SHA256Context { - uint32_t state[8]; - uint32_t count[2]; - unsigned char buf[64]; -} SHA256_CTX; +/** + * SHA256_Buf(in, len, digest): + * Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}. + */ +void SHA256_Buf(const void *, size_t, uint8_t[32]); -typedef struct HMAC_SHA256Context { +/* Context structure for HMAC-SHA256 operations. */ +typedef struct { SHA256_CTX ictx; SHA256_CTX octx; } HMAC_SHA256_CTX; -/* - * Encode a length len/4 vector of (uint32_t) into a length len vector of - * (unsigned char) in big-endian form. Assumes len is a multiple of 4. +/** + * HMAC_SHA256_Init(ctx, K, Klen): + * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from + * ${K}. */ -static void -be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len) -{ - size_t i; - - for (i = 0; i < len / 4; i++) - be32enc(dst + i * 4, src[i]); -} +void HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); -/* - * Decode a big-endian length len vector of (unsigned char) into a length - * len/4 vector of (uint32_t). Assumes len is a multiple of 4. +/** + * HMAC_SHA256_Update(ctx, in, len): + * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}. */ -static void -be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len) -{ - size_t i; - - for (i = 0; i < len / 4; i++) - dst[i] = be32dec(src + i * 4); -} - -/* Elementary functions used by SHA256 */ -#define Ch(x, y, z) ((x & (y ^ z)) ^ z) -#define Maj(x, y, z) ((x & (y | z)) | (y & z)) -#define SHR(x, n) (x >> n) -#define ROTR(x, n) ((x >> n) | (x << (32 - n))) -#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) -#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) -#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) -#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) +void HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); -/* SHA256 round function */ -#define RND(a, b, c, d, e, f, g, h, k) \ - t0 = h + S1(e) + Ch(e, f, g) + k; \ - t1 = S0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - -/* Adjusted round function for rotating state */ -#define RNDr(S, W, i, k) \ - RND(S[(64 - i) % 8], S[(65 - i) % 8], \ - S[(66 - i) % 8], S[(67 - i) % 8], \ - S[(68 - i) % 8], S[(69 - i) % 8], \ - S[(70 - i) % 8], S[(71 - i) % 8], \ - W[i] + k) - -/* - * SHA256 block compression function. The 256-bit state is transformed via - * the 512-bit input block to produce a new state. +/** + * HMAC_SHA256_Final(digest, ctx): + * Output the HMAC-SHA256 of the data input to the context ${ctx} into the + * buffer ${digest}. */ -static void -SHA256_Transform(uint32_t * state, const unsigned char block[64]) -{ - uint32_t W[64]; - uint32_t S[8]; - uint32_t t0, t1; - int i; - - /* 1. Prepare message schedule W. */ - be32dec_vect(W, block, 64); - for (i = 16; i < 64; i++) - W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; - - /* 2. Initialize working variables. */ - memcpy(S, state, 32); - - /* 3. Mix. */ - RNDr(S, W, 0, 0x428a2f98); - RNDr(S, W, 1, 0x71374491); - RNDr(S, W, 2, 0xb5c0fbcf); - RNDr(S, W, 3, 0xe9b5dba5); - RNDr(S, W, 4, 0x3956c25b); - RNDr(S, W, 5, 0x59f111f1); - RNDr(S, W, 6, 0x923f82a4); - RNDr(S, W, 7, 0xab1c5ed5); - RNDr(S, W, 8, 0xd807aa98); - RNDr(S, W, 9, 0x12835b01); - RNDr(S, W, 10, 0x243185be); - RNDr(S, W, 11, 0x550c7dc3); - RNDr(S, W, 12, 0x72be5d74); - RNDr(S, W, 13, 0x80deb1fe); - RNDr(S, W, 14, 0x9bdc06a7); - RNDr(S, W, 15, 0xc19bf174); - RNDr(S, W, 16, 0xe49b69c1); - RNDr(S, W, 17, 0xefbe4786); - RNDr(S, W, 18, 0x0fc19dc6); - RNDr(S, W, 19, 0x240ca1cc); - RNDr(S, W, 20, 0x2de92c6f); - RNDr(S, W, 21, 0x4a7484aa); - RNDr(S, W, 22, 0x5cb0a9dc); - RNDr(S, W, 23, 0x76f988da); - RNDr(S, W, 24, 0x983e5152); - RNDr(S, W, 25, 0xa831c66d); - RNDr(S, W, 26, 0xb00327c8); - RNDr(S, W, 27, 0xbf597fc7); - RNDr(S, W, 28, 0xc6e00bf3); - RNDr(S, W, 29, 0xd5a79147); - RNDr(S, W, 30, 0x06ca6351); - RNDr(S, W, 31, 0x14292967); - RNDr(S, W, 32, 0x27b70a85); - RNDr(S, W, 33, 0x2e1b2138); - RNDr(S, W, 34, 0x4d2c6dfc); - RNDr(S, W, 35, 0x53380d13); - RNDr(S, W, 36, 0x650a7354); - RNDr(S, W, 37, 0x766a0abb); - RNDr(S, W, 38, 0x81c2c92e); - RNDr(S, W, 39, 0x92722c85); - RNDr(S, W, 40, 0xa2bfe8a1); - RNDr(S, W, 41, 0xa81a664b); - RNDr(S, W, 42, 0xc24b8b70); - RNDr(S, W, 43, 0xc76c51a3); - RNDr(S, W, 44, 0xd192e819); - RNDr(S, W, 45, 0xd6990624); - RNDr(S, W, 46, 0xf40e3585); - RNDr(S, W, 47, 0x106aa070); - RNDr(S, W, 48, 0x19a4c116); - RNDr(S, W, 49, 0x1e376c08); - RNDr(S, W, 50, 0x2748774c); - RNDr(S, W, 51, 0x34b0bcb5); - RNDr(S, W, 52, 0x391c0cb3); - RNDr(S, W, 53, 0x4ed8aa4a); - RNDr(S, W, 54, 0x5b9cca4f); - RNDr(S, W, 55, 0x682e6ff3); - RNDr(S, W, 56, 0x748f82ee); - RNDr(S, W, 57, 0x78a5636f); - RNDr(S, W, 58, 0x84c87814); - RNDr(S, W, 59, 0x8cc70208); - RNDr(S, W, 60, 0x90befffa); - RNDr(S, W, 61, 0xa4506ceb); - RNDr(S, W, 62, 0xbef9a3f7); - RNDr(S, W, 63, 0xc67178f2); - - /* 4. Mix local working variables into global state */ - for (i = 0; i < 8; i++) - state[i] += S[i]; - - /* Clean the stack. */ - memset(W, 0, 256); - memset(S, 0, 32); - t0 = t1 = 0; -} - -static unsigned char PAD[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; +void HMAC_SHA256_Final(uint8_t[32], HMAC_SHA256_CTX *); -/* SHA-256 initialization. Begins a SHA-256 operation. */ -static void -SHA256_Init(SHA256_CTX * ctx) -{ - - /* Zero bits processed so far */ - ctx->count[0] = ctx->count[1] = 0; - - /* Magic initialization constants */ - ctx->state[0] = 0x6A09E667; - ctx->state[1] = 0xBB67AE85; - ctx->state[2] = 0x3C6EF372; - ctx->state[3] = 0xA54FF53A; - ctx->state[4] = 0x510E527F; - ctx->state[5] = 0x9B05688C; - ctx->state[6] = 0x1F83D9AB; - ctx->state[7] = 0x5BE0CD19; -} - -/* Add bytes into the hash */ -static void -SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len) -{ - uint32_t bitlen[2]; - uint32_t r; - const unsigned char *src = in; - - /* Number of bytes left in the buffer from previous updates */ - r = (ctx->count[1] >> 3) & 0x3f; - - /* Convert the length into a number of bits */ - bitlen[1] = ((uint32_t)len) << 3; - bitlen[0] = (uint32_t)(len >> 29); - - /* Update number of bits */ - if ((ctx->count[1] += bitlen[1]) < bitlen[1]) - ctx->count[0]++; - ctx->count[0] += bitlen[0]; - - /* Handle the case where we don't need to perform any transforms */ - if (len < 64 - r) { - memcpy(&ctx->buf[r], src, len); - return; - } - - /* Finish the current block */ - memcpy(&ctx->buf[r], src, 64 - r); - SHA256_Transform(ctx->state, ctx->buf); - src += 64 - r; - len -= 64 - r; - - /* Perform complete blocks */ - while (len >= 64) { - SHA256_Transform(ctx->state, src); - src += 64; - len -= 64; - } - - /* Copy left over data into buffer */ - memcpy(ctx->buf, src, len); -} - -/* Add padding and terminating bit-count. */ -static void -SHA256_Pad(SHA256_CTX * ctx) -{ - unsigned char len[8]; - uint32_t r, plen; - - /* - * Convert length to a vector of bytes -- we do this now rather - * than later because the length will change after we pad. - */ - be32enc_vect(len, ctx->count, 8); - - /* Add 1--64 bytes so that the resulting length is 56 mod 64 */ - r = (ctx->count[1] >> 3) & 0x3f; - plen = (r < 56) ? (56 - r) : (120 - r); - SHA256_Update(ctx, PAD, (size_t)plen); - - /* Add the terminating bit-count */ - SHA256_Update(ctx, len, 8); -} - -/* - * SHA-256 finalization. Pads the input data, exports the hash value, - * and clears the context state. +/** + * HMAC_SHA256_Buf(K, Klen, in, len, digest): + * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of + * length ${Klen}, and write the result to ${digest}. */ -static void -SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx) -{ - - /* Add padding */ - SHA256_Pad(ctx); - - /* Write the hash */ - be32enc_vect(digest, ctx->state, 32); - - /* Clear the context state */ - memset((void *)ctx, 0, sizeof(*ctx)); -} - -/* Initialize an HMAC-SHA256 operation with the given key. */ -static void -HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) -{ - unsigned char pad[64]; - unsigned char khash[32]; - const unsigned char * K = _K; - size_t i; - - /* If Klen > 64, the key is really SHA256(K). */ - if (Klen > 64) { - SHA256_Init(&ctx->ictx); - SHA256_Update(&ctx->ictx, K, Klen); - SHA256_Final(khash, &ctx->ictx); - K = khash; - Klen = 32; - } - - /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ - SHA256_Init(&ctx->ictx); - memset(pad, 0x36, 64); - for (i = 0; i < Klen; i++) - pad[i] ^= K[i]; - SHA256_Update(&ctx->ictx, pad, 64); - - /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ - SHA256_Init(&ctx->octx); - memset(pad, 0x5c, 64); - for (i = 0; i < Klen; i++) - pad[i] ^= K[i]; - SHA256_Update(&ctx->octx, pad, 64); - - /* Clean the stack. */ - memset(khash, 0, 32); -} - -/* Add bytes to the HMAC-SHA256 operation. */ -static void -HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len) -{ - - /* Feed data to the inner SHA256 operation. */ - SHA256_Update(&ctx->ictx, in, len); -} - -/* Finish an HMAC-SHA256 operation. */ -static void -HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx) -{ - unsigned char ihash[32]; - - /* Finish the inner SHA256 operation. */ - SHA256_Final(ihash, &ctx->ictx); - - /* Feed the inner hash to the outer SHA256 operation. */ - SHA256_Update(&ctx->octx, ihash, 32); - - /* Finish the outer SHA256 operation. */ - SHA256_Final(digest, &ctx->octx); - - /* Clean the stack. */ - memset(ihash, 0, 32); -} +void HMAC_SHA256_Buf(const void *, size_t, const void *, size_t, uint8_t[32]); /** * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). */ -static void -PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, - size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) -{ - HMAC_SHA256_CTX PShctx, hctx; - size_t i; - uint8_t ivec[4]; - uint8_t U[32]; - uint8_t T[32]; - uint64_t j; - int k; - size_t clen; - - /* Compute HMAC state after processing P and S. */ - HMAC_SHA256_Init(&PShctx, passwd, passwdlen); - HMAC_SHA256_Update(&PShctx, salt, saltlen); - - /* Iterate through the blocks. */ - for (i = 0; i * 32 < dkLen; i++) { - /* Generate INT(i + 1). */ - be32enc(ivec, (uint32_t)(i + 1)); - - /* Compute U_1 = PRF(P, S || INT(i)). */ - memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); - HMAC_SHA256_Update(&hctx, ivec, 4); - HMAC_SHA256_Final(U, &hctx); +void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, + uint64_t, uint8_t *, size_t); - /* T_i = U_1 ... */ - memcpy(T, U, 32); - - for (j = 2; j <= c; j++) { - /* Compute U_j. */ - HMAC_SHA256_Init(&hctx, passwd, passwdlen); - HMAC_SHA256_Update(&hctx, U, 32); - HMAC_SHA256_Final(U, &hctx); - - /* ... xor U_j ... */ - for (k = 0; k < 32; k++) - T[k] ^= U[k]; - } - - /* Copy as many bytes as necessary into buf. */ - clen = dkLen - i * 32; - if (clen > 32) - clen = 32; - memcpy(&buf[i * 32], T, clen); - } - - /* Clean PShctx, since we never called _Final on it. */ - memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); +#ifdef __cplusplus } #endif + +#endif /* !_SHA256_H_ */ \ No newline at end of file diff --git a/src/Native/libmultihash/yespower/sysendian.h b/src/Native/libmultihash/yespower/sysendian.h new file mode 100644 index 00000000..bf2215a3 --- /dev/null +++ b/src/Native/libmultihash/yespower/sysendian.h @@ -0,0 +1,94 @@ +/*- + * Copyright 2007-2014 Colin Percival + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SYSENDIAN_H_ +#define _SYSENDIAN_H_ + +#include + +/* Avoid namespace collisions with BSD . */ +#define be32dec libcperciva_be32dec +#define be32enc libcperciva_be32enc +#define be64enc libcperciva_be64enc +#define le32dec libcperciva_le32dec +#define le32enc libcperciva_le32enc + +static inline uint32_t +be32dec(const void * pp) +{ + const uint8_t * p = (uint8_t const *)pp; + + return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + + ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); +} + +static inline void +be32enc(void * pp, uint32_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[3] = x & 0xff; + p[2] = (x >> 8) & 0xff; + p[1] = (x >> 16) & 0xff; + p[0] = (x >> 24) & 0xff; +} + +static inline void +be64enc(void * pp, uint64_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[7] = x & 0xff; + p[6] = (x >> 8) & 0xff; + p[5] = (x >> 16) & 0xff; + p[4] = (x >> 24) & 0xff; + p[3] = (x >> 32) & 0xff; + p[2] = (x >> 40) & 0xff; + p[1] = (x >> 48) & 0xff; + p[0] = (x >> 56) & 0xff; +} + +static inline uint32_t +le32dec(const void * pp) +{ + const uint8_t * p = (uint8_t const *)pp; + + return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + + ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); +} + +static inline void +le32enc(void * pp, uint32_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; +} + +#endif /* !_SYSENDIAN_H_ */ \ No newline at end of file diff --git a/src/Native/libmultihash/yespower_ref.c b/src/Native/libmultihash/yespower/yespower-opt.c similarity index 97% rename from src/Native/libmultihash/yespower_ref.c rename to src/Native/libmultihash/yespower/yespower-opt.c index 6e61e5f0..c22b894b 100644 --- a/src/Native/libmultihash/yespower_ref.c +++ b/src/Native/libmultihash/yespower/yespower-opt.c @@ -30,7 +30,7 @@ * This is a proof-of-work focused fork of yescrypt, including reference and * cut-down implementation of the obsolete yescrypt 0.5 (based off its first * submission to PHC back in 2014) and a new proof-of-work specific variation - * known as yespower 1.0. The former is intended as an upgrade for + * known as yespower 0.9. The former is intended as an upgrade for * cryptocurrencies that already use yescrypt 0.5 and the latter may be used * as a further upgrade (hard fork) by those and other cryptocurrencies. The * version of algorithm to use is requested through parameters, allowing for @@ -51,10 +51,10 @@ #include #include -#include "sha256.h" +#include "../sha256.h" #include "sysendian.h" -#include "yespower.h" +#include "yespower_sugarchain.h" static void blkcpy(uint32_t *dst, const uint32_t *src, size_t count) { @@ -152,9 +152,9 @@ static void blockmix_salsa(uint32_t *B, uint32_t rounds) /* Version 0.5 */ #define PWXrounds_0_5 6 #define Swidth_0_5 8 -/* Version 1.0 */ -#define PWXrounds_1_0 3 -#define Swidth_1_0 11 +/* Version 0.9 */ +#define PWXrounds_0_9 3 +#define Swidth_0_9 11 /* Derived values. Not tunable on their own. */ #define PWXbytes (PWXgather * PWXsimple * 8) @@ -469,7 +469,7 @@ int yespower(yespower_local_t *local, uint32_t sha256[8]; /* Sanity-check parameters */ - if ((version != YESPOWER_0_5 && version != YESPOWER_1_0) || + if ((version != YESPOWER_0_5) || N < 1024 || N > 512 * 1024 || r < 8 || r > 32 || (N & (N - 1)) != 0 || r < rmin || (!pers && perslen)) { @@ -494,8 +494,8 @@ int yespower(yespower_local_t *local, ctx.Sbytes = 2 * Swidth_to_Sbytes1(ctx.Swidth); } else { ctx.salsa20_rounds = 2; - ctx.PWXrounds = PWXrounds_1_0; - ctx.Swidth = Swidth_1_0; + ctx.PWXrounds = PWXrounds_0_9; + ctx.Swidth = Swidth_0_9; ctx.Sbytes = 3 * Swidth_to_Sbytes1(ctx.Swidth); } if ((S = malloc(ctx.Sbytes)) == NULL) @@ -575,6 +575,5 @@ int yespower_init_local(yespower_local_t *local) int yespower_free_local(yespower_local_t *local) { /* The reference implementation frees its memory in yespower() */ - (void)local; /* unused */ return 0; } \ No newline at end of file diff --git a/src/Native/libmultihash/yespower/yespower-platform.c b/src/Native/libmultihash/yespower/yespower-platform.c new file mode 100644 index 00000000..8b7d0639 --- /dev/null +++ b/src/Native/libmultihash/yespower/yespower-platform.c @@ -0,0 +1,107 @@ +/*- + * Copyright 2013-2018 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef __unix__ +#include +#endif + +#define HUGEPAGE_THRESHOLD (12 * 1024 * 1024) + +#ifdef __x86_64__ +#define HUGEPAGE_SIZE (2 * 1024 * 1024) +#else +#undef HUGEPAGE_SIZE +#endif +#include "yespower_sugarchain.h" +static void *alloc_region(yespower_region_t *region, size_t size) +{ + size_t base_size = size; + uint8_t *base, *aligned; +#ifdef MAP_ANON + int flags = +#ifdef MAP_NOCORE + MAP_NOCORE | +#endif + MAP_ANON | MAP_PRIVATE; +#if defined(MAP_HUGETLB) && defined(HUGEPAGE_SIZE) + size_t new_size = size; + const size_t hugepage_mask = (size_t)HUGEPAGE_SIZE - 1; + if (size >= HUGEPAGE_THRESHOLD && size + hugepage_mask >= size) { + flags |= MAP_HUGETLB; +/* + * Linux's munmap() fails on MAP_HUGETLB mappings if size is not a multiple of + * huge page size, so let's round up to huge page size here. + */ + new_size = size + hugepage_mask; + new_size &= ~hugepage_mask; + } + base = mmap(NULL, new_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (base != MAP_FAILED) { + base_size = new_size; + } else if (flags & MAP_HUGETLB) { + flags &= ~MAP_HUGETLB; + base = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0); + } + +#else + base = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0); +#endif + if (base == MAP_FAILED) + base = NULL; + aligned = base; +#elif defined(HAVE_POSIX_MEMALIGN) + if ((errno = posix_memalign((void **)&base, 64, size)) != 0) + base = NULL; + aligned = base; +#else + base = aligned = NULL; + if (size + 63 < size) { + errno = ENOMEM; + } else if ((base = malloc(size + 63)) != NULL) { + aligned = base + 63; + aligned -= (uintptr_t)aligned & 63; + } +#endif + region->base = base; + region->aligned = aligned; + region->base_size = base ? base_size : 0; + region->aligned_size = base ? size : 0; + return aligned; +} + +static inline void init_region(yespower_region_t *region) +{ + region->base = region->aligned = NULL; + region->base_size = region->aligned_size = 0; +} + +static int free_region(yespower_region_t *region) +{ + if (region->base) { +#ifdef MAP_ANON + if (munmap(region->base, region->base_size)) + return -1; +#else + free(region->base); +#endif + } + init_region(region); + return 0; +} \ No newline at end of file diff --git a/src/Native/libmultihash/yespower_sugarchain.c b/src/Native/libmultihash/yespower/yespower_sugarchain.c similarity index 100% rename from src/Native/libmultihash/yespower_sugarchain.c rename to src/Native/libmultihash/yespower/yespower_sugarchain.c diff --git a/src/Native/libmultihash/yespower_sugarchain.h b/src/Native/libmultihash/yespower/yespower_sugarchain.h similarity index 100% rename from src/Native/libmultihash/yespower_sugarchain.h rename to src/Native/libmultihash/yespower/yespower_sugarchain.h From 9b7fdc1839abaa0bdb1efe476ea2ad8521661ea1 Mon Sep 17 00:00:00 2001 From: akshaynexus Date: Sun, 26 Apr 2020 20:04:37 +0000 Subject: [PATCH 35/36] Cleanup devault coinbase_payload code and add PEXA --- .../Blockchain/Bitcoin/BitcoinJob.cs | 31 ++++++------------- .../Bitcoin/BitcoinJobManagerBase.cs | 6 ++-- src/Miningcore/coins.json | 19 ++++++++++++ 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 62981b87..3da99de9 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -500,8 +500,8 @@ protected virtual Money CreateMasternodeOutputs(Transaction tx, Money reward) var payeeAddress = BitcoinUtils.AddressToDestination(masterNode.Payee, network); var payeeReward = masterNode.Amount; if(!(poolConfig.Template.Symbol == "IDX" ||poolConfig.Template.Symbol == "XZC")){ - reward -= payeeReward; - rewardToPool -= payeeReward; + reward -= payeeReward; + rewardToPool -= payeeReward; } tx.Outputs.Add(payeeReward, payeeAddress); } @@ -527,8 +527,8 @@ protected virtual Money CreateMasternodeOutputs(Transaction tx, Money reward) var payeeAddress = BitcoinUtils.AddressToDestination(masterNodeParameters.Payee, network); var payeeReward = masterNodeParameters.PayeeAmount; if(!(poolConfig.Template.Symbol == "IDX" ||poolConfig.Template.Symbol == "XZC")){ - reward -= payeeReward; - rewardToPool -= payeeReward; + reward -= payeeReward; + rewardToPool -= payeeReward; } tx.Outputs.Add(payeeReward, payeeAddress); @@ -546,20 +546,15 @@ protected virtual Money CreateMasternodeOutputs(Transaction tx, Money reward) protected virtual Transaction CreatePayloadOutputTransaction() { var blockReward = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); - rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); - var tx = Transaction.Create(network); - - // outputs - rewardToPool = CreatePayloadOutputs(tx, blockReward); - - // Finally distribute remaining funds to pool - tx.Outputs.Insert(0, new TxOut(rewardToPool, poolAddressDestination)); - + // Firstly pay coins to pool addr + tx.Outputs.Insert(0, new TxOut(blockReward, poolAddressDestination)); + // then create payloads incase there is any coinbase_payload in gbt + CreatePayloadOutputs(tx, rewardToPool); return tx; } - protected virtual Money CreatePayloadOutputs(Transaction tx, Money reward) + protected virtual void CreatePayloadOutputs(Transaction tx, Money reward) { if(coinbasepayloadParameters.CoinbasePayload != null) { @@ -580,14 +575,6 @@ protected virtual Money CreatePayloadOutputs(Transaction tx, Money reward) } } } - if(!string.IsNullOrEmpty(coinbasepayloadParameters.Payee)) - { - var payeeAddress = BitcoinUtils.CashAddrToDestination(coinbasepayloadParameters.Payee, network); - var payeeReward = coinbasepayloadParameters.PayeeAmount; - - tx.Outputs.Add(payeeReward, payeeAddress); - } - return reward; } #endregion // DevaultCoinbasePayload diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs index 8f797f80..ed57c6a9 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs @@ -509,9 +509,9 @@ protected override async Task PostStartInitAsync(CancellationToken ct) // Payment-processing setup if(clusterConfig.PaymentProcessing?.Enabled == true && poolConfig.PaymentProcessing?.Enabled == true) { - // ensure pool owns wallet - if (!validateAddressResponse.IsMine) - logger.ThrowLogPoolStartupException($"Daemon does not own pool-address '{poolConfig.Address}'"); + // // ensure pool owns wallet + // if (!validateAddressResponse.IsMine) + // logger.ThrowLogPoolStartupException($"Daemon does not own pool-address '{poolConfig.Address}'"); ConfigureRewards(); } diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index cf649ea5..50d7d61a 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -482,6 +482,25 @@ "explorerTxLink": "https://ravencoin.network/tx/{0}", "explorerAccountLink": "https://ravencoin.network/address/{0}" }, + "pexacoin": { + "name": "Pexacoin", + "symbol": "PEXA", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "sha256d" + }, + "headerHasher": { + "hash": "x16rv2" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "x16rv2" } ] + }, + "shareMultiplier": 256, + "explorerBlockLink": "$hash$", + "explorerTxLink": "{0}", + "explorerAccountLink": "{0}" + }, "pigeoncoin": { "name": "Pigeoncoin", "symbol": "PGN", From 3cdffac1667b487cd49b1a996e529372b56b5ed2 Mon Sep 17 00:00:00 2001 From: Akshay Cm Date: Mon, 27 Apr 2020 16:38:04 +0300 Subject: [PATCH 36/36] wip kawpow code --- .../Blockchain/Bitcoin/BitcoinJob.cs | 23 +- ...ndexBlockHeader.cs => RavenBlockHeader.cs} | 70 ++- src/Miningcore/Configuration/ClusterConfig.cs | 7 +- src/Miningcore/Miningcore.csproj | 3 +- src/Miningcore/coins.json | 23 +- src/Miningcore/windows-build.bat | 2 +- .../libmultihash/kawpow/ethash/CMakeLists.txt | 36 ++ .../kawpow/ethash/bit_manipulation.h | 81 +++ .../libmultihash/kawpow/ethash/builtins.h | 43 ++ .../libmultihash/kawpow/ethash/endianness.hpp | 99 +++ .../kawpow/ethash/ethash-internal.hpp | 68 +++ .../libmultihash/kawpow/ethash/ethash.cpp | 442 ++++++++++++++ .../libmultihash/kawpow/ethash/kiss99.hpp | 64 ++ .../libmultihash/kawpow/ethash/managed.cpp | 99 +++ .../libmultihash/kawpow/ethash/primes.c | 43 ++ .../libmultihash/kawpow/ethash/primes.h | 25 + .../libmultihash/kawpow/ethash/progpow.cpp | 569 ++++++++++++++++++ .../libmultihash/kawpow/keccak/CMakeLists.txt | 25 + .../libmultihash/kawpow/keccak/keccak.c | 123 ++++ .../libmultihash/kawpow/keccak/keccakf1600.c | 255 ++++++++ .../libmultihash/kawpow/keccak/keccakf800.c | 253 ++++++++ .../libmultihash/kawpow/support/attributes.h | 33 + src/Native/libmultihash/libmultihash.vcxproj | 18 + 23 files changed, 2357 insertions(+), 47 deletions(-) rename src/Miningcore/Blockchain/Bitcoin/{IndexBlockHeader.cs => RavenBlockHeader.cs} (81%) create mode 100644 src/Native/libmultihash/kawpow/ethash/CMakeLists.txt create mode 100644 src/Native/libmultihash/kawpow/ethash/bit_manipulation.h create mode 100644 src/Native/libmultihash/kawpow/ethash/builtins.h create mode 100644 src/Native/libmultihash/kawpow/ethash/endianness.hpp create mode 100644 src/Native/libmultihash/kawpow/ethash/ethash-internal.hpp create mode 100644 src/Native/libmultihash/kawpow/ethash/ethash.cpp create mode 100644 src/Native/libmultihash/kawpow/ethash/kiss99.hpp create mode 100644 src/Native/libmultihash/kawpow/ethash/managed.cpp create mode 100644 src/Native/libmultihash/kawpow/ethash/primes.c create mode 100644 src/Native/libmultihash/kawpow/ethash/primes.h create mode 100644 src/Native/libmultihash/kawpow/ethash/progpow.cpp create mode 100644 src/Native/libmultihash/kawpow/keccak/CMakeLists.txt create mode 100644 src/Native/libmultihash/kawpow/keccak/keccak.c create mode 100644 src/Native/libmultihash/kawpow/keccak/keccakf1600.c create mode 100644 src/Native/libmultihash/kawpow/keccak/keccakf800.c create mode 100644 src/Native/libmultihash/kawpow/support/attributes.h diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 3da99de9..ec07981a 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -37,7 +37,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using Newtonsoft.Json.Linq; using Contract = Miningcore.Contracts.Contract; using Transaction = NBitcoin.Transaction; -using Miningcore.Crypto.Hashing.Algorithms; namespace Miningcore.Blockchain.Bitcoin { @@ -249,7 +248,7 @@ protected virtual Script GenerateScriptSigInitial() // optionally push aux-flags if(!string.IsNullOrEmpty(BlockTemplate.CoinbaseAux?.Flags)) - ops.Add(Op.GetPushOp(BlockTemplate.CoinbaseAux.Flags.HexToByteArray())); + ops.Add(Op.GetPushOp(BlockTemplate.CoinbaseAux?.Flags.HexToByteArray())); // push timestamp ops.Add(Op.GetPushOp(now)); @@ -263,7 +262,7 @@ protected virtual Script GenerateScriptSigInitial() protected virtual Transaction CreateOutputTransaction() { rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); - + var tx = Transaction.Create(network); //Now check if we need to pay founder fees Re PGN pre-dash fork if(coin.HasFounderFee) @@ -335,6 +334,20 @@ protected byte[] SerializeHeader(Span coinbaseHash, uint nTime, uint nonce BlockTime = DateTimeOffset.FromUnixTimeSeconds(nTime), Nonce = nonce }; + if(coin.UsesCustomHeaderForHash) + { + var rvNblockHeader = new RavenBlockHeader + { + Version = unchecked((int) version), + Bits = new Target(Encoders.Hex.DecodeData(BlockTemplate.Bits)), + HashPrevBlock = uint256.Parse(BlockTemplate.PreviousBlockhash), + HashMerkleRoot = new uint256(merkleRoot), + BlockTime = DateTimeOffset.FromUnixTimeSeconds(nTime), + Nonce = nonce, + BlockHeight = BlockTemplate.Height + }; + return rvNblockHeader.ToBytes(); + } return blockHeader.ToBytes(); } @@ -578,7 +591,7 @@ protected virtual void CreatePayloadOutputs(Transaction tx, Money reward) } #endregion // DevaultCoinbasePayload - + #region PigeoncoinDevFee protected FounderBlockTemplateExtra FounderParameters; @@ -659,7 +672,7 @@ public void Init(BlockTemplate blockTemplate, string jobId, this.shareMultiplier = shareMultiplier; txComment = !string.IsNullOrEmpty(extraPoolConfig?.CoinbaseTxComment) ? - extraPoolConfig.CoinbaseTxComment : coin.CoinbaseTxComment; + extraPoolConfig?.CoinbaseTxComment : coin.CoinbaseTxComment; if(coin.HasMasterNodes) { diff --git a/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs b/src/Miningcore/Blockchain/Bitcoin/RavenBlockHeader.cs similarity index 81% rename from src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs rename to src/Miningcore/Blockchain/Bitcoin/RavenBlockHeader.cs index 32b0fd77..5cd50e66 100644 --- a/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs +++ b/src/Miningcore/Blockchain/Bitcoin/RavenBlockHeader.cs @@ -20,58 +20,57 @@ namespace NBitcoin /// in the block is a special one that creates a new coin owned by the creator /// of the block. /// - public class IndexBlockHeader : IBitcoinSerializable + public class RavenBlockHeader : IBitcoinSerializable { internal const int Size = 81; - public static IndexBlockHeader Parse(string hex, Network network) + public static RavenBlockHeader Parse(string hex, Network network) { if (network == null) throw new ArgumentNullException(nameof(network)); return Parse(hex, network.Consensus.ConsensusFactory); } - public static IndexBlockHeader Parse(string hex, Consensus consensus) + public static RavenBlockHeader Parse(string hex, Consensus consensus) { if (consensus == null) throw new ArgumentNullException(nameof(consensus)); return Parse(hex, consensus.ConsensusFactory); } - public static IndexBlockHeader Parse(string hex, ConsensusFactory consensusFactory) + public static RavenBlockHeader Parse(string hex, ConsensusFactory consensusFactory) { if (consensusFactory == null) throw new ArgumentNullException(nameof(consensusFactory)); - return new IndexBlockHeader(Encoders.Hex.DecodeData(hex), consensusFactory); + return new RavenBlockHeader(Encoders.Hex.DecodeData(hex), consensusFactory); } [Obsolete("Use Parse(string hex, Network|Consensus|ConsensusFactory) instead")] - public static IndexBlockHeader Parse(string hex) + public static RavenBlockHeader Parse(string hex) { return Parse(hex, Consensus.Main.ConsensusFactory); } - [Obsolete("You should instantiate IndexBlockHeader from ConsensusFactory.CreateIndexBlockHeader")] - public IndexBlockHeader() + public RavenBlockHeader() { SetNull(); } - public IndexBlockHeader(string hex, Network network) + public RavenBlockHeader(string hex, Network network) : this(hex, network?.Consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(network))) { } - public IndexBlockHeader(string hex, Consensus consensus) + public RavenBlockHeader(string hex, Consensus consensus) : this(hex, consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(consensus))) { } - public IndexBlockHeader(string hex, ConsensusFactory consensusFactory) + public RavenBlockHeader(string hex, ConsensusFactory consensusFactory) { if (hex == null) throw new ArgumentNullException(nameof(hex)); @@ -84,27 +83,27 @@ public IndexBlockHeader(string hex, ConsensusFactory consensusFactory) this.ReadWrite(bs); } - [Obsolete("Use new IndexBlockHeader(string hex, Network|Consensus|ConsensusFactory) instead")] - public IndexBlockHeader(string hex) + [Obsolete("Use new RavenBlockHeader(string hex, Network|Consensus|ConsensusFactory) instead")] + public RavenBlockHeader(string hex) : this(Encoders.Hex.DecodeData(hex)) { } - public IndexBlockHeader(byte[] data, Network network) + public RavenBlockHeader(byte[] data, Network network) : this(data, network?.Consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(network))) { } - public IndexBlockHeader(byte[] data, Consensus consensus) + public RavenBlockHeader(byte[] data, Consensus consensus) : this(data, consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(consensus))) { } - public IndexBlockHeader(byte[] data, ConsensusFactory consensusFactory) + public RavenBlockHeader(byte[] data, ConsensusFactory consensusFactory) { if (data == null) throw new ArgumentNullException(nameof(data)); @@ -118,8 +117,8 @@ public IndexBlockHeader(byte[] data, ConsensusFactory consensusFactory) } - [Obsolete("Use new IndexBlockHeader(byte[] hex, Network|Consensus|ConsensusFactory) instead")] - public IndexBlockHeader(byte[] bytes) + [Obsolete("Use new RavenBlockHeader(byte[] hex, Network|Consensus|ConsensusFactory) instead")] + public RavenBlockHeader(byte[] bytes) { this.ReadWrite(bytes); } @@ -145,6 +144,7 @@ public uint256 HashPrevBlock protected uint nTime; protected uint nBits; + protected uint nHeight; public Target Bits { @@ -196,20 +196,18 @@ public uint256 HashMerkleRoot hashMerkleRoot = value; } } - protected bool fProofOfStake; - public bool ProofOfStake - { - get - { - return fProofOfStake; - } - set - { - fProofOfStake = value; - } - } - - protected internal virtual void SetNull() + public uint BlockHeight + { + get + { + return nHeight; + } + set + { + nHeight = value; + } + } + protected internal virtual void SetNull() { nVersion = CURRENT_VERSION; hashPrevBlock = 0; @@ -217,8 +215,8 @@ protected internal virtual void SetNull() nTime = 0; nBits = 0; nNonce = 0; - fProofOfStake = false; - } + nHeight = 0; + } public virtual bool IsNull { @@ -237,7 +235,7 @@ public virtual void ReadWrite(BitcoinStream stream) stream.ReadWrite(ref nTime); stream.ReadWrite(ref nBits); stream.ReadWrite(ref nNonce); - stream.ReadWrite(ref fProofOfStake); + stream.ReadWrite(ref nHeight); } @@ -327,4 +325,4 @@ public bool CheckProofOfWork() } -} \ No newline at end of file +} diff --git a/src/Miningcore/Configuration/ClusterConfig.cs b/src/Miningcore/Configuration/ClusterConfig.cs index 8b686267..effca289 100644 --- a/src/Miningcore/Configuration/ClusterConfig.cs +++ b/src/Miningcore/Configuration/ClusterConfig.cs @@ -154,7 +154,7 @@ public partial class BitcoinNetworkParams public uint CoinbaseTxVersion { get; set; } /// - /// Default transaction comment for coins that REQUIRE tx comments + /// Default transaction comment for coins that REQUIRE tx comments /// public string CoinbaseTxComment { get; set; } @@ -167,6 +167,9 @@ public partial class BitcoinNetworkParams [JsonProperty("hasCoinbasePayload")] public bool HasCoinbasePayload { get; set; } + [JsonProperty("usesCustomHeaderForHash")] + public bool UsesCustomHeaderForHash { get; set; } + [JsonProperty("hasFounderFee")] public bool HasFounderFee { get; set; } @@ -684,7 +687,7 @@ public partial class PoolConfig public PoolShareBasedBanningConfig Banning { get; set; } public RewardRecipient[] RewardRecipients { get; set; } public string Address { get; set; } - public string PubKey { get; set; } // POS coins only + public string PubKey { get; set; } // POS coins only public int ClientConnectionTimeout { get; set; } public int JobRebroadcastTimeout { get; set; } public int BlockRefreshInterval { get; set; } diff --git a/src/Miningcore/Miningcore.csproj b/src/Miningcore/Miningcore.csproj index 141bc85e..ea6c25e1 100644 --- a/src/Miningcore/Miningcore.csproj +++ b/src/Miningcore/Miningcore.csproj @@ -44,7 +44,6 @@ - @@ -58,7 +57,7 @@ - + diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 50d7d61a..44f17888 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -377,7 +377,7 @@ "hash": "reverse", "args": [ { - "hash": "x16rv2" + "hash": "x16rv2" } ] }, @@ -482,6 +482,27 @@ "explorerTxLink": "https://ravencoin.network/tx/{0}", "explorerAccountLink": "https://ravencoin.network/address/{0}" }, + + "ravencoin-testnet": { + "name": "Ravencoin", + "symbol": "RVN", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "sha256d" + }, + "headerHasher": { + "hash": "x16rv2" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "x16rv2" } ] + }, + "usesCustomHeaderForHash":true, + "shareMultiplier": 256, + "explorerBlockLink": "https://testnet.ravencoin.network/block/$hash$", + "explorerTxLink": "https://testnet.ravencoin.network/tx/{0}", + "explorerAccountLink": "https://testnet.ravencoin.network/address/{0}" + }, "pexacoin": { "name": "Pexacoin", "symbol": "PEXA", diff --git a/src/Miningcore/windows-build.bat b/src/Miningcore/windows-build.bat index 63cfbe76..008f5fae 100644 --- a/src/Miningcore/windows-build.bat +++ b/src/Miningcore/windows-build.bat @@ -1 +1 @@ -dotnet publish -c Release --framework netcoreapp2.1 -o ../../build +dotnet publish -c Release --framework netcoreapp3.1 -o ../../build diff --git a/src/Native/libmultihash/kawpow/ethash/CMakeLists.txt b/src/Native/libmultihash/kawpow/ethash/CMakeLists.txt new file mode 100644 index 00000000..12473bb0 --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/CMakeLists.txt @@ -0,0 +1,36 @@ +# ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. +# Copyright 2018-2019 Pawel Bylica. +# Licensed under the Apache License, Version 2.0. + +include(GNUInstallDirs) + +add_library( + ethash + bit_manipulation.h + builtins.h + endianness.hpp + ${include_dir}/ethash/ethash.h + ${include_dir}/ethash/ethash.hpp + ethash-internal.hpp + ethash.cpp + ${include_dir}/ethash/hash_types.h + managed.cpp + kiss99.hpp + primes.h + primes.c + ${include_dir}/ethash/progpow.hpp + progpow.cpp +) + +target_link_libraries(ethash PRIVATE keccak) +target_include_directories(ethash PUBLIC $$) +if(CABLE_COMPILER_GNULIKE AND NOT SANITIZE MATCHES undefined) + target_compile_options(ethash PRIVATE $<$:-fno-rtti>) +endif() + +install( + TARGETS ethash + EXPORT ethashTargets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) diff --git a/src/Native/libmultihash/kawpow/ethash/bit_manipulation.h b/src/Native/libmultihash/kawpow/ethash/bit_manipulation.h new file mode 100644 index 00000000..b88bfdaa --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/bit_manipulation.h @@ -0,0 +1,81 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#pragma once + +#include "builtins.h" +#include "../support/attributes.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static inline uint32_t rotl32(uint32_t n, unsigned int c) +{ + const unsigned int mask = 31; + + c &= mask; + unsigned int neg_c = (unsigned int)(-(int)c); + return (n << c) | (n >> (neg_c & mask)); +} + +static inline uint32_t rotr32(uint32_t n, unsigned int c) +{ + const unsigned int mask = 31; + + c &= mask; + unsigned int neg_c = (unsigned int)(-(int)c); + return (n >> c) | (n << (neg_c & mask)); +} + +static inline uint32_t clz32(uint32_t x) +{ + return x ? (uint32_t)__builtin_clz(x) : 32; +} + +static inline uint32_t popcount32(uint32_t x) +{ + return (uint32_t)__builtin_popcount(x); +} + +static inline uint32_t mul_hi32(uint32_t x, uint32_t y) +{ + return (uint32_t)(((uint64_t)x * (uint64_t)y) >> 32); +} + + +/** FNV 32-bit prime. */ +static const uint32_t fnv_prime = 0x01000193; + +/** FNV 32-bit offset basis. */ +static const uint32_t fnv_offset_basis = 0x811c9dc5; + +/** + * The implementation of FNV-1 hash. + * + * See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1_hash. + */ +NO_SANITIZE("unsigned-integer-overflow") +static inline uint32_t fnv1(uint32_t u, uint32_t v) noexcept +{ + return (u * fnv_prime) ^ v; +} + +/** + * The implementation of FNV-1a hash. + * + * See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash. + */ +NO_SANITIZE("unsigned-integer-overflow") +static inline uint32_t fnv1a(uint32_t u, uint32_t v) noexcept +{ + return (u ^ v) * fnv_prime; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/Native/libmultihash/kawpow/ethash/builtins.h b/src/Native/libmultihash/kawpow/ethash/builtins.h new file mode 100644 index 00000000..0c43188a --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/builtins.h @@ -0,0 +1,43 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +/** + * @file + * Implementation of GCC/clang builtins for MSVC compiler. + */ + +#pragma once + +#ifdef _MSC_VER +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Returns the number of leading 0-bits in `x`, starting at the most significant bit position. + * If `x` is 0, the result is undefined. + */ +static inline int __builtin_clz(unsigned int x) +{ + unsigned long most_significant_bit; + _BitScanReverse(&most_significant_bit, x); + return 31 - (int)most_significant_bit; +} + +/** + * Returns the number of 1-bits in `x`. + */ +static inline int __builtin_popcount(unsigned int x) +{ + return (int)__popcnt(x); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/Native/libmultihash/kawpow/ethash/endianness.hpp b/src/Native/libmultihash/kawpow/ethash/endianness.hpp new file mode 100644 index 00000000..cdb9750e --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/endianness.hpp @@ -0,0 +1,99 @@ +// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. +// Copyright 2018-2019 Pawel Bylica. +// Licensed under the Apache License, Version 2.0. + +/// @file +/// This file contains helper functions to handle big-endian architectures. +/// The Ethash algorithm is naturally defined for little-endian architectures +/// so for those the helpers are just no-op empty functions. +/// For big-endian architectures we need 32-bit and 64-bit byte swapping in +/// some places. + +#pragma once + +#include + +#if _WIN32 + +#include + +#define bswap32 _byteswap_ulong +#define bswap64 _byteswap_uint64 + +// On Windows assume little endian. +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __BYTE_ORDER __LITTLE_ENDIAN + +#elif __APPLE__ + +#include + +#define bswap32 __builtin_bswap32 +#define bswap64 __builtin_bswap64 + +#else + +#include + +#define bswap32 __builtin_bswap32 +#define bswap64 __builtin_bswap64 + +#endif + +namespace ethash +{ +#if __BYTE_ORDER == __LITTLE_ENDIAN + +struct le +{ + static uint32_t uint32(uint32_t x) noexcept { return x; } + static uint64_t uint64(uint64_t x) noexcept { return x; } + + static const hash1024& uint32s(const hash1024& h) noexcept { return h; } + static const hash512& uint32s(const hash512& h) noexcept { return h; } + static const hash256& uint32s(const hash256& h) noexcept { return h; } +}; + +struct be +{ + static uint64_t uint64(uint64_t x) noexcept { return bswap64(x); } +}; + + +#elif __BYTE_ORDER == __BIG_ENDIAN + +struct le +{ + static uint32_t uint32(uint32_t x) noexcept { return bswap32(x); } + static uint64_t uint64(uint64_t x) noexcept { return bswap64(x); } + + static hash1024 uint32s(hash1024 h) noexcept + { + for (auto& w : h.word32s) + w = uint32(w); + return h; + } + + static hash512 uint32s(hash512 h) noexcept + { + for (auto& w : h.word32s) + w = uint32(w); + return h; + } + + static hash256 uint32s(hash256 h) noexcept + { + for (auto& w : h.word32s) + w = uint32(w); + return h; + } +}; + +struct be +{ + static uint64_t uint64(uint64_t x) noexcept { return x; } +}; + +#endif +} // namespace ethash \ No newline at end of file diff --git a/src/Native/libmultihash/kawpow/ethash/ethash-internal.hpp b/src/Native/libmultihash/kawpow/ethash/ethash-internal.hpp new file mode 100644 index 00000000..bb8e6b21 --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/ethash-internal.hpp @@ -0,0 +1,68 @@ +// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. +// Copyright 2018-2019 Pawel Bylica. +// Licensed under the Apache License, Version 2.0. + +/// @file +/// Contains declarations of internal ethash functions to allow them to be +/// unit-tested. + +#pragma once + +#include + +#include "endianness.hpp" + +#include +#include + +extern "C" struct ethash_epoch_context_full : ethash_epoch_context +{ + ethash_hash1024* full_dataset; + + constexpr ethash_epoch_context_full(int epoch, int light_num_items, + const ethash_hash512* light, const uint32_t* l1, int dataset_num_items, + ethash_hash1024* dataset) noexcept + : ethash_epoch_context{epoch, light_num_items, light, l1, dataset_num_items}, + full_dataset{dataset} + {} +}; + +namespace ethash +{ +inline bool is_less_or_equal(const hash256& a, const hash256& b) noexcept +{ + for (size_t i = 0; i < (sizeof(a) / sizeof(a.word64s[0])); ++i) + { + if (be::uint64(a.word64s[i]) > be::uint64(b.word64s[i])) + return false; + if (be::uint64(a.word64s[i]) < be::uint64(b.word64s[i])) + return true; + } + return true; +} + +inline bool is_equal(const hash256& a, const hash256& b) noexcept +{ + return std::memcmp(a.bytes, b.bytes, sizeof(a)) == 0; +} + +void build_light_cache(hash512 cache[], int num_items, const hash256& seed) noexcept; + +hash512 calculate_dataset_item_512(const epoch_context& context, int64_t index) noexcept; +hash1024 calculate_dataset_item_1024(const epoch_context& context, uint32_t index) noexcept; +hash2048 calculate_dataset_item_2048(const epoch_context& context, uint32_t index) noexcept; + +namespace generic +{ +using hash_fn_512 = hash512 (*)(const uint8_t* data, size_t size); +using build_light_cache_fn = void (*)(hash512 cache[], int num_items, const hash256& seed); + +void build_light_cache( + hash_fn_512 hash_fn, hash512 cache[], int num_items, const hash256& seed) noexcept; + +epoch_context_full* create_epoch_context( + build_light_cache_fn build_fn, int epoch_number, bool full) noexcept; + +} // namespace generic + +} // namespace ethash diff --git a/src/Native/libmultihash/kawpow/ethash/ethash.cpp b/src/Native/libmultihash/kawpow/ethash/ethash.cpp new file mode 100644 index 00000000..0a289c88 --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/ethash.cpp @@ -0,0 +1,442 @@ +// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. +// Copyright 2018-2019 Pawel Bylica. +// Licensed under the Apache License, Version 2.0. + +#include "ethash-internal.hpp" + +#include "../support/attributes.h" +#include "bit_manipulation.h" +#include "endianness.hpp" +#include "primes.h" +#include +#include + +#include +#include +#include +#include + +namespace ethash +{ +// Internal constants: +constexpr static int light_cache_init_size = 1 << 24; +constexpr static int light_cache_growth = 1 << 17; +constexpr static int light_cache_rounds = 3; +constexpr static int full_dataset_init_size = 1 << 30; +constexpr static int full_dataset_growth = 1 << 23; +constexpr static int full_dataset_item_parents = 512; + +// Verify constants: +static_assert(sizeof(hash512) == ETHASH_LIGHT_CACHE_ITEM_SIZE, ""); +static_assert(sizeof(hash1024) == ETHASH_FULL_DATASET_ITEM_SIZE, ""); +static_assert(light_cache_item_size == ETHASH_LIGHT_CACHE_ITEM_SIZE, ""); +static_assert(full_dataset_item_size == ETHASH_FULL_DATASET_ITEM_SIZE, ""); + + +namespace +{ +using ::fnv1; + +inline hash512 fnv1(const hash512& u, const hash512& v) noexcept +{ + hash512 r; + for (size_t i = 0; i < sizeof(r) / sizeof(r.word32s[0]); ++i) + r.word32s[i] = fnv1(u.word32s[i], v.word32s[i]); + return r; +} + +inline hash512 bitwise_xor(const hash512& x, const hash512& y) noexcept +{ + hash512 z; + for (size_t i = 0; i < sizeof(z) / sizeof(z.word64s[0]); ++i) + z.word64s[i] = x.word64s[i] ^ y.word64s[i]; + return z; +} +} // namespace + +int find_epoch_number(const hash256& seed) noexcept +{ + static constexpr int num_tries = 30000; // Divisible by 16. + + // Thread-local cache of the last search. + static thread_local int cached_epoch_number = 0; + static thread_local hash256 cached_seed = {}; + + // Load from memory once (memory will be clobbered by keccak256()). + const uint32_t seed_part = seed.word32s[0]; + const int e = cached_epoch_number; + hash256 s = cached_seed; + + if (s.word32s[0] == seed_part) + return e; + + // Try the next seed, will match for sequential epoch access. + s = keccak256(s); + if (s.word32s[0] == seed_part) + { + cached_seed = s; + cached_epoch_number = e + 1; + return e + 1; + } + + // Search for matching seed starting from epoch 0. + s = {}; + for (int i = 0; i < num_tries; ++i) + { + if (s.word32s[0] == seed_part) + { + cached_seed = s; + cached_epoch_number = i; + return i; + } + + s = keccak256(s); + } + + return -1; +} + +namespace generic +{ +void build_light_cache( + hash_fn_512 hash_fn, hash512 cache[], int num_items, const hash256& seed) noexcept +{ + hash512 item = hash_fn(seed.bytes, sizeof(seed)); + cache[0] = item; + for (int i = 1; i < num_items; ++i) + { + item = hash_fn(item.bytes, sizeof(item)); + cache[i] = item; + } + + for (int q = 0; q < light_cache_rounds; ++q) + { + for (int i = 0; i < num_items; ++i) + { + const uint32_t index_limit = static_cast(num_items); + + // Fist index: 4 first bytes of the item as little-endian integer. + const uint32_t t = le::uint32(cache[i].word32s[0]); + const uint32_t v = t % index_limit; + + // Second index. + const uint32_t w = static_cast(num_items + (i - 1)) % index_limit; + + const hash512 x = bitwise_xor(cache[v], cache[w]); + cache[i] = hash_fn(x.bytes, sizeof(x)); + } + } +} + +epoch_context_full* create_epoch_context( + build_light_cache_fn build_fn, int epoch_number, bool full) noexcept +{ + static_assert(sizeof(epoch_context_full) < sizeof(hash512), "epoch_context too big"); + static constexpr size_t context_alloc_size = sizeof(hash512); + + const int light_cache_num_items = calculate_light_cache_num_items(epoch_number); + const int full_dataset_num_items = calculate_full_dataset_num_items(epoch_number); + const size_t light_cache_size = get_light_cache_size(light_cache_num_items); + const size_t full_dataset_size = + full ? static_cast(full_dataset_num_items) * sizeof(hash1024) : + progpow::l1_cache_size; + + const size_t alloc_size = context_alloc_size + light_cache_size + full_dataset_size; + + char* const alloc_data = static_cast(std::calloc(1, alloc_size)); + if (!alloc_data) + return nullptr; // Signal out-of-memory by returning null pointer. + + hash512* const light_cache = reinterpret_cast(alloc_data + context_alloc_size); + const hash256 epoch_seed = calculate_epoch_seed(epoch_number); + build_fn(light_cache, light_cache_num_items, epoch_seed); + + uint32_t* const l1_cache = + reinterpret_cast(alloc_data + context_alloc_size + light_cache_size); + + hash1024* full_dataset = full ? reinterpret_cast(l1_cache) : nullptr; + + epoch_context_full* const context = new (alloc_data) epoch_context_full{ + epoch_number, + light_cache_num_items, + light_cache, + l1_cache, + full_dataset_num_items, + full_dataset, + }; + + auto* full_dataset_2048 = reinterpret_cast(l1_cache); + for (uint32_t i = 0; i < progpow::l1_cache_size / sizeof(full_dataset_2048[0]); ++i) + full_dataset_2048[i] = calculate_dataset_item_2048(*context, i); + return context; +} +} // namespace generic + +void build_light_cache(hash512 cache[], int num_items, const hash256& seed) noexcept +{ + return generic::build_light_cache(keccak512, cache, num_items, seed); +} + +struct item_state +{ + const hash512* const cache; + const int64_t num_cache_items; + const uint32_t seed; + + hash512 mix; + + ALWAYS_INLINE item_state(const epoch_context& context, int64_t index) noexcept + : cache{context.light_cache}, + num_cache_items{context.light_cache_num_items}, + seed{static_cast(index)} + { + mix = cache[index % num_cache_items]; + mix.word32s[0] ^= le::uint32(seed); + mix = le::uint32s(keccak512(mix)); + } + + ALWAYS_INLINE void update(uint32_t round) noexcept + { + static constexpr size_t num_words = sizeof(mix) / sizeof(uint32_t); + const uint32_t t = fnv1(seed ^ round, mix.word32s[round % num_words]); + const int64_t parent_index = t % num_cache_items; + mix = fnv1(mix, le::uint32s(cache[parent_index])); + } + + ALWAYS_INLINE hash512 final() noexcept { return keccak512(le::uint32s(mix)); } +}; + +hash512 calculate_dataset_item_512(const epoch_context& context, int64_t index) noexcept +{ + item_state item0{context, index}; + for (uint32_t j = 0; j < full_dataset_item_parents; ++j) + item0.update(j); + return item0.final(); +} + +/// Calculates a full dataset item +/// +/// This consist of two 512-bit items produced by calculate_dataset_item_partial(). +/// Here the computation is done interleaved for better performance. +hash1024 calculate_dataset_item_1024(const epoch_context& context, uint32_t index) noexcept +{ + item_state item0{context, int64_t(index) * 2}; + item_state item1{context, int64_t(index) * 2 + 1}; + + for (uint32_t j = 0; j < full_dataset_item_parents; ++j) + { + item0.update(j); + item1.update(j); + } + + return hash1024{{item0.final(), item1.final()}}; +} + +hash2048 calculate_dataset_item_2048(const epoch_context& context, uint32_t index) noexcept +{ + item_state item0{context, int64_t(index) * 4}; + item_state item1{context, int64_t(index) * 4 + 1}; + item_state item2{context, int64_t(index) * 4 + 2}; + item_state item3{context, int64_t(index) * 4 + 3}; + + for (uint32_t j = 0; j < full_dataset_item_parents; ++j) + { + item0.update(j); + item1.update(j); + item2.update(j); + item3.update(j); + } + + return hash2048{{item0.final(), item1.final(), item2.final(), item3.final()}}; +} + +namespace +{ +using lookup_fn = hash1024 (*)(const epoch_context&, uint32_t); + +inline hash512 hash_seed(const hash256& header_hash, uint64_t nonce) noexcept +{ + nonce = le::uint64(nonce); + uint8_t init_data[sizeof(header_hash) + sizeof(nonce)]; + std::memcpy(&init_data[0], &header_hash, sizeof(header_hash)); + std::memcpy(&init_data[sizeof(header_hash)], &nonce, sizeof(nonce)); + + return keccak512(init_data, sizeof(init_data)); +} + +inline hash256 hash_final(const hash512& seed, const hash256& mix_hash) +{ + uint8_t final_data[sizeof(seed) + sizeof(mix_hash)]; + std::memcpy(&final_data[0], seed.bytes, sizeof(seed)); + std::memcpy(&final_data[sizeof(seed)], mix_hash.bytes, sizeof(mix_hash)); + return keccak256(final_data, sizeof(final_data)); +} + +inline hash256 hash_kernel( + const epoch_context& context, const hash512& seed, lookup_fn lookup) noexcept +{ + static constexpr size_t num_words = sizeof(hash1024) / sizeof(uint32_t); + const uint32_t index_limit = static_cast(context.full_dataset_num_items); + const uint32_t seed_init = le::uint32(seed.word32s[0]); + + hash1024 mix{{le::uint32s(seed), le::uint32s(seed)}}; + + for (uint32_t i = 0; i < num_dataset_accesses; ++i) + { + const uint32_t p = fnv1(i ^ seed_init, mix.word32s[i % num_words]) % index_limit; + const hash1024 newdata = le::uint32s(lookup(context, p)); + + for (size_t j = 0; j < num_words; ++j) + mix.word32s[j] = fnv1(mix.word32s[j], newdata.word32s[j]); + } + + hash256 mix_hash; + for (size_t i = 0; i < num_words; i += 4) + { + const uint32_t h1 = fnv1(mix.word32s[i], mix.word32s[i + 1]); + const uint32_t h2 = fnv1(h1, mix.word32s[i + 2]); + const uint32_t h3 = fnv1(h2, mix.word32s[i + 3]); + mix_hash.word32s[i / 4] = h3; + } + + return le::uint32s(mix_hash); +} +} // namespace + +result hash(const epoch_context_full& context, const hash256& header_hash, uint64_t nonce) noexcept +{ + static const auto lazy_lookup = [](const epoch_context& ctx, uint32_t index) noexcept + { + auto full_dataset = static_cast(ctx).full_dataset; + hash1024& item = full_dataset[index]; + if (item.word64s[0] == 0) + { + // TODO: Copy elision here makes it thread-safe? + item = calculate_dataset_item_1024(ctx, index); + } + + return item; + }; + + const hash512 seed = hash_seed(header_hash, nonce); + const hash256 mix_hash = hash_kernel(context, seed, lazy_lookup); + return {hash_final(seed, mix_hash), mix_hash}; +} + +search_result search_light(const epoch_context& context, const hash256& header_hash, + const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept +{ + const uint64_t end_nonce = start_nonce + iterations; + for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce) + { + result r = hash(context, header_hash, nonce); + if (is_less_or_equal(r.final_hash, boundary)) + return {r, nonce}; + } + return {}; +} + +search_result search(const epoch_context_full& context, const hash256& header_hash, + const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept +{ + const uint64_t end_nonce = start_nonce + iterations; + for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce) + { + result r = hash(context, header_hash, nonce); + if (is_less_or_equal(r.final_hash, boundary)) + return {r, nonce}; + } + return {}; +} +} // namespace ethash + +using namespace ethash; + +extern "C" { + +ethash_hash256 ethash_calculate_epoch_seed(int epoch_number) noexcept +{ + ethash_hash256 epoch_seed = {}; + for (int i = 0; i < epoch_number; ++i) + epoch_seed = ethash_keccak256_32(epoch_seed.bytes); + return epoch_seed; +} + +int ethash_calculate_light_cache_num_items(int epoch_number) noexcept +{ + static constexpr int item_size = sizeof(hash512); + static constexpr int num_items_init = light_cache_init_size / item_size; + static constexpr int num_items_growth = light_cache_growth / item_size; + static_assert( + light_cache_init_size % item_size == 0, "light_cache_init_size not multiple of item size"); + static_assert( + light_cache_growth % item_size == 0, "light_cache_growth not multiple of item size"); + + int num_items_upper_bound = num_items_init + epoch_number * num_items_growth; + int num_items = ethash_find_largest_prime(num_items_upper_bound); + return num_items; +} + +int ethash_calculate_full_dataset_num_items(int epoch_number) noexcept +{ + static constexpr int item_size = sizeof(hash1024); + static constexpr int num_items_init = full_dataset_init_size / item_size; + static constexpr int num_items_growth = full_dataset_growth / item_size; + static_assert(full_dataset_init_size % item_size == 0, + "full_dataset_init_size not multiple of item size"); + static_assert( + full_dataset_growth % item_size == 0, "full_dataset_growth not multiple of item size"); + + int num_items_upper_bound = num_items_init + epoch_number * num_items_growth; + int num_items = ethash_find_largest_prime(num_items_upper_bound); + return num_items; +} + +epoch_context* ethash_create_epoch_context(int epoch_number) noexcept +{ + return generic::create_epoch_context(build_light_cache, epoch_number, false); +} + +epoch_context_full* ethash_create_epoch_context_full(int epoch_number) noexcept +{ + return generic::create_epoch_context(build_light_cache, epoch_number, true); +} + +void ethash_destroy_epoch_context_full(epoch_context_full* context) noexcept +{ + ethash_destroy_epoch_context(context); +} + +void ethash_destroy_epoch_context(epoch_context* context) noexcept +{ + context->~epoch_context(); + std::free(context); +} + +ethash_result ethash_hash( + const epoch_context* context, const hash256* header_hash, uint64_t nonce) noexcept +{ + const hash512 seed = hash_seed(*header_hash, nonce); + const hash256 mix_hash = hash_kernel(*context, seed, calculate_dataset_item_1024); + return {hash_final(seed, mix_hash), mix_hash}; +} + +bool ethash_verify_final_hash(const hash256* header_hash, const hash256* mix_hash, uint64_t nonce, + const hash256* boundary) noexcept +{ + const hash512 seed = hash_seed(*header_hash, nonce); + return is_less_or_equal(hash_final(seed, *mix_hash), *boundary); +} + +bool ethash_verify(const epoch_context* context, const hash256* header_hash, + const hash256* mix_hash, uint64_t nonce, const hash256* boundary) noexcept +{ + const hash512 seed = hash_seed(*header_hash, nonce); + if (!is_less_or_equal(hash_final(seed, *mix_hash), *boundary)) + return false; + + const hash256 expected_mix_hash = hash_kernel(*context, seed, calculate_dataset_item_1024); + return is_equal(expected_mix_hash, *mix_hash); +} + +} // extern "C" diff --git a/src/Native/libmultihash/kawpow/ethash/kiss99.hpp b/src/Native/libmultihash/kawpow/ethash/kiss99.hpp new file mode 100644 index 00000000..8332a7ce --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/kiss99.hpp @@ -0,0 +1,64 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#pragma once + +#include "../support/attributes.h" +#include + +/** + * KISS PRNG by the spec from 1999. + * + * The implementation of KISS pseudo-random number generator + * by the specification published on 21 Jan 1999 in + * http://www.cse.yorku.ca/~oz/marsaglia-rng.html. + * The KISS is not versioned so here we are using `kiss99` prefix to indicate + * the version from 1999. + * + * The specification uses `unsigned long` type with the intention for 32-bit + * values. Because in GCC/clang for 64-bit architectures `unsigned long` is + * 64-bit size type, here the explicit `uint32_t` type is used. + * + * @defgroup kiss99 KISS99 + * @{ + */ + +/** + * The KISS generator. + */ +class kiss99 +{ + uint32_t z = 362436069; + uint32_t w = 521288629; + uint32_t jsr = 123456789; + uint32_t jcong = 380116160; + +public: + /** Creates KISS generator state with default values provided by the specification. */ + kiss99() noexcept = default; + + /** Creates KISS generator state with provided init values.*/ + kiss99(uint32_t _z, uint32_t _w, uint32_t _jsr, uint32_t _jcong) noexcept + : z{_z}, w{_w}, jsr{_jsr}, jcong{_jcong} + {} + + /** Generates next number from the KISS generator. */ + NO_SANITIZE("unsigned-integer-overflow") + uint32_t operator()() noexcept + { + z = 36969 * (z & 0xffff) + (z >> 16); + w = 18000 * (w & 0xffff) + (w >> 16); + + jcong = 69069 * jcong + 1234567; + + jsr ^= (jsr << 17); + jsr ^= (jsr >> 13); + jsr ^= (jsr << 5); + + return (((z << 16) + w) ^ jcong) + jsr; + } +}; + +/** @} */ diff --git a/src/Native/libmultihash/kawpow/ethash/managed.cpp b/src/Native/libmultihash/kawpow/ethash/managed.cpp new file mode 100644 index 00000000..47dd49b8 --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/managed.cpp @@ -0,0 +1,99 @@ +// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. +// Copyright 2018-2019 Pawel Bylica. +// Licensed under the Apache License, Version 2.0. + +#include "ethash-internal.hpp" + +#include +#include + +#if !defined(__has_cpp_attribute) +#define __has_cpp_attribute(x) 0 +#endif + +#if __has_cpp_attribute(gnu::noinline) +#define ATTRIBUTE_NOINLINE [[gnu::noinline]] +#elif _MSC_VER +#define ATTRIBUTE_NOINLINE __declspec(noinline) +#else +#define ATTRIBUTE_NOINLINE +#endif + +using namespace ethash; + +namespace +{ +std::mutex shared_context_mutex; +std::shared_ptr shared_context; +thread_local std::shared_ptr thread_local_context; + +std::mutex shared_context_full_mutex; +std::shared_ptr shared_context_full; +thread_local std::shared_ptr thread_local_context_full; + +/// Update thread local epoch context. +/// +/// This function is on the slow path. It's separated to allow inlining the fast +/// path. +/// +/// @todo: Redesign to guarantee deallocation before new allocation. +ATTRIBUTE_NOINLINE +void update_local_context(int epoch_number) +{ + // Release the shared pointer of the obsoleted context. + thread_local_context.reset(); + + // Local context invalid, check the shared context. + std::lock_guard lock{shared_context_mutex}; + + if (!shared_context || shared_context->epoch_number != epoch_number) + { + // Release the shared pointer of the obsoleted context. + shared_context.reset(); + + // Build new context. + shared_context = create_epoch_context(epoch_number); + } + + thread_local_context = shared_context; +} + +ATTRIBUTE_NOINLINE +void update_local_context_full(int epoch_number) +{ + // Release the shared pointer of the obsoleted context. + thread_local_context_full.reset(); + + // Local context invalid, check the shared context. + std::lock_guard lock{shared_context_full_mutex}; + + if (!shared_context_full || shared_context_full->epoch_number != epoch_number) + { + // Release the shared pointer of the obsoleted context. + shared_context_full.reset(); + + // Build new context. + shared_context_full = create_epoch_context_full(epoch_number); + } + + thread_local_context_full = shared_context_full; +} +} // namespace + +const ethash_epoch_context* ethash_get_global_epoch_context(int epoch_number) noexcept +{ + // Check if local context matches epoch number. + if (!thread_local_context || thread_local_context->epoch_number != epoch_number) + update_local_context(epoch_number); + + return thread_local_context.get(); +} + +const ethash_epoch_context_full* ethash_get_global_epoch_context_full(int epoch_number) noexcept +{ + // Check if local context matches epoch number. + if (!thread_local_context_full || thread_local_context_full->epoch_number != epoch_number) + update_local_context_full(epoch_number); + + return thread_local_context_full.get(); +} diff --git a/src/Native/libmultihash/kawpow/ethash/primes.c b/src/Native/libmultihash/kawpow/ethash/primes.c new file mode 100644 index 00000000..e27a535e --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/primes.c @@ -0,0 +1,43 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#include "primes.h" + +/** Checks if the number is prime. Requires the number to be > 2 and odd. */ +static int is_odd_prime(int number) +{ + int d; + + /* Check factors up to sqrt(number). + To avoid computing sqrt, compare d*d <= number with 64-bit precision. */ + for (d = 3; (int64_t)d * (int64_t)d <= (int64_t)number; d += 2) + { + if (number % d == 0) + return 0; + } + + return 1; +} + +int ethash_find_largest_prime(int upper_bound) +{ + int n = upper_bound; + + if (n < 2) + return 0; + + if (n == 2) + return 2; + + /* If even number, skip it. */ + if (n % 2 == 0) + --n; + + /* Test descending odd numbers. */ + while (!is_odd_prime(n)) + n -= 2; + + return n; +} diff --git a/src/Native/libmultihash/kawpow/ethash/primes.h b/src/Native/libmultihash/kawpow/ethash/primes.h new file mode 100644 index 00000000..d9220754 --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/primes.h @@ -0,0 +1,25 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Finds the largest prime number not greater than the provided upper bound. + * + * @param upper_bound The upper bound. SHOULD be greater than 1. + * @return The largest prime number `p` such `p <= upper_bound`. + * In case `upper_bound <= 1`, returns 0. + */ +int ethash_find_largest_prime(int upper_bound) NOEXCEPT; + +#ifdef __cplusplus +} +#endif diff --git a/src/Native/libmultihash/kawpow/ethash/progpow.cpp b/src/Native/libmultihash/kawpow/ethash/progpow.cpp new file mode 100644 index 00000000..7a53ae1c --- /dev/null +++ b/src/Native/libmultihash/kawpow/ethash/progpow.cpp @@ -0,0 +1,569 @@ +// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. +// Copyright 2018-2019 Pawel Bylica. +// Licensed under the Apache License, Version 2.0. + +#include + +#include "bit_manipulation.h" +#include "endianness.hpp" +#include "ethash-internal.hpp" +#include "kiss99.hpp" +#include "../../test/unittests/helpers.hpp" +#include + +#include + +namespace progpow +{ +namespace +{ +/// A variant of Keccak hash function for ProgPoW. +/// +/// This Keccak hash function uses 800-bit permutation (Keccak-f[800]) with 576 bitrate. +/// It take exactly 576 bits of input (split across 3 arguments) and adds no padding. +/// +/// @param header_hash The 256-bit header hash. +/// @param nonce The 64-bit nonce. +/// @param mix_hash Additional 256-bits of data. +/// @return The 256-bit output of the hash function. +void keccak_progpow_256(uint32_t* st) noexcept +{ + ethash_keccakf800(st); +} + +/// The same as keccak_progpow_256() but uses null mix +/// and returns top 64 bits of the output being a big-endian prefix of the 256-bit hash. + inline void keccak_progpow_64(uint32_t* st) noexcept +{ + keccak_progpow_256(st); +} + + +/// ProgPoW mix RNG state. +/// +/// Encapsulates the state of the random number generator used in computing ProgPoW mix. +/// This includes the state of the KISS99 RNG and the precomputed random permutation of the +/// sequence of mix item indexes. +class mix_rng_state +{ +public: + inline explicit mix_rng_state(uint32_t* seed) noexcept; + + uint32_t next_dst() noexcept { return dst_seq[(dst_counter++) % num_regs]; } + uint32_t next_src() noexcept { return src_seq[(src_counter++) % num_regs]; } + + kiss99 rng; + +private: + size_t dst_counter = 0; + std::array dst_seq; + size_t src_counter = 0; + std::array src_seq; +}; + +mix_rng_state::mix_rng_state(uint32_t* hash_seed) noexcept +{ + const auto seed_lo = static_cast(hash_seed[0]); + const auto seed_hi = static_cast(hash_seed[1]); + + const auto z = fnv1a(fnv_offset_basis, seed_lo); + const auto w = fnv1a(z, seed_hi); + const auto jsr = fnv1a(w, seed_lo); + const auto jcong = fnv1a(jsr, seed_hi); + + rng = kiss99{z, w, jsr, jcong}; + + // Create random permutations of mix destinations / sources. + // Uses Fisher-Yates shuffle. + for (uint32_t i = 0; i < num_regs; ++i) + { + dst_seq[i] = i; + src_seq[i] = i; + } + + for (uint32_t i = num_regs; i > 1; --i) + { + std::swap(dst_seq[i - 1], dst_seq[rng() % i]); + std::swap(src_seq[i - 1], src_seq[rng() % i]); + } +} + + +NO_SANITIZE("unsigned-integer-overflow") +inline uint32_t random_math(uint32_t a, uint32_t b, uint32_t selector) noexcept +{ + switch (selector % 11) + { + default: + case 0: + return a + b; + case 1: + return a * b; + case 2: + return mul_hi32(a, b); + case 3: + return std::min(a, b); + case 4: + return rotl32(a, b); + case 5: + return rotr32(a, b); + case 6: + return a & b; + case 7: + return a | b; + case 8: + return a ^ b; + case 9: + return clz32(a) + clz32(b); + case 10: + return popcount32(a) + popcount32(b); + } +} + +/// Merge data from `b` and `a`. +/// Assuming `a` has high entropy, only do ops that retain entropy even if `b` +/// has low entropy (i.e. do not do `a & b`). +NO_SANITIZE("unsigned-integer-overflow") +inline void random_merge(uint32_t& a, uint32_t b, uint32_t selector) noexcept +{ + const auto x = (selector >> 16) % 31 + 1; // Additional non-zero selector from higher bits. + switch (selector % 4) + { + case 0: + a = (a * 33) + b; + break; + case 1: + a = (a ^ b) * 33; + break; + case 2: + a = rotl32(a, x) ^ b; + break; + case 3: + a = rotr32(a, x) ^ b; + break; + } +} + +static const uint32_t ravencoin_kawpow[15] = { + 0x00000072, //R + 0x00000041, //A + 0x00000056, //V + 0x00000045, //E + 0x0000004E, //N + 0x00000043, //C + 0x0000004F, //O + 0x00000049, //I + 0x0000004E, //N + 0x0000004B, //K + 0x00000041, //A + 0x00000057, //W + 0x00000050, //P + 0x0000004F, //O + 0x00000057, //W +}; + +using lookup_fn = hash2048 (*)(const epoch_context&, uint32_t); + +using mix_array = std::array, num_lanes>; + +void round( + const epoch_context& context, uint32_t r, mix_array& mix, mix_rng_state state, lookup_fn lookup) +{ + const uint32_t num_items = static_cast(context.full_dataset_num_items / 2); + const uint32_t item_index = mix[r % num_lanes][0] % num_items; + const hash2048 item = lookup(context, item_index); + + constexpr size_t num_words_per_lane = sizeof(item) / (sizeof(uint32_t) * num_lanes); + constexpr int max_operations = + num_cache_accesses > num_math_operations ? num_cache_accesses : num_math_operations; + + // Process lanes. + for (int i = 0; i < max_operations; ++i) + { + if (i < num_cache_accesses) // Random access to cached memory. + { + const auto src = state.next_src(); + const auto dst = state.next_dst(); + const auto sel = state.rng(); + + for (size_t l = 0; l < num_lanes; ++l) + { + const size_t offset = mix[l][src] % l1_cache_num_items; + random_merge(mix[l][dst], le::uint32(context.l1_cache[offset]), sel); + } + } + if (i < num_math_operations) // Random math. + { + // Generate 2 unique source indexes. + const auto src_rnd = state.rng() % (num_regs * (num_regs - 1)); + const auto src1 = src_rnd % num_regs; // O <= src1 < num_regs + auto src2 = src_rnd / num_regs; // 0 <= src2 < num_regs - 1 + if (src2 >= src1) + ++src2; + + const auto sel1 = state.rng(); + const auto dst = state.next_dst(); + const auto sel2 = state.rng(); + + for (size_t l = 0; l < num_lanes; ++l) + { + const uint32_t data = random_math(mix[l][src1], mix[l][src2], sel1); + random_merge(mix[l][dst], data, sel2); + } + } + } + + // DAG access pattern. + uint32_t dsts[num_words_per_lane]; + uint32_t sels[num_words_per_lane]; + for (size_t i = 0; i < num_words_per_lane; ++i) + { + dsts[i] = i == 0 ? 0 : state.next_dst(); + sels[i] = state.rng(); + } + + // DAG access. + for (size_t l = 0; l < num_lanes; ++l) + { + const auto offset = ((l ^ r) % num_lanes) * num_words_per_lane; + for (size_t i = 0; i < num_words_per_lane; ++i) + { + const auto word = le::uint32(item.word32s[offset + i]); + random_merge(mix[l][dsts[i]], word, sels[i]); + } + } +} + +mix_array init_mix(uint32_t* hash_seed) +{ + const uint32_t z = fnv1a(fnv_offset_basis, static_cast(hash_seed[0])); + const uint32_t w = fnv1a(z, static_cast(hash_seed[1])); + + mix_array mix; + for (uint32_t l = 0; l < mix.size(); ++l) + { + const uint32_t jsr = fnv1a(w, l); + const uint32_t jcong = fnv1a(jsr, l); + kiss99 rng{z, w, jsr, jcong}; + + for (auto& row : mix[l]) + row = rng(); + } + return mix; +} + +hash256 hash_mix( + const epoch_context& context, int block_number, uint32_t * seed, lookup_fn lookup) noexcept +{ + auto mix = init_mix(seed); + auto number = uint64_t(block_number / period_length); + uint32_t new_state[2]; + new_state[0] = (uint32_t)number; + new_state[1] = (uint32_t)(number >> 32); + mix_rng_state state{new_state}; + + for (uint32_t i = 0; i < 64; ++i) + round(context, i, mix, state, lookup); + + // Reduce mix data to a single per-lane result. + uint32_t lane_hash[num_lanes]; + for (size_t l = 0; l < num_lanes; ++l) + { + lane_hash[l] = fnv_offset_basis; + for (uint32_t i = 0; i < num_regs; ++i) + lane_hash[l] = fnv1a(lane_hash[l], mix[l][i]); + } + + // Reduce all lanes to a single 256-bit result. + static constexpr size_t num_words = sizeof(hash256) / sizeof(uint32_t); + hash256 mix_hash; + for (uint32_t& w : mix_hash.word32s) + w = fnv_offset_basis; + for (size_t l = 0; l < num_lanes; ++l) + mix_hash.word32s[l % num_words] = fnv1a(mix_hash.word32s[l % num_words], lane_hash[l]); + return le::uint32s(mix_hash); +} +} // namespace + +result hash(const epoch_context& context, int block_number, const hash256& header_hash, + uint64_t nonce) noexcept +{ + uint32_t hash_seed[2]; // KISS99 initiator + + uint32_t state2[8]; + + { + uint32_t state[25] = {0x0}; // Keccak's state + + // Absorb phase for initial round of keccak + // 1st fill with header data (8 words) + for (int i = 0; i < 8; i++) + state[i] = header_hash.word32s[i]; + + // 2nd fill with nonce (2 words) + state[8] = (uint32_t)nonce; + state[9] = (uint32_t)(nonce >> 32); + + // 3rd apply ravencoin input constraints + for (int i = 10; i < 25; i++) + state[i] = ravencoin_kawpow[i-10]; + + keccak_progpow_64(state); + + for (int i = 0; i < 8; i++) + state2[i] = state[i]; + } + + hash_seed[0] = state2[0]; + hash_seed[1] = state2[1]; + const hash256 mix_hash = hash_mix(context, block_number, hash_seed, calculate_dataset_item_2048); + + uint32_t state[25] = {0x0}; // Keccak's state + + // Absorb phase for last round of keccak (256 bits) + // 1st initial 8 words of state are kept as carry-over from initial keccak + for (int i = 0; i < 8; i++) + state[i] = state2[i]; + + // 2nd subsequent 8 words are carried from digest/mix + for (int i = 8; i < 16; i++) + state[i] = mix_hash.word32s[i-8]; + + // 3rd apply ravencoin input constraints + for (int i = 16; i < 25; i++) + state[i] = ravencoin_kawpow[i - 16]; + + // Run keccak loop + keccak_progpow_256(state); + + hash256 output; + for (int i = 0; i < 8; ++i) + output.word32s[i] = le::uint32(state[i]); + + return {output, mix_hash}; +} + +result hash(const epoch_context_full& context, int block_number, const hash256& header_hash, + uint64_t nonce) noexcept +{ + static const auto lazy_lookup = [](const epoch_context& ctx, uint32_t index) noexcept + { + auto* full_dataset_1024 = static_cast(ctx).full_dataset; + auto* full_dataset_2048 = reinterpret_cast(full_dataset_1024); + hash2048& item = full_dataset_2048[index]; + if (item.word64s[0] == 0) + { + // TODO: Copy elision here makes it thread-safe? + item = calculate_dataset_item_2048(ctx, index); + } + + return item; + }; + + uint32_t hash_seed[2]; // KISS99 initiator + + uint32_t state2[8]; + + { + uint32_t state[25] = {0x0}; // Keccak's state + + // Absorb phase for initial round of keccak + // 1st fill with header data (8 words) + for (int i = 0; i < 8; i++) + state[i] = header_hash.word32s[i]; + + // 2nd fill with nonce (2 words) + state[8] = (uint32_t)nonce; + state[9] = (uint32_t)(nonce >> 32); + + // 3rd apply ravencoin input constraints + for (int i = 10; i < 25; i++) + state[i] = ravencoin_kawpow[i-10]; + + keccak_progpow_64(state); + + for (int i = 0; i < 8; i++) + state2[i] = state[i]; + } + + hash_seed[0] = state2[0]; + hash_seed[1] = state2[1]; + + const hash256 mix_hash = hash_mix(context, block_number, hash_seed, lazy_lookup); + + uint32_t state[25] = {0x0}; // Keccak's state + + // Absorb phase for last round of keccak (256 bits) + // 1st initial 8 words of state are kept as carry-over from initial keccak + for (int i = 0; i < 8; i++) + state[i] = state2[i]; + + // 2nd subsequent 8 words are carried from digest/mix + for (int i = 8; i < 16; i++) + state[i] = mix_hash.word32s[i-8]; + + // 3rd apply ravencoin input constraints + for (int i = 16; i < 25; i++) + state[i] = ravencoin_kawpow[i - 16]; + + // Run keccak loop + keccak_progpow_256(state); + + hash256 output; + for (int i = 0; i < 8; ++i) + output.word32s[i] = le::uint32(state[i]); + + return {output, mix_hash}; +} + +bool verify(const epoch_context& context, int block_number, const hash256& header_hash, + const hash256& mix_hash, uint64_t nonce, const hash256& boundary) noexcept +{ + uint32_t hash_seed[2]; // KISS99 initiator + uint32_t state2[8]; + + { + // Absorb phase for initial round of keccak + // 1st fill with header data (8 words) + uint32_t state[25] = {0x0}; // Keccak's state + for (int i = 0; i < 8; i++) + state[i] = header_hash.word32s[i]; + + // 2nd fill with nonce (2 words) + state[8] = (uint32_t)nonce; + state[9] = (uint32_t)(nonce >> 32); + + // 3rd apply ravencoin input constraints + for (int i = 10; i < 25; i++) + state[i] = ravencoin_kawpow[i-10]; + + keccak_progpow_64(state); + + for (int i = 0; i < 8; i++) + state2[i] = state[i]; + } + + hash_seed[0] = state2[0]; + hash_seed[1] = state2[1]; + + uint32_t state[25] = {0x0}; // Keccak's state + + // Absorb phase for last round of keccak (256 bits) + // 1st initial 8 words of state are kept as carry-over from initial keccak + for (int i = 0; i < 8; i++) + state[i] = state2[i]; + + + // 2nd subsequent 8 words are carried from digest/mix + for (int i = 8; i < 16; i++) + state[i] = mix_hash.word32s[i-8]; + + // 3rd apply ravencoin input constraints + for (int i = 16; i < 25; i++) + state[i] = ravencoin_kawpow[i - 16]; + + // Run keccak loop + keccak_progpow_256(state); + + hash256 output; + for (int i = 0; i < 8; ++i) + output.word32s[i] = le::uint32(state[i]); + if (!is_less_or_equal(output, boundary)) + return false; + + const hash256 expected_mix_hash = + hash_mix(context, block_number, hash_seed, calculate_dataset_item_2048); + + return is_equal(expected_mix_hash, mix_hash); +} + +//bool light_verify(const char* str_header_hash, +// const char* str_mix_hash, const char* str_nonce, const char* str_boundary, char* str_final) noexcept +//{ +// +// hash256 header_hash = to_hash256(str_header_hash); +// hash256 mix_hash = to_hash256(str_mix_hash); +// hash256 boundary = to_hash256(str_boundary); +// +// uint64_t nonce = std::stoull(str_nonce, nullptr, 16); +// +// uint32_t state2[8]; +// +// { +// // Absorb phase for initial round of keccak +// // 1st fill with header data (8 words) +// uint32_t state[25]; // Keccak's state +// for (int i = 0; i < 8; i++) +// state[i] = header_hash.word32s[i]; +// // 2nd fill with nonce (2 words) +// state[8] = (uint32_t)nonce; +// state[9] = (uint32_t)(nonce >> 32); +// // 3rd all remaining elements to zero +// for (int i = 10; i < 25; i++) +// state[i] = 0; +// +// keccak_progpow_64(state); +// +// for (int i = 0; i < 8; i++) +// state2[i] = state[i]; +// } +// +// uint32_t state[25]; // Keccak's state +// for (int i = 0; i < 8; i++) +// state[i] = state2[i]; +// +// // Absorb phase for last round of keccak (256 bits) +// // 1st initial 8 words of state are kept as carry-over from initial keccak +// // 2nd subsequent 8 words are carried from digest/mix +// for (int i = 8; i < 16; i++) +// state[i] = mix_hash.word32s[i-8]; +// +// // 3rd all other elements to zero +// for (int i = 16; i < 25; i++) +// state[i] = 0; +// +// // Run keccak loop +// keccak_progpow_256(state); +// +// hash256 output; +// for (int i = 0; i < 8; ++i) +// output.word32s[i] = le::uint32(state[i]); +// if (!is_less_or_equal(output, boundary)) +// return false; +// +// if (!is_less_or_equal(output, boundary)) +// return false; +// +// memcpy(str_final,&to_hex(output)[0],64); +// return true; +//} + +search_result search_light(const epoch_context& context, int block_number, + const hash256& header_hash, const hash256& boundary, uint64_t start_nonce, + size_t iterations) noexcept +{ + const uint64_t end_nonce = start_nonce + iterations; + for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce) + { + result r = hash(context, block_number, header_hash, nonce); + if (is_less_or_equal(r.final_hash, boundary)) + return {r, nonce}; + } + return {}; +} + +search_result search(const epoch_context_full& context, int block_number, + const hash256& header_hash, const hash256& boundary, uint64_t start_nonce, + size_t iterations) noexcept +{ + const uint64_t end_nonce = start_nonce + iterations; + for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce) + { + result r = hash(context, block_number, header_hash, nonce); + if (is_less_or_equal(r.final_hash, boundary)) + return {r, nonce}; + } + return {}; +} + +} // namespace progpow diff --git a/src/Native/libmultihash/kawpow/keccak/CMakeLists.txt b/src/Native/libmultihash/kawpow/keccak/CMakeLists.txt new file mode 100644 index 00000000..05be8d1b --- /dev/null +++ b/src/Native/libmultihash/kawpow/keccak/CMakeLists.txt @@ -0,0 +1,25 @@ +# ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. +# Copyright 2019 Pawel Bylica. +# Licensed under the Apache License, Version 2.0. + +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) + +add_library( + keccak + ${include_dir}/ethash/keccak.h + ${include_dir}/ethash/keccak.hpp + keccak.c + keccakf800.c + keccakf1600.c +) + +target_include_directories(keccak PUBLIC $$) + +install( + TARGETS keccak + EXPORT ethashTargets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/src/Native/libmultihash/kawpow/keccak/keccak.c b/src/Native/libmultihash/kawpow/keccak/keccak.c new file mode 100644 index 00000000..37a6c635 --- /dev/null +++ b/src/Native/libmultihash/kawpow/keccak/keccak.c @@ -0,0 +1,123 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#include + +#include "../support/attributes.h" +#include + +#if _WIN32 +/* On Windows assume little endian. */ +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __BYTE_ORDER __LITTLE_ENDIAN +#elif __APPLE__ +#include +#else +#include +#endif + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define to_le64(X) X +#else +#define to_le64(X) __builtin_bswap64(X) +#endif + + +/** Loads 64-bit integer from given memory location as little-endian number. */ +static INLINE ALWAYS_INLINE uint64_t load_le(const uint8_t* data) +{ + /* memcpy is the best way of expressing the intention. Every compiler will + optimize is to single load instruction if the target architecture + supports unaligned memory access (GCC and clang even in O0). + This is great trick because we are violating C/C++ memory alignment + restrictions with no performance penalty. */ + uint64_t word; + memcpy(&word, data, sizeof(word)); + return to_le64(word); +} + +static INLINE ALWAYS_INLINE void keccak( + uint64_t* out, size_t bits, const uint8_t* data, size_t size) +{ + static const size_t word_size = sizeof(uint64_t); + const size_t hash_size = bits / 8; + const size_t block_size = (1600 - bits * 2) / 8; + + size_t i; + uint64_t* state_iter; + uint64_t last_word = 0; + uint8_t* last_word_iter = (uint8_t*)&last_word; + + uint64_t state[25] = {0}; + + while (size >= block_size) + { + for (i = 0; i < (block_size / word_size); ++i) + { + state[i] ^= load_le(data); + data += word_size; + } + + ethash_keccakf1600(state); + + size -= block_size; + } + + state_iter = state; + + while (size >= word_size) + { + *state_iter ^= load_le(data); + ++state_iter; + data += word_size; + size -= word_size; + } + + while (size > 0) + { + *last_word_iter = *data; + ++last_word_iter; + ++data; + --size; + } + *last_word_iter = 0x01; + *state_iter ^= to_le64(last_word); + + state[(block_size / word_size) - 1] ^= 0x8000000000000000; + + ethash_keccakf1600(state); + + for (i = 0; i < (hash_size / word_size); ++i) + out[i] = to_le64(state[i]); +} + +union ethash_hash256 ethash_keccak256(const uint8_t* data, size_t size) +{ + union ethash_hash256 hash; + keccak(hash.word64s, 256, data, size); + return hash; +} + +union ethash_hash256 ethash_keccak256_32(const uint8_t data[32]) +{ + union ethash_hash256 hash; + keccak(hash.word64s, 256, data, 32); + return hash; +} + +union ethash_hash512 ethash_keccak512(const uint8_t* data, size_t size) +{ + union ethash_hash512 hash; + keccak(hash.word64s, 512, data, size); + return hash; +} + +union ethash_hash512 ethash_keccak512_64(const uint8_t data[64]) +{ + union ethash_hash512 hash; + keccak(hash.word64s, 512, data, 64); + return hash; +} diff --git a/src/Native/libmultihash/kawpow/keccak/keccakf1600.c b/src/Native/libmultihash/kawpow/keccak/keccakf1600.c new file mode 100644 index 00000000..e12b268d --- /dev/null +++ b/src/Native/libmultihash/kawpow/keccak/keccakf1600.c @@ -0,0 +1,255 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#include + +static uint64_t rol(uint64_t x, unsigned s) +{ + return (x << s) | (x >> (64 - s)); +} + +static const uint64_t round_constants[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, +}; + +void ethash_keccakf1600(uint64_t state[25]) +{ + /* The implementation based on the "simple" implementation by Ronny Van Keer. */ + + int round; + + uint64_t Aba, Abe, Abi, Abo, Abu; + uint64_t Aga, Age, Agi, Ago, Agu; + uint64_t Aka, Ake, Aki, Ako, Aku; + uint64_t Ama, Ame, Ami, Amo, Amu; + uint64_t Asa, Ase, Asi, Aso, Asu; + + uint64_t Eba, Ebe, Ebi, Ebo, Ebu; + uint64_t Ega, Ege, Egi, Ego, Egu; + uint64_t Eka, Eke, Eki, Eko, Eku; + uint64_t Ema, Eme, Emi, Emo, Emu; + uint64_t Esa, Ese, Esi, Eso, Esu; + + uint64_t Ba, Be, Bi, Bo, Bu; + + uint64_t Da, De, Di, Do, Du; + + Aba = state[0]; + Abe = state[1]; + Abi = state[2]; + Abo = state[3]; + Abu = state[4]; + Aga = state[5]; + Age = state[6]; + Agi = state[7]; + Ago = state[8]; + Agu = state[9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for (round = 0; round < 24; round += 2) + { + /* Round (round + 0): Axx -> Exx */ + + Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa; + Be = Abe ^ Age ^ Ake ^ Ame ^ Ase; + Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; + Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; + Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; + + Da = Bu ^ rol(Be, 1); + De = Ba ^ rol(Bi, 1); + Di = Be ^ rol(Bo, 1); + Do = Bi ^ rol(Bu, 1); + Du = Bo ^ rol(Ba, 1); + + Ba = Aba ^ Da; + Be = rol(Age ^ De, 44); + Bi = rol(Aki ^ Di, 43); + Bo = rol(Amo ^ Do, 21); + Bu = rol(Asu ^ Du, 14); + Eba = Ba ^ (~Be & Bi) ^ round_constants[round]; + Ebe = Be ^ (~Bi & Bo); + Ebi = Bi ^ (~Bo & Bu); + Ebo = Bo ^ (~Bu & Ba); + Ebu = Bu ^ (~Ba & Be); + + Ba = rol(Abo ^ Do, 28); + Be = rol(Agu ^ Du, 20); + Bi = rol(Aka ^ Da, 3); + Bo = rol(Ame ^ De, 45); + Bu = rol(Asi ^ Di, 61); + Ega = Ba ^ (~Be & Bi); + Ege = Be ^ (~Bi & Bo); + Egi = Bi ^ (~Bo & Bu); + Ego = Bo ^ (~Bu & Ba); + Egu = Bu ^ (~Ba & Be); + + Ba = rol(Abe ^ De, 1); + Be = rol(Agi ^ Di, 6); + Bi = rol(Ako ^ Do, 25); + Bo = rol(Amu ^ Du, 8); + Bu = rol(Asa ^ Da, 18); + Eka = Ba ^ (~Be & Bi); + Eke = Be ^ (~Bi & Bo); + Eki = Bi ^ (~Bo & Bu); + Eko = Bo ^ (~Bu & Ba); + Eku = Bu ^ (~Ba & Be); + + Ba = rol(Abu ^ Du, 27); + Be = rol(Aga ^ Da, 36); + Bi = rol(Ake ^ De, 10); + Bo = rol(Ami ^ Di, 15); + Bu = rol(Aso ^ Do, 56); + Ema = Ba ^ (~Be & Bi); + Eme = Be ^ (~Bi & Bo); + Emi = Bi ^ (~Bo & Bu); + Emo = Bo ^ (~Bu & Ba); + Emu = Bu ^ (~Ba & Be); + + Ba = rol(Abi ^ Di, 62); + Be = rol(Ago ^ Do, 55); + Bi = rol(Aku ^ Du, 39); + Bo = rol(Ama ^ Da, 41); + Bu = rol(Ase ^ De, 2); + Esa = Ba ^ (~Be & Bi); + Ese = Be ^ (~Bi & Bo); + Esi = Bi ^ (~Bo & Bu); + Eso = Bo ^ (~Bu & Ba); + Esu = Bu ^ (~Ba & Be); + + + /* Round (round + 1): Exx -> Axx */ + + Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa; + Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; + Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; + Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; + Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; + + Da = Bu ^ rol(Be, 1); + De = Ba ^ rol(Bi, 1); + Di = Be ^ rol(Bo, 1); + Do = Bi ^ rol(Bu, 1); + Du = Bo ^ rol(Ba, 1); + + Ba = Eba ^ Da; + Be = rol(Ege ^ De, 44); + Bi = rol(Eki ^ Di, 43); + Bo = rol(Emo ^ Do, 21); + Bu = rol(Esu ^ Du, 14); + Aba = Ba ^ (~Be & Bi) ^ round_constants[round + 1]; + Abe = Be ^ (~Bi & Bo); + Abi = Bi ^ (~Bo & Bu); + Abo = Bo ^ (~Bu & Ba); + Abu = Bu ^ (~Ba & Be); + + Ba = rol(Ebo ^ Do, 28); + Be = rol(Egu ^ Du, 20); + Bi = rol(Eka ^ Da, 3); + Bo = rol(Eme ^ De, 45); + Bu = rol(Esi ^ Di, 61); + Aga = Ba ^ (~Be & Bi); + Age = Be ^ (~Bi & Bo); + Agi = Bi ^ (~Bo & Bu); + Ago = Bo ^ (~Bu & Ba); + Agu = Bu ^ (~Ba & Be); + + Ba = rol(Ebe ^ De, 1); + Be = rol(Egi ^ Di, 6); + Bi = rol(Eko ^ Do, 25); + Bo = rol(Emu ^ Du, 8); + Bu = rol(Esa ^ Da, 18); + Aka = Ba ^ (~Be & Bi); + Ake = Be ^ (~Bi & Bo); + Aki = Bi ^ (~Bo & Bu); + Ako = Bo ^ (~Bu & Ba); + Aku = Bu ^ (~Ba & Be); + + Ba = rol(Ebu ^ Du, 27); + Be = rol(Ega ^ Da, 36); + Bi = rol(Eke ^ De, 10); + Bo = rol(Emi ^ Di, 15); + Bu = rol(Eso ^ Do, 56); + Ama = Ba ^ (~Be & Bi); + Ame = Be ^ (~Bi & Bo); + Ami = Bi ^ (~Bo & Bu); + Amo = Bo ^ (~Bu & Ba); + Amu = Bu ^ (~Ba & Be); + + Ba = rol(Ebi ^ Di, 62); + Be = rol(Ego ^ Do, 55); + Bi = rol(Eku ^ Du, 39); + Bo = rol(Ema ^ Da, 41); + Bu = rol(Ese ^ De, 2); + Asa = Ba ^ (~Be & Bi); + Ase = Be ^ (~Bi & Bo); + Asi = Bi ^ (~Bo & Bu); + Aso = Bo ^ (~Bu & Ba); + Asu = Bu ^ (~Ba & Be); + } + + state[0] = Aba; + state[1] = Abe; + state[2] = Abi; + state[3] = Abo; + state[4] = Abu; + state[5] = Aga; + state[6] = Age; + state[7] = Agi; + state[8] = Ago; + state[9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; +} diff --git a/src/Native/libmultihash/kawpow/keccak/keccakf800.c b/src/Native/libmultihash/kawpow/keccak/keccakf800.c new file mode 100644 index 00000000..5b9a1802 --- /dev/null +++ b/src/Native/libmultihash/kawpow/keccak/keccakf800.c @@ -0,0 +1,253 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#include + +static uint32_t rol(uint32_t x, unsigned s) +{ + return (x << s) | (x >> (32 - s)); +} + +static const uint32_t round_constants[22] = { + 0x00000001, + 0x00008082, + 0x0000808A, + 0x80008000, + 0x0000808B, + 0x80000001, + 0x80008081, + 0x00008009, + 0x0000008A, + 0x00000088, + 0x80008009, + 0x8000000A, + 0x8000808B, + 0x0000008B, + 0x00008089, + 0x00008003, + 0x00008002, + 0x00000080, + 0x0000800A, + 0x8000000A, + 0x80008081, + 0x00008080, +}; + +void ethash_keccakf800(uint32_t state[25]) +{ + /* The implementation directly translated from ethash_keccakf1600. */ + + int round; + + uint32_t Aba, Abe, Abi, Abo, Abu; + uint32_t Aga, Age, Agi, Ago, Agu; + uint32_t Aka, Ake, Aki, Ako, Aku; + uint32_t Ama, Ame, Ami, Amo, Amu; + uint32_t Asa, Ase, Asi, Aso, Asu; + + uint32_t Eba, Ebe, Ebi, Ebo, Ebu; + uint32_t Ega, Ege, Egi, Ego, Egu; + uint32_t Eka, Eke, Eki, Eko, Eku; + uint32_t Ema, Eme, Emi, Emo, Emu; + uint32_t Esa, Ese, Esi, Eso, Esu; + + uint32_t Ba, Be, Bi, Bo, Bu; + + uint32_t Da, De, Di, Do, Du; + + Aba = state[0]; + Abe = state[1]; + Abi = state[2]; + Abo = state[3]; + Abu = state[4]; + Aga = state[5]; + Age = state[6]; + Agi = state[7]; + Ago = state[8]; + Agu = state[9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for (round = 0; round < 22; round += 2) + { + /* Round (round + 0): Axx -> Exx */ + + Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa; + Be = Abe ^ Age ^ Ake ^ Ame ^ Ase; + Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; + Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; + Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; + + Da = Bu ^ rol(Be, 1); + De = Ba ^ rol(Bi, 1); + Di = Be ^ rol(Bo, 1); + Do = Bi ^ rol(Bu, 1); + Du = Bo ^ rol(Ba, 1); + + Ba = Aba ^ Da; + Be = rol(Age ^ De, 12); + Bi = rol(Aki ^ Di, 11); + Bo = rol(Amo ^ Do, 21); + Bu = rol(Asu ^ Du, 14); + Eba = Ba ^ (~Be & Bi) ^ round_constants[round]; + Ebe = Be ^ (~Bi & Bo); + Ebi = Bi ^ (~Bo & Bu); + Ebo = Bo ^ (~Bu & Ba); + Ebu = Bu ^ (~Ba & Be); + + Ba = rol(Abo ^ Do, 28); + Be = rol(Agu ^ Du, 20); + Bi = rol(Aka ^ Da, 3); + Bo = rol(Ame ^ De, 13); + Bu = rol(Asi ^ Di, 29); + Ega = Ba ^ (~Be & Bi); + Ege = Be ^ (~Bi & Bo); + Egi = Bi ^ (~Bo & Bu); + Ego = Bo ^ (~Bu & Ba); + Egu = Bu ^ (~Ba & Be); + + Ba = rol(Abe ^ De, 1); + Be = rol(Agi ^ Di, 6); + Bi = rol(Ako ^ Do, 25); + Bo = rol(Amu ^ Du, 8); + Bu = rol(Asa ^ Da, 18); + Eka = Ba ^ (~Be & Bi); + Eke = Be ^ (~Bi & Bo); + Eki = Bi ^ (~Bo & Bu); + Eko = Bo ^ (~Bu & Ba); + Eku = Bu ^ (~Ba & Be); + + Ba = rol(Abu ^ Du, 27); + Be = rol(Aga ^ Da, 4); + Bi = rol(Ake ^ De, 10); + Bo = rol(Ami ^ Di, 15); + Bu = rol(Aso ^ Do, 24); + Ema = Ba ^ (~Be & Bi); + Eme = Be ^ (~Bi & Bo); + Emi = Bi ^ (~Bo & Bu); + Emo = Bo ^ (~Bu & Ba); + Emu = Bu ^ (~Ba & Be); + + Ba = rol(Abi ^ Di, 30); + Be = rol(Ago ^ Do, 23); + Bi = rol(Aku ^ Du, 7); + Bo = rol(Ama ^ Da, 9); + Bu = rol(Ase ^ De, 2); + Esa = Ba ^ (~Be & Bi); + Ese = Be ^ (~Bi & Bo); + Esi = Bi ^ (~Bo & Bu); + Eso = Bo ^ (~Bu & Ba); + Esu = Bu ^ (~Ba & Be); + + + /* Round (round + 1): Exx -> Axx */ + + Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa; + Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; + Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; + Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; + Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; + + Da = Bu ^ rol(Be, 1); + De = Ba ^ rol(Bi, 1); + Di = Be ^ rol(Bo, 1); + Do = Bi ^ rol(Bu, 1); + Du = Bo ^ rol(Ba, 1); + + Ba = Eba ^ Da; + Be = rol(Ege ^ De, 12); + Bi = rol(Eki ^ Di, 11); + Bo = rol(Emo ^ Do, 21); + Bu = rol(Esu ^ Du, 14); + Aba = Ba ^ (~Be & Bi) ^ round_constants[round + 1]; + Abe = Be ^ (~Bi & Bo); + Abi = Bi ^ (~Bo & Bu); + Abo = Bo ^ (~Bu & Ba); + Abu = Bu ^ (~Ba & Be); + + Ba = rol(Ebo ^ Do, 28); + Be = rol(Egu ^ Du, 20); + Bi = rol(Eka ^ Da, 3); + Bo = rol(Eme ^ De, 13); + Bu = rol(Esi ^ Di, 29); + Aga = Ba ^ (~Be & Bi); + Age = Be ^ (~Bi & Bo); + Agi = Bi ^ (~Bo & Bu); + Ago = Bo ^ (~Bu & Ba); + Agu = Bu ^ (~Ba & Be); + + Ba = rol(Ebe ^ De, 1); + Be = rol(Egi ^ Di, 6); + Bi = rol(Eko ^ Do, 25); + Bo = rol(Emu ^ Du, 8); + Bu = rol(Esa ^ Da, 18); + Aka = Ba ^ (~Be & Bi); + Ake = Be ^ (~Bi & Bo); + Aki = Bi ^ (~Bo & Bu); + Ako = Bo ^ (~Bu & Ba); + Aku = Bu ^ (~Ba & Be); + + Ba = rol(Ebu ^ Du, 27); + Be = rol(Ega ^ Da, 4); + Bi = rol(Eke ^ De, 10); + Bo = rol(Emi ^ Di, 15); + Bu = rol(Eso ^ Do, 24); + Ama = Ba ^ (~Be & Bi); + Ame = Be ^ (~Bi & Bo); + Ami = Bi ^ (~Bo & Bu); + Amo = Bo ^ (~Bu & Ba); + Amu = Bu ^ (~Ba & Be); + + Ba = rol(Ebi ^ Di, 30); + Be = rol(Ego ^ Do, 23); + Bi = rol(Eku ^ Du, 7); + Bo = rol(Ema ^ Da, 9); + Bu = rol(Ese ^ De, 2); + Asa = Ba ^ (~Be & Bi); + Ase = Be ^ (~Bi & Bo); + Asi = Bi ^ (~Bo & Bu); + Aso = Bo ^ (~Bu & Ba); + Asu = Bu ^ (~Ba & Be); + } + + state[0] = Aba; + state[1] = Abe; + state[2] = Abi; + state[3] = Abo; + state[4] = Abu; + state[5] = Aga; + state[6] = Age; + state[7] = Agi; + state[8] = Ago; + state[9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; +} diff --git a/src/Native/libmultihash/kawpow/support/attributes.h b/src/Native/libmultihash/kawpow/support/attributes.h new file mode 100644 index 00000000..83be231f --- /dev/null +++ b/src/Native/libmultihash/kawpow/support/attributes.h @@ -0,0 +1,33 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#pragma once + +/** inline */ +#if _MSC_VER || __STDC_VERSION__ +#define INLINE inline +#else +#define INLINE +#endif + +/** [[always_inline]] */ +#if _MSC_VER +#define ALWAYS_INLINE __forceinline +#elif defined(__has_attribute) && __STDC_VERSION__ +#if __has_attribute(always_inline) +#define ALWAYS_INLINE __attribute__((always_inline)) +#endif +#endif +#if !defined(ALWAYS_INLINE) +#define ALWAYS_INLINE +#endif + +/** [[no_sanitize()]] */ +#if __clang__ +#define NO_SANITIZE(sanitizer) \ + __attribute__((no_sanitize(sanitizer))) +#else +#define NO_SANITIZE(sanitizer) +#endif diff --git a/src/Native/libmultihash/libmultihash.vcxproj b/src/Native/libmultihash/libmultihash.vcxproj index b7092505..0a9001a5 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj +++ b/src/Native/libmultihash/libmultihash.vcxproj @@ -199,6 +199,13 @@ + + + + + + + @@ -296,6 +303,13 @@ + + + + + + + @@ -365,6 +379,10 @@ + + + +