Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/noobchain/Block.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,19 @@ public void mineBlock(int difficulty) {
}

//Add transactions to this block
public boolean addTransaction(Transaction transaction) {
public void addTransaction(Transaction transaction) throws IllegalStateException {
//process transaction and check if valid, unless block is genesis block then ignore.
if(transaction == null) return false;
if((!"0".equals(previousHash))) {
if((transaction.processTransaction() != true)) {
System.out.println("Transaction failed to process. Discarded.");
return false;
throw new IllegalStateException("Transaction failed to process. Discarded.");
}
}

transactions.add(transaction);
System.out.println("Transaction Successfully added to Block");
return true;

}

}
244 changes: 133 additions & 111 deletions src/noobchain/NoobChain.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package noobchain;

import java.security.Security;
import java.util.ArrayList;
//import java.util.Base64;
Expand All @@ -7,169 +8,190 @@
import java.util.Map;

public class NoobChain {

public static ArrayList<Block> blockchain = new ArrayList<Block>();
public static HashMap<String,TransactionOutput> UTXOs = new HashMap<String,TransactionOutput>();
public static HashMap<String, TransactionOutput> UTXOs = new HashMap<String, TransactionOutput>();

public static int difficulty = 3;
public static float minimumTransaction = 0.1f;
public static Wallet walletA;
public static Wallet walletB;
public static Transaction genesisTransaction;

public static void main(String[] args) {
//add our blocks to the blockchain ArrayList:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); //Setup Bouncey castle as a Security Provider

//Create wallets:
public static void main(String[] args) {
// add our blocks to the blockchain ArrayList:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); // Setup Bouncey castle as a
// Security Provider

// Create wallets:
walletA = new Wallet();
walletB = new Wallet();
walletB = new Wallet();
Wallet coinbase = new Wallet();

//create genesis transaction, which sends 100 NoobCoin to walletA:
genesisTransaction = new Transaction(coinbase.publicKey, walletA.publicKey, 100f, null);
genesisTransaction.generateSignature(coinbase.privateKey); //manually sign the genesis transaction
genesisTransaction.transactionId = "0"; //manually set the transaction id
genesisTransaction.outputs.add(new TransactionOutput(genesisTransaction.reciepient, genesisTransaction.value, genesisTransaction.transactionId)); //manually add the Transactions Output
UTXOs.put(genesisTransaction.outputs.get(0).id, genesisTransaction.outputs.get(0)); //its important to store our first transaction in the UTXOs list.

System.out.println("Creating and Mining Genesis block... ");
Block genesis = new Block("0");
genesis.addTransaction(genesisTransaction);
addBlock(genesis);

//testing
Block block1 = new Block(genesis.hash);
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("\nWalletA is Attempting to send funds (40) to WalletB...");
block1.addTransaction(walletA.sendFunds(walletB.publicKey, 40f));
addBlock(block1);
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("WalletB's balance is: " + walletB.getBalance());

Block block2 = new Block(block1.hash);
System.out.println("\nWalletA Attempting to send more funds (1000) than it has...");
block2.addTransaction(walletA.sendFunds(walletB.publicKey, 1000f));
addBlock(block2);
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("WalletB's balance is: " + walletB.getBalance());

Block block3 = new Block(block2.hash);
System.out.println("\nWalletB is Attempting to send funds (20) to WalletA...");
block3.addTransaction(walletB.sendFunds( walletA.publicKey, 20));
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("WalletB's balance is: " + walletB.getBalance());

isChainValid();


// create genesis transaction, which sends 100 NoobCoin to walletA:
try {
genesisTransaction = new Transaction(coinbase.publicKey, walletA.publicKey, 100f, null);
genesisTransaction.generateSignature(coinbase.privateKey); // manually sign the genesis transaction
genesisTransaction.transactionId = "0"; // manually set the transaction id
genesisTransaction.outputs.add(new TransactionOutput(genesisTransaction.reciepient,
genesisTransaction.value, genesisTransaction.transactionId)); // manually add the Transactions
// Output
UTXOs.put(genesisTransaction.outputs.get(0).id, genesisTransaction.outputs.get(0)); // its important to
// store our first
// transaction in the
// UTXOs list.

System.out.println("Creating and Mining Genesis block... ");
Block genesis = new Block("0");
genesis.addTransaction(genesisTransaction);
addBlock(genesis);

// testing
Block block1 = new Block(genesis.hash);
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("\nWalletA is Attempting to send funds (40) to WalletB...");
block1.addTransaction(walletA.sendFunds(walletB.publicKey, 40f));
addBlock(block1);
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("WalletB's balance is: " + walletB.getBalance());

Block block2 = new Block(block1.hash);
System.out.println("\nWalletA Attempting to send more funds (1000) than it has...");
block2.addTransaction(walletA.sendFunds(walletB.publicKey, 1000f));
addBlock(block2);
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("WalletB's balance is: " + walletB.getBalance());

Block block3 = new Block(block2.hash);
System.out.println("\nWalletB is Attempting to send funds (20) to WalletA...");
block3.addTransaction(walletB.sendFunds(walletA.publicKey, 20));
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("WalletB's balance is: " + walletB.getBalance());

isChainValid();
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}

}

public static Boolean isChainValid() {
Block currentBlock;
Block currentBlock;
Block previousBlock;
String hashTarget = new String(new char[difficulty]).replace('\0', '0');
HashMap<String,TransactionOutput> tempUTXOs = new HashMap<String,TransactionOutput>(); //a temporary working list of unspent transactions at a given block state.
HashMap<String, TransactionOutput> tempUTXOs = new HashMap<String, TransactionOutput>(); // a temporary working
// list of unspent
// transactions at a
// given block
// state.
tempUTXOs.put(genesisTransaction.outputs.get(0).id, genesisTransaction.outputs.get(0));
//loop through blockchain to check hashes:
for(int i=1; i < blockchain.size(); i++) {

// loop through blockchain to check hashes:
for (int i = 1; i < blockchain.size(); i++) {

currentBlock = blockchain.get(i);
previousBlock = blockchain.get(i-1);
//compare registered hash and calculated hash:
if(!currentBlock.hash.equals(currentBlock.calculateHash()) ){
previousBlock = blockchain.get(i - 1);
// compare registered hash and calculated hash:
if (!currentBlock.hash.equals(currentBlock.calculateHash())) {
System.out.println("#Current Hashes not equal");
return false;
}
//compare previous hash and registered previous hash
if(!previousBlock.hash.equals(currentBlock.previousHash) ) {
// compare previous hash and registered previous hash
if (!previousBlock.hash.equals(currentBlock.previousHash)) {
System.out.println("#Previous Hashes not equal");
return false;
}
//check if hash is solved
if(!currentBlock.hash.substring( 0, difficulty).equals(hashTarget)) {
// check if hash is solved
if (!currentBlock.hash.substring(0, difficulty).equals(hashTarget)) {
System.out.println("#This block hasn't been mined");
return false;
}
//loop thru blockchains transactions:

// loop thru blockchains transactions:
TransactionOutput tempOutput;
for(int t=0; t <currentBlock.transactions.size(); t++) {
for (int t = 0; t < currentBlock.transactions.size(); t++) {
Transaction currentTransaction = currentBlock.transactions.get(t);
if(!currentTransaction.verifySignature()) {

if (!currentTransaction.verifySignature()) {
System.out.println("#Signature on Transaction(" + t + ") is Invalid");
return false;
return false;
}
if(currentTransaction.getInputsValue() != currentTransaction.getOutputsValue()) {
if (currentTransaction.getInputsValue() != currentTransaction.getOutputsValue()) {
System.out.println("#Inputs are note equal to outputs on Transaction(" + t + ")");
return false;
return false;
}
for(TransactionInput input: currentTransaction.inputs) {

for (TransactionInput input : currentTransaction.inputs) {
tempOutput = tempUTXOs.get(input.transactionOutputId);
if(tempOutput == null) {

if (tempOutput == null) {
System.out.println("#Referenced input on Transaction(" + t + ") is Missing");
return false;
}
if(input.UTXO.value != tempOutput.value) {

if (input.UTXO.value != tempOutput.value) {
System.out.println("#Referenced input Transaction(" + t + ") value is Invalid");
return false;
}

tempUTXOs.remove(input.transactionOutputId);
}
for(TransactionOutput output: currentTransaction.outputs) {

for (TransactionOutput output : currentTransaction.outputs) {
tempUTXOs.put(output.id, output);
}

if( currentTransaction.outputs.get(0).reciepient != currentTransaction.reciepient) {
System.out.println("#Transaction(" + t + ") output reciepient is not who it should be");
return false;
}
if( currentTransaction.outputs.get(1).reciepient != currentTransaction.sender) {
System.out.println("#Transaction(" + t + ") output 'change' is not sender.");
return false;
}


// we dont need this since we verifySignature() already, the msg we signed has
// contains information like reciepient .
// if( currentTransaction.outputs.get(0).reciepient !=
// currentTransaction.reciepient) {
// System.out.println("#Transaction(" + t + ") output reciepient is not who it
// should be");
// return false;
// }
// if( currentTransaction.outputs.get(1).reciepient !=
// currentTransaction.sender) {
// System.out.println("#Transaction(" + t + ") output 'change' is not sender.");
// return false;
// }

}

}
System.out.println("Blockchain is valid");
return true;
}

public static void addBlock(Block newBlock) {
newBlock.mineBlock(difficulty);
blockchain.add(newBlock);
}
}

/*
* public static void main(String[] args) {
//add our blocks to the blockchain ArrayList:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); //Setup Bouncey castle as a Security Provider

//walletA = new Wallet();
//walletB = new Wallet();

//System.out.println("Private and public keys:");
//System.out.println(StringUtil.getStringFromKey(walletA.privateKey));
//System.out.println(StringUtil.getStringFromKey(walletA.publicKey));

createGenesis();

//Transaction transaction = new Transaction(walletA.publicKey, walletB.publicKey, 5);
//transaction.signature = transaction.generateSignature(walletA.privateKey);

//System.out.println("Is signature verified:");
//System.out.println(transaction.verifiySignature());

}
* public static void main(String[] args) { //add our blocks to the blockchain
* ArrayList: Security.addProvider(new
* org.bouncycastle.jce.provider.BouncyCastleProvider()); //Setup Bouncey castle
* as a Security Provider
*
* //walletA = new Wallet(); //walletB = new Wallet();
*
* //System.out.println("Private and public keys:");
* //System.out.println(StringUtil.getStringFromKey(walletA.privateKey));
* //System.out.println(StringUtil.getStringFromKey(walletA.publicKey));
*
* createGenesis();
*
* //Transaction transaction = new Transaction(walletA.publicKey,
* walletB.publicKey, 5); //transaction.signature =
* transaction.generateSignature(walletA.privateKey);
*
* //System.out.println("Is signature verified:");
* //System.out.println(transaction.verifiySignature());
*
* }
*/

//System.out.println("Trying to Mine block 1... ");
//addBlock(new Block("Hi im the first block", "0"));
// System.out.println("Trying to Mine block 1... ");
// addBlock(new Block("Hi im the first block", "0"));