I see many question on forum about mining process, maybe you can post some part of this code if BCnext allow it.
Part of main() method:
(new Thread() {
@Override
public void run() {
HashMap
lastBlocks = new HashMap<>();
HashMap hits = new HashMap<>();
while (state == 0) {
try {
if (bootstrappingState >= 0) {
HashMap unlockedAccounts = new HashMap<>();
for (User user : users.values()) {
if (user.secretPhrase != null) {
Account account = accounts.get(Account.getId(Crypto.getPublicKey(user.secretPhrase)));
if (account != null && account.getEffectiveBalance() > 0) {
unlockedAccounts.put(account, user);
}
}
}
for (Map.Entry unlockedAccountEntry : unlockedAccounts.entrySet()) {
Account account = unlockedAccountEntry.getKey();
User user = unlockedAccountEntry.getValue();
Block lastBlock = Block.getLastBlock();
if (lastBlocks.get(account) != lastBlock) {
byte[] generationSignature = Crypto.sign(lastBlock.generationSignature, user.secretPhrase);
byte[] generationSignatureHash = MessageDigest.getInstance("SHA-256").digest(generationSignature);
BigInteger hit = new BigInteger(1, new byte[] {generationSignatureHash[7], generationSignatureHash[6], generationSignatureHash[5], generationSignatureHash[4], generationSignatureHash[3], generationSignatureHash[2], generationSignatureHash[1], generationSignatureHash[0]});
lastBlocks.put(account, lastBlock);
hits.put(account, hit);
JSONObject response = new JSONObject();
response.put("response", "setBlockGenerationDeadline");
response.put("deadline", hit.divide(BigInteger.valueOf(Block.getBaseTarget()).multiply(BigInteger.valueOf(account.getEffectiveBalance()))).longValue() - (getEpochTime(System.currentTimeMillis()) - lastBlock.timestamp));
user.send(response);
}
int elapsedTime = getEpochTime(System.currentTimeMillis()) - lastBlock.timestamp;
if (elapsedTime > 0) {
BigInteger target = BigInteger.valueOf(Block.getBaseTarget()).multiply(BigInteger.valueOf(account.getEffectiveBalance())).multiply(BigInteger.valueOf(elapsedTime));
if (hits.get(account).compareTo(target) < 0) {
account.generateBlock(user.secretPhrase);
}
}
}
}
Thread.sleep(1000);
} catch (Exception e) {
log("9: " + e.toString());
}
}
}
}).start();
Part of Account class:
int getEffectiveBalance() {
if (height == 0) {
return (int)(balance / 100);
}
if (Block.getLastBlock().height - height < 1440) {
return 0;
}
int amount = 0;
for (long transactionId : Block.getLastBlock().transactions) {
Transaction transaction = transactions.get(transactionId);
if (transaction.recipient == id) {
amount += transaction.amount;
}
}
return (int)(balance / 100) - amount;
}
Part of Account class:
void generateBlock(String secretPhrase) throws Exception {
HashMap newTransactions;
synchronized (transactions) {
Transaction[] sortedTransactions = unconfirmedTransactions.values().toArray(new Transaction[0]);
while (sortedTransactions.length > 0) {
int i;
for (i = 0; i < sortedTransactions.length; i++) {
Transaction transaction = sortedTransactions[i];
if (transaction.referencedTransaction != 0 && transactions.get(transaction.referencedTransaction) == null) {
sortedTransactions[i] = sortedTransactions[sortedTransactions.length - 1];
Transaction[] tmp = new Transaction[sortedTransactions.length - 1];
System.arraycopy(sortedTransactions, 0, tmp, 0, tmp.length);
sortedTransactions = tmp;
break;
}
}
if (i == sortedTransactions.length) {
break;
}
}
Arrays.sort(sortedTransactions);
newTransactions = new HashMap<>();
for (int i = 0; i < 255 && i < sortedTransactions.length; i++) {
long id = sortedTransactions[i].getId();
newTransactions.put(id, sortedTransactions[i]);
}
}
Block block = new Block(1, getEpochTime(System.currentTimeMillis()), lastBlock, newTransactions.size(), 0, 0, 0, null, Crypto.getPublicKey(secretPhrase), null, new byte[64]);
block.transactions = new long[block.numberOfTransactions];
int i = 0;
for (Map.Entry transactionEntry : newTransactions.entrySet()) {
Transaction transaction = transactionEntry.getValue();
if (transaction.type == Transaction.TYPE_PAYMENT && transaction.subtype == Transaction.SUBTYPE_PAYMENT_ORDINARY_PAYMENT) {
block.totalAmount += transaction.amount;
}
block.totalFee += transaction.fee;
block.payloadLength += transaction.getBytes().length;
block.transactions[i++] = transactionEntry.getKey();
}
Arrays.sort(block.transactions);
MessageDigest digest = MessageDigest.getInstance("SHA-256");
for (i = 0; i < block.numberOfTransactions; i++) {
digest.update(newTransactions.get(block.transactions[i]).getBytes());
}
block.payloadHash = digest.digest();
block.generationSignature = Crypto.sign(Block.getLastBlock().generationSignature, secretPhrase);
byte[] data = block.getBytes();
byte[] data2 = new byte[data.length - 64];
System.arraycopy(data, 0, data2, 0, data2.length);
block.blockSignature = Crypto.sign(data2, secretPhrase);
ByteBuffer outputBuffer = Peer.getOutputBuffer(224 + block.payloadLength, Peer.PACKET_TYPE_NEW_BLOCK_REQUEST);
outputBuffer.put(block.getBytes());
for (i = 0; i < block.numberOfTransactions; i++) {
Transaction transaction = newTransactions.get(block.transactions[i]);
outputBuffer.put(transaction.getBytes());
}
Peer.sendToAllPeers(outputBuffer);
}
Part of Transaction class (used by Arrays.sort()):
public int compareTo(Transaction o) {
if (height < o.height) {
return -1;
} else if (height > o.height) {
return 1;
} else {
if (fee * 32768L / getBytes().length > o.fee * 32768L / o.getBytes().length) {
return -1;
} else if (fee * 32768L / getBytes().length < o.fee * 32768L / o.getBytes().length) {
return 1;
} else {
if (timestamp < o.timestamp) {
return -1;
} else if (timestamp > o.timestamp) {
return 1;
} else {
if (index < o.index) {
return -1;
} else if (index > o.index) {
return 1;
} else {
return 0;
}
}
}
}
}