Post
Topic
Board Altcoin Discussion
Re: Nxt source code
by
Come-from-Beyond
on 30/11/2013, 07:33:29 UTC
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:

Code:
(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:

Code:
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:

Code:
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()):

Code:
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;

}

}

}

}

}