diff --git a/Makefile.am b/Makefile.am
index e2f2d1ec5..5a0ed0791 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,6 +31,7 @@ minerd_SOURCES = elist.h \
cryptonight.c \
fresh.c \
neoscrypt.c \
+ s3.c \
x11.c \
x13.c \
x14.c \
diff --git a/NEWS b/NEWS
index 2d6b1ad7e..ded67ff38 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Version multi 1.0.6 (Tanguy Pruvot)
- Fix scrypt algo
- More work on VC2013
- Add -f tuning option to test with reduced difficulty
+- Add S3 algo
Version multi 1.0.5 (Tanguy Pruvot)
diff --git a/README.md b/README.md
index a3bf950a6..303b16c2f 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,7 @@ Algorithms
* ✓ __scrypt__ (Litecoin, Dogecoin, Feathercoin, etc..)
* ✓ __scrypt:N__ (Vertcoin [VTC])
* ✓ __sha256d__ (Bitcoin, Freicoin, Peercoin/PPCoin, Terracoin, etc..)
+ * ✓ __s3__ (OneCoin)
* ✓ __x11__ (Darkcoin [DRK], Hirocoin, Limecoin)
* ✓ __x13__ (Sherlockcoin, [ACE], [B2B], [GRC], [XHC], etc..)
* ✓ __x14__ (X14, Webcoin [WEB])
diff --git a/cpu-miner.c b/cpu-miner.c
index 9ffe66a24..ef4a72704 100644
--- a/cpu-miner.c
+++ b/cpu-miner.c
@@ -130,6 +130,7 @@ enum algos {
ALGO_SHAVITE3, /* Shavite3 */
ALGO_BLAKE, /* Blake */
ALGO_FRESH, /* Fresh */
+ ALGO_S3, /* S3 */
ALGO_X11, /* X11 */
ALGO_X13, /* X13 */
ALGO_X14, /* X14 */
@@ -150,6 +151,7 @@ static const char *algo_names[] = {
"shavite3",
"blake",
"fresh",
+ "s3",
"x11",
"x13",
"x14",
@@ -241,6 +243,7 @@ Options:\n\
shavite3 Shavite3\n\
blake Blake\n\
fresh Fresh\n\
+ s3 S3\n\
x11 X11\n\
x13 X13\n\
x14 X14\n\
@@ -1742,6 +1745,10 @@ static void *miner_thread(void *userdata)
rc = scanhash_fresh(thr_id, work.data, work.target, max_nonce,
&hashes_done);
break;
+ case ALGO_S3:
+ rc = scanhash_s3(thr_id, work.data, work.target, max_nonce,
+ &hashes_done);
+ break;
case ALGO_X11:
rc = scanhash_x11(thr_id, work.data, work.target, max_nonce,
&hashes_done);
diff --git a/cpuminer.vcxproj b/cpuminer.vcxproj
index 88cb692b9..4db872cfb 100644
--- a/cpuminer.vcxproj
+++ b/cpuminer.vcxproj
@@ -186,6 +186,7 @@
+
diff --git a/cpuminer.vcxproj.filters b/cpuminer.vcxproj.filters
index e923a5935..649e9d8ee 100644
--- a/cpuminer.vcxproj.filters
+++ b/cpuminer.vcxproj.filters
@@ -152,6 +152,7 @@
arch\x86
+
diff --git a/miner.h b/miner.h
index 2ba374506..25c80f42a 100644
--- a/miner.h
+++ b/miner.h
@@ -219,6 +219,9 @@ extern int scanhash_blake(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
extern int scanhash_fresh(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, uint64_t *hashes_done);
+extern int scanhash_s3(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
+ uint32_t max_nonce, uint64_t *hashes_done);
+
extern int scanhash_x11(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, uint64_t *hashes_done);
@@ -400,6 +403,7 @@ void freshhash(void* output, const void* input, uint32_t len);
void keccakhash(void *state, const void *input);
void inkhash(void *state, const void *input); /* shavite */
void neoscrypt(unsigned char *output, const unsigned char *password, uint32_t profile);
+void s3hash(void *output, const void *input);
void x11hash(void *output, const void *input);
void x13hash(void *output, const void *input);
void x14hash(void *output, const void *input);
diff --git a/s3.c b/s3.c
new file mode 100644
index 000000000..f6c3ce64c
--- /dev/null
+++ b/s3.c
@@ -0,0 +1,101 @@
+#include "miner.h"
+
+#include
+#include
+#include
+#include
+
+#include "sha3/sph_skein.h"
+#include "sha3/sph_shavite.h"
+#include "sha3/sph_simd.h"
+
+void s3hash(void *output, const void *input)
+{
+ sph_shavite512_context ctx_shavite;
+ sph_simd512_context ctx_simd;
+ sph_skein512_context ctx_skein;
+
+ unsigned char _ALIGN(128) hash[64];
+
+ sph_shavite512_init(&ctx_shavite);
+ sph_shavite512(&ctx_shavite, input, 80);
+ sph_shavite512_close(&ctx_shavite, (void*)hash);
+
+ sph_simd512_init(&ctx_simd);
+ sph_simd512(&ctx_simd, (const void*)hash, 64);
+ sph_simd512_close(&ctx_simd, (void*)hash);
+
+ sph_skein512_init(&ctx_skein);
+ sph_skein512(&ctx_skein, (const void*)hash, 64);
+ sph_skein512_close(&ctx_skein, (void*)hash);
+
+ memcpy(output, hash, 32);
+}
+
+int scanhash_s3(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
+ uint32_t max_nonce, uint64_t *hashes_done)
+{
+ uint32_t n = pdata[19] - 1;
+ const uint32_t first_nonce = pdata[19];
+ const uint32_t Htarg = ptarget[7];
+
+ uint32_t _ALIGN(32) hash64[8];
+ uint32_t endiandata[32];
+
+
+ uint64_t htmax[] = {
+ 0,
+ 0xF,
+ 0xFF,
+ 0xFFF,
+ 0xFFFF,
+ 0x10000000
+ };
+ uint32_t masks[] = {
+ 0xFFFFFFFF,
+ 0xFFFFFFF0,
+ 0xFFFFFF00,
+ 0xFFFFF000,
+ 0xFFFF0000,
+ 0
+ };
+
+ // we need bigendian data...
+ for (int kk=0; kk < 32; kk++) {
+ be32enc(&endiandata[kk], ((uint32_t*)pdata)[kk]);
+ };
+#ifdef DEBUG_ALGO
+ printf("[%d] Htarg=%X\n", thr_id, Htarg);
+#endif
+ for (int m=0; m < 6; m++) {
+ if (Htarg <= htmax[m]) {
+ uint32_t mask = masks[m];
+ do {
+ pdata[19] = ++n;
+ be32enc(&endiandata[19], n);
+ s3hash(hash64, endiandata);
+#ifndef DEBUG_ALGO
+ if ((!(hash64[7] & mask)) && fulltest(hash64, ptarget)) {
+ *hashes_done = n - first_nonce + 1;
+ return true;
+ }
+#else
+ if (!(n % 0x1000) && !thr_id) printf(".");
+ if (!(hash64[7] & mask)) {
+ printf("[%d]",thr_id);
+ if (fulltest(hash64, ptarget)) {
+ *hashes_done = n - first_nonce + 1;
+ return true;
+ }
+ }
+#endif
+ } while (n < max_nonce && !work_restart[thr_id].restart);
+ // see blake.c if else to understand the loop on htmax => mask
+ break;
+ }
+ }
+
+ *hashes_done = n - first_nonce + 1;
+ pdata[19] = n;
+ return 0;
+}
diff --git a/util.c b/util.c
index 572067496..e1bb80256 100644
--- a/util.c
+++ b/util.c
@@ -1641,6 +1641,10 @@ void print_hash_tests(void)
freshhash(&hash[0], &buf[0], 80);
printpfx("Fresh", hash);
+ memset(hash, 0, sizeof hash);
+ s3hash(&hash[0], &buf[0]);
+ printpfx("S3", hash);
+
memset(hash, 0, sizeof hash);
x11hash(&hash[0], &buf[0]);
printpfx("X11", hash);