forked from Qortal/qortal
Fix incorrect PoW buffer length usage
This commit is contained in:
parent
758a42db36
commit
847093edac
@ -2,85 +2,8 @@ package org.qortal.crypto;
|
|||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import com.google.common.primitives.Bytes;
|
|
||||||
|
|
||||||
public class MemoryPoW {
|
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) {
|
public static Integer compute2(byte[] data, int workBufferLength, long difficulty) {
|
||||||
// Hash data with SHA256
|
// Hash data with SHA256
|
||||||
byte[] hash = Crypto.digest(data);
|
byte[] hash = Crypto.digest(data);
|
||||||
@ -94,7 +17,7 @@ public class MemoryPoW {
|
|||||||
byteBuffer = null;
|
byteBuffer = null;
|
||||||
|
|
||||||
int longBufferLength = workBufferLength / 8;
|
int longBufferLength = workBufferLength / 8;
|
||||||
long[] workBuffer = new long[longBufferLength / 8];
|
long[] workBuffer = new long[longBufferLength];
|
||||||
long[] state = new long[4];
|
long[] state = new long[4];
|
||||||
|
|
||||||
long seed = 8682522807148012L;
|
long seed = 8682522807148012L;
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
typedef unsigned long long uint64_t;
|
typedef unsigned long long uint64_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WORKBUFFER_LENGTH (longBufferLength / 8)
|
|
||||||
#define INTEGER_MAX_VALUE 0x7fffffffULL
|
#define INTEGER_MAX_VALUE 0x7fffffffULL
|
||||||
|
|
||||||
uint64_t xoshiro256p(uint64_t state[]) {
|
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;
|
state[3] = longHash[3] ^ seed;
|
||||||
|
|
||||||
// Fill work buffer with random
|
// 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);
|
workBuffer[i] = xoshiro256p(state);
|
||||||
|
|
||||||
// Random bounce through whole buffer
|
// Random bounce through whole buffer
|
||||||
result = workBuffer[0];
|
result = workBuffer[0];
|
||||||
for (uint32_t i = 0; i < 1024; ++i) {
|
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];
|
result ^= workBuffer[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user