1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
| package io.ryanluoxu.blockchain;
import java.sql.Timestamp; import java.util.ArrayList; import java.util.List;
public class Blockchain {
private List<Block> chain; private Block genesisBlock; private int difficulty; private List<Transaction> pendingTransactions; private long miningReward; private long bonusAmount; private List<Account> accounts;
public Blockchain() { chain = new ArrayList<>(); genesisBlock = createGenesisBlock(); chain.add(genesisBlock); // genesisBlock info System.out.println("Genesis Block is created:"); System.out.println("\tgenesisBlock.hash : " + genesisBlock.getHash()); System.out.println("\tgenesisBlock.nonce : " + genesisBlock.getNonce()); System.out.println("\tgenesisBlock.timestamp : " + genesisBlock.getTimestamp()); System.out.println("");
difficulty = 1; pendingTransactions = new ArrayList<>(); miningReward = 1000; bonusAmount = 100; accounts = new ArrayList<>(); accounts.add(new Account("system", "system", 0)); }
private Block createGenesisBlock() { return new Block(null, new Timestamp(System.currentTimeMillis()), null); }
private Block getLatestBlock(){ return chain.get(chain.size()-1); }
public boolean isChainValid() {
for (int i = 0; i < chain.size(); i++) { Block currentBlock = chain.get(i); Block previousBlock = chain.get(i-1);
if (currentBlock.getHash() != currentBlock.calculateHash()) { return false; }
if (currentBlock.getPreviousHash() != previousBlock.getHash()) { return false; } }
return true; }
void createTransaction(Transaction newTransaction, String fromKey) { // verification boolean isValidFromAddress = false; boolean isValidFromKey = false; boolean isValidToAddress = false;
String fromAddress = newTransaction.getFromAddress(); String toAddress = newTransaction.getToAddress();
for (Account account : accounts) { if (account.getAddress().equals(fromAddress)) { isValidFromAddress = true; if (account.getKey().equals(fromKey)) { isValidFromKey = true; } break; } }
for (Account account : accounts) { if (account.getAddress().equals(toAddress)) { isValidToAddress = true; break; } }
if (isValidToAddress && isValidFromAddress && isValidFromKey) { pendingTransactions.add(newTransaction); } else { System.out.println("Invalid fromAddress, fromKey or toAddress.."); } }
void minePendingTransaction(String miningRewardAddress) { Block newBlock = new Block(getLatestBlock().getHash(), new Timestamp(System.currentTimeMillis()), pendingTransactions); newBlock.mineBlock(difficulty); chain.add(newBlock); // newBlock info System.out.println("new Block is created:"); System.out.println("\tnewBlock.previousHash : " + newBlock.getPreviousHash()); System.out.println("\tnewBlock.hash : " + newBlock.getHash()); System.out.println("\tnewBlock.nonce : " + newBlock.getNonce()); System.out.println("\tnewBlock.timestamp : " + newBlock.getTimestamp()); System.out.println("");
// close pending transaction for (Transaction transaction : pendingTransactions) { // deduct from FromAddress boolean isWithdrawSuccess = false; boolean isTopUpSuccess = false; for (Account account : accounts) { if (account.getAddress().equals(transaction.getFromAddress())) { isWithdrawSuccess = account.withdraw(transaction.getAmount()); break; } } // top up on toAddress for (Account account : accounts) { if (isWithdrawSuccess) { if (account.getAddress().equals(transaction.getToAddress())) { isTopUpSuccess = account.topUp(transaction.getAmount()); break; } } }
if (isWithdrawSuccess && !isTopUpSuccess) { System.out.println("miningRewardAddress to [" + miningRewardAddress + "] is not successful.."); } }
// cleare pending transaction pendingTransactions = new ArrayList<>();
// reward given in next new block accounts.get(0).topUp(miningReward); // System.out.println("System top up mining reward amount : " + miningReward); pendingTransactions.add(new Transaction("system", miningRewardAddress, miningReward)); }
public void addAccount(Account newAccount) { accounts.add(newAccount); }
public void bonus() { for (int i = 1; i < accounts.size(); i++) { accounts.get(0).topUp(bonusAmount); // System.out.println("System top up bonus amount : " + bonusAmount); pendingTransactions.add(new Transaction("system", accounts.get(i).getAddress(), bonusAmount)); } }
public void viewAccount() { System.out.println("View Accounts: "); for (int i = 1; i < accounts.size(); i++) { System.out.println("\t" + accounts.get(i).getAddress() + " : " + accounts.get(i).getBalance()); } System.out.println(""); } }
|