From 709bbc52c4c0fe3799d791e25fc7b1d1da160638 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Tue, 27 Jan 2015 14:04:23 +0200 Subject: [PATCH 1/3] replaced 64-bit multiplication in difficulty.cpp with a portable version --- src/cryptonote_core/difficulty.cpp | 38 ++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/cryptonote_core/difficulty.cpp b/src/cryptonote_core/difficulty.cpp index 106520440..6486d8124 100644 --- a/src/cryptonote_core/difficulty.cpp +++ b/src/cryptonote_core/difficulty.cpp @@ -56,10 +56,40 @@ namespace cryptonote { #else static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { - typedef unsigned __int128 uint128_t; - uint128_t res = (uint128_t) a * (uint128_t) b; - low = (uint64_t) res; - high = (uint64_t) (res >> 64); + // __int128 isn't part of the standard, so the previous function wasn't portable. mul128() in Windows is fine, + // but this portable function should be used elsewhere. Credit for this function goes to latexi95. + + uint64_t aLow = a & 0xFFFFFFFF; + uint64_t aHigh = a >> 32; + uint64_t bLow = b & 0xFFFFFFFF; + uint64_t bHigh = b >> 32; + + uint64_t res = aLow * bLow; + uint64_t lowRes1 = res & 0xFFFFFFFF; + uint64_t carry = res >> 32; + + res = aHigh * bLow + carry; + uint64_t highResHigh1 = res >> 32; + uint64_t highResLow1 = res & 0xFFFFFFFF; + + res = aLow * bHigh; + uint64_t lowRes2 = res & 0xFFFFFFFF; + carry = res >> 32; + + res = aHigh * bHigh + carry; + uint64_t highResHigh2 = res >> 32; + uint64_t highResLow2 = res & 0xFFFFFFFF; + + //Addition + + uint64_t r = highResLow1 + lowRes2; + carry = r >> 32; + low = (r << 32) | lowRes1; + r = highResHigh1 + highResLow2 + carry; + uint64_t d3 = r & 0xFFFFFFFF; + carry = r >> 32; + r = highResHigh2 + carry; + high = d3 | (r << 32); } #endif From 497a514bd328400c8572041c1217ab2adac5e2c8 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Tue, 27 Jan 2015 14:04:23 +0200 Subject: [PATCH 2/3] replaced 64-bit multiplication in difficulty.cpp with a portable version --- src/cryptonote_core/difficulty.cpp | 38 ++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/cryptonote_core/difficulty.cpp b/src/cryptonote_core/difficulty.cpp index 106520440..6486d8124 100644 --- a/src/cryptonote_core/difficulty.cpp +++ b/src/cryptonote_core/difficulty.cpp @@ -56,10 +56,40 @@ namespace cryptonote { #else static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { - typedef unsigned __int128 uint128_t; - uint128_t res = (uint128_t) a * (uint128_t) b; - low = (uint64_t) res; - high = (uint64_t) (res >> 64); + // __int128 isn't part of the standard, so the previous function wasn't portable. mul128() in Windows is fine, + // but this portable function should be used elsewhere. Credit for this function goes to latexi95. + + uint64_t aLow = a & 0xFFFFFFFF; + uint64_t aHigh = a >> 32; + uint64_t bLow = b & 0xFFFFFFFF; + uint64_t bHigh = b >> 32; + + uint64_t res = aLow * bLow; + uint64_t lowRes1 = res & 0xFFFFFFFF; + uint64_t carry = res >> 32; + + res = aHigh * bLow + carry; + uint64_t highResHigh1 = res >> 32; + uint64_t highResLow1 = res & 0xFFFFFFFF; + + res = aLow * bHigh; + uint64_t lowRes2 = res & 0xFFFFFFFF; + carry = res >> 32; + + res = aHigh * bHigh + carry; + uint64_t highResHigh2 = res >> 32; + uint64_t highResLow2 = res & 0xFFFFFFFF; + + //Addition + + uint64_t r = highResLow1 + lowRes2; + carry = r >> 32; + low = (r << 32) | lowRes1; + r = highResHigh1 + highResLow2 + carry; + uint64_t d3 = r & 0xFFFFFFFF; + carry = r >> 32; + r = highResHigh2 + carry; + high = d3 | (r << 32); } #endif From 3ece1584f081fb995217b3dfc718b5e099f10220 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Wed, 28 Jan 2015 11:32:52 +0200 Subject: [PATCH 3/3] make fallback compatible with newer slow-hash --- src/crypto/slow-hash.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index fda854ea5..6b410b01a 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -627,6 +627,18 @@ void cn_slow_hash(const void *data, size_t length, char *hash) #else // Portable implementation as a fallback +void slow_hash_allocate_state(void) +{ + // Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c + return; +} + +void slow_hash_free_state(void) +{ + // As above + return; +} + static void (*const extra_hashes[4])(const void *, size_t, char *) = { hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein };