diff --git a/java-blockchain/.gitignore b/java-blockchain/.gitignore new file mode 100644 index 0000000000..3de4cc647e --- /dev/null +++ b/java-blockchain/.gitignore @@ -0,0 +1,26 @@ +*.class + +0.* + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* +.resourceCache + +# Packaged files # +*.jar +*.war +*.ear + +# Files generated by integration tests +*.txt +backup-pom.xml +/bin/ +/temp + +#IntelliJ specific +.idea/ +*.iml \ No newline at end of file diff --git a/java-blockchain/README.md b/java-blockchain/README.md new file mode 100644 index 0000000000..600f4dd610 --- /dev/null +++ b/java-blockchain/README.md @@ -0,0 +1,6 @@ +========= + +## Basic Implementation of Blockchian in Java + +### Relevant Articles: +- []() diff --git a/java-blockchain/pom.xml b/java-blockchain/pom.xml new file mode 100644 index 0000000000..2f9e011aa7 --- /dev/null +++ b/java-blockchain/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + com.baeldung.blockchain + java-blockchain + 0.1.0-SNAPSHOT + java-blockchain + jar + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + java-blockchain + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + 1.8 + 1.8 + + \ No newline at end of file diff --git a/java-blockchain/src/main/java/com/baeldung/blockchain/Block.java b/java-blockchain/src/main/java/com/baeldung/blockchain/Block.java new file mode 100644 index 0000000000..264e3c4b69 --- /dev/null +++ b/java-blockchain/src/main/java/com/baeldung/blockchain/Block.java @@ -0,0 +1,65 @@ +package com.baeldung.blockchain; + +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Date; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class Block { + + private static Logger logger = Logger.getLogger(Block.class.getName()); + + private String hash; + private String previousHash; + private String data; + private long timeStamp; + private int nonce; + + public Block(String data, String previousHash) { + this.data = data; + this.previousHash = previousHash; + this.timeStamp = new Date().getTime(); + this.hash = calculateBlockHash(); + } + + public String mineBlock(int prefix) { + String prefixString = new String(new char[prefix]).replace('\0', '0'); + while (!hash.substring(0, prefix) + .equals(prefixString)) { + nonce++; + hash = calculateBlockHash(); + } + return hash; + } + + public String calculateBlockHash() { + String dataToHash = previousHash + Long.toString(timeStamp) + Integer.toString(nonce) + data; + MessageDigest digest = null; + byte[] bytes = null; + try { + digest = MessageDigest.getInstance("SHA-256"); + bytes = digest.digest(dataToHash.getBytes("UTF-8")); + } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) { + logger.log(Level.SEVERE, ex.getMessage()); + } + StringBuffer buffer = new StringBuffer(); + for (byte b : bytes) { + buffer.append(String.format("%02x", b)); + } + return buffer.toString(); + } + + public String getHash() { + return this.hash; + } + + public String getPreviousHash() { + return this.previousHash; + } + + public void setData(String data) { + this.data = data; + } +} diff --git a/java-blockchain/src/main/resources/logback.xml b/java-blockchain/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/java-blockchain/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/java-blockchain/src/test/java/com/baeldung/blockchain/BlockchainUnitTest.java b/java-blockchain/src/test/java/com/baeldung/blockchain/BlockchainUnitTest.java new file mode 100644 index 0000000000..acbf651e78 --- /dev/null +++ b/java-blockchain/src/test/java/com/baeldung/blockchain/BlockchainUnitTest.java @@ -0,0 +1,67 @@ +package com.baeldung.blockchain; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class BlockchainUnitTest { + + public static List blockchain = new ArrayList(); + public static int prefix = 4; + public static String prefixString = new String(new char[prefix]).replace('\0', '0'); + + @BeforeClass + public static void setUp() { + Block genesisBlock = new Block("The is the Genesis Block.", "0"); + genesisBlock.mineBlock(prefix); + blockchain.add(genesisBlock); + Block firstBlock = new Block("The is the First Block.", genesisBlock.getHash()); + firstBlock.mineBlock(prefix); + blockchain.add(firstBlock); + } + + @Test + public void givenBlockchain_whenNewBlockAdded_thenSuccess() { + Block newBlock = new Block("The is a New Block.", blockchain.get(blockchain.size() - 1) + .getHash()); + newBlock.mineBlock(prefix); + assertTrue(newBlock.getHash() + .substring(0, prefix) + .equals(prefixString)); + blockchain.add(newBlock); + } + + @Test + public void givenBlockchain_whenValidated_thenSuccess() { + boolean flag = true; + for (int i = 0; i < blockchain.size(); i++) { + String previousHash = i == 0 ? "0" + : blockchain.get(i - 1) + .getHash(); + flag = blockchain.get(i) + .getHash() + .equals(blockchain.get(i) + .calculateBlockHash()) + && previousHash.equals(blockchain.get(i) + .getPreviousHash()) + && blockchain.get(i) + .getHash() + .substring(0, prefix) + .equals(prefixString); + if (!flag) + break; + } + assertTrue(flag); + } + + @AfterClass + public static void tearDown() { + blockchain.clear(); + } + +} diff --git a/java-blockchain/src/test/resources/.gitignore b/java-blockchain/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/java-blockchain/src/test/resources/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/pom.xml b/pom.xml index a4f2a13c28..1dbc3647b5 100644 --- a/pom.xml +++ b/pom.xml @@ -566,6 +566,7 @@ oauth2-framework-impl spring-boot-nashorn + java-blockchain @@ -802,6 +803,7 @@ spring-security-kerberos spring-boot-nashorn + java-blockchain