diff --git a/src/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp index ef9466629..cf5a64352 100644 --- a/src/cryptonote_basic/difficulty.cpp +++ b/src/cryptonote_basic/difficulty.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "int-util.h" @@ -102,18 +103,25 @@ namespace cryptonote { return a + b < a || (c && a + b == (uint64_t) -1); } + static inline uint64_t load_u64_from_hash(const crypto::hash &hash, size_t index) { + assert(index < sizeof(hash.data) / sizeof(uint64_t)); + uint64_t word; + memcpy(&word, hash.data + index * sizeof(word), sizeof(word)); + return SWAP64LE(word); + } + bool check_hash_64(const crypto::hash &hash, uint64_t difficulty) { uint64_t low, high, top, cur; // First check the highest word, this will most likely fail for a random hash. - mul(swap64le(((const uint64_t *) &hash)[3]), difficulty, top, high); + mul(load_u64_from_hash(hash, 3), difficulty, top, high); if (high != 0) { return false; } - mul(swap64le(((const uint64_t *) &hash)[0]), difficulty, low, cur); - mul(swap64le(((const uint64_t *) &hash)[1]), difficulty, low, high); + mul(load_u64_from_hash(hash, 0), difficulty, low, cur); + mul(load_u64_from_hash(hash, 1), difficulty, low, high); bool carry = cadd(cur, low); cur = high; - mul(swap64le(((const uint64_t *) &hash)[2]), difficulty, low, high); + mul(load_u64_from_hash(hash, 2), difficulty, low, high); carry = cadc(cur, low, carry); carry = cadc(high, top, carry); return !carry; @@ -171,7 +179,7 @@ namespace cryptonote { bool check_hash_128(const crypto::hash &hash, difficulty_type difficulty) { #ifndef FORCE_FULL_128_BITS // fast check - if (difficulty >= max64bit && ((const uint64_t *) &hash)[3] > 0) + if (difficulty >= max64bit && load_u64_from_hash(hash, 3) > 0) return false; #endif // usual slow check @@ -182,7 +190,7 @@ namespace cryptonote { for(int i = 1; i < 4; i++) { // highest word is zero #endif hashVal <<= 64; - hashVal |= swap64le(((const uint64_t *) &hash)[3 - i]); + hashVal |= load_u64_from_hash(hash, 3 - i); } return hashVal * difficulty <= max256bit; } diff --git a/tests/unit_tests/difficulty.cpp b/tests/unit_tests/difficulty.cpp index c8e9ceefc..6a01eabc3 100644 --- a/tests/unit_tests/difficulty.cpp +++ b/tests/unit_tests/difficulty.cpp @@ -26,6 +26,9 @@ // 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 "gtest/gtest.h" #include "int-util.h" #include "cryptonote_basic/difficulty.h" @@ -37,6 +40,13 @@ static cryptonote::difficulty_type MKDIFF(uint64_t high, uint64_t low) return d; } +static void set_hash_word(crypto::hash &hash, std::size_t index, uint64_t value) +{ + ASSERT_LT(index, sizeof(hash.data) / sizeof(value)); + value = SWAP64LE(value); + memcpy(hash.data + index * sizeof(value), &value, sizeof(value)); +} + static crypto::hash MKHASH(uint64_t high, uint64_t low) { cryptonote::difficulty_type hash_target = high; @@ -45,16 +55,16 @@ static crypto::hash MKHASH(uint64_t high, uint64_t low) crypto::hash h; uint64_t val; val = (hash_value & 0xffffffffffffffff).convert_to(); - ((uint64_t*)&h)[0] = SWAP64LE(val); + set_hash_word(h, 0, val); hash_value >>= 64; val = (hash_value & 0xffffffffffffffff).convert_to(); - ((uint64_t*)&h)[1] = SWAP64LE(val); + set_hash_word(h, 1, val); hash_value >>= 64; val = (hash_value & 0xffffffffffffffff).convert_to(); - ((uint64_t*)&h)[2] = SWAP64LE(val); + set_hash_word(h, 2, val); hash_value >>= 64; val = (hash_value & 0xffffffffffffffff).convert_to(); - ((uint64_t*)&h)[3] = SWAP64LE(val); + set_hash_word(h, 3, val); return h; }