I have this while loop in my code,
while(!this.hash.substring(0, difficulty).equals(offset)) {
this.nonce++;
this.hash = this.generateHash();
}
I need to run every iteration of this while loop in a new thread and making the overall task faster!!
I tried overriding the run()
method of the Runnable
interface as follows,
@Override
public void run() {
while(!this.hash.substring(0, this.difficulty).equals(this.offset)) {
this.nonce++;
this.hash = this.generateHash();
}
}
And running it like below,
ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
Runnable c = new Create(this.timestamp, this.transactions, this.previousHash, difficulty, offset)
es.execute(c);
es.shutdown();
But this does not seem to be working either!!
Is it possible?
Any answer would be great!! Thanks in advance!
-- EDIT --
Following is the full code and the while loop is inside the mineBlock()
method.
public class Block {
public static final String HASH_FN = "SHA-256";
public static final String ENCODING = "UTF-8";
private Date timestamp;
private Transaction transaction;
private String previousHash = "";
private String hash;
private Integer nonce = 0; //random number, dynamic part
public Block(Date timestamp, Transaction transaction) {
super();
this.timestamp = timestamp;
this.transaction = transaction;
hash = generateHash();
}
public String generateHash() {
//0, 1, 2 --> 000000000adf0991111111...64
String base = this.timestamp + this.previousHash + this.nonce + this.transaction.toString();
try {
final MessageDigest digest = MessageDigest.getInstance(HASH_FN);
final byte[] hash = digest.digest(base.getBytes(ENCODING));
final StringBuilder hexString = new StringBuilder();
for (int i = 0; i < hash.length; i++) {
final String hex = Integer.toHexString(0xff & hash[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (Exception ex) {
throw new RuntimeException("Hash Generation Exception");
}
}
//[TODO]
public void mineBlock(int difficulty) {
String offset = String.join("", Collections.nCopies(difficulty, "0")); //add leading 0
while(!this.hash.substring(0, difficulty).equals(offset)) {
this.nonce++;
this.hash = this.generateHash();
}
System.out.println("A block mined!, hash " + this.hash);
}
public String getPreviousHash() {
return previousHash;
}
public void setPreviousHash(String previousHash) {
this.previousHash = previousHash;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
@Override
public String toString() {
return "Block [timestamp=" + timestamp + ", transaction=" + transaction + ", previousHash="
+ previousHash + ", hash=" + hash + "]";
}
public void setFakeAmount(int fakeAmount) {
this.transaction.setAmount(fakeAmount);
}
}
-- EDIT 2 --
I used the following method since there are sharing resources. But, that method also does not seem to be working!!
BlockThread.java
public class BlockThread extends Thread {
private Block block;
public BlockThread(Block block) {
this.block = block;
}
@Override
public void run() {
this.block.countNonce();
this.block.genNewHash();
}
}
Inside Block.java
, I added the following methods to update corresponding variables.
public synchronized void countNonce() {
this.nonce++;
}
public synchronized void genNewHash() {
this.hash = this.generateHash();
}
Finally, I ran it like this (I took the mineBlock()
method into another class where the blk
is initialized with a new Block(...)
, and ran it from there. The non-parallel way works as expected in this design also.),
while(!blk.hash.substring(0, difficulty).equals(offset)) {
Create create = new Create(blk);
create.start();
}
When I'm viewing, nonce
seems to be getting updated parallelly. But, the overall method does not work in multiple threads as expected!!
It would be great if anyone could help!!