Browse Source

Fix incorrect PoW buffer length usage

pull/67/head
catbref 4 years ago
parent
commit
847093edac
  1. 79
      src/main/java/org/qortal/crypto/MemoryPoW.java
  2. 5
      src/main/wasm/memory-pow/memory-pow.c

79
src/main/java/org/qortal/crypto/MemoryPoW.java

@ -2,85 +2,8 @@ package org.qortal.crypto;
import java.nio.ByteBuffer;
import com.google.common.primitives.Bytes;
public class MemoryPoW {
private static final int HASH_LENGTH = 32;
private static final int HASH_LENGTH_MASK = HASH_LENGTH - 1;
public static Integer compute(byte[] data, int workBufferLength, int start, int range, int difficulty) {
if (range < 1)
throw new IllegalArgumentException("range must be at least 1");
if (difficulty < 1)
throw new IllegalArgumentException("difficulty must be at least 1");
final int workBufferLengthMask = workBufferLength - 1;
// Hash data with SHA256
byte[] hash = Crypto.digest(data);
assert hash.length == HASH_LENGTH;
byte[] perturbedHash = new byte[HASH_LENGTH];
byte[] workBuffer = new byte[workBufferLength];
byte[] bufferHash = new byte[HASH_LENGTH];
// For each nonce...
for (int nonce = start; nonce < start + range; ++nonce) {
// Perturb hash using nonce
int temp = nonce;
for (int hi = 0; hi < HASH_LENGTH; ++hi) {
perturbedHash[hi] = (byte) (hash[hi] ^ (temp & 0xff));
temp >>>= 1;
}
// Fill large working memory buffer using hash, further perturbing as we go
int wanderingBufferOffset = 0;
byte ch = 0;
int hashOffset = 0;
for (int workBufferOffset = 0; workBufferOffset < workBufferLength; workBufferOffset += HASH_LENGTH) {
System.arraycopy(perturbedHash, 0, workBuffer, workBufferOffset, HASH_LENGTH);
hashOffset = ++hashOffset & HASH_LENGTH_MASK;
ch += perturbedHash[hashOffset];
for (byte hi = 0; hi < HASH_LENGTH; ++hi) {
byte hashByte = perturbedHash[hi];
wanderingBufferOffset = (wanderingBufferOffset << 3) ^ (hashByte & 0xff);
perturbedHash[hi] = (byte) (hashByte ^ (ch + hi));
}
workBuffer[wanderingBufferOffset & workBufferLengthMask] ^= 0xAA;
// final int finalWanderingBufferOffset = wanderingBufferOffset & WORK_BUFFER_LENGTH_MASK;
// System.out.println(String.format("wanderingBufferOffset: 0x%08x / 0x%08x - %02d%%", finalWanderingBufferOffset, WORK_BUFFER_LENGTH, finalWanderingBufferOffset * 100 / WORK_BUFFER_LENGTH));
}
Bytes.reverse(workBuffer);
// bufferHash = Crypto.digest(workBuffer);
System.arraycopy(workBuffer, 0, bufferHash, 0, HASH_LENGTH);
int hi = 0;
for (hi = 0; hi < difficulty; ++hi)
if (bufferHash[hi] != 0)
break;
if (hi == difficulty)
return nonce;
Thread.yield();
}
return null;
}
public static Integer compute2(byte[] data, int workBufferLength, long difficulty) {
// Hash data with SHA256
byte[] hash = Crypto.digest(data);
@ -94,7 +17,7 @@ public class MemoryPoW {
byteBuffer = null;
int longBufferLength = workBufferLength / 8;
long[] workBuffer = new long[longBufferLength / 8];
long[] workBuffer = new long[longBufferLength];
long[] state = new long[4];
long seed = 8682522807148012L;

5
src/main/wasm/memory-pow/memory-pow.c

@ -4,7 +4,6 @@
typedef unsigned long long uint64_t;
#endif
#define WORKBUFFER_LENGTH (longBufferLength / 8)
#define INTEGER_MAX_VALUE 0x7fffffffULL
uint64_t xoshiro256p(uint64_t state[]) {
@ -71,13 +70,13 @@ uint32_t compute2(uint8_t *hash, uint64_t *workBuffer, uint32_t workBufferLength
state[3] = longHash[3] ^ seed;
// Fill work buffer with random
for (uint32_t i = 0; i < WORKBUFFER_LENGTH; ++i)
for (uint32_t i = 0; i < longBufferLength; ++i)
workBuffer[i] = xoshiro256p(state);
// Random bounce through whole buffer
result = workBuffer[0];
for (uint32_t i = 0; i < 1024; ++i) {
uint32_t index = (uint32_t) (xoshiro256p(state) & INTEGER_MAX_VALUE) % WORKBUFFER_LENGTH;
uint32_t index = (uint32_t) (xoshiro256p(state) & INTEGER_MAX_VALUE) % longBufferLength;
result ^= workBuffer[index];
}

Loading…
Cancel
Save